Jelajahi Sumber

Refactor struct literal parse nodes. (#4470)

Split StructComma into StructLiteralComma and StructTypeLiteralComma in
order to easily differentiate handling (remains the same in this PR).

Add "Literal" to StructField and StructTypeField because it feels
inconsistent versus the other non-shared things. StructFieldDesignator
remains shared between value literals and type literals.

Note I probably would've made StructFieldDesignator non-shared too, but
that'd require either a lookahead of 2 (to see the separator`) or a
writeback after parsing the separator, neither of which felt especially
crucial for this, when what I'm really trying to do is split type
literal handling a little further.
Jon Ross-Perkins 1 tahun lalu
induk
melakukan
dd43bb92b5

+ 10 - 3
toolchain/check/handle_struct.cpp

@@ -34,13 +34,20 @@ auto HandleParseNode(Context& context,
   return true;
   return true;
 }
 }
 
 
-auto HandleParseNode(Context& context, Parse::StructCommaId /*node_id*/)
+auto HandleParseNode(Context& context, Parse::StructLiteralCommaId /*node_id*/)
     -> bool {
     -> bool {
   context.param_and_arg_refs_stack().ApplyComma();
   context.param_and_arg_refs_stack().ApplyComma();
   return true;
   return true;
 }
 }
 
 
