diff options
| author | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2026-03-24 14:13:50 +0900 |
|---|---|---|
| committer | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2026-03-24 14:49:12 +0900 |
| commit | c675ec66e912b3000e05d65bba473e8bf6e18c96 (patch) | |
| tree | 1e5ed51e34f3703b1eb6618f190d57c9fb36daa1 | |
| parent | 83637aea6ea726f7fc4c17e56ac60c289e2d98db (diff) | |
merge revision(s) 1e7cf7b2bc1f9b356b2e980e1e18548618da6363: [Backport #21446]
[PATCH] Fix refinement modification of method visibility in superclass
Previously, this didn't work correctly, resulting in a
SystemStackError. This fixes the issue by finding the related
superclass method entry, and updating the orig_me in the
refinement method to point to the superclass method.
Fixes [Bug #21446]
| -rw-r--r-- | test/ruby/test_refinement.rb | 23 | ||||
| -rw-r--r-- | version.h | 2 | ||||
| -rw-r--r-- | vm_method.c | 6 |
3 files changed, 30 insertions, 1 deletions
diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb index b05e651c90..a8d46f4d07 100644 --- a/test/ruby/test_refinement.rb +++ b/test/ruby/test_refinement.rb @@ -1939,6 +1939,29 @@ class TestRefinement < Test::Unit::TestCase end; end + def test_public_in_refine_for_method_in_superclass + assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}") + begin; + bug21446 = '[ruby-core:122558] [Bug #21446]' + + class CowSuper + private + def moo() "Moo"; end + end + class Cow < CowSuper + end + + module PublicCows + refine(Cow) { + public :moo + } + end + + using PublicCows + assert_equal("Moo", Cow.new.moo, bug21446) + end; + end + module SuperToModule class Parent end @@ -11,7 +11,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 10 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 198 +#define RUBY_PATCHLEVEL 199 #include "ruby/version.h" #include "ruby/internal/abi.h" diff --git a/vm_method.c b/vm_method.c index 855ddd14c8..4dc67ad37b 100644 --- a/vm_method.c +++ b/vm_method.c @@ -941,6 +941,7 @@ check_override_opt_method(VALUE klass, VALUE mid) } } +static inline rb_method_entry_t* search_method0(VALUE klass, ID id, VALUE *defined_class_ptr, bool skip_refined); /* * klass->method_table[mid] = method_entry(defined_class, visi, def) * @@ -981,7 +982,12 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil if (RB_TYPE_P(klass, T_MODULE) && FL_TEST(klass, RMODULE_IS_REFINEMENT)) { VALUE refined_class = rb_refinement_module_get_refined_class(klass); + bool search_superclass = type == VM_METHOD_TYPE_ZSUPER && !lookup_method_table(refined_class, mid); rb_add_refined_method_entry(refined_class, mid); + if (search_superclass) { + rb_method_entry_t *me = lookup_method_table(refined_class, mid); + me->def->body.refined.orig_me = search_method0(refined_class, mid, NULL, true); + } } if (type == VM_METHOD_TYPE_REFINED) { rb_method_entry_t *old_me = lookup_method_table(RCLASS_ORIGIN(klass), mid); |
