Search refinement module along nested usings

[Bug #16107]
This commit is contained in:
Nobuyoshi Nakada 2019-08-17 00:17:15 +09:00
Родитель 042be439d9
Коммит 11a9f7ab94
2 изменённых файлов: 54 добавлений и 28 удалений

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

@ -2295,6 +2295,34 @@ class TestRefinement < Test::Unit::TestCase
d
end
class RefineInUsing
module M1
refine RefineInUsing do
def foo
:ok
end
end
end
module M2
using M1
refine RefineInUsing do
def call_foo
RefineInUsing.new.foo
end
end
end
using M2
def self.test
new.call_foo
end
end
def test_refine_in_using
assert_equal(:ok, RefineInUsing.test)
end
private
def eval_using(mod, s)

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

@ -2604,39 +2604,37 @@ vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp, st
case VM_METHOD_TYPE_REFINED: {
const rb_cref_t *cref = vm_get_cref(cfp->ep);
VALUE refinements = cref ? CREF_REFINEMENTS(cref) : Qnil;
VALUE refinement;
const rb_callable_method_entry_t *ref_me;
refinement = find_refinement(refinements, cc->me->owner);
for (; cref; cref = CREF_NEXT(cref)) {
const rb_callable_method_entry_t *ref_me;
VALUE refinements = CREF_REFINEMENTS(cref);
VALUE refinement = find_refinement(refinements, cc->me->owner);
if (NIL_P(refinement)) continue;
if (NIL_P(refinement)) {
goto no_refinement_dispatch;
}
ref_me = rb_callable_method_entry(refinement, ci->mid);
ref_me = rb_callable_method_entry(refinement, ci->mid);
if (ref_me) {
if (cc->call == vm_call_super_method) {
const rb_control_frame_t *top_cfp = current_method_entry(ec, cfp);
const rb_callable_method_entry_t *top_me = rb_vm_frame_method_entry(top_cfp);
if (top_me && rb_method_definition_eq(ref_me->def, top_me->def)) {
goto no_refinement_dispatch;
}
}
if (cc->me->def->type != VM_METHOD_TYPE_REFINED ||
cc->me->def != ref_me->def) {
cc->me = ref_me;
if (ref_me) {
if (cc->call == vm_call_super_method) {
const rb_control_frame_t *top_cfp = current_method_entry(ec, cfp);
const rb_callable_method_entry_t *top_me = rb_vm_frame_method_entry(top_cfp);
if (top_me && rb_method_definition_eq(ref_me->def, top_me->def)) {
continue;
}
}
if (cc->me->def->type != VM_METHOD_TYPE_REFINED ||
cc->me->def != ref_me->def) {
cc->me = ref_me;
}
if (ref_me->def->type != VM_METHOD_TYPE_REFINED) {
return vm_call_method(ec, cfp, calling, ci, cc);
}
}
if (ref_me->def->type != VM_METHOD_TYPE_REFINED) {
return vm_call_method(ec, cfp, calling, ci, cc);
}
}
else {
cc->me = NULL;
return vm_call_method_nome(ec, cfp, calling, ci, cc);
}
else {
cc->me = NULL;
return vm_call_method_nome(ec, cfp, calling, ci, cc);
}
}
no_refinement_dispatch:
if (cc->me->def->body.refined.orig_me) {
cc->me = refined_method_callable_without_refinement(cc->me);
}