-auto HandleParseNode(Context& context, Parse::StructFieldId node_id) -> bool {
+auto HandleParseNode(Context& context,
+                     Parse::StructTypeLiteralCommaId /*node_id*/) -> bool {
+  context.param_and_arg_refs_stack().ApplyComma();
+  return true;
+}
+
+auto HandleParseNode(Context& context, Parse::StructLiteralFieldId node_id)
+    -> bool {
   auto value_inst_id = context.node_stack().PopExpr();
   auto value_inst_id = context.node_stack().PopExpr();
   auto [name_node, name_id] = context.node_stack().PopNameWithNodeId();
   auto [name_node, name_id] = context.node_stack().PopNameWithNodeId();
 
 
@@ -56,7 +63,7 @@ auto HandleParseNode(Context& context, Parse::StructFieldId node_id) -> bool {
   return true;
   return true;
 }
 }
 
 
-auto HandleParseNode(Context& context, Parse::StructTypeFieldId node_id)
+auto HandleParseNode(Context& context, Parse::StructTypeLiteralFieldId node_id)
     -> bool {
     -> bool {
   auto [type_node, type_id] = context.node_stack().PopExprWithNodeId();
   auto [type_node, type_id] = context.node_stack().PopExprWithNodeId();
   SemIR::TypeId cast_type_id = ExprAsType(context, type_node, type_id).type_id;
   SemIR::TypeId cast_type_id = ExprAsType(context, type_node, type_id).type_id;

+ 4 - 3
toolchain/check/node_stack.h

@@ -423,8 +423,8 @@ class NodeStack {
         case Parse::NodeKind::ReturnType:
         case Parse::NodeKind::ReturnType:
         case Parse::NodeKind::ShortCircuitOperandAnd:
         case Parse::NodeKind::ShortCircuitOperandAnd:
         case Parse::NodeKind::ShortCircuitOperandOr:
         case Parse::NodeKind::ShortCircuitOperandOr:
-        case Parse::NodeKind::StructField:
-        case Parse::NodeKind::StructTypeField:
+        case Parse::NodeKind::StructLiteralField:
+        case Parse::NodeKind::StructTypeLiteralField:
         case Parse::NodeKind::WhereOperand:
         case Parse::NodeKind::WhereOperand:
           return Id::KindFor<SemIR::InstId>();
           return Id::KindFor<SemIR::InstId>();
         case Parse::NodeKind::IfCondition:
         case Parse::NodeKind::IfCondition:
@@ -631,8 +631,9 @@ class NodeStack {
         case Parse::NodeKind::ShortCircuitOperatorOr:
         case Parse::NodeKind::ShortCircuitOperatorOr:
         case Parse::NodeKind::StringLiteral:
         case Parse::NodeKind::StringLiteral:
         case Parse::NodeKind::StringTypeLiteral:
         case Parse::NodeKind::StringTypeLiteral:
-        case Parse::NodeKind::StructComma:
+        case Parse::NodeKind::StructLiteralComma:
         case Parse::NodeKind::StructFieldDesignator:
         case Parse::NodeKind::StructFieldDesignator:
+        case Parse::NodeKind::StructTypeLiteralComma:
         case Parse::NodeKind::StructLiteral:
         case Parse::NodeKind::StructLiteral:
         case Parse::NodeKind::StructTypeLiteral:
         case Parse::NodeKind::StructTypeLiteral:
         case Parse::NodeKind::Template:
         case Parse::NodeKind::Template:

+ 3 - 3
toolchain/check/param_and_arg_refs_stack.h

@@ -30,8 +30,8 @@ class ParamAndArgRefsStack {
   // On a comma, pushes the most recent instruction, becoming param or arg ref.
   // On a comma, pushes the most recent instruction, becoming param or arg ref.
   // This also pops the NodeStack, meaning its top will remain start_kind.
   // This also pops the NodeStack, meaning its top will remain start_kind.
   auto ApplyComma() -> void {
   auto ApplyComma() -> void {
-    // Support expressions, parameters, and other nodes like `StructField`
-    // that produce InstIds.
+    // Support expressions, parameters, and other nodes like
+    // `StructLiteralField` that produce InstIds.
     stack_.AddInstId(node_stack_->Pop<SemIR::InstId>());
     stack_.AddInstId(node_stack_->Pop<SemIR::InstId>());
   }
   }
 
 
@@ -43,7 +43,7 @@ class ParamAndArgRefsStack {
   auto EndNoPop(Parse::NodeKind start_kind) -> void {
   auto EndNoPop(Parse::NodeKind start_kind) -> void {
     if (!node_stack_->PeekIs(start_kind)) {
     if (!node_stack_->PeekIs(start_kind)) {
       // Support expressions, parameters, and other nodes like
       // Support expressions, parameters, and other nodes like
-      // `StructField` that produce InstIds.
+      // `StructLiteralField` that produce InstIds.
       stack_.AddInstId(node_stack_->Pop<SemIR::InstId>());
       stack_.AddInstId(node_stack_->Pop<SemIR::InstId>());
     }
     }
   }
   }

+ 1 - 1
toolchain/docs/parse.md

@@ -156,7 +156,7 @@ have two children: the lhs and rhs expressions. Many nodes have a child count of
 
 
 Because the tree structure is always valid, these are treated as contracts. Some
 Because the tree structure is always valid, these are treated as contracts. Some
 nodes exist only to be used to construct valid tree structures for invalid
 nodes exist only to be used to construct valid tree structures for invalid
-input, such as `StructFieldUnknown`.
+input, such as `InvalidParse`.
 
 
 Although each subtree's size is also tracked as part of the node, we're
 Although each subtree's size is also tracked as part of the node, we're
 currently trying to avoid relying on it and may eliminate it if it turns out to
 currently trying to avoid relying on it and may eliminate it if it turns out to

+ 12 - 8
toolchain/parse/handle_brace_expr.cpp

@@ -149,8 +149,9 @@ auto HandleBraceExprParamAfterDesignatorAsUnknown(Context& context) -> void {
 }
 }
 
 
 // Handles BraceExprParamFinishAs(Type|Value|Unknown).
 // Handles BraceExprParamFinishAs(Type|Value|Unknown).
-static auto HandleBraceExprParamFinish(Context& context, NodeKind node_kind,
-                                       State param_state) -> void {
+static auto HandleBraceExprParamFinish(Context& context, NodeKind field_kind,
+                                       NodeKind comma_kind, State param_state)
+    -> void {
   auto state = context.PopState();
   auto state = context.PopState();
 
 
   if (state.has_error) {
   if (state.has_error) {
@@ -158,28 +159,31 @@ static auto HandleBraceExprParamFinish(Context& context, NodeKind node_kind,
                         /*has_error=*/true);
                         /*has_error=*/true);
     context.ReturnErrorOnState();
     context.ReturnErrorOnState();
   } else {
   } else {
-    context.AddNode(node_kind, state.token, /*has_error=*/false);
+    context.AddNode(field_kind, state.token, /*has_error=*/false);
   }
   }
 
 
-  if (context.ConsumeListToken(
-          NodeKind::StructComma, Lex::TokenKind::CloseCurlyBrace,
-          state.has_error) == Context::ListTokenKind::Comma) {
+  if (context.ConsumeListToken(comma_kind, Lex::TokenKind::CloseCurlyBrace,
+                               state.has_error) ==
+      Context::ListTokenKind::Comma) {
     context.PushState(param_state);
     context.PushState(param_state);
   }
   }
 }
 }
 
 
 auto HandleBraceExprParamFinishAsType(Context& context) -> void {
 auto HandleBraceExprParamFinishAsType(Context& context) -> void {
-  HandleBraceExprParamFinish(context, NodeKind::StructTypeField,
+  HandleBraceExprParamFinish(context, NodeKind::StructTypeLiteralField,
+                             NodeKind::StructTypeLiteralComma,
                              State::BraceExprParamAsType);
                              State::BraceExprParamAsType);
 }
 }
 
 
 auto HandleBraceExprParamFinishAsValue(Context& context) -> void {
 auto HandleBraceExprParamFinishAsValue(Context& context) -> void {
-  HandleBraceExprParamFinish(context, NodeKind::StructField,
+  HandleBraceExprParamFinish(context, NodeKind::StructLiteralField,
+                             NodeKind::StructLiteralComma,
                              State::BraceExprParamAsValue);
                              State::BraceExprParamAsValue);
 }
 }
 
 
 auto HandleBraceExprParamFinishAsUnknown(Context& context) -> void {
 auto HandleBraceExprParamFinishAsUnknown(Context& context) -> void {
   HandleBraceExprParamFinish(context, NodeKind::InvalidParse,
   HandleBraceExprParamFinish(context, NodeKind::InvalidParse,
+                             NodeKind::InvalidParse,
                              State::BraceExprParamAsUnknown);
                              State::BraceExprParamAsUnknown);
 }
 }
 
 

+ 8 - 5
toolchain/parse/node_kind.def

@@ -287,13 +287,16 @@ CARBON_PARSE_NODE_KIND(IfExprIf)
 CARBON_PARSE_NODE_KIND(IfExprThen)
 CARBON_PARSE_NODE_KIND(IfExprThen)
 CARBON_PARSE_NODE_KIND(IfExprElse)
 CARBON_PARSE_NODE_KIND(IfExprElse)
 
 
-CARBON_PARSE_NODE_KIND(StructLiteralStart)
-CARBON_PARSE_NODE_KIND(StructTypeLiteralStart)
 CARBON_PARSE_NODE_KIND(StructFieldDesignator)
 CARBON_PARSE_NODE_KIND(StructFieldDesignator)
-CARBON_PARSE_NODE_KIND(StructField)
-CARBON_PARSE_NODE_KIND(StructTypeField)
-CARBON_PARSE_NODE_KIND(StructComma)
+
+CARBON_PARSE_NODE_KIND(StructLiteralStart)
+CARBON_PARSE_NODE_KIND(StructLiteralField)
+CARBON_PARSE_NODE_KIND(StructLiteralComma)
 CARBON_PARSE_NODE_KIND(StructLiteral)
 CARBON_PARSE_NODE_KIND(StructLiteral)
+
+CARBON_PARSE_NODE_KIND(StructTypeLiteralStart)
+CARBON_PARSE_NODE_KIND(StructTypeLiteralField)
+CARBON_PARSE_NODE_KIND(StructTypeLiteralComma)
 CARBON_PARSE_NODE_KIND(StructTypeLiteral)
 CARBON_PARSE_NODE_KIND(StructTypeLiteral)
 
 
 CARBON_PARSE_NODE_KIND(ExternModifierWithLibrary)
 CARBON_PARSE_NODE_KIND(ExternModifierWithLibrary)

+ 2 - 2
toolchain/parse/testdata/basics/fail_bracket_recovery.carbon

@@ -63,7 +63,7 @@ fn F() {
 // CHECK:STDOUT:               {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:               {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:                 {kind: 'TupleLiteralStart', text: '('},
 // CHECK:STDOUT:                 {kind: 'TupleLiteralStart', text: '('},
 // CHECK:STDOUT:               {kind: 'TupleLiteral', text: ')', subtree_size: 2},
 // CHECK:STDOUT:               {kind: 'TupleLiteral', text: ')', subtree_size: 2},
-// CHECK:STDOUT:             {kind: 'StructTypeField', text: ':', subtree_size: 5},
+// CHECK:STDOUT:             {kind: 'StructTypeLiteralField', text: ':', subtree_size: 5},
 // CHECK:STDOUT:           {kind: 'StructTypeLiteral', text: '}', subtree_size: 7},
 // CHECK:STDOUT:           {kind: 'StructTypeLiteral', text: '}', subtree_size: 7},
 // CHECK:STDOUT:         {kind: 'BindingPattern', text: ':', subtree_size: 9},
 // CHECK:STDOUT:         {kind: 'BindingPattern', text: ':', subtree_size: 9},
 // CHECK:STDOUT:         {kind: 'VariableInitializer', text: '='},
 // CHECK:STDOUT:         {kind: 'VariableInitializer', text: '='},
@@ -74,7 +74,7 @@ fn F() {
 // CHECK:STDOUT:                 {kind: 'TupleLiteralStart', text: '('},
 // CHECK:STDOUT:                 {kind: 'TupleLiteralStart', text: '('},
 // CHECK:STDOUT:               {kind: 'TupleLiteral', text: ')', subtree_size: 2},
 // CHECK:STDOUT:               {kind: 'TupleLiteral', text: ')', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'ParenExpr', text: ')', subtree_size: 4},
 // CHECK:STDOUT:             {kind: 'ParenExpr', text: ')', subtree_size: 4},
-// CHECK:STDOUT:           {kind: 'StructField', text: '=', subtree_size: 7},
+// CHECK:STDOUT:           {kind: 'StructLiteralField', text: '=', subtree_size: 7},
 // CHECK:STDOUT:         {kind: 'StructLiteral', text: '}', subtree_size: 9},
 // CHECK:STDOUT:         {kind: 'StructLiteral', text: '}', subtree_size: 9},
 // CHECK:STDOUT:       {kind: 'VariableDecl', text: ';', subtree_size: 21},
 // CHECK:STDOUT:       {kind: 'VariableDecl', text: ';', subtree_size: 21},
 // CHECK:STDOUT:     {kind: 'FunctionDefinition', text: '}', subtree_size: 46},
 // CHECK:STDOUT:     {kind: 'FunctionDefinition', text: '}', subtree_size: 46},

+ 3 - 3
toolchain/parse/testdata/class/adapt.carbon

@@ -108,12 +108,12 @@ fn F() {
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
-// CHECK:STDOUT:           {kind: 'StructTypeField', text: ':', subtree_size: 4},
-// CHECK:STDOUT:           {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralComma', text: ','},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'b'},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'b'},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
-// CHECK:STDOUT:           {kind: 'StructTypeField', text: ':', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4},
 // CHECK:STDOUT:         {kind: 'StructTypeLiteral', text: '}', subtree_size: 11},
 // CHECK:STDOUT:         {kind: 'StructTypeLiteral', text: '}', subtree_size: 11},
 // CHECK:STDOUT:       {kind: 'AdaptDecl', text: ';', subtree_size: 14},
 // CHECK:STDOUT:       {kind: 'AdaptDecl', text: ';', subtree_size: 14},
 // CHECK:STDOUT:     {kind: 'ClassDefinition', text: '}', subtree_size: 18},
 // CHECK:STDOUT:     {kind: 'ClassDefinition', text: '}', subtree_size: 18},

+ 1 - 1
toolchain/parse/testdata/class/fn_definitions.carbon

@@ -34,7 +34,7 @@ class Foo {
 // CHECK:STDOUT:                 {kind: 'IdentifierName', text: 'x'},
 // CHECK:STDOUT:                 {kind: 'IdentifierName', text: 'x'},
 // CHECK:STDOUT:               {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:               {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:               {kind: 'IntLiteral', text: '0'},
 // CHECK:STDOUT:               {kind: 'IntLiteral', text: '0'},
-// CHECK:STDOUT:             {kind: 'StructField', text: '=', subtree_size: 4},
+// CHECK:STDOUT:             {kind: 'StructLiteralField', text: '=', subtree_size: 4},
 // CHECK:STDOUT:           {kind: 'StructLiteral', text: '}', subtree_size: 6},
 // CHECK:STDOUT:           {kind: 'StructLiteral', text: '}', subtree_size: 6},
 // CHECK:STDOUT:         {kind: 'ReturnStatement', text: ';', subtree_size: 8},
 // CHECK:STDOUT:         {kind: 'ReturnStatement', text: ';', subtree_size: 8},
 // CHECK:STDOUT:       {kind: 'FunctionDefinition', text: '}', subtree_size: 16},
 // CHECK:STDOUT:       {kind: 'FunctionDefinition', text: '}', subtree_size: 16},

+ 1 - 1
toolchain/parse/testdata/struct/fail_comma_only.carbon

@@ -20,7 +20,7 @@ var x: {,} = {};
 // CHECK:STDOUT:         {kind: 'IdentifierName', text: 'x'},
 // CHECK:STDOUT:         {kind: 'IdentifierName', text: 'x'},
 // CHECK:STDOUT:           {kind: 'StructLiteralStart', text: '{'},
 // CHECK:STDOUT:           {kind: 'StructLiteralStart', text: '{'},
 // CHECK:STDOUT:           {kind: 'InvalidParse', text: ',', has_error: yes},
 // CHECK:STDOUT:           {kind: 'InvalidParse', text: ',', has_error: yes},
-// CHECK:STDOUT:           {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:           {kind: 'InvalidParse', text: ','},
 // CHECK:STDOUT:         {kind: 'StructLiteral', text: '}', has_error: yes, subtree_size: 4},
 // CHECK:STDOUT:         {kind: 'StructLiteral', text: '}', has_error: yes, subtree_size: 4},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 6},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 6},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},

+ 3 - 3
toolchain/parse/testdata/struct/fail_comma_repeat_in_type.carbon

@@ -22,10 +22,10 @@ var x: {.a: i32,,} = {};
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
-// CHECK:STDOUT:           {kind: 'StructTypeField', text: ':', subtree_size: 4},
-// CHECK:STDOUT:           {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralComma', text: ','},
 // CHECK:STDOUT:           {kind: 'InvalidParse', text: ',', has_error: yes},
 // CHECK:STDOUT:           {kind: 'InvalidParse', text: ',', has_error: yes},
-// CHECK:STDOUT:           {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralComma', text: ','},
 // CHECK:STDOUT:         {kind: 'StructTypeLiteral', text: '}', has_error: yes, subtree_size: 9},
 // CHECK:STDOUT:         {kind: 'StructTypeLiteral', text: '}', has_error: yes, subtree_size: 9},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 11},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 11},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},

+ 3 - 3
toolchain/parse/testdata/struct/fail_comma_repeat_in_value.carbon

@@ -22,10 +22,10 @@ var x: {.a = 0,,} = {};
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'IntLiteral', text: '0'},
 // CHECK:STDOUT:             {kind: 'IntLiteral', text: '0'},
-// CHECK:STDOUT:           {kind: 'StructField', text: '=', subtree_size: 4},
-// CHECK:STDOUT:           {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:           {kind: 'StructLiteralField', text: '=', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'StructLiteralComma', text: ','},
 // CHECK:STDOUT:           {kind: 'InvalidParse', text: ',', has_error: yes},
 // CHECK:STDOUT:           {kind: 'InvalidParse', text: ',', has_error: yes},
-// CHECK:STDOUT:           {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:           {kind: 'StructLiteralComma', text: ','},
 // CHECK:STDOUT:         {kind: 'StructLiteral', text: '}', has_error: yes, subtree_size: 9},
 // CHECK:STDOUT:         {kind: 'StructLiteral', text: '}', has_error: yes, subtree_size: 9},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 11},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 11},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},

+ 2 - 2
toolchain/parse/testdata/struct/fail_extra_token_in_type.carbon

@@ -22,7 +22,7 @@ var x: {.a: i32 banana} = {.a = 0};
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
-// CHECK:STDOUT:           {kind: 'StructTypeField', text: ':', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4},
 // CHECK:STDOUT:         {kind: 'StructTypeLiteral', text: '}', has_error: yes, subtree_size: 6},
 // CHECK:STDOUT:         {kind: 'StructTypeLiteral', text: '}', has_error: yes, subtree_size: 6},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 8},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 8},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},
@@ -30,7 +30,7 @@ var x: {.a: i32 banana} = {.a = 0};
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'IntLiteral', text: '0'},
 // CHECK:STDOUT:           {kind: 'IntLiteral', text: '0'},
-// CHECK:STDOUT:         {kind: 'StructField', text: '=', subtree_size: 4},
+// CHECK:STDOUT:         {kind: 'StructLiteralField', text: '=', subtree_size: 4},
 // CHECK:STDOUT:       {kind: 'StructLiteral', text: '}', subtree_size: 6},
 // CHECK:STDOUT:       {kind: 'StructLiteral', text: '}', subtree_size: 6},
 // CHECK:STDOUT:     {kind: 'VariableDecl', text: ';', subtree_size: 17},
 // CHECK:STDOUT:     {kind: 'VariableDecl', text: ';', subtree_size: 17},
 // CHECK:STDOUT:     {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT:     {kind: 'FileEnd', text: ''},

+ 2 - 2
toolchain/parse/testdata/struct/fail_extra_token_in_value.carbon

@@ -22,7 +22,7 @@ var x: {.a: i32} = {.a = 0 banana};
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
-// CHECK:STDOUT:           {kind: 'StructTypeField', text: ':', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4},
 // CHECK:STDOUT:         {kind: 'StructTypeLiteral', text: '}', subtree_size: 6},
 // CHECK:STDOUT:         {kind: 'StructTypeLiteral', text: '}', subtree_size: 6},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 8},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 8},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},
@@ -30,7 +30,7 @@ var x: {.a: i32} = {.a = 0 banana};
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'IntLiteral', text: '0'},
 // CHECK:STDOUT:           {kind: 'IntLiteral', text: '0'},
-// CHECK:STDOUT:         {kind: 'StructField', text: '=', subtree_size: 4},
+// CHECK:STDOUT:         {kind: 'StructLiteralField', text: '=', subtree_size: 4},
 // CHECK:STDOUT:       {kind: 'StructLiteral', text: '}', has_error: yes, subtree_size: 6},
 // CHECK:STDOUT:       {kind: 'StructLiteral', text: '}', has_error: yes, subtree_size: 6},
 // CHECK:STDOUT:     {kind: 'VariableDecl', text: ';', subtree_size: 17},
 // CHECK:STDOUT:     {kind: 'VariableDecl', text: ';', subtree_size: 17},
 // CHECK:STDOUT:     {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT:     {kind: 'FileEnd', text: ''},

+ 2 - 2
toolchain/parse/testdata/struct/fail_mix_type_and_value.carbon

@@ -22,8 +22,8 @@ var x: {.a: i32, .b = 0} = {};
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
-// CHECK:STDOUT:           {kind: 'StructTypeField', text: ':', subtree_size: 4},
-// CHECK:STDOUT:           {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralComma', text: ','},
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'b'},
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'b'},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'InvalidParse', text: '.', has_error: yes},
 // CHECK:STDOUT:           {kind: 'InvalidParse', text: '.', has_error: yes},

+ 2 - 2
toolchain/parse/testdata/struct/fail_mix_value_and_type.carbon

@@ -22,8 +22,8 @@ var x: {.a = 0, b: i32} = {};
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'IntLiteral', text: '0'},
 // CHECK:STDOUT:             {kind: 'IntLiteral', text: '0'},
-// CHECK:STDOUT:           {kind: 'StructField', text: '=', subtree_size: 4},
-// CHECK:STDOUT:           {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:           {kind: 'StructLiteralField', text: '=', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'StructLiteralComma', text: ','},
 // CHECK:STDOUT:           {kind: 'InvalidParse', text: 'b', has_error: yes},
 // CHECK:STDOUT:           {kind: 'InvalidParse', text: 'b', has_error: yes},
 // CHECK:STDOUT:         {kind: 'StructLiteral', text: '}', has_error: yes, subtree_size: 8},
 // CHECK:STDOUT:         {kind: 'StructLiteral', text: '}', has_error: yes, subtree_size: 8},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 10},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 10},

+ 6 - 6
toolchain/parse/testdata/struct/fail_mix_with_unknown.carbon

@@ -39,12 +39,12 @@ var x: i32 = {.a: i32, .b, .c = 1};
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'IntLiteral', text: '1'},
 // CHECK:STDOUT:           {kind: 'IntLiteral', text: '1'},
-// CHECK:STDOUT:         {kind: 'StructField', text: '=', subtree_size: 4},
-// CHECK:STDOUT:         {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:         {kind: 'StructLiteralField', text: '=', subtree_size: 4},
+// CHECK:STDOUT:         {kind: 'StructLiteralComma', text: ','},
 // CHECK:STDOUT:           {kind: 'IdentifierName', text: 'b'},
 // CHECK:STDOUT:           {kind: 'IdentifierName', text: 'b'},
 // CHECK:STDOUT:         {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:         {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:         {kind: 'InvalidParse', text: '.', has_error: yes},
 // CHECK:STDOUT:         {kind: 'InvalidParse', text: '.', has_error: yes},
-// CHECK:STDOUT:         {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:         {kind: 'StructLiteralComma', text: ','},
 // CHECK:STDOUT:           {kind: 'IdentifierName', text: 'c'},
 // CHECK:STDOUT:           {kind: 'IdentifierName', text: 'c'},
 // CHECK:STDOUT:         {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:         {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:         {kind: 'InvalidParse', text: '.', has_error: yes},
 // CHECK:STDOUT:         {kind: 'InvalidParse', text: '.', has_error: yes},
@@ -59,12 +59,12 @@ var x: i32 = {.a: i32, .b, .c = 1};
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'IntTypeLiteral', text: 'i32'},
 // CHECK:STDOUT:           {kind: 'IntTypeLiteral', text: 'i32'},
