summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2023-10-26 14:28:39 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2023-10-26 14:28:39 +0900
commitc8d162c889008028b148437d02f36f4edaa749fd (patch)
tree51d0430755b0d2880ab10899d331a1f4e5e5e33d
parent634e0ac140d890904c59eab8bdec09b80c78b1a4 (diff)
[Bug #19973] Warn duplicated keyword arguments after keyword splat
-rw-r--r--parse.y11
-rw-r--r--test/ruby/test_syntax.rb6
2 files changed, 13 insertions, 4 deletions
diff --git a/parse.y b/parse.y
index 46d9567093..eb2a2b3984 100644
--- a/parse.y
+++ b/parse.y
@@ -14551,15 +14551,18 @@ remove_duplicate_keys(struct parser_params *p, NODE *hash)
NODE *result = 0;
NODE *last_expr = 0;
rb_code_location_t loc = hash->nd_loc;
- while (hash && RNODE_LIST(hash)->nd_head && RNODE_LIST(hash)->nd_next) {
+ while (hash && RNODE_LIST(hash)->nd_next) {
NODE *head = RNODE_LIST(hash)->nd_head;
NODE *value = RNODE_LIST(hash)->nd_next;
NODE *next = RNODE_LIST(value)->nd_next;
st_data_t key = (st_data_t)head;
st_data_t data;
RNODE_LIST(value)->nd_next = 0;
- if (nd_type_p(head, NODE_LIT) &&
- st_delete(literal_keys, (key = (st_data_t)RNODE_LIT(head)->nd_lit, &key), &data)) {
+ if (!head) {
+ key = (st_data_t)value;
+ }
+ else if (nd_type_p(head, NODE_LIT) &&
+ st_delete(literal_keys, (key = (st_data_t)RNODE_LIT(head)->nd_lit, &key), &data)) {
NODE *dup_value = (RNODE_LIST((NODE *)data))->nd_next;
rb_compile_warn(p->ruby_sourcefile, nd_line((NODE *)data),
"key %+"PRIsVALUE" is duplicated and overwritten on line %d",
@@ -14572,7 +14575,7 @@ remove_duplicate_keys(struct parser_params *p, NODE *hash)
}
}
st_insert(literal_keys, (st_data_t)key, (st_data_t)hash);
- last_expr = nd_type_p(head, NODE_LIT) ? value : head;
+ last_expr = !head || nd_type_p(head, NODE_LIT) ? value : head;
hash = next;
}
st_foreach(literal_keys, append_literal_keys, (st_data_t)&result);
diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb
index cda84c6368..69d1bb3024 100644
--- a/test/ruby/test_syntax.rb
+++ b/test/ruby/test_syntax.rb
@@ -335,6 +335,12 @@ class TestSyntax < Test::Unit::TestCase
assert_warn(/duplicated/) {r = eval("a.f(**{k: a.add(1), j: a.add(2), k: a.add(3), k: a.add(4)})")}
assert_equal(4, r)
assert_equal([1, 2, 3, 4], a)
+ a.clear
+ r = nil
+ z = {}
+ assert_warn(/duplicated/) {r = eval("a.f(k: a.add(1), **z, k: a.add(2))")}
+ assert_equal(2, r)
+ assert_equal([1, 2], a)
end
def test_keyword_empty_splat