From: Michael Edgar Date: 2011-06-08T05:25:18+09:00 Subject: [ruby-core:36828] Re: implicit super + define_method in Ruby 1.9.3? Top-posting my own message for a quick correction: class B < A in all examples listed. Michael Edgar adgar@carboni.ca http://carboni.ca/ On Jun 7, 2011, at 4:19 PM, Michael Edgar wrote: > 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 = 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/ > >