-// CHECK:STDOUT:         {kind: 'StructTypeField', text: ':', subtree_size: 4},
-// CHECK:STDOUT:         {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:         {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4},
+// CHECK:STDOUT:         {kind: 'StructTypeLiteralComma', text: ','},
 // CHECK:STDOUT:           {kind: 'IdentifierName', text: 'b'},
 // CHECK:STDOUT:           {kind: 'IdentifierName', text: 'b'},
 // CHECK:STDOUT:         {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:         {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:         {kind: 'InvalidParse', text: '.', has_error: yes},
 // CHECK:STDOUT:         {kind: 'InvalidParse', text: '.', has_error: yes},
-// CHECK:STDOUT:         {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:         {kind: 'StructTypeLiteralComma', text: ','},
 // CHECK:STDOUT:           {kind: 'IdentifierName', text: 'c'},
 // CHECK:STDOUT:           {kind: 'IdentifierName', text: 'c'},
 // CHECK:STDOUT:         {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:         {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:         {kind: 'InvalidParse', text: '.', has_error: yes},
 // CHECK:STDOUT:         {kind: 'InvalidParse', text: '.', has_error: yes},

+ 2 - 2
toolchain/parse/testdata/struct/fail_period_string_colon.carbon

@@ -23,11 +23,11 @@ var x: {."hello": i32, .y: i32} = {};
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'IntTypeLiteral', text: 'i32'},
 // CHECK:STDOUT:           {kind: 'IntTypeLiteral', text: 'i32'},
 // CHECK:STDOUT:           {kind: 'InvalidParse', text: ':', has_error: yes},
 // CHECK:STDOUT:           {kind: 'InvalidParse', text: ':', has_error: yes},
