From: "Eregon (Benoit Daloze)" Date: 2022-05-17T10:42:32+00:00 Subject: [ruby-core:108584] [Ruby master Bug#15790] Strange interaction between autoload and $LOADED_FEATURES Issue #15790 has been updated by Eregon (Benoit Daloze). There is some discussion on https://github.com/ruby/ruby/pull/5910#issuecomment-1128149901 as we well. I think it'd be great to unify more the behavior when an autoload fail, and specifically avoid those "undefined constants" completely. So after a failed autoload (for any reason, e.g. the file does not exist, an exception was raised, the constant was not assigned) either: * don't change anything, leave the autoload in place. The program should still fail from that exception if well-behaved (but I could also easily see that exception swallowed, since it can happen on any constant access, maybe with some `rescue` around it). Also the behavior might be weird if e.g. the file loaded fine but did not define the expected constant. Then the file shouldn't be loaded per `require` semantics. So just `NameError` in that case since the constant was not defined after `require` was called. * remove the autoload so it's not retried again (it's not great if a given file is partially loaded multiple times, can be quite confusing). Because all threads should wait each other for loading an autoload constant there should be no race in doing that, i.e., if it's done at the same place where we assign temp values from the loaded file into the real constants ("assign all the constants" in the PR terms), i.e., just before releasing the autoload lock for that constant. Other threads should simply recheck the state once they get the enter the lock, whether the constant is now set or no longer exists. ---------------------------------------- Bug #15790: Strange interaction between autoload and $LOADED_FEATURES https://bugs.ruby-lang.org/issues/15790#change-97621 * Author: fxn (Xavier Noria) * Status: Closed * Priority: Normal * ruby -v: ruby 2.6.1p33 (2019-01-30 revision 66950) [x86_64-darwin18] * Backport: 2.4: UNKNOWN, 2.5: UNKNOWN, 2.6: UNKNOWN ---------------------------------------- If an autoload fails and we remove its associated file from `$LOADED_FEATURES`, the autoload is back: ``` $ cat x.rb Y = 1 # should be X, emulates a typo $ cat test.rb def au Object.autoload?(:X).inspect end x_rb = File.realpath("x.rb") autoload :X, x_rb puts "before failed autoload autoload path is #{au}" X rescue nil puts "after failed autoload autoload path is #{au}" $LOADED_FEATURES.delete(x_rb) puts "after $LOADED_FEATURES deletion autoload path is #{au}" ``` The output is ``` $ ruby -v test.rb ruby 2.6.1p33 (2019-01-30 revision 66950) [x86_64-darwin18] before failed autoload autoload path is "/Users/fxn/tmp/x.rb" after failed autoload autoload path is nil after $LOADED_FEATURES deletion autoload path is "/Users/fxn/tmp/x.rb" ``` See? Last line would be expected to print a `nil` autoload path. -- https://bugs.ruby-lang.org/ Unsubscribe: