Fix assertion failure with anonymous splats
When calling a method that accepts an anonymous splat and literal keywords without any arguments, an assertion failure was previously raised. Set rest_index to 0 when setting rest to the frozen hash, so the args_argc calculation is accurate. While here, add more tests for methods with anonymous splats with and without keywords and keyword splats to confirm behavior is correct. Also add a basic bootstrap test that would hit the previous assertion failure. Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
This commit is contained in:
parent
b8e2bec914
commit
29dafa5fc2
Notes:
git
2025-04-03 02:31:22 +00:00
@ -1419,3 +1419,11 @@ assert_equal 'ok', %q{
|
|||||||
"ok"
|
"ok"
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert_equal 'ok', <<~RUBY
|
||||||
|
def test(*, kw: false)
|
||||||
|
"ok"
|
||||||
|
end
|
||||||
|
|
||||||
|
test
|
||||||
|
RUBY
|
||||||
|
@ -374,6 +374,55 @@ class TestCall < Test::Unit::TestCase
|
|||||||
assert_equal({splat_modified: false}, b)
|
assert_equal({splat_modified: false}, b)
|
||||||
end
|
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 test_kwsplat_block_eval_order
|
||||||
def self.t(**kw, &b) [kw, b] end
|
def self.t(**kw, &b) [kw, b] end
|
||||||
|
|
||||||
|
@ -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 (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)) {
|
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;
|
*(locals + ISEQ_BODY(iseq)->param.rest_start) = args->rest = rb_cArray_empty_frozen;
|
||||||
|
args->rest_index = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
args_setup_rest_parameter(args, locals + ISEQ_BODY(iseq)->param.rest_start);
|
args_setup_rest_parameter(args, locals + ISEQ_BODY(iseq)->param.rest_start);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user