-// CHECK:STDOUT:           {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralComma', text: ','},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'y'},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'y'},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
-// CHECK:STDOUT:           {kind: 'StructTypeField', text: ':', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4},
 // CHECK:STDOUT:         {kind: 'StructTypeLiteral', text: '}', has_error: yes, subtree_size: 11},
 // CHECK:STDOUT:         {kind: 'StructTypeLiteral', text: '}', has_error: yes, subtree_size: 11},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 13},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 13},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},

+ 2 - 2
toolchain/parse/testdata/struct/fail_period_string_equals.carbon

@@ -23,11 +23,11 @@ var x: {."hello" = 0, .y = 4} = {};
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'IntLiteral', text: '0'},
 // CHECK:STDOUT:           {kind: 'IntLiteral', text: '0'},
 // CHECK:STDOUT:           {kind: 'InvalidParse', text: '=', has_error: yes},
 // CHECK:STDOUT:           {kind: 'InvalidParse', text: '=', has_error: yes},
-// CHECK:STDOUT:           {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:           {kind: 'StructLiteralComma', text: ','},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'y'},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'y'},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'IntLiteral', text: '4'},
 // CHECK:STDOUT:             {kind: 'IntLiteral', text: '4'},
-// CHECK:STDOUT:           {kind: 'StructField', text: '=', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'StructLiteralField', text: '=', subtree_size: 4},
 // CHECK:STDOUT:         {kind: 'StructLiteral', text: '}', has_error: yes, subtree_size: 11},
 // CHECK:STDOUT:         {kind: 'StructLiteral', text: '}', has_error: yes, subtree_size: 11},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 13},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 13},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},

