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.
This commit is contained in:
parent
e70e7f4ad3
commit
7950c4eb2d
Notes:
git
2022-04-17 03:41:22 +09:00
2
class.c
2
class.c
@ -567,6 +567,8 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
|
|||||||
else {
|
else {
|
||||||
rb_bug("no origin for class that has origin");
|
rb_bug("no origin for class that has origin");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rb_class_update_superclasses(clone);
|
||||||
}
|
}
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
|
@ -572,6 +572,26 @@ class TestModule < Test::Unit::TestCase
|
|||||||
assert_equal(2, a2.b)
|
assert_equal(2, a2.b)
|
||||||
end
|
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
|
def test_gc_prepend_chain
|
||||||
assert_separately([], <<-EOS)
|
assert_separately([], <<-EOS)
|
||||||
10000.times { |i|
|
10000.times { |i|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user