@@ -13206,10 +13206,16 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod
1320613206 pm_token_t operator = parser->previous;
1320713207 pm_node_t *value = NULL;
1320813208
13209- if (token_begins_expression_p(parser->current.type)) {
13209+ if (match1(parser, PM_TOKEN_BRACE_LEFT)) {
13210+ // If we're about to parse a nested hash that is being
13211+ // pushed into this hash directly with **, then we want the
13212+ // inner hash to share the static literals with the outer
13213+ // hash.
13214+ parser->current_hash_keys = literals;
1321013215 value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
13211- }
13212- else {
13216+ } else if (token_begins_expression_p(parser->current.type)) {
13217+ value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
13218+ } else {
1321313219 pm_parser_scope_forwarding_keywords_check(parser, &operator);
1321413220 }
1321513221
@@ -13360,15 +13366,15 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
1336013366 pm_keyword_hash_node_t *hash = pm_keyword_hash_node_create(parser);
1336113367 argument = (pm_node_t *) hash;
1336213368
13363- pm_static_literals_t literals = { 0 };
13364- bool contains_keyword_splat = parse_assocs(parser, &literals , (pm_node_t *) hash);
13369+ pm_static_literals_t hash_keys = { 0 };
13370+ bool contains_keyword_splat = parse_assocs(parser, &hash_keys , (pm_node_t *) hash);
1336513371
1336613372 parse_arguments_append(parser, arguments, argument);
1336713373 if (contains_keyword_splat) {
13368- pm_node_flag_set((pm_node_t *)arguments->arguments, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT);
13374+ pm_node_flag_set((pm_node_t *) arguments->arguments, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT);
1336913375 }
1337013376
13371- pm_static_literals_free(&literals );
13377+ pm_static_literals_free(&hash_keys );
1337213378 parsed_bare_hash = true;
1337313379
1337413380 break;
@@ -13460,8 +13466,8 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
1346013466 pm_keyword_hash_node_t *bare_hash = pm_keyword_hash_node_create(parser);
1346113467
1346213468 // Create the set of static literals for this hash.
13463- pm_static_literals_t literals = { 0 };
13464- pm_hash_key_static_literals_add(parser, &literals , argument);
13469+ pm_static_literals_t hash_keys = { 0 };
13470+ pm_hash_key_static_literals_add(parser, &hash_keys , argument);
1346513471
1346613472 // Finish parsing the one we are part way through.
1346713473 pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_VALUE);
@@ -13475,10 +13481,10 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
1347513481 token_begins_expression_p(parser->current.type) ||
1347613482 match2(parser, PM_TOKEN_USTAR_STAR, PM_TOKEN_LABEL)
1347713483 )) {
13478- contains_keyword_splat = parse_assocs(parser, &literals , (pm_node_t *) bare_hash);
13484+ contains_keyword_splat = parse_assocs(parser, &hash_keys , (pm_node_t *) bare_hash);
1347913485 }
1348013486
13481- pm_static_literals_free(&literals );
13487+ pm_static_literals_free(&hash_keys );
1348213488 parsed_bare_hash = true;
1348313489 } else if (accept1(parser, PM_TOKEN_KEYWORD_IN)) {
1348413490 // TODO: Could we solve this with binding powers instead?
@@ -16724,13 +16730,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1672416730 }
1672516731
1672616732 element = (pm_node_t *) pm_keyword_hash_node_create(parser);
16727- pm_static_literals_t literals = { 0 };
16733+ pm_static_literals_t hash_keys = { 0 };
1672816734
1672916735 if (!match8(parser, PM_TOKEN_EOF, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_TOKEN_EOF, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_KEYWORD_DO, PM_TOKEN_PARENTHESIS_RIGHT)) {
16730- parse_assocs(parser, &literals , element);
16736+ parse_assocs(parser, &hash_keys , element);
1673116737 }
1673216738
16733- pm_static_literals_free(&literals );
16739+ pm_static_literals_free(&hash_keys );
1673416740 parsed_bare_hash = true;
1673516741 } else {
1673616742 element = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_ARRAY_EXPRESSION);
@@ -16741,8 +16747,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1674116747 }
1674216748
1674316749 pm_keyword_hash_node_t *hash = pm_keyword_hash_node_create(parser);
16744- pm_static_literals_t literals = { 0 };
16745- pm_hash_key_static_literals_add(parser, &literals , element);
16750+ pm_static_literals_t hash_keys = { 0 };
16751+ pm_hash_key_static_literals_add(parser, &hash_keys , element);
1674616752
1674716753 pm_token_t operator;
1674816754 if (parser->previous.type == PM_TOKEN_EQUAL_GREATER) {
@@ -16757,10 +16763,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1675716763
1675816764 element = (pm_node_t *) hash;
1675916765 if (accept1(parser, PM_TOKEN_COMMA) && !match1(parser, PM_TOKEN_BRACKET_RIGHT)) {
16760- parse_assocs(parser, &literals , element);
16766+ parse_assocs(parser, &hash_keys , element);
1676116767 }
1676216768
16763- pm_static_literals_free(&literals );
16769+ pm_static_literals_free(&hash_keys );
1676416770 parsed_bare_hash = true;
1676516771 }
1676616772 }
@@ -16920,22 +16926,37 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1692016926 return (pm_node_t *) pm_parentheses_node_create(parser, &opening, (pm_node_t *) statements, &parser->previous);
1692116927 }
1692216928 case PM_TOKEN_BRACE_LEFT: {
16929+ // If we were passed a current_hash_keys via the parser, then that
16930+ // means we're already parsing a hash and we want to share the set
16931+ // of hash keys with this inner hash we're about to parse for the
16932+ // sake of warnings. We'll set it to NULL after we grab it to make
16933+ // sure subsequent expressions don't use it. Effectively this is a
16934+ // way of getting around passing it to every call to
16935+ // parse_expression.
16936+ pm_static_literals_t *current_hash_keys = parser->current_hash_keys;
16937+ parser->current_hash_keys = NULL;
16938+
1692316939 pm_accepts_block_stack_push(parser, true);
1692416940 parser_lex(parser);
1692516941
1692616942 pm_hash_node_t *node = pm_hash_node_create(parser, &parser->previous);
16927- pm_static_literals_t literals = { 0 };
1692816943
1692916944 if (!match2(parser, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_EOF)) {
16930- parse_assocs(parser, &literals, (pm_node_t *) node);
16945+ if (current_hash_keys != NULL) {
16946+ parse_assocs(parser, current_hash_keys, (pm_node_t *) node);
16947+ } else {
16948+ pm_static_literals_t hash_keys = { 0 };
16949+ parse_assocs(parser, &hash_keys, (pm_node_t *) node);
16950+ pm_static_literals_free(&hash_keys);
16951+ }
16952+
1693116953 accept1(parser, PM_TOKEN_NEWLINE);
1693216954 }
1693316955
1693416956 pm_accepts_block_stack_pop(parser);
1693516957 expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_HASH_TERM);
1693616958 pm_hash_node_closing_loc_set(node, &parser->previous);
1693716959
16938- pm_static_literals_free(&literals);
1693916960 return (pm_node_t *) node;
1694016961 }
1694116962 case PM_TOKEN_CHARACTER_LITERAL: {
0 commit comments