Project

General

Profile

Actions

Bug #20411

closed

Kenrel.autoload? behaviour

Added by gmcgibbon (Gannon McGibbon) 9 months ago. Updated 8 months ago.

Status:
Closed
Assignee:
-
Target version:
-
[ruby-core:117445]

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) 9 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) 9 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) 9 months ago

gmcgibbon (Gannon McGibbon) wrote in #note-2:

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.

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) 8 months ago

  • Status changed from Open to Closed
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0