summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2020-01-22 18:12:34 -0800
committerJeremy Evans <code@jeremyevans.net>2020-01-23 09:30:29 -0800
commitf8a8f055123bc81fc13fa295b936504196df0da4 (patch)
treec6e9890c08b7370a3e89e3980004f254f10ad641
parent6551a25a1951525f27c54c18207f95b6d253cbb9 (diff)
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.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/2857
-rw-r--r--test/ruby/test_keyword.rb8
-rw-r--r--test/test_pp.rb2
-rw-r--r--vm_args.c36
3 files changed, 14 insertions, 32 deletions
diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb
index 02745a1dfe..75991ca0b4 100644
--- a/test/ruby/test_keyword.rb
+++ b/test/ruby/test_keyword.rb
@@ -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))
diff --git a/test/test_pp.rb b/test/test_pp.rb
index cd16af6394..3434c2b04c 100644
--- a/test/test_pp.rb
+++ b/test/test_pp.rb
@@ -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
diff --git a/vm_args.c b/vm_args.c
index 5bed9711de..256ab5b7f4 100644
--- a/vm_args.c
+++ b/vm_args.c
@@ -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) {