aboutsummaryrefslogtreecommitdiffstats
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2019-10-24 09:47:30 -0700
committerJeremy Evans <code@jeremyevans.net>2019-10-24 12:35:04 -0700
commitd6a2507e494f0fffca375c9e2eede38b6a777874 (patch)
tree8216d116837c7c3d291018cf96aceb4e0ad90d54 /vm_insnhelper.c
parent8c59b9250c25c66d6ed16429da139558295a4517 (diff)
downloadruby-d6a2507e494f0fffca375c9e2eede38b6a777874.tar.gz
Duplicate hash when converting keyword hash to keywords
This mirrors the behavior when manually splatting a hash. This mirrors the changes made in setup_parameters_complex in 6081ddd6e6f2297862b3c7e898d28a76b8f9240b, so that splatting to a non-iseq method works the same as splatting to an iseq method.
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 44a44d5db1..c72ad6e9d7 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1783,14 +1783,16 @@ CALLER_SETUP_ARG(struct rb_control_frame_struct *restrict cfp,
const struct rb_call_info *restrict ci)
{
if (UNLIKELY(IS_ARGS_SPLAT(ci))) {
+ VALUE final_hash;
/* This expands the rest argument to the stack.
* So, ci->flag & VM_CALL_ARGS_SPLAT is now inconsistent.
*/
vm_caller_setup_arg_splat(cfp, calling);
if (!IS_ARGS_KW_OR_KW_SPLAT(ci) &&
calling->argc > 0 &&
- RB_TYPE_P(*(cfp->sp - 1), T_HASH) &&
- (((struct RHash *)*(cfp->sp - 1))->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
+ RB_TYPE_P((final_hash = *(cfp->sp - 1)), T_HASH) &&
+ (((struct RHash *)final_hash)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
+ *(cfp->sp - 1) = rb_hash_dup(final_hash);
calling->kw_splat = 1;
}
}