Permalink
Browse files

detect circular constant autoloading

Nowadays circular autoloads do not work, but the user gets a NameError
that says some constant is undefined. That's puzzling, because he is
normally trying to autoload a constant he knows can be autoloaded.
With this check we can give a better error message.
  • Loading branch information...
1 parent 844e944 commit b33700f5580b4cd85379a1dc60fa341ac4d8deb2 @fxn fxn committed Aug 28, 2012
@@ -479,10 +479,17 @@ def load_missing_constant(from_mod, const_name)
file_path = search_for_file(path_suffix)
- if file_path && ! loaded.include?(File.expand_path(file_path).sub(/\.rb\z/, '')) # We found a matching file to load
- require_or_load file_path
- raise LoadError, "Expected #{file_path} to define #{qualified_name}" unless from_mod.const_defined?(const_name, false)
- return from_mod.const_get(const_name)
+ if file_path
+ expanded = File.expand_path(file_path)
+ expanded.sub!(/\.rb/, '')
+
+ if loaded.include?(expanded)
+ raise "Circular dependency detected while autoloading constant #{qualified_name}"
+ else
+ require_or_load(expanded)
+ raise LoadError, "Expected #{file_path} to define #{qualified_name}" unless from_mod.const_defined?(const_name, false)
+ return from_mod.const_get(const_name)
+ end
elsif mod = autoload_module!(from_mod, const_name, qualified_name, path_suffix)
return mod
elsif (parent = from_mod.parent) && parent != from_mod &&
@@ -0,0 +1,6 @@
+silence_warnings do
+ Circular2
+end
+
+class Circular1
+end
@@ -0,0 +1,4 @@
+Circular1
+
+class Circular2
+end
@@ -145,6 +145,12 @@ def test_mutual_dependencies_dont_infinite_loop
end
end
+ def test_circular_autoloading_detection
+ with_autoloading_fixtures do
+ assert_raise(RuntimeError, "Circular dependency detected while autoloading constant Circular1") { Circular1 }
+ end
+ end
+
def test_module_loading
with_autoloading_fixtures do
assert_kind_of Module, A

2 comments on commit b33700f

@dhh
Member
dhh commented on b33700f Aug 29, 2012

This commit causes the following failure for me in BCX:

/Users/david/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/bundler/gems/rails-8e974f2e3c06/activesupport/lib/active_support/dependencies.rb:450:in `load': cannot load such file -- /Users/david/env/versions/1.9.3-p194/lib/ruby/gems/1.9.1/bundler/gems/signal_id-192ee560cb79/app/models/signal_id/product.rb (LoadError)
    from /Users/david/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/bundler/gems/rails-8e974f2e3c06/activesupport/lib/active_support/dependencies.rb:450:in `block in load_file'
    from /Users/david/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/bundler/gems/rails-8e974f2e3c06/activesupport/lib/active_support/dependencies.rb:624:in `new_constants_in'
    from /Users/david/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/bundler/gems/rails-8e974f2e3c06/activesupport/lib/active_support/dependencies.rb:449:in `load_file'
    from /Users/david/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/bundler/gems/rails-8e974f2e3c06/activesupport/lib/active_support/dependencies.rb:352:in `require_or_load'
    from /Users/david/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/bundler/gems/rails-8e974f2e3c06/activesupport/lib/active_support/dependencies.rb:489:in `load_missing_constant'
    from /Users/david/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/bundler/gems/rails-8e974f2e3c06/activesupport/lib/active_support/dependencies.rb:202:in `block in const_missing'
    from /Users/david/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/bundler/gems/rails-8e974f2e3c06/activesupport/lib/active_support/dependencies.rb:200:in `each'
    from /Users/david/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/bundler/gems/rails-8e974f2e3c06/activesupport/lib/active_support/dependencies.rb:200:in `const_missing'
    from /Users/david/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/bundler/gems/signal_id-192ee560cb79/lib/signal_id.rb:44:in `product='
    from /Users/david/Code/37signals/bcx/config/initializers/signal_id.rb:4:in `<module:SignalId>'
@ngollan

It would be very useful to show information about the entire cycle.

Please sign in to comment.