summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2026-05-11 19:50:07 -0400
committerPeter Zhu <peter@peterzhu.ca>2026-05-12 19:22:07 -0400
commitbaec5bbfffb38083b4180240a0319d20c9afc2a7 (patch)
treefba745dc37dd0fa36fc66711ceaf16160752b9be /test
parent6297af9883baa274a316eca77a9333e7c8b440d3 (diff)
Fix GC compaction for compare-by-identity sets
[Bug #22064] Compare-by-identity sets use the address for hashing, so we must pin it so the object does not move in GC compaction. Objects in a compare-by-identity set is not currently pinned, causing the set to be broken if the object is moved. For example: set = Set.new.compare_by_identity o = Object.new set.add(o) puts set.include?(o) GC.verify_compaction_references(expand_heap: true, toward: :empty) puts set.include?(o) It should output true twice, but it outputs true and false.
Diffstat (limited to 'test')
-rw-r--r--test/ruby/test_set.rb19
1 files changed, 19 insertions, 0 deletions
diff --git a/test/ruby/test_set.rb b/test/ruby/test_set.rb
index 46d649ee73..427dd4b6b0 100644
--- a/test/ruby/test_set.rb
+++ b/test/ruby/test_set.rb
@@ -902,6 +902,25 @@ class TC_Set < Test::Unit::TestCase
assert_equal(array.uniq.sort, set.sort)
end
+ def test_compare_by_identity_compact
+ omit "compaction is not supported on this platform" unless GC.respond_to?(:compact)
+
+ # [Bug #22064]
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ set = Set.new.compare_by_identity
+
+ o = Object.new
+ set.add(o)
+
+ assert_include(set, o)
+
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ assert_include(set, o)
+ end;
+ end
+
def test_reset
[Set, Class.new(Set)].each { |klass|
a = [1, 2]