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 {