summaryrefslogtreecommitdiff
path: root/vm_args.c
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2023-03-14 03:42:47 +0900
committerKoichi Sasada <ko1@atdot.net>2023-03-15 18:05:13 +0900
commit6462c1a042fec4017f7e3bf2c13ec6a29efd23d6 (patch)
tree01b3c6e3819e91525acce8c68bd0de8931551fe9 /vm_args.c
parent7fd53eeb46db261bbc20025cdab70096245a5cbe (diff)
downloadruby-6462c1a042fec4017f7e3bf2c13ec6a29efd23d6.tar.gz
`Hash#dup` for kwsplat arguments
On `f(*a, **kw)` method calls, a rest keyword parameter is identically same Hash object is passed and it should make `#dup`ed Hahs. fix https://bugs.ruby-lang.org/issues/19526
Diffstat (limited to 'vm_args.c')
-rw-r--r--vm_args.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/vm_args.c b/vm_args.c
index 1af69cceee..cc7f1e29b5 100644
--- a/vm_args.c
+++ b/vm_args.c
@@ -450,6 +450,18 @@ ignore_keyword_hash_p(VALUE keyword_hash, const rb_iseq_t * const iseq, unsigned
RHASH_EMPTY_P(keyword_hash);
}
+static VALUE
+check_kwrestarg(VALUE keyword_hash, unsigned int *kw_flag)
+{
+ if (!(*kw_flag & VM_CALL_KW_SPLAT_MUT)) {
+ *kw_flag |= VM_CALL_KW_SPLAT_MUT;
+ return rb_hash_dup(keyword_hash);
+ }
+ else {
+ return keyword_hash;
+ }
+}
+
static int
setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * const iseq,
struct rb_calling_info *const calling,
@@ -528,12 +540,14 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
keyword_hash = Qnil;
}
else if (UNLIKELY(ISEQ_BODY(iseq)->param.flags.ruby2_keywords)) {
- flag_keyword_hash = keyword_hash;
- rb_ary_push(args->rest, keyword_hash);
+ converted_keyword_hash = check_kwrestarg(converted_keyword_hash, &kw_flag);
+ flag_keyword_hash = converted_keyword_hash;
+ rb_ary_push(args->rest, converted_keyword_hash);
keyword_hash = Qnil;
}
else if (!ISEQ_BODY(iseq)->param.flags.has_kwrest && !ISEQ_BODY(iseq)->param.flags.has_kw) {
- rb_ary_push(args->rest, keyword_hash);
+ converted_keyword_hash = check_kwrestarg(converted_keyword_hash, &kw_flag);
+ rb_ary_push(args->rest, converted_keyword_hash);
keyword_hash = Qnil;
}