Issue #17055 has been updated by jeremyevans0 (Jeremy Evans).


Eregon (Benoit Daloze) wrote in #note-22:
> FWIW I noticed that using `attr_reader` does not warn if the @ivar is not set:
> ```
> $ ruby -w -e 'class T; def foo; @foo; end; end; t=T.new; p t.foo'
> -e:1: warning: instance variable @foo not initialized
> nil
> 
> $ ruby -w -e 'class T; attr_reader :foo; end; t=T.new; p t.foo'  
> nil
> ```
> 
> Which sounds like an easy way to speed up that case in Sequel.
> @jeremyevans0 Could you try that maybe? (so no initialization, but all accesses use the generated reader methods, which can be `private`)

I don't want to define private methods for all of the instance variables in use just to work around verbose warnings.  The attr_reader approach is definitely faster than the approach that eagerly initializes instance variables, but still slower than accessing the instance variables directly (instance variable access is ~25% faster than attr_reader method calls).

> OTOH this inconsistency seems weird to me.
> Maybe we should not have the uninitialized @ivar warning at all?

That was my first proposal to fix the issue, back in 2014 (#10396).  That ticket was closed by a commit that did something different than I proposed, with no discussion of the differences.

Since then, I've softened a little and understand that the current verbose warning is helpful in some cases, especially to new programmers.  That is why allowing for custom behavior per-object is so beneficial.  High performance code can turn off the warnings, while they are still used by default to help new programmers.  A single global setting as we have now is a suboptimal.

> I do like that warning for encouraging initializing @ivars in the constructor though, since that helps readability.
> But the fact there will be no warning when using `attr_reader :ivar` seems unfortunate.
> Maybe `attr_reader` should take a `warn_if_uninitialized:` keyword argument?

There was a bug filed for the fact that attr_reader doesn't warn (#9815), which was rejected.  I'm not in favor of adding keyword arguments to attr_reader.

----------------------------------------
Feature #17055: Allow suppressing uninitialized instance variable and method redefined verbose mode warnings
https://bugs.ruby-lang.org/issues/17055#change-87369

* Author: jeremyevans0 (Jeremy Evans)
* Status: Open
* Priority: Normal
----------------------------------------
These two verbose mode warnings are both fairly common and have good reasons why you would not want to warn about them in specific cases.  Not initializing instance variables to nil can be much better for performance, and redefining methods without removing the method first is the only safe approach in multi-threaded code.

There are reasons that you may want to issue verbose warnings by default in these cases.  For uninitialized instance variables, it helps catch typos. For method redefinition, it could alert you that a method already exists when you didn't expect it to, such as when a file is loaded multiple times when it should only be loaded once.

I propose we keep the default behavior the same, but offer the ability to opt-out of these warnings by defining methods.  For uninitialized instance variables in verbose mode, I propose we call `expected_uninitialized_instance_variable?(iv)` on the object.  If this method doesn't exist or returns false/nil, we issue the warning.  If the method exists and returns true, we suppress the warning.  Similarly, for redefined methods, we call `expected_redefined_method?(method_name)` on the class or module.  If the method doesn't exist or returns false/nil, we issue the warning.  If the method exists and returns true, we suppress the warning.

This approach allows high performance code (uninitialized instance variables) and safe code (redefining methods without removing) to work without verbose mode warnings.

I have implemented this support in a pull request: https://github.com/ruby/ruby/pull/3371

---Files--------------------------------
t.rb (5.59 KB)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>