+ 2 - 2
toolchain/parse/testdata/struct/one_entry_no_comma.carbon

@@ -19,7 +19,7 @@ var z: {.n: i32} = {.n = 4};
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'n'},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'n'},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
-// CHECK:STDOUT:           {kind: 'StructTypeField', text: ':', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4},
 // CHECK:STDOUT:         {kind: 'StructTypeLiteral', text: '}', subtree_size: 6},
 // CHECK:STDOUT:         {kind: 'StructTypeLiteral', text: '}', subtree_size: 6},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 8},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 8},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},
@@ -27,7 +27,7 @@ var z: {.n: i32} = {.n = 4};
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'n'},
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'n'},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'IntLiteral', text: '4'},
 // CHECK:STDOUT:           {kind: 'IntLiteral', text: '4'},
-// CHECK:STDOUT:         {kind: 'StructField', text: '=', subtree_size: 4},
+// CHECK:STDOUT:         {kind: 'StructLiteralField', text: '=', subtree_size: 4},
 // CHECK:STDOUT:       {kind: 'StructLiteral', text: '}', subtree_size: 6},
 // CHECK:STDOUT:       {kind: 'StructLiteral', text: '}', subtree_size: 6},
 // CHECK:STDOUT:     {kind: 'VariableDecl', text: ';', subtree_size: 17},
 // CHECK:STDOUT:     {kind: 'VariableDecl', text: ';', subtree_size: 17},
 // CHECK:STDOUT:     {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT:     {kind: 'FileEnd', text: ''},

