diff options
author | Jeremy Evans <[email protected]> | 2021-07-15 10:04:17 -0700 |
---|---|---|
committer | GitHub <[email protected]> | 2021-07-15 10:04:17 -0700 |
commit | 95f8ffa5f6c70aa9383e1f6db02b22707c183402 (patch) | |
tree | c03a20a9c978253d2537c83581a46d2bdf2cd9b6 /hash.c | |
parent | fa87f72e1e84e2b55516be188f00434a683b924c (diff) |
Copy hash compare_by_identity setting in more cases
This makes the compare_by_identity setting always copied
for the following methods:
* except
* merge
* reject
* select
* slice
* transform_values
Some of these methods did not copy the setting, or only
copied the setting if the receiver was not empty.
Fixes [Bug #17757]
Co-authored-by: Kenichi Kamiya <[email protected]>
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/4616
Merged-By: jeremyevans <[email protected]>
Diffstat (limited to 'hash.c')
-rw-r--r-- | hash.c | 32 |
1 files changed, 24 insertions, 8 deletions
@@ -1559,6 +1559,17 @@ rb_hash_new(void) return hash_alloc(rb_cHash); } +static VALUE rb_hash_compare_by_id(VALUE hash); + +static VALUE +copy_compare_by_id(VALUE hash, VALUE basis) +{ + if (rb_hash_compare_by_id_p(basis)) { + return rb_hash_compare_by_id(hash); + } + return hash; +} + MJIT_FUNC_EXPORTED VALUE rb_hash_new_with_size(st_index_t size) { @@ -1588,6 +1599,12 @@ hash_copy(VALUE ret, VALUE hash) } static VALUE +hash_dup_with_compare_by_id(VALUE hash) +{ + return hash_copy(copy_compare_by_id(rb_hash_new(), hash), hash); +} + +static VALUE hash_dup(VALUE hash, VALUE klass, VALUE flags) { return hash_copy(hash_alloc_flags(klass, flags, RHASH_IFNONE(hash)), @@ -2597,7 +2614,7 @@ rb_hash_reject(VALUE hash) rb_warn("extra states are no longer copied: %+"PRIsVALUE, hash); } } - result = hash_copy(hash_alloc(rb_cHash), hash); + result = hash_dup_with_compare_by_id(hash); if (!RHASH_EMPTY_P(hash)) { rb_hash_foreach(result, delete_if_i, result); } @@ -2622,9 +2639,9 @@ rb_hash_slice(int argc, VALUE *argv, VALUE hash) VALUE key, value, result; if (argc == 0 || RHASH_EMPTY_P(hash)) { - return rb_hash_new(); + return copy_compare_by_id(rb_hash_new(), hash); } - result = rb_hash_new_with_size(argc); + result = copy_compare_by_id(rb_hash_new_with_size(argc), hash); for (i = 0; i < argc; i++) { key = argv[i]; @@ -2653,8 +2670,7 @@ rb_hash_except(int argc, VALUE *argv, VALUE hash) int i; VALUE key, result; - result = hash_alloc(rb_cHash); - hash_copy(result, hash); + result = hash_dup_with_compare_by_id(hash); for (i = 0; i < argc; i++) { key = argv[i]; @@ -2754,7 +2770,7 @@ rb_hash_select(VALUE hash) VALUE result; RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size); - result = hash_copy(hash_alloc(rb_cHash), hash); + result = hash_dup_with_compare_by_id(hash); if (!RHASH_EMPTY_P(hash)) { rb_hash_foreach(result, keep_if_i, result); } @@ -3348,7 +3364,7 @@ rb_hash_transform_values(VALUE hash) VALUE result; RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size); - result = hash_copy(hash_alloc(rb_cHash), hash); + result = hash_dup_with_compare_by_id(hash); SET_DEFAULT(result, Qnil); if (!RHASH_EMPTY_P(hash)) { @@ -4102,7 +4118,7 @@ rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func) static VALUE rb_hash_merge(int argc, VALUE *argv, VALUE self) { - return rb_hash_update(argc, argv, rb_hash_dup(self)); + return rb_hash_update(argc, argv, copy_compare_by_id(rb_hash_dup(self), self)); } static int |