From 636d4f7eb9f3fcb088e1a44af4181c4aa36789b4 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Thu, 20 May 2021 18:52:32 -0400 Subject: [PATCH] Avoid setting the visibility of refinement method entries Since refinement search is always performed, these entries should always be public. The method entry that the refinement search returns decides the visibility. Fixes [Bug #17822] --- test/ruby/test_refinement.rb | 22 ++++++++++++++++++++++ vm_method.c | 15 ++++++++++----- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb index 50f0333c2c..14c112f344 100644 --- a/test/ruby/test_refinement.rb +++ b/test/ruby/test_refinement.rb @@ -2537,6 +2537,28 @@ class TestRefinement < Test::Unit::TestCase assert_equal(:second, klass.new.foo) end + class Bug17822 + module Ext + refine(Bug17822) do + def foo = :refined + end + end + + private(def foo = :not_refined) + + module Client + using Ext + def self.call_foo + Bug17822.new.foo + end + end + end + + # [Bug #17822] + def test_privatizing_refined_method + assert_equal(:refined, Bug17822::Client.call_foo) + end + private def eval_using(mod, s) diff --git a/vm_method.c b/vm_method.c index 34200dc5f8..740279cdc9 100644 --- a/vm_method.c +++ b/vm_method.c @@ -1409,11 +1409,16 @@ rb_export_method(VALUE klass, ID name, rb_method_visibility_t visi) rb_vm_check_redefinition_opt_method(me, klass); if (klass == defined_class || origin_class == defined_class) { - METHOD_ENTRY_VISI_SET(me, visi); - - if (me->def->type == VM_METHOD_TYPE_REFINED && me->def->body.refined.orig_me) { - METHOD_ENTRY_VISI_SET((rb_method_entry_t *)me->def->body.refined.orig_me, visi); - } + if (me->def->type == VM_METHOD_TYPE_REFINED) { + // Refinement method entries should always be public because the refinement + // search is always performed. + if (me->def->body.refined.orig_me) { + METHOD_ENTRY_VISI_SET((rb_method_entry_t *)me->def->body.refined.orig_me, visi); + } + } + else { + METHOD_ENTRY_VISI_SET(me, visi); + } rb_clear_method_cache(klass, name); } else {