mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
Do not autosplat when calling proc with empty keyword splat
With the removal of the splatted argument when using an empty
keyword splat, the autosplat code considered an empty keyword
splat the same as no argument at all. However, that results
in autosplat behavior changing dependent on the content of
the splatted hash, which is not what anyone would expect or
want. This change always skips an autosplat if keywords were
provided.
Fixes [Bug #16560]
(cherry picked from commit c1d8829ef5
)
This commit is contained in:
parent
c858a10ce8
commit
3efbd527a8
2 changed files with 22 additions and 1 deletions
|
@ -1087,6 +1087,26 @@ class TestProc < Test::Unit::TestCase
|
||||||
assert_equal([1,2,[3],4,5], r, "[ruby-core:19485]")
|
assert_equal([1,2,[3],4,5], r, "[ruby-core:19485]")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_proc_autosplat
|
||||||
|
def self.a(arg, kw)
|
||||||
|
yield arg
|
||||||
|
yield arg, **kw
|
||||||
|
yield arg, kw
|
||||||
|
end
|
||||||
|
|
||||||
|
arr = []
|
||||||
|
a([1,2,3], {}) do |arg1, arg2=0|
|
||||||
|
arr << [arg1, arg2]
|
||||||
|
end
|
||||||
|
assert_equal([[1, 2], [[1, 2, 3], 0], [[1, 2, 3], {}]], arr)
|
||||||
|
|
||||||
|
arr = []
|
||||||
|
a([1,2,3], a: 1) do |arg1, arg2=0|
|
||||||
|
arr << [arg1, arg2]
|
||||||
|
end
|
||||||
|
assert_equal([[1, 2], [[1, 2, 3], {a: 1}], [[1, 2, 3], {a: 1}]], arr)
|
||||||
|
end
|
||||||
|
|
||||||
def test_parameters
|
def test_parameters
|
||||||
assert_equal([], proc {}.parameters)
|
assert_equal([], proc {}.parameters)
|
||||||
assert_equal([], proc {||}.parameters)
|
assert_equal([], proc {||}.parameters)
|
||||||
|
|
|
@ -725,10 +725,10 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
|
||||||
{
|
{
|
||||||
const int min_argc = iseq->body->param.lead_num + iseq->body->param.post_num;
|
const int min_argc = iseq->body->param.lead_num + iseq->body->param.post_num;
|
||||||
const int max_argc = (iseq->body->param.flags.has_rest == FALSE) ? min_argc + iseq->body->param.opt_num : UNLIMITED_ARGUMENTS;
|
const int max_argc = (iseq->body->param.flags.has_rest == FALSE) ? min_argc + iseq->body->param.opt_num : UNLIMITED_ARGUMENTS;
|
||||||
int opt_pc = 0;
|
|
||||||
int given_argc;
|
int given_argc;
|
||||||
int kw_splat = FALSE;
|
int kw_splat = FALSE;
|
||||||
unsigned int kw_flag = ci->flag & (VM_CALL_KWARG | VM_CALL_KW_SPLAT);
|
unsigned int kw_flag = ci->flag & (VM_CALL_KWARG | VM_CALL_KW_SPLAT);
|
||||||
|
int opt_pc = 0, allow_autosplat = !kw_flag;
|
||||||
struct args_info args_body, *args;
|
struct args_info args_body, *args;
|
||||||
VALUE keyword_hash = Qnil;
|
VALUE keyword_hash = Qnil;
|
||||||
VALUE * const orig_sp = ec->cfp->sp;
|
VALUE * const orig_sp = ec->cfp->sp;
|
||||||
|
@ -879,6 +879,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
|
||||||
break; /* do nothing special */
|
break; /* do nothing special */
|
||||||
case arg_setup_block:
|
case arg_setup_block:
|
||||||
if (given_argc == 1 &&
|
if (given_argc == 1 &&
|
||||||
|
allow_autosplat &&
|
||||||
(min_argc > 0 || iseq->body->param.opt_num > 1 ||
|
(min_argc > 0 || iseq->body->param.opt_num > 1 ||
|
||||||
iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) &&
|
iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) &&
|
||||||
!iseq->body->param.flags.ambiguous_param0 &&
|
!iseq->body->param.flags.ambiguous_param0 &&
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue