Repository: ruby/prism
Pull request #2276 (2024-01-25 19:35:14)

Mark forwarding parameters in the lexical scope
@kddnewton I need some help to push this over the line 🙇 


Patch:
diff --git a/include/prism/parser.h b/include/prism/parser.h
index c7ebb64b..8c7401f6 100644
--- a/include/prism/parser.h
+++ b/include/prism/parser.h
@@ -466,6 +466,19 @@ typedef struct pm_scope {
      */
     bool explicit_params;
 
+    /**
+     * Booleans indicating whether the parameters for this scope have declared
+     * forwarding parameters.
+     *
+     * For example, some combinations of:
+     *   def foo(*); end
+     *   def foo(**); end
+     *   def foo(&); end
+     *   def foo(...); end
+     */
+
+    uint8_t forwarding_params;
+
     /**
      * An integer indicating the number of numbered parameters on this scope.
      * This is necessary to determine if child blocks are allowed to use
@@ -475,6 +488,11 @@ typedef struct pm_scope {
     uint8_t numbered_parameters;
 } pm_scope_t;
 
+static const uint8_t PM_FORWARDING_POSITIONALS = 0x1;
+static const uint8_t PM_FORWARDING_KEYWORDS = 0x2;
+static const uint8_t PM_FORWARDING_BLOCK = 0x4;
+static const uint8_t PM_FORWARDING_ALL = 0x8;
+
 /**
  * This struct represents the overall parser. It contains a reference to the
  * source file, as well as pointers that indicate where in the source it's
diff --git a/lib/prism/debug.rb b/lib/prism/debug.rb
index f4c0bcf9..d8daf36f 100644
--- a/lib/prism/debug.rb
+++ b/lib/prism/debug.rb
@@ -129,7 +129,7 @@ module Prism
             if params.keyword_rest.is_a?(ForwardingParameterNode)
               sorted.push(:*, :**, :&, :"...")
             elsif params.keyword_rest.is_a?(KeywordRestParameterNode)
-              sorted << params.keyword_rest.name if params.keyword_rest.name
+              sorted << (params.keyword_rest.name || :**)
             end
 
             # Recurse down the parameter tree to find any destructured
@@ -148,7 +148,9 @@ module Prism
               end
             end
 
-            sorted << params.block.name if params.block&.name
+            if params.block
+              sorted << (params.block.name || :&)
+            end
 
             names = sorted.concat(names - sorted)
           end
diff --git a/src/prism.c b/src/prism.c
index 4d2602cd..d0f52cff 100644
--- a/src/prism.c
+++ b/src/prism.c
@@ -5979,6 +5979,7 @@ pm_parser_scope_push(pm_parser_t *parser, bool closed) {
         .closed = closed,
         .explicit_params = false,
         .numbered_parameters = 0,
+        .forwarding_params = 0,
     };
 
     pm_constant_id_list_init(&scope->locals);
@@ -5987,6 +5988,49 @@ pm_parser_scope_push(pm_parser_t *parser, bool closed) {
     return true;
 }
 
+static void
+pm_parser_scope_forwarding_param_check(pm_parser_t *parser, const pm_token_t * token, const uint8_t mask, pm_diagnostic_id_t diag)
+{
+    pm_scope_t *scope = parser->current_scope;
+    while (scope) {
+        if (scope->forwarding_params & mask) {
+            if (!scope->closed) {
+                pm_parser_err_token(parser, token, diag);
+                return;
+            }
+            return;
+        }
+        if (scope->closed) break;
+        scope = scope->previous;
+    }
+
+    pm_parser_err_token(parser, token, diag);
+}
+
+static inline void
+pm_parser_scope_forwarding_block_check(pm_parser_t *parser, const pm_token_t * token)
+{
+    pm_parser_scope_forwarding_param_check(parser, token, PM_FORWARDING_BLOCK, PM_ERR_ARGUMENT_NO_FORWARDING_AMP);
+}
+
+static void
+pm_parser_scope_forwarding_positionals_check(pm_parser_t *parser, const pm_token_t * token)
+{
+    pm_parser_scope_forwarding_param_check(parser, token, PM_FORWARDING_POSITIONALS, PM_ERR_ARGUMENT_NO_FORWARDING_STAR);
+}
+
+static inline void
+pm_parser_scope_forwarding_all_check(pm_parser_t *parser, const pm_token_t * token)
+{
+    pm_parser_scope_forwarding_param_check(parser, token, PM_FORWARDING_ALL, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES);
+}
+
+static inline void
+pm_parser_scope_forwarding_keywords_check(pm_parser_t *parser, const pm_token_t * token)
+{
+    pm_parser_scope_forwarding_param_check(parser, token, PM_FORWARDING_KEYWORDS, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
+}
+
 /**
  * Save the current param name as the return value and set it to the given
  * constant id.
@@ -11238,8 +11282,9 @@ parse_assocs(pm_parser_t *parser, pm_node_t *node) {
 
                 if (token_begins_expression_p(parser->current.type)) {
                     value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
-                } else if (pm_parser_local_depth(parser, &operator) == -1) {
-                    pm_parser_err_token(parser, &operator, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
+                }
+                else {
+                    pm_parser_scope_forwarding_keywords_check(parser, &operator);
                 }
 
                 element = (pm_node_t *) pm_assoc_splat_node_create(parser, value, &operator);
@@ -11388,13 +11433,8 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
                 if (token_begins_expression_p(parser->current.type)) {
                     expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_ARGUMENT);
                 } else {
-                    if (pm_parser_local_depth(parser, &operator) == -1) {
-                        // A block forwarding in a method having `...` parameter (e.g. `def foo(...); bar(&); end`) is available.
-                        pm_constant_id_t ellipsis_id = pm_parser_constant_id_constant(parser, "...", 3);
-                        if (pm_parser_local_depth_constant_id(parser, ellipsis_id) == -1) {
-                            pm_parser_err_token(parser, &operator, PM_ERR_ARGUMENT_NO_FORWARDING_AMP);
-                        }
-                    }
+                    // A block forwarding in a method having `...` parameter (e.g. `def foo(...); bar(&); end`) is available.
+                    pm_parser_scope_forwarding_block_check(parser, &operator);
                 }
 
                 argument = (pm_node_t *) pm_block_argument_node_create(parser, &operator, expression);
@@ -11412,10 +11452,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
                 pm_token_t operator = parser->previous;
 
                 if (match4(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_COMMA, PM_TOKEN_SEMICOLON, PM_TOKEN_BRACKET_RIGHT)) {
-                    if (pm_parser_local_depth(parser, &parser->previous) == -1) {
-                        pm_parser_err_token(parser, &operator, PM_ERR_ARGUMENT_NO_FORWARDING_STAR);
-                    }
-
+                    pm_parser_scope_forwarding_positionals_check(parser, &operator);
                     argument = (pm_node_t *) pm_splat_node_create(parser, &operator, NULL);
                 } else {
                     pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT);
@@ -11441,9 +11478,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
                         pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_RANGE, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
                         argument = (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right);
                     } else {
-                        if (pm_parser_local_depth(parser, &parser->previous) == -1) {
-                            pm_parser_err_previous(parser, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES);
-                        }
+                        pm_parser_scope_forwarding_all_check(parser, &parser->previous);
                         if (parsed_first_argument && terminator == PM_TOKEN_EOF) {
                             pm_parser_err_previous(parser, PM_ERR_ARGUMENT_FORWARDING_UNBOUND);
                         }
@@ -11710,10 +11745,7 @@ parse_parameters(
                     pm_parser_local_add_token(parser, &name);
                 } else {
                     name = not_provided(parser);
-
-                    if (allows_forwarding_parameters) {
-                        pm_parser_local_add_token(parser, &operator);
-                    }
+                    parser->current_scope->forwarding_params |= PM_FORWARDING_BLOCK;
                 }
 
                 pm_block_parameter_node_t *param = pm_block_parameter_node_create(parser, &name, &operator);
@@ -11738,9 +11770,8 @@ parse_parameters(
                     update_parameter_state(parser, &parser->current, &order);
                     parser_lex(parser);
 
-                    if (allows_forwarding_parameters) {
-                        pm_parser_local_add_token(parser, &parser->previous);
-                    }
+                    parser->current_scope->forwarding_params |= PM_FORWARDING_BLOCK;
+                    parser->current_scope->forwarding_params |= PM_FORWARDING_ALL;
 
                     pm_forwarding_parameter_node_t *param = pm_forwarding_parameter_node_create(parser, &parser->previous);
                     if (params->keyword_rest != NULL) {
@@ -11922,9 +11953,7 @@ parse_parameters(
                 } else {
                     name = not_provided(parser);
 
-                    if (allows_forwarding_parameters) {
-                        pm_parser_local_add_token(parser, &operator);
-                    }
+                    parser->current_scope->forwarding_params |= PM_FORWARDING_POSITIONALS;
                 }
 
                 pm_node_t *param = (pm_node_t *) pm_rest_parameter_node_create(parser, &operator, &name);
@@ -11961,9 +11990,7 @@ parse_parameters(
                     } else {
                         name = not_provided(parser);
 
-                        if (allows_forwarding_parameters) {
-                            pm_parser_local_add_token(parser, &operator);
-                        }
+                        parser->current_scope->forwarding_params |= PM_FORWARDING_KEYWORDS;
                     }
 
                     param = (pm_node_t *) pm_keyword_rest_parameter_node_create(parser, &operator, &name);
@@ -14146,9 +14173,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
                     pm_node_t *expression = NULL;
 
                     if (match3(parser, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_COMMA, PM_TOKEN_EOF)) {
-                        if (pm_parser_local_depth(parser, &parser->previous) == -1) {
-                            pm_parser_err_token(parser, &operator, PM_ERR_ARGUMENT_NO_FORWARDING_STAR);
-                        }
+                        pm_parser_scope_forwarding_positionals_check(parser, &operator);
                     } else {
                         expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_ARRAY_EXPRESSION_AFTER_STAR);
                     }


Test patch:
diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb
index 60322585..45618ab0 100644
--- a/test/prism/errors_test.rb
+++ b/test/prism/errors_test.rb
@@ -751,8 +751,8 @@ module Prism
         nil,
         ParametersNode([], [], nil, [RequiredParameterNode(0, :a)], [], nil, BlockParameterNode(0, nil, nil, Location())),
         nil,
-        [:&, :a],
-        2,
+        [:a],
+        1,
         Location(),
         nil,
         Location(),
@@ -781,8 +781,8 @@ module Prism
           nil
         ),
         nil,
-        [:"...", :a],
-        2,
+        [:a],
+        1,
         Location(),
         nil,
         Location(),
@@ -861,8 +861,8 @@ module Prism
         nil,
         ParametersNode([], [], nil, [], [], ForwardingParameterNode(), nil),
         nil,
-        [:"..."],
-        1,
+        [],
+        0,
         Location(),
         nil,
         Location(),
diff --git a/test/prism/snapshots/arrays.txt b/test/prism/snapshots/arrays.txt
index c1b29134..cdba0451 100644
--- a/test/prism/snapshots/arrays.txt
+++ b/test/prism/snapshots/arrays.txt
@@ -1066,8 +1066,8 @@
         │   │               @ BlockArgumentNode (location: (89,6)-(89,7))
         │   │               ├── expression: ∅
         │   │               └── operator_loc: (89,6)-(89,7) = "&"
-        │   ├── locals: [:&]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (88,0)-(88,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (88,7)-(88,8) = "("
@@ -1847,8 +1847,8 @@
         │   │           │           └── expression: ∅
         │   │           ├── closing_loc: (128,13)-(128,14) = "]"
         │   │           └── block: ∅
-        │   ├── locals: [:*]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (128,0)-(128,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (128,5)-(128,6) = "("
@@ -1904,8 +1904,8 @@
         │   │           │           └── expression: ∅
         │   │           ├── closing_loc: (130,16)-(130,17) = "]"
         │   │           └── block: ∅
-        │   ├── locals: [:*]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (130,0)-(130,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (130,5)-(130,6) = "("
@@ -1961,8 +1961,8 @@
         │   │           │           └── flags: decimal
         │   │           ├── closing_loc: (132,13)-(132,14) = "]"
         │   │           └── block: ∅
-        │   ├── locals: [:*]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (132,0)-(132,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (132,5)-(132,6) = "("
@@ -2020,8 +2020,8 @@
         │   │           │           └── flags: decimal
         │   │           ├── closing_loc: (134,16)-(134,17) = "]"
         │   │           └── block: ∅
-        │   ├── locals: [:*]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (134,0)-(134,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (134,5)-(134,6) = "("
@@ -2078,8 +2078,8 @@
         │   │           └── value:
         │   │               @ IntegerNode (location: (136,18)-(136,19))
         │   │               └── flags: decimal
-        │   ├── locals: [:*]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (136,0)-(136,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (136,5)-(136,6) = "("
@@ -2137,8 +2137,8 @@
         │   │           └── value:
         │   │               @ IntegerNode (location: (138,22)-(138,23))
         │   │               └── flags: decimal
-        │   ├── locals: [:*]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (138,0)-(138,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (138,5)-(138,6) = "("
@@ -2201,8 +2201,8 @@
         │   │   ├── else_clause: ∅
         │   │   ├── ensure_clause: ∅
         │   │   └── end_keyword_loc: (140,26)-(140,29) = "end"
-        │   ├── locals: [:*]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (140,0)-(140,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (140,5)-(140,6) = "("
@@ -2267,8 +2267,8 @@
             │   ├── else_clause: ∅
             │   ├── ensure_clause: ∅
             │   └── end_keyword_loc: (142,29)-(142,32) = "end"
-            ├── locals: [:*]
-            ├── locals_body_index: 1
+            ├── locals: []
+            ├── locals_body_index: 0
             ├── def_keyword_loc: (142,0)-(142,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (142,5)-(142,6) = "("
diff --git a/test/prism/snapshots/method_calls.txt b/test/prism/snapshots/method_calls.txt
index ff6e0dd7..a7a4bfcd 100644
--- a/test/prism/snapshots/method_calls.txt
+++ b/test/prism/snapshots/method_calls.txt
@@ -2341,8 +2341,8 @@
         │   │           │           └── expression: ∅
         │   │           ├── closing_loc: ∅
         │   │           └── block: ∅
-        │   ├── locals: [:*]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (149,0)-(149,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (149,5)-(149,6) = "("
diff --git a/test/prism/snapshots/methods.txt b/test/prism/snapshots/methods.txt
index 9e0e0548..11e8055a 100644
--- a/test/prism/snapshots/methods.txt
+++ b/test/prism/snapshots/methods.txt
@@ -202,8 +202,8 @@
         │   │   │   @ ForwardingParameterNode (location: (19,6)-(19,9))
         │   │   └── block: ∅
         │   ├── body: ∅
-        │   ├── locals: [:"..."]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (19,0)-(19,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (19,5)-(19,6) = "("
@@ -370,8 +370,8 @@
         │   │   │   └── operator_loc: (41,6)-(41,8) = "**"
         │   │   └── block: ∅
         │   ├── body: ∅
-        │   ├── locals: [:**]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (41,0)-(41,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (41,5)-(41,6) = "("
@@ -743,8 +743,8 @@
         │   │   ├── keyword_rest: ∅
         │   │   └── block: ∅
         │   ├── body: ∅
-        │   ├── locals: [:*]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (82,0)-(82,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (82,5)-(82,6) = "("
@@ -983,8 +983,8 @@
         │   │           │           └── expression: ∅
         │   │           ├── closing_loc: (110,13)-(110,14) = ")"
         │   │           └── block: ∅
-        │   ├── locals: [:*]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (110,0)-(110,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (110,5)-(110,6) = "("
@@ -1022,8 +1022,8 @@
         │   │           │       └── @ ForwardingArgumentsNode (location: (112,14)-(112,17))
         │   │           ├── closing_loc: (112,17)-(112,18) = ")"
         │   │           └── block: ∅
-        │   ├── locals: [:"..."]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (112,0)-(112,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (112,5)-(112,6) = "("
@@ -1065,8 +1065,8 @@
         │   │           │       └── @ ForwardingArgumentsNode (location: (114,20)-(114,23))
         │   │           ├── closing_loc: (114,23)-(114,24) = ")"
         │   │           └── block: ∅
-        │   ├── locals: [:"..."]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (114,0)-(114,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (114,5)-(114,6) = "("
@@ -1153,8 +1153,8 @@
         │   │       ├── name_loc: ∅
         │   │       └── operator_loc: (122,6)-(122,7) = "&"
         │   ├── body: ∅
-        │   ├── locals: [:&]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (122,0)-(122,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (122,5)-(122,6) = "("
@@ -1296,8 +1296,8 @@
         │   │           │       │           └── block: ∅
         │   │           │       └── closing_loc: (136,24)-(136,25) = "}"
         │   │           └── closing_loc: (136,25)-(136,26) = "\""
-        │   ├── locals: [:"..."]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (136,0)-(136,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (136,5)-(136,6) = "("
@@ -1747,8 +1747,8 @@
         │   │           │       └── expression: ∅
         │   │           ├── opening_loc: (167,10)-(167,11) = "["
         │   │           └── closing_loc: (167,12)-(167,13) = "]"
-        │   ├── locals: [:*]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (167,0)-(167,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (167,5)-(167,6) = "("
@@ -1959,8 +1959,8 @@
         │   │               @ BlockArgumentNode (location: (178,6)-(178,7))
         │   │               ├── expression: ∅
         │   │               └── operator_loc: (178,6)-(178,7) = "&"
-        │   ├── locals: [:"..."]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (177,0)-(177,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (177,7)-(177,8) = "("
diff --git a/test/prism/snapshots/seattlerb/block_arg__bare.txt b/test/prism/snapshots/seattlerb/block_arg__bare.txt
index f3b6d3c1..9bf5016a 100644
--- a/test/prism/snapshots/seattlerb/block_arg__bare.txt
+++ b/test/prism/snapshots/seattlerb/block_arg__bare.txt
@@ -22,8 +22,8 @@
             │       ├── name_loc: ∅
             │       └── operator_loc: (1,6)-(1,7) = "&"
             ├── body: ∅
-            ├── locals: [:&]
-            ├── locals_body_index: 1
+            ├── locals: []
+            ├── locals_body_index: 0
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt b/test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt
index ecc7ad04..fc726fe4 100644
--- a/test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt
+++ b/test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt
@@ -28,8 +28,8 @@
             │   ├── keyword_rest: ∅
             │   └── block: ∅
             ├── body: ∅
-            ├── locals: [:interp, :*, :args]
-            ├── locals_body_index: 3
+            ├── locals: [:interp, :args]
+            ├── locals_body_index: 2
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,8)-(1,9) = "("
diff --git a/test/prism/snapshots/seattlerb/defn_arg_forward_args.txt b/test/prism/snapshots/seattlerb/defn_arg_forward_args.txt
index 46c0e91a..2068a801 100644
--- a/test/prism/snapshots/seattlerb/defn_arg_forward_args.txt
+++ b/test/prism/snapshots/seattlerb/defn_arg_forward_args.txt
@@ -40,8 +40,8 @@
             │           │       └── @ ForwardingArgumentsNode (location: (1,20)-(1,23))
             │           ├── closing_loc: (1,23)-(1,24) = ")"
             │           └── block: ∅
-            ├── locals: [:x, :"..."]
-            ├── locals_body_index: 2
+            ├── locals: [:x]
+            ├── locals_body_index: 1
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/seattlerb/defn_args_forward_args.txt b/test/prism/snapshots/seattlerb/defn_args_forward_args.txt
index 76d0fbe7..861fb297 100644
--- a/test/prism/snapshots/seattlerb/defn_args_forward_args.txt
+++ b/test/prism/snapshots/seattlerb/defn_args_forward_args.txt
@@ -52,8 +52,8 @@
             │           │       └── @ ForwardingArgumentsNode (location: (1,32)-(1,35))
             │           ├── closing_loc: (1,35)-(1,36) = ")"
             │           └── block: ∅
-            ├── locals: [:x, :y, :z, :"..."]
-            ├── locals_body_index: 4
+            ├── locals: [:x, :y, :z]
+            ├── locals_body_index: 3
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/seattlerb/defn_forward_args.txt b/test/prism/snapshots/seattlerb/defn_forward_args.txt
index 4782e055..e13c469f 100644
--- a/test/prism/snapshots/seattlerb/defn_forward_args.txt
+++ b/test/prism/snapshots/seattlerb/defn_forward_args.txt
@@ -34,8 +34,8 @@
             │           │       └── @ ForwardingArgumentsNode (location: (1,14)-(1,17))
             │           ├── closing_loc: (1,17)-(1,18) = ")"
             │           └── block: ∅
-            ├── locals: [:"..."]
-            ├── locals_body_index: 1
+            ├── locals: []
+            ├── locals_body_index: 0
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/seattlerb/defn_forward_args__no_parens.txt b/test/prism/snapshots/seattlerb/defn_forward_args__no_parens.txt
index c357b76b..8b62141c 100644
--- a/test/prism/snapshots/seattlerb/defn_forward_args__no_parens.txt
+++ b/test/prism/snapshots/seattlerb/defn_forward_args__no_parens.txt
@@ -34,8 +34,8 @@
             │           │       └── @ ForwardingArgumentsNode (location: (2,4)-(2,7))
             │           ├── closing_loc: (2,7)-(2,8) = ")"
             │           └── block: ∅
-            ├── locals: [:"..."]
-            ├── locals_body_index: 1
+            ├── locals: []
+            ├── locals_body_index: 0
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: ∅
diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt b/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt
index 897a36bc..d1cab9b2 100644
--- a/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt
+++ b/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt
@@ -29,8 +29,8 @@
             │   │   └── operator_loc: (1,12)-(1,14) = "**"
             │   └── block: ∅
             ├── body: ∅
-            ├── locals: [:b, :**]
-            ├── locals_body_index: 2
+            ├── locals: [:b]
+            ├── locals_body_index: 1
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/seattlerb/defn_splat_arg.txt b/test/prism/snapshots/seattlerb/defn_splat_arg.txt
index 6533258f..a187ae49 100644
--- a/test/prism/snapshots/seattlerb/defn_splat_arg.txt
+++ b/test/prism/snapshots/seattlerb/defn_splat_arg.txt
@@ -25,8 +25,8 @@
             │   ├── keyword_rest: ∅
             │   └── block: ∅
             ├── body: ∅
-            ├── locals: [:*, :a]
-            ├── locals_body_index: 2
+            ├── locals: [:a]
+            ├── locals_body_index: 1
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/unparser/corpus/literal/def.txt b/test/prism/snapshots/unparser/corpus/literal/def.txt
index d1face88..b6d88a4e 100644
--- a/test/prism/snapshots/unparser/corpus/literal/def.txt
+++ b/test/prism/snapshots/unparser/corpus/literal/def.txt
@@ -774,8 +774,8 @@
         │   │           ├── arguments: ∅
         │   │           ├── closing_loc: ∅
         │   │           └── block: ∅
-        │   ├── locals: [:*]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (83,0)-(83,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (83,7)-(83,8) = "("
diff --git a/test/prism/snapshots/unparser/corpus/literal/since/31.txt b/test/prism/snapshots/unparser/corpus/literal/since/31.txt
index 7927a8e4..09e94d6b 100644
--- a/test/prism/snapshots/unparser/corpus/literal/since/31.txt
+++ b/test/prism/snapshots/unparser/corpus/literal/since/31.txt
@@ -37,8 +37,8 @@
         │   │               @ BlockArgumentNode (location: (2,6)-(2,7))
         │   │               ├── expression: ∅
         │   │               └── operator_loc: (2,6)-(2,7) = "&"
-        │   ├── locals: [:&]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (1,0)-(1,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (1,7)-(1,8) = "("
@@ -82,8 +82,8 @@
             │               @ BlockArgumentNode (location: (6,6)-(6,7))
             │               ├── expression: ∅
             │               └── operator_loc: (6,6)-(6,7) = "&"
-            ├── locals: [:a, :&]
-            ├── locals_body_index: 2
+            ├── locals: [:a]
+            ├── locals_body_index: 1
             ├── def_keyword_loc: (5,0)-(5,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (5,7)-(5,8) = "("
diff --git a/test/prism/snapshots/unparser/corpus/literal/since/32.txt b/test/prism/snapshots/unparser/corpus/literal/since/32.txt
index a2026285..9b7fa85f 100644
--- a/test/prism/snapshots/unparser/corpus/literal/since/32.txt
+++ b/test/prism/snapshots/unparser/corpus/literal/since/32.txt
@@ -49,8 +49,8 @@
         │   │           │                   └── operator_loc: (2,16)-(2,18) = "**"
         │   │           ├── closing_loc: (2,18)-(2,19) = ")"
         │   │           └── block: ∅
-        │   ├── locals: [:argument, :**]
-        │   ├── locals_body_index: 2
+        │   ├── locals: [:argument]
+        │   ├── locals_body_index: 1
         │   ├── def_keyword_loc: (1,0)-(1,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (1,7)-(1,8) = "("
@@ -100,8 +100,8 @@
             │           │           └── expression: ∅
             │           ├── closing_loc: (6,17)-(6,18) = ")"
             │           └── block: ∅
-            ├── locals: [:argument, :*]
-            ├── locals_body_index: 2
+            ├── locals: [:argument]
+            ├── locals_body_index: 1
             ├── def_keyword_loc: (5,0)-(5,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (5,7)-(5,8) = "("
diff --git a/test/prism/snapshots/whitequark/anonymous_blockarg.txt b/test/prism/snapshots/whitequark/anonymous_blockarg.txt
index aaeef280..da760b78 100644
--- a/test/prism/snapshots/whitequark/anonymous_blockarg.txt
+++ b/test/prism/snapshots/whitequark/anonymous_blockarg.txt
@@ -37,8 +37,8 @@
             │               @ BlockArgumentNode (location: (1,16)-(1,17))
             │               ├── expression: ∅
             │               └── operator_loc: (1,16)-(1,17) = "&"
-            ├── locals: [:&]
-            ├── locals_body_index: 1
+            ├── locals: []
+            ├── locals_body_index: 0
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/prism/snapshots/whitequark/args.txt b/test/prism/snapshots/whitequark/args.txt
index 927ee3c1..53bd2ebb 100644
--- a/test/prism/snapshots/whitequark/args.txt
+++ b/test/prism/snapshots/whitequark/args.txt
@@ -521,8 +521,8 @@
         │   │   │   └── operator_loc: (29,9)-(29,11) = "**"
         │   │   └── block: ∅
         │   ├── body: ∅
-        │   ├── locals: [:*, :**]
-        │   ├── locals_body_index: 2
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (29,0)-(29,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: ∅
diff --git a/test/prism/snapshots/whitequark/endless_method_forwarded_args_legacy.txt b/test/prism/snapshots/whitequark/endless_method_forwarded_args_legacy.txt
index 366258cf..039b014a 100644
--- a/test/prism/snapshots/whitequark/endless_method_forwarded_args_legacy.txt
+++ b/test/prism/snapshots/whitequark/endless_method_forwarded_args_legacy.txt
@@ -34,8 +34,8 @@
             │           │       └── @ ForwardingArgumentsNode (location: (1,19)-(1,22))
             │           ├── closing_loc: (1,22)-(1,23) = ")"
             │           └── block: ∅
-            ├── locals: [:"..."]
-            ├── locals_body_index: 1
+            ├── locals: []
+            ├── locals_body_index: 0
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/prism/snapshots/whitequark/forward_arg.txt b/test/prism/snapshots/whitequark/forward_arg.txt
index c81fc7a1..0ec87510 100644
--- a/test/prism/snapshots/whitequark/forward_arg.txt
+++ b/test/prism/snapshots/whitequark/forward_arg.txt
@@ -34,8 +34,8 @@
             │           │       └── @ ForwardingArgumentsNode (location: (1,18)-(1,21))
             │           ├── closing_loc: (1,21)-(1,22) = ")"
             │           └── block: ∅
-            ├── locals: [:"..."]
-            ├── locals_body_index: 1
+            ├── locals: []
+            ├── locals_body_index: 0
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt b/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt
index 75fb87e0..a85400a3 100644
--- a/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt
+++ b/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt
@@ -38,8 +38,8 @@
         │   │           │           │       └── @ ForwardingArgumentsNode (location: (2,6)-(2,9))
         │   │           │           ├── closing_loc: (2,9)-(2,10) = ")"
         │   │           │           └── block: ∅
-        │   │           ├── locals: [:"..."]
-        │   │           ├── locals_body_index: 1
+        │   │           ├── locals: []
+        │   │           ├── locals_body_index: 0
         │   │           ├── def_keyword_loc: (1,1)-(1,4) = "def"
         │   │           ├── operator_loc: ∅
         │   │           ├── lparen_loc: ∅
@@ -83,8 +83,8 @@
         │   │           │           │       └── @ ForwardingArgumentsNode (location: (5,18)-(5,21))
         │   │           │           ├── closing_loc: (5,21)-(5,22) = ")"
         │   │           │           └── block: ∅
-        │   │           ├── locals: [:"..."]
-        │   │           ├── locals_body_index: 1
+        │   │           ├── locals: []
+        │   │           ├── locals_body_index: 0
         │   │           ├── def_keyword_loc: (5,1)-(5,4) = "def"
         │   │           ├── operator_loc: ∅
         │   │           ├── lparen_loc: ∅
@@ -108,8 +108,8 @@
         │   │   │   @ ForwardingParameterNode (location: (7,8)-(7,11))
         │   │   └── block: ∅
         │   ├── body: ∅
-        │   ├── locals: [:"..."]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (7,0)-(7,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: ∅
@@ -147,8 +147,8 @@
         │   │           │       └── @ ForwardingArgumentsNode (location: (10,17)-(10,20))
         │   │           ├── closing_loc: (10,20)-(10,21) = ")"
         │   │           └── block: ∅
-        │   ├── locals: [:"..."]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (10,0)-(10,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: ∅
@@ -189,8 +189,8 @@
         │   │           │       └── @ ForwardingArgumentsNode (location: (13,6)-(13,9))
         │   │           ├── closing_loc: (13,9)-(13,10) = ")"
         │   │           └── block: ∅
-        │   ├── locals: [:a, :"..."]
-        │   ├── locals_body_index: 2
+        │   ├── locals: [:a]
+        │   ├── locals_body_index: 1
         │   ├── def_keyword_loc: (12,0)-(12,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: ∅
@@ -231,8 +231,8 @@
         │   │           │       └── @ ForwardingArgumentsNode (location: (16,20)-(16,23))
         │   │           ├── closing_loc: (16,23)-(16,24) = ")"
         │   │           └── block: ∅
-        │   ├── locals: [:a, :"..."]
-        │   ├── locals_body_index: 2
+        │   ├── locals: [:a]
+        │   ├── locals_body_index: 1
         │   ├── def_keyword_loc: (16,0)-(16,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: ∅
@@ -265,8 +265,8 @@
         │   │   │   @ ForwardingParameterNode (location: (18,18)-(18,21))
         │   │   └── block: ∅
         │   ├── body: ∅
-        │   ├── locals: [:a, :b, :"..."]
-        │   ├── locals_body_index: 3
+        │   ├── locals: [:a, :b]
+        │   ├── locals_body_index: 2
         │   ├── def_keyword_loc: (18,0)-(18,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: ∅
@@ -312,8 +312,8 @@
         │   │           │       └── @ ForwardingArgumentsNode (location: (22,6)-(22,9))
         │   │           ├── closing_loc: (22,9)-(22,10) = ")"
         │   │           └── block: ∅
-        │   ├── locals: [:b, :"..."]
-        │   ├── locals_body_index: 2
+        │   ├── locals: [:b]
+        │   ├── locals_body_index: 1
         │   ├── def_keyword_loc: (21,0)-(21,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: ∅
@@ -359,8 +359,8 @@
         │   │           │       └── @ ForwardingArgumentsNode (location: (25,24)-(25,27))
         │   │           ├── closing_loc: (25,27)-(25,28) = ")"
         │   │           └── block: ∅
-        │   ├── locals: [:b, :"..."]
-        │   ├── locals_body_index: 2
+        │   ├── locals: [:b]
+        │   ├── locals_body_index: 1
         │   ├── def_keyword_loc: (25,0)-(25,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: ∅
@@ -401,8 +401,8 @@
             │           │       └── @ ForwardingArgumentsNode (location: (27,20)-(27,23))
             │           ├── closing_loc: (27,23)-(27,24) = ")"
             │           └── block: ∅
-            ├── locals: [:a, :"..."]
-            ├── locals_body_index: 2
+            ├── locals: [:a]
+            ├── locals_body_index: 1
             ├── def_keyword_loc: (27,0)-(27,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (27,7)-(27,8) = "("
diff --git a/test/prism/snapshots/whitequark/forward_args_legacy.txt b/test/prism/snapshots/whitequark/forward_args_legacy.txt
index 6175e658..d2774737 100644
--- a/test/prism/snapshots/whitequark/forward_args_legacy.txt
+++ b/test/prism/snapshots/whitequark/forward_args_legacy.txt
@@ -34,8 +34,8 @@
         │   │           │       └── @ ForwardingArgumentsNode (location: (1,18)-(1,21))
         │   │           ├── closing_loc: (1,21)-(1,22) = ")"
         │   │           └── block: ∅
-        │   ├── locals: [:"..."]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (1,0)-(1,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (1,7)-(1,8) = "("
@@ -57,8 +57,8 @@
         │   │   │   @ ForwardingParameterNode (location: (3,8)-(3,11))
         │   │   └── block: ∅
         │   ├── body: ∅
-        │   ├── locals: [:"..."]
-        │   ├── locals_body_index: 1
+        │   ├── locals: []
+        │   ├── locals_body_index: 0
         │   ├── def_keyword_loc: (3,0)-(3,3) = "def"
         │   ├── operator_loc: ∅
         │   ├── lparen_loc: (3,7)-(3,8) = "("
@@ -92,8 +92,8 @@
             │           │       └── @ ForwardingArgumentsNode (location: (5,20)-(5,23))
             │           ├── rparen_loc: (5,23)-(5,24) = ")"
             │           └── block: ∅
-            ├── locals: [:"..."]
-            ├── locals_body_index: 1
+            ├── locals: []
+            ├── locals_body_index: 0
             ├── def_keyword_loc: (5,0)-(5,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (5,7)-(5,8) = "("
diff --git a/test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt b/test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt
index ff7a0945..d7a1d53d 100644
--- a/test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt
+++ b/test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt
@@ -49,8 +49,8 @@
             │           │                   └── operator_loc: (1,37)-(1,39) = "**"
             │           ├── closing_loc: (1,39)-(1,40) = ")"
             │           └── block: ∅
-            ├── locals: [:argument, :**]
-            ├── locals_body_index: 2
+            ├── locals: [:argument]
+            ├── locals_body_index: 1
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt b/test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt
index 249a6260..df93c463 100644
--- a/test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt
+++ b/test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt
@@ -46,8 +46,8 @@
             │           │           └── expression: ∅
             │           ├── closing_loc: (1,37)-(1,38) = ")"
             │           └── block: ∅
-            ├── locals: [:argument, :*]
-            ├── locals_body_index: 2
+            ├── locals: [:argument]
+            ├── locals_body_index: 1
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/prism/snapshots/whitequark/forwarded_kwrestarg.txt b/test/prism/snapshots/whitequark/forwarded_kwrestarg.txt
index bd2f55ae..2d44055e 100644
--- a/test/prism/snapshots/whitequark/forwarded_kwrestarg.txt
+++ b/test/prism/snapshots/whitequark/forwarded_kwrestarg.txt
@@ -43,8 +43,8 @@
             │           │                   └── operator_loc: (1,17)-(1,19) = "**"
             │           ├── closing_loc: (1,19)-(1,20) = ")"
             │           └── block: ∅
-            ├── locals: [:**]
-            ├── locals_body_index: 1
+            ├── locals: []
+            ├── locals_body_index: 0
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt b/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt
index 0af593e9..7a4eca05 100644
--- a/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt
+++ b/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt
@@ -54,8 +54,8 @@
             │           │                   └── operator_loc: ∅
             │           ├── closing_loc: (1,35)-(1,36) = ")"
             │           └── block: ∅
-            ├── locals: [:**]
-            ├── locals_body_index: 1
+            ├── locals: []
+            ├── locals_body_index: 0
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/prism/snapshots/whitequark/forwarded_restarg.txt b/test/prism/snapshots/whitequark/forwarded_restarg.txt
index 43e514bd..ac24409e 100644
--- a/test/prism/snapshots/whitequark/forwarded_restarg.txt
+++ b/test/prism/snapshots/whitequark/forwarded_restarg.txt
@@ -40,8 +40,8 @@
             │           │           └── expression: ∅
             │           ├── closing_loc: (1,17)-(1,18) = ")"
             │           └── block: ∅
-            ├── locals: [:*]
-            ├── locals_body_index: 1
+            ├── locals: []
+            ├── locals_body_index: 0
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,7)-(1,8) = "("
diff --git a/test/prism/snapshots/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt b/test/prism/snapshots/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt
index f39e6e44..d9514972 100644
--- a/test/prism/snapshots/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt
+++ b/test/prism/snapshots/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt
@@ -49,8 +49,8 @@
             │           │                   └── operator_loc: (1,21)-(1,23) = "**"
             │           ├── closing_loc: (1,23)-(1,24) = ")"
             │           └── block: ∅
-            ├── locals: [:a, :**]
-            ├── locals_body_index: 2
+            ├── locals: [:a]
+            ├── locals_body_index: 1
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/whitequark/kwrestarg_unnamed.txt b/test/prism/snapshots/whitequark/kwrestarg_unnamed.txt
index 564dfbcd..92e65deb 100644
--- a/test/prism/snapshots/whitequark/kwrestarg_unnamed.txt
+++ b/test/prism/snapshots/whitequark/kwrestarg_unnamed.txt
@@ -22,8 +22,8 @@
             │   │   └── operator_loc: (1,6)-(1,8) = "**"
             │   └── block: ∅
             ├── body: ∅
-            ├── locals: [:**]
-            ├── locals_body_index: 1
+            ├── locals: []
+            ├── locals_body_index: 0
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/whitequark/restarg_unnamed.txt b/test/prism/snapshots/whitequark/restarg_unnamed.txt
index 388dad19..cf8c57f0 100644
--- a/test/prism/snapshots/whitequark/restarg_unnamed.txt
+++ b/test/prism/snapshots/whitequark/restarg_unnamed.txt
@@ -22,8 +22,8 @@
             │   ├── keyword_rest: ∅
             │   └── block: ∅
             ├── body: ∅
-            ├── locals: [:*]
-            ├── locals_body_index: 1
+            ├── locals: []
+            ├── locals_body_index: 0
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,5)-(1,6) = "("
diff --git a/test/prism/snapshots/whitequark/trailing_forward_arg.txt b/test/prism/snapshots/whitequark/trailing_forward_arg.txt
index fa6036e4..20bfe574 100644
--- a/test/prism/snapshots/whitequark/trailing_forward_arg.txt
+++ b/test/prism/snapshots/whitequark/trailing_forward_arg.txt
@@ -45,8 +45,8 @@
             │           │       └── @ ForwardingArgumentsNode (location: (1,31)-(1,34))
             │           ├── closing_loc: (1,34)-(1,35) = ")"
             │           └── block: ∅
-            ├── locals: [:a, :b, :"..."]
-            ├── locals_body_index: 3
+            ├── locals: [:a, :b]
+            ├── locals_body_index: 2
             ├── def_keyword_loc: (1,0)-(1,3) = "def"
             ├── operator_loc: ∅
             ├── lparen_loc: (1,7)-(1,8) = "("