+ 4 - 4
toolchain/parse/testdata/struct/one_entry_with_comma.carbon

@@ -19,8 +19,8 @@ var z: {.n: i32,} = {.n = 4,};
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'n'},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'n'},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
-// CHECK:STDOUT:           {kind: 'StructTypeField', text: ':', subtree_size: 4},
-// CHECK:STDOUT:           {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralComma', text: ','},
 // CHECK:STDOUT:         {kind: 'StructTypeLiteral', text: '}', subtree_size: 7},
 // CHECK:STDOUT:         {kind: 'StructTypeLiteral', text: '}', subtree_size: 7},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 9},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 9},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},
@@ -28,8 +28,8 @@ var z: {.n: i32,} = {.n = 4,};
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'n'},
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'n'},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'IntLiteral', text: '4'},
 // CHECK:STDOUT:           {kind: 'IntLiteral', text: '4'},
-// CHECK:STDOUT:         {kind: 'StructField', text: '=', subtree_size: 4},
-// CHECK:STDOUT:         {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:         {kind: 'StructLiteralField', text: '=', subtree_size: 4},
+// CHECK:STDOUT:         {kind: 'StructLiteralComma', text: ','},
 // CHECK:STDOUT:       {kind: 'StructLiteral', text: '}', subtree_size: 7},
 // CHECK:STDOUT:       {kind: 'StructLiteral', text: '}', subtree_size: 7},
 // CHECK:STDOUT:     {kind: 'VariableDecl', text: ';', subtree_size: 19},
 // CHECK:STDOUT:     {kind: 'VariableDecl', text: ';', subtree_size: 19},
 // CHECK:STDOUT:     {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT:     {kind: 'FileEnd', text: ''},

