Howdy,

I've recently been investigating one of the 1.9 regressions that still =
hasn't been corrected yet, as far as I can tell: implicit super failing =
in methods defined via define_method.

The following code works in Ruby 1.8, but not Ruby 1.9:

class A
  def foo(x)
    p x
  end
end
class B
  define_method(:foo) do |y|
    super
  end
end
B.new.foo(2)

This is a result of the current bytecode compilation strategy for =
implicit-argument passing for super: when in a method,
find the method's top-level ISeq (where its arguments can be found), =
insert the appropriate bytecode instructions
(such as getlocal, etc.) to form the arguments to the super method, and =
run invokesuper.

A straightforward attempt to implement such a strategy for a method =
defined with define_method fails for a
simple reason: one must determine which block's arguments should be =
passed. The following examples make it
clear why this is difficult:

class B
  define_method(:foo) do |y|
    y.each do |z|
      # do I pass z, or y? The answer is y, but how do we know this at =
compilation time?
      super
    end
  end

  p =3D proc do |y|
    proc do |z|
      puts y
      # super doesn't even make sense here until we say what method it's =
in, which we
      # don't currently know at compile time. And even then, is "y" the =
argument to pass? or "z"?
      super
    end
  end
  define_method(:foo, &p.call(10))
end

That said, this is not an unsolvable problem: it works fine in Ruby 1.8, =
JRuby successfully implements
this capability with bytecode compilation, and while I haven't tried it, =
I expect Rubinius to be okay too.

What does seem clear, however, is that the current approach (which works =
fine for methods) does not
work outside of a method context, and will not. I would like to see this =
addressed in Ruby 1.9.3: it is
a breaking regression, it does affect real code (my gems have suffered =
from this - RubyLexer, at the
version I currently target, expects this to work), and it should be =
fixable.

At present, this case is detected and raised up on at =
vm_insnhelper.c:1407. It appears that what is
necessary is to, at that location, perform the necessary introspection =
by following the chain to the
method definition and examine its parameters, re-performing the argument =
construction that compilation
would otherwise do. I'm looking into writing a patch that does this, but =
I figured it'd be smart to reach out to
fellow developers to see if there's something I'm missing - a tough =
reason why this hasn't been done yet,
current technical limitations, etc. It seems it should be slow, but =
possible.

Any thoughts?

Michael Edgar
adgar / carboni.ca
http://carboni.ca/