summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/ruby/test_keyword.rb8
-rw-r--r--vm_insnhelper.c6
2 files changed, 12 insertions, 2 deletions
diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb
index 25337712fe..0f67c28963 100644
--- a/test/ruby/test_keyword.rb
+++ b/test/ruby/test_keyword.rb
@@ -2692,6 +2692,10 @@ class TestKeywordArguments < Test::Unit::TestCase
args
end
+ def pass_cfunc(*args)
+ self.class.new(*args).init_args
+ end
+
ruby2_keywords def block(*args)
->(*args, **kw){[args, kw]}.(*args)
end
@@ -2915,6 +2919,10 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal([[1], h1], o.foo(:pass_bar, 1, :a=>1))
end
+ assert_warn(/The last argument is used as the keyword parameter.* for `initialize'/m) do
+ assert_equal([[1], h1], o.foo(:pass_cfunc, 1, :a=>1))
+ end
+
assert_warn(/Skipping set of ruby2_keywords flag for bar \(method accepts keywords or method does not accept argument splat\)/) do
assert_nil(c.send(:ruby2_keywords, :bar))
end
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;
}
}