🎃

[Bug #21376] Set を継承したオブジェクトを比較したときの挙動が Ruby 3.5 から変わっているというバグ報告

に公開

[Bug #21376] Inconsistent equality between Sets with different compare_by_identity, different classes

  • Set#compare_by_identity したオブジェクトと Set を継承したオブジェクトを比較したときの挙動が Ruby 3.5 から変わっているというバグ報告
class MySet < Set
end
s1 = MySet.new([1]).compare_by_identity
s2 = Set.new([1])

pp s1 == s2
# Ruby 3.4 => true
# Ruby 3.5 => false
  • #compare_by_identity しているオブジェクトが逆の場合でも再現しますね
  • 逆に同じクラスのオブジェクトであれば再現はしない
    • 一貫して false になる
class MySet < Set
end

# Ruby 3.4 も 3.5 も false を返す
pp Set.new([1]).compare_by_identity == Set.new([1])
# => false

pp MySet.new([1]).compare_by_identity == MySet.new([1])
# => false
  • これはそもそも Ruby 3.4 の挙動がバグみたいで Ruby 3.5 の挙動が正しいみたいですね
  • ちなみに Set#compare_by_identitySet の要素の一致判定をオブジェクトの同一性で判定するように変更するようにするメソッド
s = Set.new

# 通常は同じ値の場合は重複しない
s << "a"
s << "a"
pp s
# => #<Set: {"a"}>

# compare_by_identity を呼ぶと object_id 等で比較するようになる
s.compare_by_identity

# なのでこの場合の "a" は別のオブジェクトとして Set に追加される
s << "a"
pp s
# => #<Set: {"a", "a"}>
GitHubで編集を提案

Discussion