From: "Eregon (Benoit Daloze) via ruby-core" Date: 2025-02-12T11:36:45+00:00 Subject: [ruby-core:120947] [Ruby master Misc#21035] Clarify or redefine Module#autoload? and Module#const_defined? Issue #21035 has been updated by Eregon (Benoit Daloze). Right that last example is weird, it's like it considers the `autoload :Foo` is ongoing even though `Foo` was never accessed. I think it does consider the autoload to be ongoing because there is a feature `foo.rb` being loaded. In general this is the very messy interactions when doing a `require "xxx"` which matches an `autoload "xxx"` (see #15663). I would love if we can simplify those somehow and/or document the behavior well. @fxn Maybe you would be interested to start a document covering the behavior of autoload in details? (I think that could leave under https://github.com/ruby/ruby/tree/master/doc, or maybe a comment in `load.c`). It would be good to compare it to the actual implementation to make sure it's accurate. BTW, `const_defined?(:Foo)` is similar to `defined?(Foo)` and I guess when performing an autoload it makes some sense for those to return false/nil, because the autoloaded file should define those constants (and defining those constants should e.g. not warn that the constant is already defined or something like that). But I'm not sure it needs to be that complicated, maybe they should always return true/"constant" even during the autoload, that would be a nice simplification. > Please, note that the present behavior is not documented, so on paper the change would not be backwards incompatible. > If, on the other side, it is preferred to keep the behavior as it is, I guess it should be documented with precision (accounting for symlinks, relative paths in $LOAD_PATH, etc.) In general I never trust Ruby methods documentation, especially about edge cases like that, the documentation is usually pretty short and only covers the happy cases. Sometimes it's completely wrong, and I gave up on trying to fix those documentation errors because there are too many. I think part of the reason of that is the documentation for many of the methods was added long after the method was implemented, by people who didn't write those methods or have time to look at their implementation in details. ---------------------------------------- Misc #21035: Clarify or redefine Module#autoload? and Module#const_defined? https://bugs.ruby-lang.org/issues/21035#change-111841 * Author: fxn (Xavier Noria) * Status: Open ---------------------------------------- The documentation for `Module#autoload?` says: > Returns filename to be loaded if name is registered as autoload in the namespace of mod or one of its ancestors. As a user, if I declare an autoload, I expect this API: ```ruby module M autoload :Foo, 'foo' constants # => [:Foo] const_defined?(:Foo) # => true autoload?(:Foo) # => 'foo' end ``` That it is indeed how it generally works. Even if the autoload path does not exist. But there is an edge case. While `constants` does include always `:Foo` as far as I can tell, the return value of `const_defined?` and `autoload?` depends on the stack of features being loaded: The autoload path is resolved and if seen to be in the stack of features being loaded, the predicates return `false` and `nil`, respectively. Do you think that is intuitive? I find that logic totally unexpected. I just defined an autoload, therefore, I think it would be natural for `autoload?` to return what I just configured. Why should `const_defined?` return nothing but `true`? And why is it not consistent with `constants`? To me, it would make more sense that in the previous example `const_defined?` returns `true`, and `autoload?` returns `foo` unconditionally (and instantly, nowadays it takes a relative long time due to the lookup). Now, if the autoload is triggered in a lookup **then** I would expect `Kernel#require` logic to apply. But not when calling some simple predicates. Please, note that the present behavior is not documented, so on paper the change would not be backwards incompatible. If, on the other side, it is preferred to keep the behavior as it is, I guess it should be documented with precision (accounting for symlinks, relative paths in `$LOAD_PATH`, etc.) -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/