Issue #17354 has been updated by mame (Yusuke Endoh).


I think that the current behavior is the most flexible.

1. If we want to check if a constant is set as autoload (and not actually loaded), we can use `Module#autoload?`.
2. If we want to identify where a constant is set as autoload, we can use the current `Module#const_source_location`.
3. If we want to make sure a constant is loaded and identify where a constant is defined, we can use `Module#const_get` and then `Module#const_source_location`.

If `Module#const_source_location` returns `[]` or `nil` when a constant is not actually loaded, it breaks the scenario 2. In fact I have used the method to identify the callsite of autoload for debugging.

----------------------------------------
Bug #17354: Module#const_source_location is misleading for constants awaiting autoload
https://bugs.ruby-lang.org/issues/17354#change-90928

* 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: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>