vm_method.c: fix super in refined module

* vm_method.c (rb_method_entry_complement_defined_class): clone
  the original method entry of refined module instance method with
  the active ICLASS, to track super method chain.
  [ruby-dev:50390] [Bug #14232]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61484 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2017-12-26 10:32:58 +00:00
Родитель 3802fb92ff
Коммит e973bde0d0
2 изменённых файлов: 44 добавлений и 2 удалений

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

@ -2055,6 +2055,25 @@ class TestRefinement < Test::Unit::TestCase
INPUT
end
def test_super_from_refined_module
a = EnvUtil.labeled_module("A") do
def foo;"[A#{super}]";end
end
b = EnvUtil.labeled_class("B") do
def foo;"[B]";end
end
c = EnvUtil.labeled_class("C", b) do
include a
def foo;"[C#{super}]";end
end
d = EnvUtil.labeled_module("D") do
refine(a) do
def foo;end
end
end
assert_equal("[C[A[B]]]", c.new.foo, '[ruby-dev:50390] [Bug #14232]')
end
private
def eval_using(mod, s)

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

@ -404,10 +404,33 @@ rb_method_entry_clone(const rb_method_entry_t *src_me)
const rb_callable_method_entry_t *
rb_method_entry_complement_defined_class(const rb_method_entry_t *src_me, ID called_id, VALUE defined_class)
{
rb_method_entry_t *me = rb_method_entry_alloc(called_id, src_me->owner, defined_class,
method_definition_addref_complement(src_me->def));
rb_method_definition_t *def = src_me->def;
rb_method_entry_t *me;
struct {
const struct rb_method_entry_struct *orig_me;
VALUE owner;
} refined = {0};
if (!src_me->defined_class &&
def->type == VM_METHOD_TYPE_REFINED &&
def->body.refined.orig_me) {
const rb_method_entry_t *orig_me =
rb_method_entry_clone(def->body.refined.orig_me);
RB_OBJ_WRITE((VALUE)orig_me, &orig_me->defined_class, defined_class);
refined.orig_me = orig_me;
refined.owner = orig_me->owner;
def = NULL;
}
else {
def = method_definition_addref_complement(def);
}
me = rb_method_entry_alloc(called_id, src_me->owner, defined_class, def);
METHOD_ENTRY_FLAGS_COPY(me, src_me);
METHOD_ENTRY_COMPLEMENTED_SET(me);
if (!def) {
def = method_definition_create(VM_METHOD_TYPE_REFINED, called_id);
method_definition_set(me, def, &refined);
}
VM_ASSERT(RB_TYPE_P(me->owner, T_MODULE));