diff options
-rw-r--r-- | test/ruby/test_keyword.rb | 92 | ||||
-rw-r--r-- | vm_insnhelper.c | 10 |
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 && |