summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2021-07-15 10:04:17 -0700
committerGitHub <noreply@github.com>2021-07-15 10:04:17 -0700
commit95f8ffa5f6c70aa9383e1f6db02b22707c183402 (patch)
treec03a20a9c978253d2537c83581a46d2bdf2cd9b6 /hash.c
parentfa87f72e1e84e2b55516be188f00434a683b924c (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 <kachick1@gmail.com>
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4616 Merged-By: jeremyevans <code@jeremyevans.net>
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/hash.c b/hash.c
index ec41bf13c7..045e739b48 100644
--- a/hash.c
+++ b/hash.c
@@ -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