+ 6 - 6
toolchain/parse/testdata/struct/two_entries.carbon

@@ -19,12 +19,12 @@ var x: {.a: i32, .b: i32} = {.a = 1, .b = 2};
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
-// CHECK:STDOUT:           {kind: 'StructTypeField', text: ':', subtree_size: 4},
-// CHECK:STDOUT:           {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralComma', text: ','},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'b'},
 // CHECK:STDOUT:               {kind: 'IdentifierName', text: 'b'},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
 // CHECK:STDOUT:             {kind: 'IntTypeLiteral', text: 'i32'},
-// CHECK:STDOUT:           {kind: 'StructTypeField', text: ':', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4},
 // CHECK:STDOUT:         {kind: 'StructTypeLiteral', text: '}', subtree_size: 11},
 // CHECK:STDOUT:         {kind: 'StructTypeLiteral', text: '}', subtree_size: 11},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 13},
 // CHECK:STDOUT:       {kind: 'BindingPattern', text: ':', subtree_size: 13},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},
 // CHECK:STDOUT:       {kind: 'VariableInitializer', text: '='},
@@ -32,12 +32,12 @@ var x: {.a: i32, .b: i32} = {.a = 1, .b = 2};
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'a'},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'IntLiteral', text: '1'},
 // CHECK:STDOUT:           {kind: 'IntLiteral', text: '1'},
