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]
This commit is contained in:
Alan Wu 2021-05-20 18:52:32 -04:00
Родитель 50a534a152
Коммит 636d4f7eb9
2 изменённых файлов: 32 добавлений и 5 удалений

Просмотреть файл

@ -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)

Просмотреть файл

@ -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 {