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

ruby-changes:71757

From: John <ko1@a...>
Date: Sun, 17 Apr 2022 03:41:12 +0900 (JST)
Subject: [ruby-changes:71757] 7950c4eb2d (master): Fix class ancestry checks for duped classes

https://git.ruby-lang.org/ruby.git/commit/?id=7950c4eb2d

From 7950c4eb2d132fca40d1e9383e8a7240781cc575 Mon Sep 17 00:00:00 2001
From: John Hawthorn <john@h...>
Date: Fri, 15 Apr 2022 15:21:10 -0700
Subject: Fix class ancestry checks for duped classes

Previously in some when classes were duped (specifically those with a
prepended module), they would not correctly have their "superclasses"
array or depth filled in.

This could cause ancestry checks (like is_a? and Module comparisons) to
return incorrect results.

This happened because rb_mod_init_copy builds origin classes in an order
that doesn't have the super linked list fully connected until it's
finished. This commit fixes the previous issue by calling
rb_class_update_superclasses before returning the cloned class. This is
similar to what's already done in make_metaclass.
---
 class.c                  |  2 ++
 test/ruby/test_module.rb | 20 ++++++++++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/class.c b/class.c
index 39899d5e05..b41e1a37e8 100644
--- a/class.c
+++ b/class.c
@@ -567,6 +567,8 @@ rb_mod_init_copy(VALUE clone, VALUE orig) https://github.com/ruby/ruby/blob/trunk/class.c#L567
         else {
             rb_bug("no origin for class that has origin");
         }
+
+        rb_class_update_superclasses(clone);
     }
 
     return clone;
diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index 6bbe168348..c7245ab2db 100644
--- a/test/ruby/test_module.rb
+++ b/test/ruby/test_module.rb
@@ -572,6 +572,26 @@ class TestModule < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_module.rb#L572
     assert_equal(2, a2.b)
   end
 
+  def test_ancestry_of_duped_classes
+    m = Module.new
+    sc = Class.new
+    a = Class.new(sc) do
+      def b; 2 end
+      prepend m
+    end
+
+    a2 = a.dup.new
+
+    assert_kind_of Object, a2
+    assert_kind_of sc, a2
+    refute_kind_of a, a2
+    assert_kind_of m, a2
+
+    assert_kind_of Class, a2.class
+    assert_kind_of sc.singleton_class, a2.class
+    assert_same sc, a2.class.superclass
+  end
+
   def test_gc_prepend_chain
     assert_separately([], <<-EOS)
       10000.times { |i|
-- 
cgit v1.2.1


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

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