(Originally reported in rails/rails#43691).
The debug console prevents Zeitwerk from autoloading constants that are children of namespaces defined in a file. This script reproduces the issue:
require 'tmpdir'
Dir.mktmpdir do |dir|
Dir.chdir(dir)
FileUtils.mkdir_p('lib/git/ref')
File.write('lib/git/ref.rb', 'module Git::Ref; end')
File.write('lib/git/ref/collection.rb', 'module Git::Ref::Collection; end')
File.write('test.rb', <<~EOS)
require 'zeitwerk'
loader = Zeitwerk::Loader.new
loader.push_dir('lib')
loader.setup
p Git::Ref::Collection
EOS
system 'ruby test.rb'
system 'rdbg test.rb'
end
ruby is able to autoload Git::Ref::Collection just fine.
- If you type
continue in the debug console, test.rb is also executed correctly.
- If, instead, you
next 4 and type eval Git::Ref::Collection you'll get a NameError.
- Same if you use the
irb debugger command and try to evaluate Git::Ref::Collection in that session.
In case it matters, when Zeitwerk finds a file like ref.rb that defines a namespace, it sets a trace point on the :class event, because if the file had this content:
module Git
module Ref
Collection
end
end
it should be able to autoload Git::Ref::Collection on line 3. In order to provide that feature, Zeitwerk listens to :class events, and as soon as the one for Git::Ref is triggered, Zeitwerk lists the contents of all git/ref directories in the root paths, and sets autoloads for what it finds. In this case, it would set an autoload for Collection on the module object stored in Git::Ref.
Problem with byebug was that Ruby does not support nested trace points. Are we in the same situation perhaps?