summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Daloze <eregontp@gmail.com>2022-09-28 18:54:05 +0200
committerBenoit Daloze <eregontp@gmail.com>2022-09-29 15:48:35 +0200
commit94cea3e4d0a60326bd95be762819eed8ccd59ca6 (patch)
tree3f1ce9e04741e68ab53728e8ced70fa05e759d40
parent892f350a7db4d2cc99c5061d2e74498dfc4809ca (diff)
downloadruby-94cea3e4d0a60326bd95be762819eed8ccd59ca6.tar.gz
Fix {Method,UnboundMethod}#super_method for zsuper methods
* We need to resolve the zsuper method first, and then look the super method of that.
-rw-r--r--proc.c25
-rw-r--r--spec/ruby/core/method/super_method_spec.rb15
-rw-r--r--spec/ruby/core/unboundmethod/super_method_spec.rb16
3 files changed, 22 insertions, 34 deletions
diff --git a/proc.c b/proc.c
index 50db2daa46..8e79007d5c 100644
--- a/proc.c
+++ b/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);
}
/*
diff --git a/spec/ruby/core/method/super_method_spec.rb b/spec/ruby/core/method/super_method_spec.rb
index dc8764f6c7..c63a7aaa0f 100644
--- a/spec/ruby/core/method/super_method_spec.rb
+++ b/spec/ruby/core/method/super_method_spec.rb
@@ -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
diff --git a/spec/ruby/core/unboundmethod/super_method_spec.rb b/spec/ruby/core/unboundmethod/super_method_spec.rb
index 5cf96e6fa9..aa7c129377 100644
--- a/spec/ruby/core/unboundmethod/super_method_spec.rb
+++ b/spec/ruby/core/unboundmethod/super_method_spec.rb
@@ -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