From: tenderlove@... Date: 2020-11-30T19:06:04+00:00 Subject: [ruby-core:101165] [Ruby master Bug#17354] Module#const_source_location is misleading for constants awaiting autoload Issue #17354 has been updated by tenderlovemaking (Aaron Patterson). We can probably never change this behavior due to backwards compatibility, but along the same lines, I think this behavior is weird too: ``` irb(main):001:0> File.read "foo.rb" => "class Bar\nend\n" irb(main):002:0> autoload(:Foo, "./foo.rb") => nil irb(main):003:0> Object.const_defined?(:Foo) => true irb(main):004:0> Foo Traceback (most recent call last): 4: from /Users/aaron/.rubies/ruby-trunk/bin/irb:23:in `
' 3: from /Users/aaron/.rubies/ruby-trunk/bin/irb:23:in `load' 2: from /Users/aaron/.rubies/ruby-trunk/lib/ruby/gems/3.0.0/gems/irb-1.2.7/exe/irb:11:in `' 1: from (irb):4 NameError (uninitialized constant Foo) irb(main):005:0> Object.const_defined?(:Foo) => false ``` `Foo` was never defined and could never be defined, yet `const_defined?` returned true. It seems like `const_defined?` should return `:not_yet` or something ���� ---------------------------------------- Bug #17354: Module#const_source_location is misleading for constants awaiting autoload https://bugs.ruby-lang.org/issues/17354#change-88851 * Author: tomstuart (Tom Stuart) * Status: Open * Priority: Normal * ruby -v: ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin20] * Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN ---------------------------------------- Feature #10771 added `Module#const_source_location` as a way to find the source location of a constant���s definition. Bug #16764 reported that it didn���t work correctly for autoloaded constants, instead giving the source location of the `autoload` call site. This was fixed in `v3_0_0_preview1` in commit:92730810 and backported to `v2_7_2` in commit:c65aae11. However, `#const_source_location` still returns the `autoload` call site for constants which have not yet been loaded: ``` % echo 'class Foo; end' > foo.rb % irb >> Module.const_defined?(:Foo) => false >> Module.const_source_location(:Foo) => nil >> autoload :Foo, './foo' => nil >> Module.const_defined?(:Foo) => true >> Module.const_source_location(:Foo) => ["(irb)", 3] >> Module.const_get(:Foo) => Foo >> Module.const_defined?(:Foo) => true >> Module.const_source_location(:Foo) => ["./foo.rb", 1] ``` This edge case is undocumented and surprising. It looks like a bug to the programmer who receives the `autoload` location instead of one of the documented return values of `#const_source_location` (`nil`, `[]`, or the definition���s source location). We could either: * change the behaviour of `#const_source_location` to return `[]` for constants awaiting autoload, which is consistent with the [return value of `Module#const_defined?`](https://docs.ruby-lang.org/en/2.7.0/Module.html#method-i-const_defined-3F) in this case (���if the constant is not present but there is an autoload for it, `true` is returned directly���), as well as the [return value of `#const_source_location`](https://docs.ruby-lang.org/en/2.7.0/Module.html#method-i-const_source_location) for other constants whose source location is unknown (���if the constant is found, but its source location can not be extracted (constant is defined in C code), empty array is returned���); or * document the current behaviour of `#const_source_location` to make it less surprising. I recommend the first option ��� although the current behaviour was recently specified in source:spec/ruby/core/module/const_source_location_spec.rb@6d059674#L209, it doesn���t seem intentional ��� but if that���s not feasible, simply documenting this edge case would also be an improvement. -- https://bugs.ruby-lang.org/ Unsubscribe: