Bug #20411
closedKenrel.autoload? behaviour
Description
👋 I recently tried checking if a top-level constant was autoloaded within a module, and it doesn't seem to work properly when calling autoload?
from Kernel
. Here's a simple reproduction script:
autoload :A, "a.rb"
module B
puts Kernel.autoload?(:A) # nil
puts Module.autoload?(:A) # a.rb
end
puts Kernel.autoload?(:A) # a.rb
puts Module.autoload?(:A) # a.rb
I would expect Kernel.autoload?
and Module.autoload?
to behave the same way, and return the path of the autoloaded constant until it is loaded.
Updated by jeremyevans0 (Jeremy Evans) 5 months ago
These are separate methods:
Kernel.autoload?/Kernel#autoload? (it's a global/module function) is documented here: https://docs.ruby-lang.org/en/master/Kernel.html#method-i-autoload-3F
Module#autoload? is documented here: https://docs.ruby-lang.org/en/master/Module.html#method-i-autoload-3F
Once you understand that Kernel.autoload? and Kernel#autoload? are the same method, the behavior makes more sense:
autoload :A, "a.rb"
module B
puts Kernel.autoload?(:A) # nil
puts Module.autoload?(:A) # a.rb
puts autoload?(:A) # nil
puts B.autoload?(:A) # nil
end
puts Kernel.autoload?(:A) # a.rb
puts Module.autoload?(:A) # a.rb
puts autoload?(:A) # a.rb
puts B.autoload?(:A) # nil
Kernel#autoload?
looks up in the currently open namespace, so Kernel.autoload?
does as well.
Not defining Kernel.autoload?
as a singleton method would fix the behavior, but would break backwards compatibility. I don't think it is worth changing.
The behavior is currently expected and not a bug. I'm leaving this open as I think the documentation for Kernel#autoload?
should be improved to mention it uses the current namespace.
Updated by gmcgibbon (Gannon McGibbon) 5 months ago
Ah, I see. Thank you for clarifying! Strangely, if you use class B
and not a module B
, the behaviour changes. Do classes not count as a namespace? I agree the documentation could be improved. I will submit a patch to improve the docs.
Updated by jeremyevans0 (Jeremy Evans) 5 months ago
gmcgibbon (Gannon McGibbon) wrote in #note-2:
Ah, I see. Thank you for clarifying! Strangely, if you use
class B
and not amodule B
, the behaviour changes. Do classes not count as a namespace? I agree the documentation could be improved. I will submit a patch to improve the docs.
The lookup considers autoloads in ancestors, and unless you are subclassing BasicObject, your class eventually subclasses Object, which is the location for autoloads at top level. Classes have superclasses, modules do not. Modules still have ancestors (other included modules), but as Object is a class and not a module, lookup for a module will not look up into Object.
Updated by jeremyevans0 (Jeremy Evans) 5 months ago
- Status changed from Open to Closed