Bug #16187
closedHash#replace no longer rehashes keys for small (array table) hashes
Description
Here is a script that shows the problem
which outputs true in ruby 2.5 and lower versions and false in ruby 2.6 and later versions.
This is because ruby 2.6 introduced array table backed hashes and rb_hash_replace uses ar_copy(hash, hash2) when both hashes use an array table. If either hash used a symbol table, then the it would rehash the keys. This can be shown by forcing an symbol table to be used using Hash#compare_by_identity
mutable_key = [1]
h = { mutable_key => 'a' }
h.compare_by_identity
mutable_key[0] = 2
p(h == {}.replace(h))
which returns true in all versions of ruby.
I think Hash#replace should definitely be consistent about whether it rehashes or not.
In https://bugs.ruby-lang.org/issues/16121 ko1 (Koichi Sasada) suggested using rb_hash_replace to implement Hash#initialize_copy. Since Hash#dup already has tests to ensure that it rehashes, I think it makes sense to have Hash#replace go back to always rehashing so we can share an implementation between these methods. I've opened https://github.com/ruby/ruby/pull/2489 which does this and addresses https://bugs.ruby-lang.org/issues/16121
Updated by dylants (Dylan Thacker-Smith) over 6 years ago
This can be closed now. It was fixed by commit b9702590445dfea62d271d0a5c942b7adfaaacdd.
Sorry, I should have linked to this bug in the relevant commit in that changeset.
Updated by jeremyevans0 (Jeremy Evans) over 6 years ago
- Status changed from Open to Closed