summaryrefslogtreecommitdiff
path: root/compile.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 /compile.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 'compile.c')
-rw-r--r--compile.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/compile.c b/compile.c
index 8aa2228c53..08d21d760e 100644
--- a/compile.c
+++ b/compile.c
@@ -5789,6 +5789,16 @@ check_keyword(const NODE *node)
}
#endif
+static bool
+keyword_node_single_splat_p(NODE *kwnode)
+{
+ RUBY_ASSERT(keyword_node_p(kwnode));
+
+ NODE *node = kwnode->nd_head;
+ return node->nd_head == NULL &&
+ node->nd_next->nd_next == NULL;
+}
+
static int
setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
int dup_rest, unsigned int *flag_ptr, struct rb_callinfo_kwarg **kwarg_ptr)
@@ -5881,7 +5891,9 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
if (kwnode) {
// f(*a, k:1)
*flag_ptr |= VM_CALL_KW_SPLAT;
- *flag_ptr |= VM_CALL_KW_SPLAT_MUT;
+ if (!keyword_node_single_splat_p(kwnode)) {
+ *flag_ptr |= VM_CALL_KW_SPLAT_MUT;
+ }
compile_hash(iseq, args, kwnode, TRUE, FALSE);
argc += 1;
}