mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Fix {Method,UnboundMethod}#super_method for zsuper methods
* We need to resolve the zsuper method first, and then look the super method of that.
This commit is contained in:
parent
892f350a7d
commit
94cea3e4d0
Notes:
git
2022-09-29 22:49:00 +09:00
3 changed files with 22 additions and 34 deletions
25
proc.c
25
proc.c
|
@ -3363,24 +3363,25 @@ method_super_method(VALUE method)
|
|||
const struct METHOD *data;
|
||||
VALUE super_class, iclass;
|
||||
ID mid;
|
||||
const rb_method_entry_t *me;
|
||||
const rb_method_entry_t *super_me, *me;
|
||||
|
||||
TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
|
||||
iclass = data->iclass;
|
||||
if (!iclass) return Qnil;
|
||||
if (data->me->def->type == VM_METHOD_TYPE_ALIAS && data->me->defined_class) {
|
||||
super_class = RCLASS_SUPER(rb_find_defined_class_by_owner(data->me->defined_class,
|
||||
data->me->def->body.alias.original_me->owner));
|
||||
mid = data->me->def->body.alias.original_me->def->original_id;
|
||||
me = zsuper_resolve(data->me);
|
||||
VALUE defined_class = me->defined_class ? me->defined_class : me->owner;
|
||||
if (!defined_class) return Qnil;
|
||||
if (me->def->type == VM_METHOD_TYPE_ALIAS && me->defined_class) {
|
||||
super_class = RCLASS_SUPER(rb_find_defined_class_by_owner(me->defined_class,
|
||||
me->def->body.alias.original_me->owner));
|
||||
mid = me->def->body.alias.original_me->def->original_id;
|
||||
}
|
||||
else {
|
||||
super_class = RCLASS_SUPER(RCLASS_ORIGIN(iclass));
|
||||
mid = data->me->def->original_id;
|
||||
super_class = RCLASS_SUPER(RCLASS_ORIGIN(defined_class));
|
||||
mid = me->def->original_id;
|
||||
}
|
||||
if (!super_class) return Qnil;
|
||||
me = (rb_method_entry_t *)rb_callable_method_entry_with_refinements(super_class, mid, &iclass);
|
||||
if (!me) return Qnil;
|
||||
return mnew_internal(me, me->owner, iclass, data->recv, mid, rb_obj_class(method), FALSE, FALSE);
|
||||
super_me = (rb_method_entry_t *)rb_callable_method_entry_with_refinements(super_class, mid, &iclass);
|
||||
if (!super_me) return Qnil;
|
||||
return mnew_internal(super_me, super_me->owner, iclass, data->recv, mid, rb_obj_class(method), FALSE, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -49,18 +49,9 @@ describe "Method#super_method" do
|
|||
MethodSpecs::InheritedMethods::C.new.derp.should == 'BA'
|
||||
end
|
||||
|
||||
ruby_version_is ""..."3.2" do
|
||||
it "returns the expected super_method" do
|
||||
method = MethodSpecs::InheritedMethods::C.new.method(:derp)
|
||||
method.super_method.owner.should == MethodSpecs::InheritedMethods::A
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "3.2" do
|
||||
it "returns the expected super_method" do
|
||||
method = MethodSpecs::InheritedMethods::C.new.method(:derp)
|
||||
method.super_method.owner.should == MethodSpecs::InheritedMethods::B
|
||||
end
|
||||
it "returns the expected super_method" do
|
||||
method = MethodSpecs::InheritedMethods::C.new.method(:derp)
|
||||
method.super_method.owner.should == MethodSpecs::InheritedMethods::A
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -29,18 +29,14 @@ describe "UnboundMethod#super_method" do
|
|||
|
||||
# https://github.com/jruby/jruby/issues/7240
|
||||
context "after changing an inherited methods visibility" do
|
||||
ruby_version_is ""..."3.2" do
|
||||
it "returns the expected super_method" do
|
||||
method = MethodSpecs::InheritedMethods::C.instance_method(:derp)
|
||||
method.super_method.owner.should == MethodSpecs::InheritedMethods::A
|
||||
end
|
||||
it "calls the proper super method" do
|
||||
method = MethodSpecs::InheritedMethods::C.instance_method(:derp)
|
||||
method.bind(MethodSpecs::InheritedMethods::C.new).call.should == 'BA'
|
||||
end
|
||||
|
||||
ruby_version_is "3.2" do
|
||||
it "returns the expected super_method" do
|
||||
method = MethodSpecs::InheritedMethods::C.instance_method(:derp)
|
||||
method.super_method.owner.should == MethodSpecs::InheritedMethods::B
|
||||
end
|
||||
it "returns the expected super_method" do
|
||||
method = MethodSpecs::InheritedMethods::C.instance_method(:derp)
|
||||
method.super_method.owner.should == MethodSpecs::InheritedMethods::A
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue