call Kernel.require ruby method from autoload callback instead of callin... #281

Closed
wants to merge 1 commit into from

4 participants

@ashanbrown

In jruby, the autoload mechanism doesn't actually call Kernel.require like the rubydocs claims it will. This change attempts to fix that.

From http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-autoload:

autoload(module, filename) → nil click to toggle source

Registers filename to be loaded (using Kernel::require) the first time that module (which may be a String or a symbol) is accessed in the namespace of mod.

Note that this change uses the context when require happens rather than when the autoload method is called. I wasn't sure what the right thing to do is, or whether it really matters.

The purpose of this change is to allow the user to override Kernel.require even with autoloading. I assume it rubygems is the most well-known overrider of Kernel.require. It presumably ends up pulling in enough stuff into LOAD_PATH via direct requires that any autoloading it does still works, but I suspect it could be problematic if it tried to add paths for autoloaded files.

Thanks for your consideration,

Andrew

@travisbot

This pull request passes (merged a311d53 into b37a0bd).

@headius
JRuby Team member

Ok, the change looks fine, but I want to make sure this is actually proper...i.e. that 1.9.3 does this too. I know there have been debates about MRI sometimes not actually dynamically dispatching to methods like require, and I think it should dynamically dispatch here, but doing so when MRI does not would be a significant behavioral difference.

@headius
JRuby Team member

Ok, my fears are confirmed...unfortunately.

blah.rb:

system ~/projects/jruby $ cat blah.rb
puts 'there'

Before your patch:


system ~/projects/jruby $ jruby -e "class Foo; autoload :Bar, './blah.rb'; end; def Kernel.require(a); puts a; end; Foo::Bar"
there
NameError: uninitialized constant Foo::Bar
  const_missing at org/jruby/RubyModule.java:2694
         (root) at -e:1

After your patch:

system ~/projects/jruby $ jruby -e "class Foo; autoload :Bar, './blah.rb'; end; def Kernel.require(a); puts a; end; Foo::Bar"
./blah.rb
NameError: uninitialized constant Foo::Bar
  const_missing at org/jruby/RubyModule.java:2694
         (root) at -e:1

Ruby 1.9.3:

system ~/projects/jruby $ ruby-1.9.3 -e "class Foo; autoload :Bar, './blah.rb'; end; def Kernel.require(a); puts a; end; Foo::Bar"
there
-e:1:in `<main>': uninitialized constant Foo::Bar (NameError)

So yeah, the bad news is that MRI does not exhibit this behavior, regardless of what the documentation claims, and therefore we can't accept this patch.

I would support you if you want to raise this as an issue with the MRI folks, since I agree it should be redispatching here to pick up require hooks like RubyGems installs. However, at this time I need to reject this pull request :(

@headius headius closed this Sep 4, 2012
@ashanbrown
@nahi
JRuby Team member

We should solve that issue for 2.0. See http://bugs.ruby-lang.org/issues/5481, "Make autoload for stdlib gems work as long as autoload feature exists in 2.0."

Thanks @dontfidget, it would be nice to have test next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment