summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/ruby/test_keyword.rb92
-rw-r--r--vm_insnhelper.c10
2 files changed, 37 insertions, 65 deletions
diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb
index 81ac432979..c5b9c15ba9 100644
--- a/test/ruby/test_keyword.rb
+++ b/test/ruby/test_keyword.rb
@@ -280,37 +280,23 @@ class TestKeywordArguments < Test::Unit::TestCase
f = -> { true }
assert_equal(true, f[**{}])
assert_equal(true, f[**kw])
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_raise(ArgumentError) { f[**h] }
- end
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_raise(ArgumentError) { f[a: 1] }
- end
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_raise(ArgumentError) { f[**h2] }
- end
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_raise(ArgumentError) { f[**h3] }
- end
+ assert_raise(ArgumentError) { f[**h] }
+ assert_raise(ArgumentError) { f[a: 1] }
+ assert_raise(ArgumentError) { f[**h2] }
+ assert_raise(ArgumentError) { f[**h3] }
f = ->(a) { a }
- assert_raise(ArgumentError) { f[**{}] }
- assert_raise(ArgumentError) { f[**kw] }
assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_equal(h, f[**h])
+ assert_equal(kw, f[**{}])
end
assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_equal(h, f[a: 1])
- end
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_equal(h2, f[**h2])
- end
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_equal(h3, f[**h3])
- end
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_equal(h3, f[a: 1, **h2])
+ assert_equal(kw, f[**kw])
end
+ assert_equal(h, f[**h])
+ assert_equal(h, f[a: 1])
+ assert_equal(h2, f[**h2])
+ assert_equal(h3, f[**h3])
+ assert_equal(h3, f[a: 1, **h2])
f = ->(**x) { x }
assert_equal(kw, f[**{}])
@@ -800,43 +786,27 @@ class TestKeywordArguments < Test::Unit::TestCase
end
assert_nil(c.m(**{}))
assert_nil(c.m(**kw))
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_raise(ArgumentError) { c.m(**h) }
- end
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_raise(ArgumentError) { c.m(a: 1) }
- end
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_raise(ArgumentError) { c.m(**h2) }
- end
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_raise(ArgumentError) { c.m(**h3) }
- end
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_raise(ArgumentError) { c.m(a: 1, **h2) }
- end
+ assert_raise(ArgumentError) { c.m(**h) }
+ assert_raise(ArgumentError) { c.m(a: 1) }
+ assert_raise(ArgumentError) { c.m(**h2) }
+ assert_raise(ArgumentError) { c.m(**h3) }
+ assert_raise(ArgumentError) { c.m(a: 1, **h2) }
c = Object.new
class << c
define_method(:m) {|arg| arg }
end
- assert_raise(ArgumentError) { c.m(**{}) }
- assert_raise(ArgumentError) { c.m(**kw) }
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_equal(h, c.m(**h))
- end
assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_equal(h, c.m(a: 1))
- end
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_equal(h2, c.m(**h2))
- end
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_equal(h3, c.m(**h3))
+ assert_equal(kw, c.m(**{}))
end
assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_equal(h3, c.m(a: 1, **h2))
+ assert_equal(kw, c.m(**kw))
end
+ assert_equal(h, c.m(**h))
+ assert_equal(h, c.m(a: 1))
+ assert_equal(h2, c.m(**h2))
+ assert_equal(h3, c.m(**h3))
+ assert_equal(h3, c.m(a: 1, **h2))
c = Object.new
class << c
@@ -866,8 +836,12 @@ class TestKeywordArguments < Test::Unit::TestCase
class << c
define_method(:m) {|arg, **opt| [arg, opt] }
end
- assert_raise(ArgumentError) { c.m(**{}) }
- assert_raise(ArgumentError) { c.m(**kw) }
+ assert_warn(/The keyword argument is passed as the last hash parameter/m) do
+ assert_equal([kw, kw], c.m(**{}))
+ end
+ assert_warn(/The keyword argument is passed as the last hash parameter/m) do
+ assert_equal([kw, kw], c.m(**kw))
+ end
assert_warn(/The keyword argument is passed as the last hash parameter/m) do
assert_equal([h, kw], c.m(**h))
end
@@ -1347,14 +1321,10 @@ class TestKeywordArguments < Test::Unit::TestCase
o = Object.new
def o.to_hash() { a: 1 } end
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_equal({a: 1}, m1(**o) {|x| break x}, bug9898)
- end
+ assert_equal({a: 1}, m1(**o) {|x| break x}, bug9898)
o2 = Object.new
def o2.to_hash() { b: 2 } end
- assert_warn(/The keyword argument is passed as the last hash parameter/m) do
- assert_equal({a: 1, b: 2}, m1(**o, **o2) {|x| break x}, bug9898)
- end
+ assert_equal({a: 1, b: 2}, m1(**o, **o2) {|x| break x}, bug9898)
end
def test_implicit_hash_conversion
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index fe333d1ea1..b1ea71a828 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -2294,7 +2294,7 @@ vm_call_bmethod(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_c
VALUE *argv;
int argc;
- CALLER_SETUP_ARG(cfp, calling, ci);
+ CALLER_SETUP_ARG_WITHOUT_KW_SPLAT(cfp, calling, ci);
argc = calling->argc;
argv = ALLOCA_N(VALUE, argc);
MEMCPY(argv, cfp->sp - argc, VALUE, argc);
@@ -2949,11 +2949,13 @@ vm_callee_setup_block_arg(rb_execution_context_t *ec, struct rb_calling_info *ca
rb_control_frame_t *cfp = ec->cfp;
VALUE arg0;
- CALLER_SETUP_ARG(cfp, calling, ci);
-
- if (calling->kw_splat) {
+ if (calling->kw_splat && calling->argc == iseq->body->param.lead_num + iseq->body->param.post_num && RHASH_EMPTY_P(cfp->sp[-1])) {
+ CALLER_SETUP_ARG_WITHOUT_KW_SPLAT(cfp, calling, ci);
rb_warn_keyword_to_last_hash(calling, ci, iseq);
}
+ else {
+ CALLER_SETUP_ARG(cfp, calling, ci);
+ }
if (arg_setup_type == arg_setup_block &&
calling->argc == 1 &&