Remove empty keyword splats when calling even when using ruby2_keywords

Keeping empty keyword splats for ruby2_keywords methods was
necessary in 2.7 to prevent the final positional hash being
treated as keywords.  Now that keyword argument separation
has been committed, the final positional hash is never
treated as keywords, so there is no need to keep empty
keyword splats when using ruby2_keywords.
This commit is contained in:
Jeremy Evans 2020-01-22 18:12:34 -08:00
Родитель 6551a25a19
Коммит f8a8f05512
3 изменённых файлов: 14 добавлений и 32 удалений

Просмотреть файл

@ -2339,10 +2339,10 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal([[1, h1, 1], {}], o.foo_bar_mod(1, **h1))
assert_equal([1, h1, 1], o.foo_baz_mod(1, **h1))
assert_equal([[h1, {}, 1], {}], o.foo_mod(:bar, h1, **{}))
assert_equal([h1, {}, 1], o.foo_mod(:baz, h1, **{}))
assert_equal([[h1, {}, 1], {}], o.foo_bar_mod(h1, **{}))
assert_equal([h1, {}, 1], o.foo_baz_mod(h1, **{}))
assert_equal([[h1, 1], {}], o.foo_mod(:bar, h1, **{}))
assert_equal([h1, 1], o.foo_mod(:baz, h1, **{}))
assert_equal([[h1, 1], {}], o.foo_bar_mod(h1, **{}))
assert_equal([h1, 1], o.foo_baz_mod(h1, **{}))
assert_equal([[1, h1, 1], {}], o.foo_mod(:bar, 1, h1))
assert_equal([1, h1, 1], o.foo_mod(:baz, 1, h1))

Просмотреть файл

@ -178,7 +178,7 @@ class PPSingleLineTest < Test::Unit::TestCase
end
def test_hash_in_array
assert_equal("[{}]", PP.singleline_pp([->(*a){a.last}.ruby2_keywords.call(**{})], ''.dup))
assert_equal("[{}]", PP.singleline_pp([->(*a){a.last.clear}.ruby2_keywords.call(a: 1)], ''.dup))
assert_equal("[{}]", PP.singleline_pp([Hash.ruby2_keywords_hash({})], ''.dup))
end
end

Просмотреть файл

@ -452,7 +452,6 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
VALUE keyword_hash = Qnil;
VALUE * const orig_sp = ec->cfp->sp;
unsigned int i;
int remove_empty_keyword_hash = 1;
VALUE flag_keyword_hash = 0;
vm_check_canary(ec, orig_sp);
@ -503,10 +502,6 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
args->kw_argv = NULL;
}
if (kw_flag && iseq->body->param.flags.ruby2_keywords) {
remove_empty_keyword_hash = 0;
}
if (ci->flag & VM_CALL_ARGS_SPLAT) {
VALUE rest_last = 0;
int len;
@ -521,9 +516,6 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
(((struct RHash *)rest_last)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
rest_last = rb_hash_dup(rest_last);
kw_flag |= VM_CALL_KW_SPLAT;
if (iseq->body->param.flags.ruby2_keywords) {
remove_empty_keyword_hash = 0;
}
}
else {
rest_last = 0;
@ -532,17 +524,12 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
if (kw_flag & VM_CALL_KW_SPLAT) {
if (len > 0 && ignore_keyword_hash_p(rest_last, iseq)) {
if (remove_empty_keyword_hash) {
arg_rest_dup(args);
rb_ary_pop(args->rest);
given_argc--;
kw_flag &= ~VM_CALL_KW_SPLAT;
}
else {
flag_keyword_hash = rest_last;
}
arg_rest_dup(args);
rb_ary_pop(args->rest);
given_argc--;
kw_flag &= ~VM_CALL_KW_SPLAT;
}
else if (!remove_empty_keyword_hash && rest_last) {
else if (iseq->body->param.flags.ruby2_keywords && rest_last) {
flag_keyword_hash = rest_last;
}
else if (iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) {
@ -557,16 +544,11 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
if (kw_flag & VM_CALL_KW_SPLAT) {
VALUE last_arg = args->argv[args->argc-1];
if (ignore_keyword_hash_p(last_arg, iseq)) {
if (remove_empty_keyword_hash) {
args->argc--;
given_argc--;
kw_flag &= ~VM_CALL_KW_SPLAT;
}
else {
flag_keyword_hash = last_arg;
}
args->argc--;
given_argc--;
kw_flag &= ~VM_CALL_KW_SPLAT;
}
else if (!remove_empty_keyword_hash) {
else if (iseq->body->param.flags.ruby2_keywords) {
flag_keyword_hash = last_arg;
}
else if (iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) {