Issue #22071 has been updated by shugo (Shugo Maeda). jeremyevans0 (Jeremy Evans) wrote in #note-3:
```diff diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 84daaa85a5..f449ff0324 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -5061,6 +5061,13 @@ vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *c cc = vm_cc_new(Qundef, NULL, vm_call_method_missing, cc_type_super); RB_OBJ_WRITE(iseq, &cd->cc, cc); } + else if (klass == rb_cBasicObject && + RB_TYPE_P(me->defined_class, T_ICLASS) && + ((struct RClass_and_rb_classext_t*)me->defined_class)->classext.as.iclass.includer == 0) { + rb_raise(rb_eNoMethodError, + "super in a method in a module that has been refined and that is called via super" + " from a refinement method is not supported."); + } else { cc = vm_search_method_fastpath(reg_cfp, cd, klass); const rb_callable_method_entry_t *cached_cme = vm_cc_cme(cc); ```
This implements the approach described in 2. above. Does this seem reasonable?
Thank you. It seems reasonable except that `RCLASS_INCLUDER(me->defined_class)` is better than `((struct RClass_and_rb_classext_t*)me->defined_class)->classext.as.iclass.includer`. ---------------------------------------- Bug #22071: super in method in module that is refined results in NoMethodError https://bugs.ruby-lang.org/issues/22071#change-117343 * Author: jeremyevans0 (Jeremy Evans) * Status: Assigned * Assignee: shugo (Shugo Maeda) * ruby -v: ruby 4.1.0dev (2026-05-03T23:57:21Z master d8d2ed5dc9) +PRISM [x86_64-openbsd7.9] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- 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: ```ruby 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 `NoMethodError` is raised not in the refinement method `super` (line 17), but in the `super` in 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 the `refine F` call, 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 `super` when the refinement is activated to use the correct method lookup and return "RFA" instead of raising the `NoMethodError`. Also fix the documentation to describe how refinements of included/prepended modules work during method lookup. -- https://bugs.ruby-lang.org/