-// CHECK:STDOUT:         {kind: 'StructField', text: '=', subtree_size: 4},
-// CHECK:STDOUT:         {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:         {kind: 'StructLiteralField', text: '=', subtree_size: 4},
+// CHECK:STDOUT:         {kind: 'StructLiteralComma', text: ','},
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'b'},
 // CHECK:STDOUT:             {kind: 'IdentifierName', text: 'b'},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
 // CHECK:STDOUT:           {kind: 'IntLiteral', text: '2'},
 // CHECK:STDOUT:           {kind: 'IntLiteral', text: '2'},
-// CHECK:STDOUT:         {kind: 'StructField', text: '=', subtree_size: 4},
+// CHECK:STDOUT:         {kind: 'StructLiteralField', text: '=', subtree_size: 4},
 // CHECK:STDOUT:       {kind: 'StructLiteral', text: '}', subtree_size: 11},
 // CHECK:STDOUT:       {kind: 'StructLiteral', text: '}', subtree_size: 11},
 // CHECK:STDOUT:     {kind: 'VariableDecl', text: ';', subtree_size: 27},
 // CHECK:STDOUT:     {kind: 'VariableDecl', text: ';', subtree_size: 27},
 // CHECK:STDOUT:     {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT:     {kind: 'FileEnd', text: ''},

+ 12 - 7
toolchain/parse/typed_nodes.h

@@ -1122,9 +1122,14 @@ using StructLiteralStart =
 using StructTypeLiteralStart =
 using StructTypeLiteralStart =
     LeafNode<NodeKind::StructTypeLiteralStart, Lex::OpenCurlyBraceTokenIndex>;
     LeafNode<NodeKind::StructTypeLiteralStart, Lex::OpenCurlyBraceTokenIndex>;
 // `,`
 // `,`
-using StructComma = LeafNode<NodeKind::StructComma, Lex::CommaTokenIndex>;
+using StructLiteralComma =
+    LeafNode<NodeKind::StructLiteralComma, Lex::CommaTokenIndex>;
+using StructTypeLiteralComma =
+    LeafNode<NodeKind::StructTypeLiteralComma, Lex::CommaTokenIndex>;
 
 
 // `.a`
 // `.a`
+// This is shared for struct literals and type literals in order to reduce
+// lookahead for parse (the `=` versus `:` would require lookahead of 2).
 struct StructFieldDesignator {
 struct StructFieldDesignator {
   static constexpr auto Kind =
   static constexpr auto Kind =
       NodeKind::StructFieldDesignator.Define({.child_count = 1});
       NodeKind::StructFieldDesignator.Define({.child_count = 1});
@@ -1134,8 +1139,8 @@ struct StructFieldDesignator {
 };
 };
 
 
 // `.a = 0`
 // `.a = 0`
-struct StructField {
-  static constexpr auto Kind = NodeKind::StructField.Define(
+struct StructLiteralField {
+  static constexpr auto Kind = NodeKind::StructLiteralField.Define(
       {.bracketed_by = StructFieldDesignator::Kind, .child_count = 2});
       {.bracketed_by = StructFieldDesignator::Kind, .child_count = 2});
 
 
   StructFieldDesignatorId designator;
   StructFieldDesignatorId designator;
@@ -1144,8 +1149,8 @@ struct StructField {
 };
 };
 
 
 // `.a: i32`
 // `.a: i32`
-struct StructTypeField {
-  static constexpr auto Kind = NodeKind::StructTypeField.Define(
+struct StructTypeLiteralField {
+  static constexpr auto Kind = NodeKind::StructTypeLiteralField.Define(
       {.bracketed_by = StructFieldDesignator::Kind, .child_count = 2});
       {.bracketed_by = StructFieldDesignator::Kind, .child_count = 2});
 
 
   StructFieldDesignatorId designator;
   StructFieldDesignatorId designator;
@@ -1160,7 +1165,7 @@ struct StructLiteral {
        .bracketed_by = StructLiteralStart::Kind});
        .bracketed_by = StructLiteralStart::Kind});
 
 
   StructLiteralStartId start;
   StructLiteralStartId start;
-  CommaSeparatedList<StructFieldId, StructCommaId> fields;
+  CommaSeparatedList<StructLiteralFieldId, StructLiteralCommaId> fields;
   Lex::CloseCurlyBraceTokenIndex token;
   Lex::CloseCurlyBraceTokenIndex token;
 };
 };
 
 
@@ -1171,7 +1176,7 @@ struct StructTypeLiteral {
        .bracketed_by = StructTypeLiteralStart::Kind});
        .bracketed_by = StructTypeLiteralStart::Kind});
 
 
   StructTypeLiteralStartId start;
   StructTypeLiteralStartId start;
-  CommaSeparatedList<StructTypeFieldId, StructCommaId> fields;
+  CommaSeparatedList<StructTypeLiteralFieldId, StructTypeLiteralCommaId> fields;
   Lex::CloseCurlyBraceTokenIndex token;
   Lex::CloseCurlyBraceTokenIndex token;
 };
 };