[前][次][番号順一覧][スレッド一覧]

ruby-changes:73817

From: nagachika <ko1@a...>
Date: Sat, 1 Oct 2022 15:34:12 +0900 (JST)
Subject: [ruby-changes:73817] 9e739022de (ruby_3_1): merge revision(s) 94cea3e4d0a60326bd95be762819eed8ccd59ca6,aa53d69aa21c4dfa2a78a1cec5cb34e9697b3d30,6b7d32a5e54088b6b4014529bbf2b4b8c1a96029,c6319026caa6c8f0f569f80011e8502349a04b14,aa490f9442c32cd0e1e449ac817f410bd5924c8b: [Backport #18435]

https://git.ruby-lang.org/ruby.git/commit/?id=9e739022de

From 9e739022ded433f189a575017d3936b79541f229 Mon Sep 17 00:00:00 2001
From: nagachika <nagachika@r...>
Date: Sat, 1 Oct 2022 13:39:47 +0900
Subject: merge revision(s)
 94cea3e4d0a60326bd95be762819eed8ccd59ca6,aa53d69aa21c4dfa2a78a1cec5cb34e9697b3d30,6b7d32a5e54088b6b4014529bbf2b4b8c1a96029,c6319026caa6c8f0f569f80011e8502349a04b14,aa490f9442c32cd0e1e449ac817f410bd5924c8b:
 [Backport #18435]

	Fix {Method,UnboundMethod}#super_method for zsuper methods

	* We need to resolve the zsuper method first, and then look the super
	  method of that.
	---
	 proc.c                                            | 25 ++++++++++++-----------
	 spec/ruby/core/method/super_method_spec.rb        | 15 +++-----------
	 spec/ruby/core/unboundmethod/super_method_spec.rb | 16 ++++++---------
	 3 files changed, 22 insertions(+), 34 deletions(-)

	Add specs for {Method,UnboundMethod}#owner of a zsuper method

	---
	 spec/ruby/core/method/owner_spec.rb        | 6 ++++++
	 spec/ruby/core/unboundmethod/owner_spec.rb | 7 +++++++
	 2 files changed, 13 insertions(+)

	Resolve zsuper method during lookup but preserve owner separately

	* See https://bugs.ruby-lang.org/issues/18729#note-34
	* See [Bug #18729]
	---
	 proc.c                   | 109 +++++++++++++++++++++++++----------------------
	 test/ruby/test_method.rb |  66 +++++++++++++++++++++++-----
	 2 files changed, 114 insertions(+), 61 deletions(-)

	Extend tests for a zsuper method of which the method it resolved to
	 has been removed

	---
	 test/ruby/test_method.rb | 41 +++++++++++++++++++++++++++++++++++++++++
	 1 file changed, 41 insertions(+)

	Reduce diff to proc.c @ b0b9f7201acab05c2a3ad92c3043a1f01df3e17f

	* So it's easy to review https://github.com/ruby/ruby/pull/6242 +
	  https://github.com/ruby/ruby/pull/6467 and there are less changes
	  overall.
	---
	 proc.c                   | 76 ++++++++++++++++++------------------------------
	 test/ruby/test_method.rb |  7 +++--
	 2 files changed, 34 insertions(+), 49 deletions(-)
---
 proc.c                                            |  76 +++++++--------
 spec/ruby/core/method/fixtures/classes.rb         |  24 +++++
 spec/ruby/core/method/owner_spec.rb               |   6 ++
 spec/ruby/core/method/super_method_spec.rb        |  19 ++++
 spec/ruby/core/unboundmethod/owner_spec.rb        |   7 ++
 spec/ruby/core/unboundmethod/super_method_spec.rb |  21 ++++
 test/ruby/test_method.rb                          | 112 +++++++++++++++++++---
 version.h                                         |   6 +-
 8 files changed, 214 insertions(+), 57 deletions(-)

diff --git a/proc.c b/proc.c
index 83c7fe4410..84e6645835 100644
--- a/proc.c
+++ b/proc.c
@@ -37,7 +37,11 @@ const rb_cref_t *rb_vm_cref_in_context(VALUE self, VALUE cbase); https://github.com/ruby/ruby/blob/trunk/proc.c#L37
 struct METHOD {
     const VALUE recv;
     const VALUE klass;
+    /* needed for #super_method */
     const VALUE iclass;
+    /* Different than me->owner only for ZSUPER methods.
+       This is error-prone but unavoidable unless ZSUPER methods are removed. */
+    const VALUE owner;
     const rb_method_entry_t * const me;
     /* for bound methods, `me' should be rb_callable_method_entry_t * */
 };
@@ -1618,6 +1622,7 @@ mnew_missing(VALUE klass, VALUE obj, ID id, VALUE mclass) https://github.com/ruby/ruby/blob/trunk/proc.c#L1622
 
     RB_OBJ_WRITE(method, &data->recv, obj);
     RB_OBJ_WRITE(method, &data->klass, klass);
+    RB_OBJ_WRITE(method, &data->owner, klass);
 
     def = ZALLOC(rb_method_definition_t);
     def->type = VM_METHOD_TYPE_MISSING;
@@ -1641,12 +1646,14 @@ mnew_missing_by_name(VALUE klass, VALUE obj, VALUE *name, int scope, VALUE mclas https://github.com/ruby/ruby/blob/trunk/proc.c#L1646
 
 static VALUE
 mnew_internal(const rb_method_entry_t *me, VALUE klass, VALUE iclass,
-	      VALUE obj, ID id, VALUE mclass, int scope, int error)
+              VALUE obj, ID id, VALUE mclass, int scope, int error)
 {
     struct METHOD *data;
     VALUE method;
+    const rb_method_entry_t *original_me = me;
     rb_method_visibility_t visi = METHOD_VISI_UNDEF;
 
+  again:
     if (UNDEFINED_METHOD_ENTRY_P(me)) {
 	if (respond_to_missing_p(klass, obj, ID2SYM(id), scope)) {
 	    return mnew_missing(klass, obj, id, mclass);
@@ -1662,12 +1669,26 @@ mnew_internal(const rb_method_entry_t *me, VALUE klass, VALUE iclass, https://github.com/ruby/ruby/blob/trunk/proc.c#L1669
 	    rb_print_inaccessible(klass, id, visi);
 	}
     }
+    if (me->def->type == VM_METHOD_TYPE_ZSUPER) {
+        if (me->defined_class) {
+            VALUE klass = RCLASS_SUPER(RCLASS_ORIGIN(me->defined_class));
+            id = me->def->original_id;
+            me = (rb_method_entry_t *)rb_callable_method_entry_with_refinements(klass, id, &iclass);
+        }
+        else {
+            VALUE klass = RCLASS_SUPER(RCLASS_ORIGIN(me->owner));
+            id = me->def->original_id;
+            me = rb_method_entry_without_refinements(klass, id, &iclass);
+        }
+        goto again;
+    }
 
     method = TypedData_Make_Struct(mclass, struct METHOD, &method_data_type, data);
 
     RB_OBJ_WRITE(method, &data->recv, obj);
     RB_OBJ_WRITE(method, &data->klass, klass);
     RB_OBJ_WRITE(method, &data->iclass, iclass);
+    RB_OBJ_WRITE(method, &data->owner, original_me->owner);
     RB_OBJ_WRITE(method, &data->me, me);
 
     return method;
@@ -1701,27 +1722,6 @@ mnew_unbound(VALUE klass, ID id, VALUE mclass, int scope) https://github.com/ruby/ruby/blob/trunk/proc.c#L1722
     return mnew_from_me(me, klass, iclass, Qundef, id, mclass, scope);
 }
 
-static const rb_method_entry_t*
-zsuper_resolve(const rb_method_entry_t *me)
-{
-    const rb_method_entry_t *super_me;
-    while (me->def->type == VM_METHOD_TYPE_ZSUPER) {
-        VALUE defined_class = me->defined_class ? me->defined_class : me->owner;
-        VALUE super_class = RCLASS_SUPER(RCLASS_ORIGIN(defined_class));
-        if (!super_class) {
-            break;
-        }
-        ID id = me->def->original_id;
-        VALUE iclass;
-        super_me = (rb_method_entry_t *)rb_callable_method_entry_with_refinements(super_class, id, &iclass);
-        if (!super_me) {
-            break;
-        }
-        me = super_me;
-    }
-    return me;
-}
-
 static inline VALUE
 method_entry_defined_class(const rb_method_entry_t *me)
 {
@@ -1782,13 +1782,10 @@ method_eq(VALUE method, VALUE other) https://github.com/ruby/ruby/blob/trunk/proc.c#L1782
     m1 = (struct METHOD *)DATA_PTR(method);
     m2 = (struct METHOD *)DATA_PTR(other);
 
-    const rb_method_entry_t *m1_me = zsuper_resolve(m1->me);
-    const rb_method_entry_t *m2_me = zsuper_resolve(m2->me);
+    klass1 = method_entry_defined_class(m1->me);
+    klass2 = method_entry_defined_class(m2->me);
 
-    klass1 = method_entry_defined_class(m1_me);
-    klass2 = method_entry_defined_class(m2_me);
-
-    if (!rb_method_entry_eq(m1_me, m2_me) ||
+    if (!rb_method_entry_eq(m1->me, m2->me) ||
         klass1 != klass2 ||
         m1->klass != m2->klass ||
         m1->recv != m2->recv) {
@@ -1842,6 +1839,7 @@ method_unbind(VALUE obj) https://github.com/ruby/ruby/blob/trunk/proc.c#L1839
     RB_OBJ_WRITE(method, &data->recv, Qundef);
     RB_OBJ_WRITE(method, &data->klass, orig->klass);
     RB_OBJ_WRITE(method, &data->iclass, orig->iclass);
+    RB_OBJ_WRITE(method, &data->owner, orig->owner);
     RB_OBJ_WRITE(method, &data->me, rb_method_entry_clone(orig->me));
 
     return method;
@@ -1926,7 +1924,7 @@ method_owner(VALUE obj) https://github.com/ruby/ruby/blob/trunk/proc.c#L1924
 {
     struct METHOD *data;
     TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
-    return data->me->owner;
+    return data->owner;
 }
 
 void
@@ -2357,6 +2355,7 @@ method_clone(VALUE self) https://github.com/ruby/ruby/blob/trunk/proc.c#L2355
     RB_OBJ_WRITE(clone, &data->recv, orig->recv);
     RB_OBJ_WRITE(clone, &data->klass, orig->klass);
     RB_OBJ_WRITE(clone, &data->iclass, orig->iclass);
+    RB_OBJ_WRITE(clone, &data->owner, orig->owner);
     RB_OBJ_WRITE(clone, &data->me, rb_method_entry_clone(orig->me));
     return clone;
 }
@@ -2518,7 +2517,7 @@ rb_method_call_with_block(int argc, const VALUE *argv, VALUE method, VALUE passe https://github.com/ruby/ruby/blob/trunk/proc.c#L2517
 static void
 convert_umethod_to_method_components(const struct METHOD *data, VALUE recv, VALUE *methclass_out, VALUE *klass_out, VALUE *iclass_out, const rb_method_entry_t **me_out)
 {
-    VALUE methclass = data->me->owner;
+    VALUE methclass = data->owner;
     VALUE iclass = data->me->defined_class;
     VALUE klass = CLASS_OF(recv);
 
@@ -2607,6 +2606,7 @@ umethod_bind(VALUE method, VALUE recv) https://github.com/ruby/ruby/blob/trunk/proc.c#L2606
     RB_OBJ_WRITE(method, &bound->recv, recv);
     RB_OBJ_WRITE(method, &bound->klass, klass);
     RB_OBJ_WRITE(method, &bound->iclass, iclass);
+    RB_OBJ_WRITE(method, &bound->owner, methclass);
     RB_OBJ_WRITE(method, &bound->me, me);
 
     return method;
@@ -2643,7 +2643,7 @@ umethod_bind_call(int argc, VALUE *argv, VALUE method) https://github.com/ruby/ruby/blob/trunk/proc.c#L2643
         VALUE methclass, klass, iclass;
         const rb_method_entry_t *me;
         convert_umethod_to_method_components(data, recv, &methclass, &klass, &iclass, &me);
-        struct METHOD bound = { recv, klass, 0, me };
+        struct METHOD bound = { recv, klass, 0, methclass, me };
 
         return call_method_data(ec, &bound, argc, argv, passed_procval, RB_PASS_CALLED_KEYWORDS);
     }
@@ -2914,14 +2914,6 @@ rb_method_entry_location(const rb_method_entry_t *me) https://github.com/ruby/ruby/blob/trunk/proc.c#L2914
     return method_def_location(me->def);
 }
 
-static const rb_method_definition_t *
-zsuper_ref_method_def(VALUE method)
-{
-    const struct METHOD *data;
-    TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
-    return zsuper_resolve(data->me)->def;
-}
-
 /*
  * call-seq:
  *    meth.source_locati (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]