diff --git a/bootstraptest/test_method.rb b/bootstraptest/test_method.rb index 41823b5007..997675200e 100644 --- a/bootstraptest/test_method.rb +++ b/bootstraptest/test_method.rb @@ -1419,3 +1419,11 @@ assert_equal 'ok', %q{ "ok" end } + +assert_equal 'ok', <<~RUBY + def test(*, kw: false) + "ok" + end + + test +RUBY diff --git a/test/ruby/test_call.rb b/test/ruby/test_call.rb index ffbda1fdb9..7843f3b476 100644 --- a/test/ruby/test_call.rb +++ b/test/ruby/test_call.rb @@ -374,6 +374,55 @@ class TestCall < Test::Unit::TestCase assert_equal({splat_modified: false}, b) end + def test_anon_splat + r2kh = Hash.ruby2_keywords_hash(kw: 2) + r2kea = [r2kh] + r2ka = [1, r2kh] + + def self.s(*) ->(*a){a}.call(*) end + assert_equal([], s) + assert_equal([1], s(1)) + assert_equal([{kw: 2}], s(kw: 2)) + assert_equal([{kw: 2}], s(**{kw: 2})) + assert_equal([1, {kw: 2}], s(1, kw: 2)) + assert_equal([1, {kw: 2}], s(1, **{kw: 2})) + assert_equal([{kw: 2}], s(*r2kea)) + assert_equal([1, {kw: 2}], s(*r2ka)) + + singleton_class.remove_method(:s) + def self.s(*, kw: 0) [*->(*a){a}.call(*), kw] end + assert_equal([0], s) + assert_equal([1, 0], s(1)) + assert_equal([2], s(kw: 2)) + assert_equal([2], s(**{kw: 2})) + assert_equal([1, 2], s(1, kw: 2)) + assert_equal([1, 2], s(1, **{kw: 2})) + assert_equal([2], s(*r2kea)) + assert_equal([1, 2], s(*r2ka)) + + singleton_class.remove_method(:s) + def self.s(*, **kw) [*->(*a){a}.call(*), kw] end + assert_equal([{}], s) + assert_equal([1, {}], s(1)) + assert_equal([{kw: 2}], s(kw: 2)) + assert_equal([{kw: 2}], s(**{kw: 2})) + assert_equal([1, {kw: 2}], s(1, kw: 2)) + assert_equal([1, {kw: 2}], s(1, **{kw: 2})) + assert_equal([{kw: 2}], s(*r2kea)) + assert_equal([1, {kw: 2}], s(*r2ka)) + + singleton_class.remove_method(:s) + def self.s(*, kw: 0, **kws) [*->(*a){a}.call(*), kw, kws] end + assert_equal([0, {}], s) + assert_equal([1, 0, {}], s(1)) + assert_equal([2, {}], s(kw: 2)) + assert_equal([2, {}], s(**{kw: 2})) + assert_equal([1, 2, {}], s(1, kw: 2)) + assert_equal([1, 2, {}], s(1, **{kw: 2})) + assert_equal([2, {}], s(*r2kea)) + assert_equal([1, 2, {}], s(*r2ka)) + end + def test_kwsplat_block_eval_order def self.t(**kw, &b) [kw, b] end diff --git a/vm_args.c b/vm_args.c index a84540c61b..4738eda72c 100644 --- a/vm_args.c +++ b/vm_args.c @@ -896,6 +896,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co if (ISEQ_BODY(iseq)->param.flags.has_rest) { if (UNLIKELY(ISEQ_BODY(iseq)->param.flags.anon_rest && args->argc == 0 && !args->rest && !ISEQ_BODY(iseq)->param.flags.has_post)) { *(locals + ISEQ_BODY(iseq)->param.rest_start) = args->rest = rb_cArray_empty_frozen; + args->rest_index = 0; } else { args_setup_rest_parameter(args, locals + ISEQ_BODY(iseq)->param.rest_start);