Bug #22071
closedsuper in method in module that is refined results in NoMethodError
Description
We currently support refinements of modules, even though doc/syntax/refinements.rdoc and https://github.com/ruby/ruby/wiki/Refinements-Spec imply that we would not respect refinements of included or prepended modules and would only respect refinements of classes and superclasses.
If you refine a module, and have the refined method definition call super and the method in the refined module call super, and that refined method is found first during method lookup, the super call in the method in the refined module results in a NoMethodError. Example:
module F
def a; "F" + super end
end
class A
def a; "A" end
end
class B < A
include F
end
p B.new.a
module R
refine F do
def a; "R" + super end
end
end
using R
p B.new.a
Output:
"FA"
t.rb:2:in 'F#a': super: no superclass method 'a' for an instance of B (NoMethodError)
from t.rb:17:in 'a'
from t.rb:22:in '<main>'
Two things to note:
- Before the refinement is activated, things work as expected, returning "FA".
- After the refinement is activated, the
NoMethodErroris raised not in the refinement methodsuper(line 17), but in thesuperin the method in the module that is refined (line 2).
What should be the expected behavior here? I can think of two possibilities:
-
Per the documentation, we should not consider refinements of included/prepended modules. So in this example, we should print "FA" and ignore the refinement instead of raising the
NoMethodError. In this case, it would be best to raise during therefine Fcall, and prohibit the refining of modules completely. This would break backwards compatibility, though I'm not sure how much real world code uses refinements of modules. -
Fix
superwhen the refinement is activated to use the correct method lookup and return "RFA" instead of raising theNoMethodError. Also fix the documentation to describe how refinements of included/prepended modules work during method lookup.