summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index e0e1f9e971..626557cb45 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1985,12 +1985,27 @@ CALLER_SETUP_ARG(struct rb_control_frame_struct *restrict cfp,
calling->kw_splat = 1;
}
}
- if (UNLIKELY(IS_ARGS_KEYWORD(ci))) {
- /* This converts VM_CALL_KWARG style to VM_CALL_KW_SPLAT style
- * by creating a keyword hash.
- * So, vm_ci_flag(ci) & VM_CALL_KWARG is now inconsistent.
- */
- vm_caller_setup_arg_kw(cfp, calling, ci);
+ if (UNLIKELY(IS_ARGS_KW_OR_KW_SPLAT(ci))) {
+ if (IS_ARGS_KEYWORD(ci)) {
+ /* This converts VM_CALL_KWARG style to VM_CALL_KW_SPLAT style
+ * by creating a keyword hash.
+ * So, vm_ci_flag(ci) & VM_CALL_KWARG is now inconsistent.
+ */
+ vm_caller_setup_arg_kw(cfp, calling, ci);
+ }
+ else {
+ VALUE keyword_hash = cfp->sp[-1];
+ if (!RB_TYPE_P(keyword_hash, T_HASH)) {
+ /* Convert a non-hash keyword splat to a new hash */
+ cfp->sp[-1] = rb_hash_dup(rb_to_hash_type(keyword_hash));
+ }
+ else if (!IS_ARGS_KW_SPLAT_MUT(ci)) {
+ /* Convert a hash keyword splat to a new hash unless
+ * a mutable keyword splat was passed.
+ */
+ cfp->sp[-1] = rb_hash_dup(keyword_hash);
+ }
+ }
}
}