You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
NoMethodError: super: no superclass method `stuff' for #<A:0x5d767218>
stuff at scratch.rb:14
<main> at scratch.rb:20
Unless this is illegal Ruby, I guess JRuby should behave the same as MRI.
Why is the stuff method of module X not called when using MRI? If I move the definition of class A below the call to M.prepend it works.
jruby 184.108.40.206 (2.5.7) 2020-08-03 9a89c94 OpenJDK 64-Bit Server VM 11.0.7+10 on 11.0.7+10 +jit [darwin-x86_64]
Darwin 19.6.0 Darwin Kernel Version 19.6.0: Mon Aug 31 22:12:52 PDT 2020; root:xnu-6153.141.2~1/RELEASE_X86_64 x86_64
Any help is appreciated :-)
The text was updated successfully, but these errors were encountered:
For @donv original snippet I notice that they seem to have fixed the oddity raised in the original report:
2.7 and lower:
Based on this and how I would expect things to work I would expect the 3.0 behavior. So MRI must have fixed this lookup at some point. I would not use this pattern an expect 'Stuff M' since it will stop working.
With that said JRuby dispatches to X like we would expect but then the super does not find M. At this point I feel like for 9.2/3/4 we should make it behave like 3.0 but that obviously has a potential to be reported again. I will examine the other bugs to see how closely they seem to the same problem or not.
So in talking yesterday we figured out a few things.
Ruby 3.0 will keep track of all included stuff somehow and the ancestors will reflect current state of the originally included/prepended thing (including other modules included/prepended into it). This is why in 3.0 it sees X even though X was prepended AFTER M was included into A. So while we have to support this and my original advice about behavior changing means not depending on behavior that has already changed...it will be a bigger change we will only do for 3.0.
Ruby 2.7 and earlier will only reflect what the module has included/prepended into it at the time it is included/prepended into something else. So X is not seen because it has been prepended after it was included into A.
JRuby does inclusion a bit differently. We include the same way as Ruby 2.7 except that we delegate method lookup (and some other things) to the original module definition. In MRI, they do not delegate back to original module but will copy the method pointer into the included copy of the module. Because we go back to ask original M for the stuff method it actually ends up finding X's stuff instead. If we had just copied the reference to the method table and used the included module as our method search module it would not find X.
So one idea we are considering (which will only be 9.3+ due to risk) is to change our IncludedModuleWrapper (PrependedModule) to just contain a reference to the original modules method map. This involves changing alot of code which tends to do something like: included_module.get_non_included_module.search_method. It will become included_module.search_method. Sounds simple? It is all over and there are likely other things we have not considered but it is the current thing to correct this behavior.