[parser] Empty record

https://github.com/dart-lang/language/pull/2535

Change-Id: I8241119ee858ce39673472056b88c9393799e1a0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/262600
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index ca3aca0..3262d60 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -9962,17 +9962,6 @@
     problemMessage: r"""An optional named parameter can't start with '_'.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeRecordLiteralEmpty = messageRecordLiteralEmpty;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageRecordLiteralEmpty = const MessageCode(
-    "RecordLiteralEmpty",
-    index: 128,
-    problemMessage: r"""Record literal can't be empty.""",
-    correctionMessage:
-        r"""Try adding elements or use 'Record.empty()' instead.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeRecordLiteralOnePositionalFieldNoTrailingComma =
     messageRecordLiteralOnePositionalFieldNoTrailingComma;
 
@@ -9985,18 +9974,42 @@
         correctionMessage: r"""Try adding a trailing comma.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeRecordLiteralZeroFieldsWithTrailingComma =
+    messageRecordLiteralZeroFieldsWithTrailingComma;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageRecordLiteralZeroFieldsWithTrailingComma =
+    const MessageCode("RecordLiteralZeroFieldsWithTrailingComma",
+        index: 128,
+        problemMessage:
+            r"""Record literal without fields can't have a trailing comma.""",
+        correctionMessage: r"""Try removing the trailing comma.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeRecordTypeOnePositionalFieldNoTrailingComma =
     messageRecordTypeOnePositionalFieldNoTrailingComma;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode messageRecordTypeOnePositionalFieldNoTrailingComma =
     const MessageCode("RecordTypeOnePositionalFieldNoTrailingComma",
-        index: 130,
+        index: 131,
         problemMessage:
             r"""Record type with one entry requires a trailing comma.""",
         correctionMessage: r"""Try adding a trailing comma.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeRecordTypeZeroFieldsButTrailingComma =
+    messageRecordTypeZeroFieldsButTrailingComma;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageRecordTypeZeroFieldsButTrailingComma =
+    const MessageCode("RecordTypeZeroFieldsButTrailingComma",
+        index: 130,
+        problemMessage:
+            r"""Record type without fields can't have a trailing comma.""",
+        correctionMessage: r"""Try removing the trailing comma.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeRedirectingConstructorWithAnotherInitializer =
     messageRedirectingConstructorWithAnotherInitializer;
 
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
index e2bc00d..4f28b6f 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -1403,20 +1403,16 @@
 
   /// Parse a record type similarly as a formal parameter list of a function.
   ///
-  /// TODO(jensj): Update this to fit any new updates to the spec.
-  /// E.g. having two recordTypeNamedField entries doesn't make sense.
-  ///
   /// recordType          ::= '(' recordTypeFields ',' recordTypeNamedFields ')'
   ///                       | '(' recordTypeFields ','? ')'
-  ///                       | '(' recordTypeNamedFields ')'
+  ///                       | '(' recordTypeNamedFields? ')'
   ///
   /// recordTypeFields      ::= recordTypeField ( ',' recordTypeField )*
   /// recordTypeField       ::= metadata type identifier?
   ///
   /// recordTypeNamedFields ::= '{' recordTypeNamedField
   ///                           ( ',' recordTypeNamedField )* ','? '}'
-  /// recordTypeNamedField  ::= type identifier
-  /// recordTypeNamedField  ::= metadata typedIdentifier
+  /// recordTypeNamedField  ::= metadata type identifier
   Token parseRecordType(final Token start, Token token) {
     token = token.next!;
     assert(optional('(', token));
@@ -1429,11 +1425,18 @@
     int parameterCount = 0;
     bool hasNamedFields = false;
     bool sawComma = false;
+    Token? illegalTrailingComma;
     while (true) {
       Token next = token.next!;
       if (optional(')', next)) {
         token = next;
         break;
+      } else if (parameterCount == 0 &&
+          optional(',', next) &&
+          optional(')', next.next!)) {
+        illegalTrailingComma = next;
+        token = next.next!;
+        break;
       }
       ++parameterCount;
       String? value = next.stringValue;
@@ -1478,7 +1481,11 @@
     }
     assert(optional(')', token));
 
-    if (parameterCount == 1 && !hasNamedFields && !sawComma) {
+    if (parameterCount == 0 && illegalTrailingComma != null) {
+      // Empty record type with a comma `(,)`.
+      reportRecoverableError(illegalTrailingComma,
+          codes.messageRecordTypeZeroFieldsButTrailingComma);
+    } else if (parameterCount == 1 && !hasNamedFields && !sawComma) {
       // Single non-named element without trailing comma.
       reportRecoverableError(
           token, codes.messageRecordTypeOnePositionalFieldNoTrailingComma);
@@ -6143,9 +6150,20 @@
     int count = 0;
     bool wasRecord = constKeywordForRecord != null;
     bool wasValidRecord = false;
+    Token? illegalTrailingComma;
     while (true) {
       Token next = token.next!;
-      if ((count > 0 || wasRecord) && optional(')', next)) {
+      if (optional(')', next)) {
+        if (count == 0) {
+          wasRecord = true;
+        }
+        break;
+      } else if (count == 0 &&
+          optional(',', next) &&
+          optional(')', next.next!)) {
+        illegalTrailingComma = next;
+        wasRecord = true;
+        token = next;
         break;
       }
       Token? colon = null;
@@ -6179,8 +6197,10 @@
     assert(wasRecord || count <= 1);
 
     if (wasRecord) {
-      if (count == 0) {
-        reportRecoverableError(token, codes.messageRecordLiteralEmpty);
+      if (count == 0 && illegalTrailingComma != null) {
+        // Empty record literal with a comma `(,)`.
+        reportRecoverableError(illegalTrailingComma,
+            codes.messageRecordLiteralZeroFieldsWithTrailingComma);
       } else if (count == 1 && !wasValidRecord) {
         reportRecoverableError(
             token, codes.messageRecordLiteralOnePositionalFieldNoTrailingComma);
@@ -9484,9 +9504,7 @@
     assert(wasRecord || count <= 1);
 
     if (wasRecord) {
-      if (count == 0) {
-        reportRecoverableError(token, codes.messageRecordLiteralEmpty);
-      } else if (count == 1 && !wasValidRecord) {
+      if (count == 1 && !wasValidRecord) {
         reportRecoverableError(
             token, codes.messageRecordLiteralOnePositionalFieldNoTrailingComma);
       }
diff --git a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
index 7f084dc..b50b858 100644
--- a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
+++ b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
@@ -2180,8 +2180,12 @@
   notes: |-
     We can't guess at the names or number of the enum constants that should be
     added.
+ParserErrorCode.EMPTY_RECORD_LITERAL_WITH_COMMA:
+  status: needsEvaluation
 ParserErrorCode.EMPTY_RECORD_TYPE_NAMED_FIELDS_LIST:
   status: needsEvaluation
+ParserErrorCode.EMPTY_RECORD_TYPE_WITH_COMMA:
+  status: needsEvaluation
 ParserErrorCode.ENUM_IN_CLASS:
   status: needsEvaluation
 ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND:
@@ -2464,8 +2468,6 @@
   status: needsEvaluation
 ParserErrorCode.PREFIX_AFTER_COMBINATOR:
   status: needsEvaluation
-ParserErrorCode.RECORD_LITERAL_EMPTY:
-  status: needsEvaluation
 ParserErrorCode.RECORD_LITERAL_ONE_POSITIONAL_NO_TRAILING_COMMA:
   status: needsEvaluation
 ParserErrorCode.RECORD_TYPE_ONE_POSITIONAL_NO_TRAILING_COMMA:
diff --git a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
index f2bece5..d63bf90 100644
--- a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
+++ b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
@@ -1451,13 +1451,14 @@
 ''',
         atEnd: true);
     _assertHasChange(
-        'Insert a newline at the end of the current line',
+        'Add a semicolon and newline',
         '''
 void f() {
-  int g()
+  int g();
+  
 }
 ''',
-        (s) => _afterLast(s, '()'));
+        (s) => _afterLast(s, '();\n  '));
   }
 
   @failingTest
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 7eae7fa..94638d6 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -749,7 +749,9 @@
   ParserErrorCode.DUPLICATE_PREFIX,
   ParserErrorCode.DUPLICATED_MODIFIER,
   ParserErrorCode.EMPTY_ENUM_BODY,
+  ParserErrorCode.EMPTY_RECORD_LITERAL_WITH_COMMA,
   ParserErrorCode.EMPTY_RECORD_TYPE_NAMED_FIELDS_LIST,
+  ParserErrorCode.EMPTY_RECORD_TYPE_WITH_COMMA,
   ParserErrorCode.ENUM_IN_CLASS,
   ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND,
   ParserErrorCode.EXPECTED_BODY,
@@ -891,7 +893,6 @@
   ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT,
   ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP,
   ParserErrorCode.PREFIX_AFTER_COMBINATOR,
-  ParserErrorCode.RECORD_LITERAL_EMPTY,
   ParserErrorCode.RECORD_LITERAL_ONE_POSITIONAL_NO_TRAILING_COMMA,
   ParserErrorCode.RECORD_TYPE_ONE_POSITIONAL_NO_TRAILING_COMMA,
   ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY,
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
index f44efcc..6f65b3b 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -142,8 +142,9 @@
   ParserErrorCode.INVALID_UNICODE_ESCAPE_U_BRACKET,
   ParserErrorCode.INVALID_UNICODE_ESCAPE_STARTED,
   ParserErrorCode.RECORD_LITERAL_ONE_POSITIONAL_NO_TRAILING_COMMA,
-  ParserErrorCode.RECORD_LITERAL_EMPTY,
+  ParserErrorCode.EMPTY_RECORD_LITERAL_WITH_COMMA,
   ParserErrorCode.EMPTY_RECORD_TYPE_NAMED_FIELDS_LIST,
+  ParserErrorCode.EMPTY_RECORD_TYPE_WITH_COMMA,
   ParserErrorCode.RECORD_TYPE_ONE_POSITIONAL_NO_TRAILING_COMMA,
 ];
 
@@ -435,6 +436,13 @@
     correctionMessage: "Try declaring a constant.",
   );
 
+  static const ParserErrorCode EMPTY_RECORD_LITERAL_WITH_COMMA =
+      ParserErrorCode(
+    'EMPTY_RECORD_LITERAL_WITH_COMMA',
+    "Record literal without fields can't have a trailing comma.",
+    correctionMessage: "Try removing the trailing comma.",
+  );
+
   static const ParserErrorCode EMPTY_RECORD_TYPE_NAMED_FIELDS_LIST =
       ParserErrorCode(
     'EMPTY_RECORD_TYPE_NAMED_FIELDS_LIST',
@@ -442,6 +450,12 @@
     correctionMessage: "Try adding a record type named field to the list.",
   );
 
+  static const ParserErrorCode EMPTY_RECORD_TYPE_WITH_COMMA = ParserErrorCode(
+    'EMPTY_RECORD_TYPE_WITH_COMMA',
+    "Record type without fields can't have a trailing comma.",
+    correctionMessage: "Try removing the trailing comma.",
+  );
+
   static const ParserErrorCode ENUM_IN_CLASS = ParserErrorCode(
     'ENUM_IN_CLASS',
     "Enums can't be declared inside classes.",
@@ -1422,12 +1436,6 @@
     correctionMessage: "Try moving the prefix before the combinators.",
   );
 
-  static const ParserErrorCode RECORD_LITERAL_EMPTY = ParserErrorCode(
-    'RECORD_LITERAL_EMPTY',
-    "Record literal can't be empty.",
-    correctionMessage: "Try adding elements or use 'Record.empty()' instead.",
-  );
-
   static const ParserErrorCode RECORD_LITERAL_ONE_POSITIONAL_NO_TRAILING_COMMA =
       ParserErrorCode(
     'RECORD_LITERAL_ONE_POSITIONAL_NO_TRAILING_COMMA',
diff --git a/pkg/analyzer/test/generated/class_member_parser_test.dart b/pkg/analyzer/test/generated/class_member_parser_test.dart
index 64cf9e8..e92f270 100644
--- a/pkg/analyzer/test/generated/class_member_parser_test.dart
+++ b/pkg/analyzer/test/generated/class_member_parser_test.dart
@@ -1540,7 +1540,7 @@
     // https://github.com/dart-lang/sdk/issues/37693
     parseCompilationUnit('class C{ C() : super() * (); }', errors: [
       expectedError(ParserErrorCode.INVALID_INITIALIZER, 15, 12),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 26, 1),
+      expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 25, 1),
     ]);
   }
 
diff --git a/pkg/analyzer/test/generated/error_parser_test.dart b/pkg/analyzer/test/generated/error_parser_test.dart
index f30512f..84afe64 100644
--- a/pkg/analyzer/test/generated/error_parser_test.dart
+++ b/pkg/analyzer/test/generated/error_parser_test.dart
@@ -1445,7 +1445,7 @@
     expectNotNullIfNoErrors(statement);
     listener.assertErrors([
       expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 1),
+      expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 1),
       expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1),
     ]);
   }
diff --git a/pkg/analyzer/test/generated/recovery_parser_test.dart b/pkg/analyzer/test/generated/recovery_parser_test.dart
index 9a891bd..c8c9bbb 100644
--- a/pkg/analyzer/test/generated/recovery_parser_test.dart
+++ b/pkg/analyzer/test/generated/recovery_parser_test.dart
@@ -490,7 +490,7 @@
     CompilationUnit unit =
         parseCompilationUnit("class A { A() : a = (){}; var v; }", codes: [
       ParserErrorCode.EXPECTED_CLASS_MEMBER,
-      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.EXPERIMENT_NOT_ENABLED,
     ]);
 // Make sure we recovered and parsed "var v" correctly
     ClassDeclaration declaration = unit.declarations[0] as ClassDeclaration;
diff --git a/pkg/analyzer/test/generated/simple_parser_test.dart b/pkg/analyzer/test/generated/simple_parser_test.dart
index 53c2c61..8e96cc5 100644
--- a/pkg/analyzer/test/generated/simple_parser_test.dart
+++ b/pkg/analyzer/test/generated/simple_parser_test.dart
@@ -127,7 +127,6 @@
       expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 24, 5),
       expectedError(ParserErrorCode.MISSING_IDENTIFIER, 24, 5),
       expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 29, 1),
-      expectedError(ParserErrorCode.RECORD_LITERAL_EMPTY, 30, 1),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_super_in_initializer_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_super_in_initializer_test.dart
index 72319fa..c5420ce 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_super_in_initializer_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_super_in_initializer_test.dart
@@ -24,7 +24,6 @@
       error(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 18, 5),
       error(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 24, 5),
       error(ParserErrorCode.MISSING_IDENTIFIER, 24, 5),
-      error(ParserErrorCode.RECORD_LITERAL_EMPTY, 30, 1)
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart
index ef7bce2..0704efc 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart
@@ -423,9 +423,10 @@
   p.();
 }
 ''', [
+      if (!isNullSafetyEnabled)
+        error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 32, 1),
       error(ParserErrorCode.MISSING_IDENTIFIER, 32, 1),
       error(CompileTimeErrorCode.UNDEFINED_GETTER, 32, 1),
-      error(ParserErrorCode.MISSING_IDENTIFIER, 33, 1),
     ]);
   }
 }
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index b194ebb..dd26106 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -334,15 +334,15 @@
       var record = const (1);
     }
 
-RecordLiteralEmpty:
-  problemMessage: "Record literal can't be empty."
-  correctionMessage: "Try adding elements or use 'Record.empty()' instead."
-  analyzerCode: ParserErrorCode.RECORD_LITERAL_EMPTY
+RecordLiteralZeroFieldsWithTrailingComma:
+  problemMessage: "Record literal without fields can't have a trailing comma."
+  correctionMessage: "Try removing the trailing comma."
+  analyzerCode: ParserErrorCode.EMPTY_RECORD_LITERAL_WITH_COMMA
   index: 128
   experiments: records
   script: >
     main() {
-      var record = const ();
+      var record = (,);
     }
 
 EmptyRecordTypeNamedFieldsList:
@@ -356,11 +356,22 @@
       (int, int, {/*missing*/}) record = (1, 2,);
     }
 
+RecordTypeZeroFieldsButTrailingComma:
+  problemMessage: "Record type without fields can't have a trailing comma."
+  correctionMessage: "Try removing the trailing comma."
+  analyzerCode: ParserErrorCode.EMPTY_RECORD_TYPE_WITH_COMMA
+  index: 130
+  experiments: records
+  script: >
+    main() {
+      (,) record = ();
+    }
+
 RecordTypeOnePositionalFieldNoTrailingComma:
   problemMessage: "Record type with one entry requires a trailing comma."
   correctionMessage: "Try adding a trailing comma."
   analyzerCode: ParserErrorCode.RECORD_TYPE_ONE_POSITIONAL_NO_TRAILING_COMMA
-  index: 130
+  index: 131
   experiments: records
   script: >
     main() {
diff --git a/pkg/front_end/parser_testcases/general/augment_super.dart.expect b/pkg/front_end/parser_testcases/general/augment_super.dart.expect
index 0068277..2d99d17 100644
--- a/pkg/front_end/parser_testcases/general/augment_super.dart.expect
+++ b/pkg/front_end/parser_testcases/general/augment_super.dart.expect
@@ -16,10 +16,6 @@
   augment super();
           ^^^^^
 
-parser/general/augment_super:2:17: Expected an identifier, but got ')'.
-  augment super();
-                ^
-
 parser/general/augment_super:5:1: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
 augment void topLevelMethodError() {
 ^^^^^^^
@@ -76,10 +72,6 @@
   augment super();
           ^^^^^
 
-parser/general/augment_super:21:17: Expected an identifier, but got ')'.
-  augment super();
-                ^
-
 parser/general/augment_super:22:11: 'super' can't be used as an identifier because it's a keyword.
   augment super;
           ^^^^^
@@ -112,10 +104,6 @@
     augment super();
             ^^^^^
 
-parser/general/augment_super:29:19: Expected an identifier, but got ')'.
-    augment super();
-                  ^
-
 parser/general/augment_super:32:3: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
   augment void instanceMethodErrors() {
   ^^^^^^^
@@ -172,10 +160,6 @@
     augment super();
             ^^^^^
 
-parser/general/augment_super:48:19: Expected an identifier, but got ')'.
-    augment super();
-                  ^
-
 parser/general/augment_super:49:13: 'super' can't be used as an identifier because it's a keyword.
     augment super;
             ^^^^^
@@ -221,12 +205,7 @@
           handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], super, super)
         endVariablesDeclaration(1, ;)
         beginParenthesizedExpressionOrRecordLiteral(()
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
-          handleIdentifier(, expression)
-          handleNoTypeArguments())
-          handleNoArguments())
-          handleSend(, ))
-        endParenthesizedExpression(()
+        endRecordLiteral((, 0, null)
         handleExpressionStatement(;)
       endBlockFunctionBody(2, {, })
     endTopLevelMethod(void, null, })
@@ -439,12 +418,7 @@
           handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], super, super)
         endVariablesDeclaration(1, ;)
         beginParenthesizedExpressionOrRecordLiteral(()
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
-          handleIdentifier(, expression)
-          handleNoTypeArguments())
-          handleNoArguments())
-          handleSend(, ))
-        endParenthesizedExpression(()
+        endRecordLiteral((, 0, null)
         handleExpressionStatement(;)
         beginMetadataStar(augment)
         endMetadataStar(0)
@@ -543,12 +517,7 @@
                 handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], super, super)
               endVariablesDeclaration(1, ;)
               beginParenthesizedExpressionOrRecordLiteral(()
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
-                handleIdentifier(, expression)
-                handleNoTypeArguments())
-                handleNoArguments())
-                handleSend(, ))
-              endParenthesizedExpression(()
+              endRecordLiteral((, 0, null)
               handleExpressionStatement(;)
             endBlockFunctionBody(2, {, })
           endClassMethod(null, void, (, null, })
@@ -744,12 +713,7 @@
                 handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], super, super)
               endVariablesDeclaration(1, ;)
               beginParenthesizedExpressionOrRecordLiteral(()
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
-                handleIdentifier(, expression)
-                handleNoTypeArguments())
-                handleNoArguments())
-                handleSend(, ))
-              endParenthesizedExpression(()
+              endRecordLiteral((, 0, null)
               handleExpressionStatement(;)
               beginMetadataStar(augment)
               endMetadataStar(0)
diff --git a/pkg/front_end/parser_testcases/general/augment_super.dart.intertwined.expect b/pkg/front_end/parser_testcases/general/augment_super.dart.intertwined.expect
index 84a1789..5c86225 100644
--- a/pkg/front_end/parser_testcases/general/augment_super.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/general/augment_super.dart.intertwined.expect
@@ -88,23 +88,8 @@
                             parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(;)
                               parseParenthesizedExpressionOrRecordLiteral(;, null)
                                 listener: beginParenthesizedExpressionOrRecordLiteral(()
-                                parseExpression(()
-                                  parsePrecedenceExpression((, 1, true)
-                                    parseUnaryExpression((, true)
-                                      parsePrimary((, expression)
-                                        parseSend((, expression)
-                                          isNextIdentifier(()
-                                          ensureIdentifier((, expression)
-                                            reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
-                                            rewriter()
-                                            listener: handleIdentifier(, expression)
-                                          listener: handleNoTypeArguments())
-                                          parseArgumentsOpt()
-                                            listener: handleNoArguments())
-                                          listener: handleSend(, ))
-                                ensureCloseParen(, ()
-                                listener: endParenthesizedExpression(()
+                                ensureCloseParen((, ()
+                                listener: endRecordLiteral((, 0, null)
                     ensureSemicolon())
                     listener: handleExpressionStatement(;)
           notEofOrValue(}, })
@@ -601,23 +586,8 @@
                             parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(;)
                               parseParenthesizedExpressionOrRecordLiteral(;, null)
                                 listener: beginParenthesizedExpressionOrRecordLiteral(()
-                                parseExpression(()
-                                  parsePrecedenceExpression((, 1, true)
-                                    parseUnaryExpression((, true)
-                                      parsePrimary((, expression)
-                                        parseSend((, expression)
-                                          isNextIdentifier(()
-                                          ensureIdentifier((, expression)
-                                            reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
-                                            rewriter()
-                                            listener: handleIdentifier(, expression)
-                                          listener: handleNoTypeArguments())
-                                          parseArgumentsOpt()
-                                            listener: handleNoArguments())
-                                          listener: handleSend(, ))
-                                ensureCloseParen(, ()
-                                listener: endParenthesizedExpression(()
+                                ensureCloseParen((, ()
+                                listener: endRecordLiteral((, 0, null)
                     ensureSemicolon())
                     listener: handleExpressionStatement(;)
           notEofOrValue(}, augment)
@@ -849,23 +819,8 @@
                                     parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(;)
                                       parseParenthesizedExpressionOrRecordLiteral(;, null)
                                         listener: beginParenthesizedExpressionOrRecordLiteral(()
-                                        parseExpression(()
-                                          parsePrecedenceExpression((, 1, true)
-                                            parseUnaryExpression((, true)
-                                              parsePrimary((, expression)
-                                                parseSend((, expression)
-                                                  isNextIdentifier(()
-                                                  ensureIdentifier((, expression)
-                                                    reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
-                                                    rewriter()
-                                                    listener: handleIdentifier(, expression)
-                                                  listener: handleNoTypeArguments())
-                                                  parseArgumentsOpt()
-                                                    listener: handleNoArguments())
-                                                  listener: handleSend(, ))
-                                        ensureCloseParen(, ()
-                                        listener: endParenthesizedExpression(()
+                                        ensureCloseParen((, ()
+                                        listener: endRecordLiteral((, 0, null)
                             ensureSemicolon())
                             listener: handleExpressionStatement(;)
                   notEofOrValue(}, })
@@ -1349,23 +1304,8 @@
                                     parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(;)
                                       parseParenthesizedExpressionOrRecordLiteral(;, null)
                                         listener: beginParenthesizedExpressionOrRecordLiteral(()
-                                        parseExpression(()
-                                          parsePrecedenceExpression((, 1, true)
-                                            parseUnaryExpression((, true)
-                                              parsePrimary((, expression)
-                                                parseSend((, expression)
-                                                  isNextIdentifier(()
-                                                  ensureIdentifier((, expression)
-                                                    reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
-                                                    rewriter()
-                                                    listener: handleIdentifier(, expression)
-                                                  listener: handleNoTypeArguments())
-                                                  parseArgumentsOpt()
-                                                    listener: handleNoArguments())
-                                                  listener: handleSend(, ))
-                                        ensureCloseParen(, ()
-                                        listener: endParenthesizedExpression(()
+                                        ensureCloseParen((, ()
+                                        listener: endRecordLiteral((, 0, null)
                             ensureSemicolon())
                             listener: handleExpressionStatement(;)
                   notEofOrValue(}, augment)
diff --git a/pkg/front_end/parser_testcases/general/augment_super.dart.parser.expect b/pkg/front_end/parser_testcases/general/augment_super.dart.parser.expect
index 0e2e061..6bf8a8f 100644
--- a/pkg/front_end/parser_testcases/general/augment_super.dart.parser.expect
+++ b/pkg/front_end/parser_testcases/general/augment_super.dart.parser.expect
@@ -1,7 +1,7 @@
 NOTICE: Stream was rewritten by parser!
 
 augment ;void topLevelMethod() {
-augment super;(*synthetic*);
+augment super;();
 }
 
 augment ;void topLevelMethodError() {
@@ -20,7 +20,7 @@
 }
 
 void injectedTopLevelMethod() {
-augment super;(*synthetic*);
+augment super;();
 augment super;
 augment int ;local;
 augment;
@@ -28,7 +28,7 @@
 
 augment ;class Class {
 augment ;void instanceMethod() {
-augment super;(*synthetic*);
+augment super;();
 }
 
 augment ;void instanceMethodErrors() {
@@ -47,7 +47,7 @@
 }
 
 void injectedInstanceMethod() {
-augment super;(*synthetic*);
+augment super;();
 augment super;
 augment int ;local;
 augment;
@@ -55,7 +55,7 @@
 }
 
 augment[StringToken] ;[SyntheticToken]void[KeywordToken] topLevelMethod[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
-augment[StringToken] super[KeywordToken];[SyntheticToken]([BeginToken][SyntheticStringToken])[SimpleToken];[SimpleToken]
+augment[StringToken] super[KeywordToken];[SyntheticToken]([BeginToken])[SimpleToken];[SimpleToken]
 }[SimpleToken]
 
 augment[StringToken] ;[SyntheticToken]void[KeywordToken] topLevelMethodError[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
@@ -74,7 +74,7 @@
 }[SimpleToken]
 
 void[KeywordToken] injectedTopLevelMethod[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
-augment[StringToken] super[KeywordToken];[SyntheticToken]([BeginToken][SyntheticStringToken])[SimpleToken];[SimpleToken]
+augment[StringToken] super[KeywordToken];[SyntheticToken]([BeginToken])[SimpleToken];[SimpleToken]
 augment[StringToken] super[KeywordToken];[SimpleToken]
 augment[StringToken] int[StringToken] ;[SyntheticToken]local[StringToken];[SimpleToken]
 augment[StringToken];[SimpleToken]
@@ -82,7 +82,7 @@
 
 augment[StringToken] ;[SyntheticToken]class[KeywordToken] Class[StringToken] {[BeginToken]
 augment[StringToken] ;[SyntheticToken]void[KeywordToken] instanceMethod[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
-augment[StringToken] super[KeywordToken];[SyntheticToken]([BeginToken][SyntheticStringToken])[SimpleToken];[SimpleToken]
+augment[StringToken] super[KeywordToken];[SyntheticToken]([BeginToken])[SimpleToken];[SimpleToken]
 }[SimpleToken]
 
 augment[StringToken] ;[SyntheticToken]void[KeywordToken] instanceMethodErrors[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
@@ -101,7 +101,7 @@
 }[SimpleToken]
 
 void[KeywordToken] injectedInstanceMethod[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
-augment[StringToken] super[KeywordToken];[SyntheticToken]([BeginToken][SyntheticStringToken])[SimpleToken];[SimpleToken]
+augment[StringToken] super[KeywordToken];[SyntheticToken]([BeginToken])[SimpleToken];[SimpleToken]
 augment[StringToken] super[KeywordToken];[SimpleToken]
 augment[StringToken] int[StringToken] ;[SyntheticToken]local[StringToken];[SimpleToken]
 augment[StringToken];[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/record/record_and_commas.dart b/pkg/front_end/parser_testcases/record/record_and_commas.dart
new file mode 100644
index 0000000..496cde6
--- /dev/null
+++ b/pkg/front_end/parser_testcases/record/record_and_commas.dart
@@ -0,0 +1,15 @@
+main() {
+  // OK.
+  () emptyRecord1 = ();
+
+  // Error: Empty with comma.
+  (,) emptyRecord2 = ();
+  () emptyRecord3 = (,);
+  (,) emptyRecord4 = (,);
+
+  // Error: More than one trailing comma.
+  (int, ,) emptyRecord5 = (42, 42, ,);
+  (int, int, ,) emptyRecord6 = (42, 42, ,);
+  (int, , ,) emptyRecord7 = (42, 42, , ,);
+  (int, int, , ,) emptyRecord8 = (42, 42, , ,);
+}
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/record/record_and_commas.dart.expect b/pkg/front_end/parser_testcases/record/record_and_commas.dart.expect
new file mode 100644
index 0000000..d11df8d
--- /dev/null
+++ b/pkg/front_end/parser_testcases/record/record_and_commas.dart.expect
@@ -0,0 +1,330 @@
+Problems reported:
+
+parser/record/record_and_commas:6:4: Record type without fields can't have a trailing comma.
+  (,) emptyRecord2 = ();
+   ^
+
+parser/record/record_and_commas:7:22: Record literal without fields can't have a trailing comma.
+  () emptyRecord3 = (,);
+                     ^
+
+parser/record/record_and_commas:8:4: Record type without fields can't have a trailing comma.
+  (,) emptyRecord4 = (,);
+   ^
+
+parser/record/record_and_commas:8:23: Record literal without fields can't have a trailing comma.
+  (,) emptyRecord4 = (,);
+                      ^
+
+parser/record/record_and_commas:11:9: Expected a type, but got ','.
+  (int, ,) emptyRecord5 = (42, 42, ,);
+        ^
+
+parser/record/record_and_commas:11:36: Expected an identifier, but got ','.
+  (int, ,) emptyRecord5 = (42, 42, ,);
+                                   ^
+
+parser/record/record_and_commas:12:14: Expected a type, but got ','.
+  (int, int, ,) emptyRecord6 = (42, 42, ,);
+             ^
+
+parser/record/record_and_commas:12:41: Expected an identifier, but got ','.
+  (int, int, ,) emptyRecord6 = (42, 42, ,);
+                                        ^
+
+parser/record/record_and_commas:13:9: Expected a type, but got ','.
+  (int, , ,) emptyRecord7 = (42, 42, , ,);
+        ^
+
+parser/record/record_and_commas:13:11: Expected a type, but got ','.
+  (int, , ,) emptyRecord7 = (42, 42, , ,);
+          ^
+
+parser/record/record_and_commas:13:38: Expected an identifier, but got ','.
+  (int, , ,) emptyRecord7 = (42, 42, , ,);
+                                     ^
+
+parser/record/record_and_commas:13:40: Expected an identifier, but got ','.
+  (int, , ,) emptyRecord7 = (42, 42, , ,);
+                                       ^
+
+parser/record/record_and_commas:14:14: Expected a type, but got ','.
+  (int, int, , ,) emptyRecord8 = (42, 42, , ,);
+             ^
+
+parser/record/record_and_commas:14:16: Expected a type, but got ','.
+  (int, int, , ,) emptyRecord8 = (42, 42, , ,);
+               ^
+
+parser/record/record_and_commas:14:43: Expected an identifier, but got ','.
+  (int, int, , ,) emptyRecord8 = (42, 42, , ,);
+                                          ^
+
+parser/record/record_and_commas:14:45: Expected an identifier, but got ','.
+  (int, int, , ,) emptyRecord8 = (42, 42, , ,);
+                                            ^
+
+beginCompilationUnit(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(, null, null)
+      handleNoType()
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginMetadataStar(()
+        endMetadataStar(0)
+        beginRecordType(()
+        endRecordType((, null, 0, false)
+        beginVariablesDeclaration(emptyRecord1, null, null)
+          handleIdentifier(emptyRecord1, localVariableDeclaration)
+          beginInitializedIdentifier(emptyRecord1)
+            beginVariableInitializer(=)
+              beginParenthesizedExpressionOrRecordLiteral(()
+              endRecordLiteral((, 0, null)
+            endVariableInitializer(=)
+          endInitializedIdentifier(emptyRecord1)
+        endVariablesDeclaration(1, ;)
+        beginMetadataStar(()
+        endMetadataStar(0)
+        beginRecordType(()
+          handleRecoverableError(RecordTypeZeroFieldsButTrailingComma, ,, ,)
+        endRecordType((, null, 0, false)
+        beginVariablesDeclaration(emptyRecord2, null, null)
+          handleIdentifier(emptyRecord2, localVariableDeclaration)
+          beginInitializedIdentifier(emptyRecord2)
+            beginVariableInitializer(=)
+              beginParenthesizedExpressionOrRecordLiteral(()
+              endRecordLiteral((, 0, null)
+            endVariableInitializer(=)
+          endInitializedIdentifier(emptyRecord2)
+        endVariablesDeclaration(1, ;)
+        beginMetadataStar(()
+        endMetadataStar(0)
+        beginRecordType(()
+        endRecordType((, null, 0, false)
+        beginVariablesDeclaration(emptyRecord3, null, null)
+          handleIdentifier(emptyRecord3, localVariableDeclaration)
+          beginInitializedIdentifier(emptyRecord3)
+            beginVariableInitializer(=)
+              beginParenthesizedExpressionOrRecordLiteral(()
+                handleRecoverableError(RecordLiteralZeroFieldsWithTrailingComma, ,, ,)
+              endRecordLiteral((, 0, null)
+            endVariableInitializer(=)
+          endInitializedIdentifier(emptyRecord3)
+        endVariablesDeclaration(1, ;)
+        beginMetadataStar(()
+        endMetadataStar(0)
+        beginRecordType(()
+          handleRecoverableError(RecordTypeZeroFieldsButTrailingComma, ,, ,)
+        endRecordType((, null, 0, false)
+        beginVariablesDeclaration(emptyRecord4, null, null)
+          handleIdentifier(emptyRecord4, localVariableDeclaration)
+          beginInitializedIdentifier(emptyRecord4)
+            beginVariableInitializer(=)
+              beginParenthesizedExpressionOrRecordLiteral(()
+                handleRecoverableError(RecordLiteralZeroFieldsWithTrailingComma, ,, ,)
+              endRecordLiteral((, 0, null)
+            endVariableInitializer(=)
+          endInitializedIdentifier(emptyRecord4)
+        endVariablesDeclaration(1, ;)
+        beginMetadataStar(()
+        endMetadataStar(0)
+        beginRecordType(()
+          beginRecordTypeEntry()
+            beginMetadataStar(int)
+            endMetadataStar(0)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(,)
+            handleType(int, null)
+            handleNoName(,)
+          endRecordTypeEntry()
+          beginRecordTypeEntry()
+            beginMetadataStar(,)
+            endMetadataStar(0)
+            handleRecoverableError(Message[ExpectedType, Expected a type, but got ','., null, {lexeme: ,}], ,, ,)
+            handleIdentifier(, typeReference)
+            handleNoTypeArguments(,)
+            handleType(, null)
+            handleNoName(,)
+          endRecordTypeEntry()
+        endRecordType((, null, 2, false)
+        beginVariablesDeclaration(emptyRecord5, null, null)
+          handleIdentifier(emptyRecord5, localVariableDeclaration)
+          beginInitializedIdentifier(emptyRecord5)
+            beginVariableInitializer(=)
+              beginParenthesizedExpressionOrRecordLiteral(()
+                handleLiteralInt(42)
+                handleLiteralInt(42)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ','., Try inserting an identifier before ','., {lexeme: ,}], ,, ,)
+                handleIdentifier(, expression)
+                handleNoTypeArguments(,)
+                handleNoArguments(,)
+                handleSend(, ,)
+              endRecordLiteral((, 3, null)
+            endVariableInitializer(=)
+          endInitializedIdentifier(emptyRecord5)
+        endVariablesDeclaration(1, ;)
+        beginMetadataStar(()
+        endMetadataStar(0)
+        beginRecordType(()
+          beginRecordTypeEntry()
+            beginMetadataStar(int)
+            endMetadataStar(0)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(,)
+            handleType(int, null)
+            handleNoName(,)
+          endRecordTypeEntry()
+          beginRecordTypeEntry()
+            beginMetadataStar(int)
+            endMetadataStar(0)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(,)
+            handleType(int, null)
+            handleNoName(,)
+          endRecordTypeEntry()
+          beginRecordTypeEntry()
+            beginMetadataStar(,)
+            endMetadataStar(0)
+            handleRecoverableError(Message[ExpectedType, Expected a type, but got ','., null, {lexeme: ,}], ,, ,)
+            handleIdentifier(, typeReference)
+            handleNoTypeArguments(,)
+            handleType(, null)
+            handleNoName(,)
+          endRecordTypeEntry()
+        endRecordType((, null, 3, false)
+        beginVariablesDeclaration(emptyRecord6, null, null)
+          handleIdentifier(emptyRecord6, localVariableDeclaration)
+          beginInitializedIdentifier(emptyRecord6)
+            beginVariableInitializer(=)
+              beginParenthesizedExpressionOrRecordLiteral(()
+                handleLiteralInt(42)
+                handleLiteralInt(42)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ','., Try inserting an identifier before ','., {lexeme: ,}], ,, ,)
+                handleIdentifier(, expression)
+                handleNoTypeArguments(,)
+                handleNoArguments(,)
+                handleSend(, ,)
+              endRecordLiteral((, 3, null)
+            endVariableInitializer(=)
+          endInitializedIdentifier(emptyRecord6)
+        endVariablesDeclaration(1, ;)
+        beginMetadataStar(()
+        endMetadataStar(0)
+        beginRecordType(()
+          beginRecordTypeEntry()
+            beginMetadataStar(int)
+            endMetadataStar(0)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(,)
+            handleType(int, null)
+            handleNoName(,)
+          endRecordTypeEntry()
+          beginRecordTypeEntry()
+            beginMetadataStar(,)
+            endMetadataStar(0)
+            handleRecoverableError(Message[ExpectedType, Expected a type, but got ','., null, {lexeme: ,}], ,, ,)
+            handleIdentifier(, typeReference)
+            handleNoTypeArguments(,)
+            handleType(, null)
+            handleNoName(,)
+          endRecordTypeEntry()
+          beginRecordTypeEntry()
+            beginMetadataStar(,)
+            endMetadataStar(0)
+            handleRecoverableError(Message[ExpectedType, Expected a type, but got ','., null, {lexeme: ,}], ,, ,)
+            handleIdentifier(, typeReference)
+            handleNoTypeArguments(,)
+            handleType(, null)
+            handleNoName(,)
+          endRecordTypeEntry()
+        endRecordType((, null, 3, false)
+        beginVariablesDeclaration(emptyRecord7, null, null)
+          handleIdentifier(emptyRecord7, localVariableDeclaration)
+          beginInitializedIdentifier(emptyRecord7)
+            beginVariableInitializer(=)
+              beginParenthesizedExpressionOrRecordLiteral(()
+                handleLiteralInt(42)
+                handleLiteralInt(42)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ','., Try inserting an identifier before ','., {lexeme: ,}], ,, ,)
+                handleIdentifier(, expression)
+                handleNoTypeArguments(,)
+                handleNoArguments(,)
+                handleSend(, ,)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ','., Try inserting an identifier before ','., {lexeme: ,}], ,, ,)
+                handleIdentifier(, expression)
+                handleNoTypeArguments(,)
+                handleNoArguments(,)
+                handleSend(, ,)
+              endRecordLiteral((, 4, null)
+            endVariableInitializer(=)
+          endInitializedIdentifier(emptyRecord7)
+        endVariablesDeclaration(1, ;)
+        beginMetadataStar(()
+        endMetadataStar(0)
+        beginRecordType(()
+          beginRecordTypeEntry()
+            beginMetadataStar(int)
+            endMetadataStar(0)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(,)
+            handleType(int, null)
+            handleNoName(,)
+          endRecordTypeEntry()
+          beginRecordTypeEntry()
+            beginMetadataStar(int)
+            endMetadataStar(0)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(,)
+            handleType(int, null)
+            handleNoName(,)
+          endRecordTypeEntry()
+          beginRecordTypeEntry()
+            beginMetadataStar(,)
+            endMetadataStar(0)
+            handleRecoverableError(Message[ExpectedType, Expected a type, but got ','., null, {lexeme: ,}], ,, ,)
+            handleIdentifier(, typeReference)
+            handleNoTypeArguments(,)
+            handleType(, null)
+            handleNoName(,)
+          endRecordTypeEntry()
+          beginRecordTypeEntry()
+            beginMetadataStar(,)
+            endMetadataStar(0)
+            handleRecoverableError(Message[ExpectedType, Expected a type, but got ','., null, {lexeme: ,}], ,, ,)
+            handleIdentifier(, typeReference)
+            handleNoTypeArguments(,)
+            handleType(, null)
+            handleNoName(,)
+          endRecordTypeEntry()
+        endRecordType((, null, 4, false)
+        beginVariablesDeclaration(emptyRecord8, null, null)
+          handleIdentifier(emptyRecord8, localVariableDeclaration)
+          beginInitializedIdentifier(emptyRecord8)
+            beginVariableInitializer(=)
+              beginParenthesizedExpressionOrRecordLiteral(()
+                handleLiteralInt(42)
+                handleLiteralInt(42)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ','., Try inserting an identifier before ','., {lexeme: ,}], ,, ,)
+                handleIdentifier(, expression)
+                handleNoTypeArguments(,)
+                handleNoArguments(,)
+                handleSend(, ,)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ','., Try inserting an identifier before ','., {lexeme: ,}], ,, ,)
+                handleIdentifier(, expression)
+                handleNoTypeArguments(,)
+                handleNoArguments(,)
+                handleSend(, ,)
+              endRecordLiteral((, 4, null)
+            endVariableInitializer(=)
+          endInitializedIdentifier(emptyRecord8)
+        endVariablesDeclaration(1, ;)
+      endBlockFunctionBody(8, {, })
+    endTopLevelMethod(main, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/record/record_and_commas.dart.intertwined.expect b/pkg/front_end/parser_testcases/record/record_and_commas.dart.intertwined.expect
new file mode 100644
index 0000000..f0d8b69
--- /dev/null
+++ b/pkg/front_end/parser_testcases/record/record_and_commas.dart.intertwined.expect
@@ -0,0 +1,574 @@
+parseUnit(main)
+  skipErrorTokens(main)
+  listener: beginCompilationUnit(main)
+  syntheticPreviousToken(main)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(main)
+      isReservedKeyword(()
+      parseTopLevelMethod(, null, null, , Instance of 'NoType', null, main, false)
+        listener: beginTopLevelMethod(, null, null)
+        listener: handleNoType()
+        ensureIdentifierPotentiallyRecovered(, topLevelFunctionDeclaration, false)
+          listener: handleIdentifier(main, topLevelFunctionDeclaration)
+        parseMethodTypeVar(main)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(main, main, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(main, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, ()
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclaration({, false)
+                parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                  looksLikeLocalFunction(emptyRecord1)
+                  listener: beginMetadataStar(()
+                  listener: endMetadataStar(0)
+                  parseRecordType((, {)
+                    listener: beginRecordType(()
+                    listener: endRecordType((, null, 0, false)
+                  listener: beginVariablesDeclaration(emptyRecord1, null, null)
+                  parseVariablesDeclarationRest(), true)
+                    parseOptionallyInitializedIdentifier())
+                      ensureIdentifier(), localVariableDeclaration)
+                        listener: handleIdentifier(emptyRecord1, localVariableDeclaration)
+                      listener: beginInitializedIdentifier(emptyRecord1)
+                      parseVariableInitializerOpt(emptyRecord1)
+                        listener: beginVariableInitializer(=)
+                        parseExpression(=)
+                          parsePrecedenceExpression(=, 1, true)
+                            parseUnaryExpression(=, true)
+                              parsePrimary(=, expression)
+                                parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=)
+                                  parseParenthesizedExpressionOrRecordLiteral(=, null)
+                                    listener: beginParenthesizedExpressionOrRecordLiteral(()
+                                    ensureCloseParen((, ()
+                                    listener: endRecordLiteral((, 0, null)
+                        listener: endVariableInitializer(=)
+                      listener: endInitializedIdentifier(emptyRecord1)
+                    ensureSemicolon())
+                    listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, ()
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclaration(;, false)
+                parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                  looksLikeLocalFunction(emptyRecord2)
+                  listener: beginMetadataStar(()
+                  listener: endMetadataStar(0)
+                  parseRecordType((, ;)
+                    listener: beginRecordType(()
+                    reportRecoverableError(,, RecordTypeZeroFieldsButTrailingComma)
+                      listener: handleRecoverableError(RecordTypeZeroFieldsButTrailingComma, ,, ,)
+                    listener: endRecordType((, null, 0, false)
+                  listener: beginVariablesDeclaration(emptyRecord2, null, null)
+                  parseVariablesDeclarationRest(), true)
+                    parseOptionallyInitializedIdentifier())
+                      ensureIdentifier(), localVariableDeclaration)
+                        listener: handleIdentifier(emptyRecord2, localVariableDeclaration)
+                      listener: beginInitializedIdentifier(emptyRecord2)
+                      parseVariableInitializerOpt(emptyRecord2)
+                        listener: beginVariableInitializer(=)
+                        parseExpression(=)
+                          parsePrecedenceExpression(=, 1, true)
+                            parseUnaryExpression(=, true)
+                              parsePrimary(=, expression)
+                                parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=)
+                                  parseParenthesizedExpressionOrRecordLiteral(=, null)
+                                    listener: beginParenthesizedExpressionOrRecordLiteral(()
+                                    ensureCloseParen((, ()
+                                    listener: endRecordLiteral((, 0, null)
+                        listener: endVariableInitializer(=)
+                      listener: endInitializedIdentifier(emptyRecord2)
+                    ensureSemicolon())
+                    listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, ()
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclaration(;, false)
+                parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                  looksLikeLocalFunction(emptyRecord3)
+                  listener: beginMetadataStar(()
+                  listener: endMetadataStar(0)
+                  parseRecordType((, ;)
+                    listener: beginRecordType(()
+                    listener: endRecordType((, null, 0, false)
+                  listener: beginVariablesDeclaration(emptyRecord3, null, null)
+                  parseVariablesDeclarationRest(), true)
+                    parseOptionallyInitializedIdentifier())
+                      ensureIdentifier(), localVariableDeclaration)
+                        listener: handleIdentifier(emptyRecord3, localVariableDeclaration)
+                      listener: beginInitializedIdentifier(emptyRecord3)
+                      parseVariableInitializerOpt(emptyRecord3)
+                        listener: beginVariableInitializer(=)
+                        parseExpression(=)
+                          parsePrecedenceExpression(=, 1, true)
+                            parseUnaryExpression(=, true)
+                              parsePrimary(=, expression)
+                                parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=)
+                                  parseParenthesizedExpressionOrRecordLiteral(=, null)
+                                    listener: beginParenthesizedExpressionOrRecordLiteral(()
+                                    ensureCloseParen(,, ()
+                                    reportRecoverableError(,, RecordLiteralZeroFieldsWithTrailingComma)
+                                      listener: handleRecoverableError(RecordLiteralZeroFieldsWithTrailingComma, ,, ,)
+                                    listener: endRecordLiteral((, 0, null)
+                        listener: endVariableInitializer(=)
+                      listener: endInitializedIdentifier(emptyRecord3)
+                    ensureSemicolon())
+                    listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, ()
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclaration(;, false)
+                parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                  looksLikeLocalFunction(emptyRecord4)
+                  listener: beginMetadataStar(()
+                  listener: endMetadataStar(0)
+                  parseRecordType((, ;)
+                    listener: beginRecordType(()
+                    reportRecoverableError(,, RecordTypeZeroFieldsButTrailingComma)
+                      listener: handleRecoverableError(RecordTypeZeroFieldsButTrailingComma, ,, ,)
+                    listener: endRecordType((, null, 0, false)
+                  listener: beginVariablesDeclaration(emptyRecord4, null, null)
+                  parseVariablesDeclarationRest(), true)
+                    parseOptionallyInitializedIdentifier())
+                      ensureIdentifier(), localVariableDeclaration)
+                        listener: handleIdentifier(emptyRecord4, localVariableDeclaration)
+                      listener: beginInitializedIdentifier(emptyRecord4)
+                      parseVariableInitializerOpt(emptyRecord4)
+                        listener: beginVariableInitializer(=)
+                        parseExpression(=)
+                          parsePrecedenceExpression(=, 1, true)
+                            parseUnaryExpression(=, true)
+                              parsePrimary(=, expression)
+                                parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=)
+                                  parseParenthesizedExpressionOrRecordLiteral(=, null)
+                                    listener: beginParenthesizedExpressionOrRecordLiteral(()
+                                    ensureCloseParen(,, ()
+                                    reportRecoverableError(,, RecordLiteralZeroFieldsWithTrailingComma)
+                                      listener: handleRecoverableError(RecordLiteralZeroFieldsWithTrailingComma, ,, ,)
+                                    listener: endRecordLiteral((, 0, null)
+                        listener: endVariableInitializer(=)
+                      listener: endInitializedIdentifier(emptyRecord4)
+                    ensureSemicolon())
+                    listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, ()
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclaration(;, false)
+                parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                  looksLikeLocalFunction(emptyRecord5)
+                  listener: beginMetadataStar(()
+                  listener: endMetadataStar(0)
+                  parseRecordType((, ;)
+                    listener: beginRecordType(()
+                    parseRecordTypeField((, identifierIsOptional: true)
+                      listener: beginRecordTypeEntry()
+                      parseMetadataStar(()
+                        listener: beginMetadataStar(int)
+                        listener: endMetadataStar(0)
+                      listener: handleIdentifier(int, typeReference)
+                      listener: handleNoTypeArguments(,)
+                      listener: handleType(int, null)
+                      listener: handleNoName(,)
+                      listener: endRecordTypeEntry()
+                    parseRecordTypeField(,, identifierIsOptional: true)
+                      listener: beginRecordTypeEntry()
+                      parseMetadataStar(,)
+                        listener: beginMetadataStar(,)
+                        listener: endMetadataStar(0)
+                      reportRecoverableErrorWithToken(,, Instance of 'Template<(Token) => Message>')
+                        listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got ','., null, {lexeme: ,}], ,, ,)
+                      rewriter()
+                      listener: handleIdentifier(, typeReference)
+                      listener: handleNoTypeArguments(,)
+                      listener: handleType(, null)
+                      listener: handleNoName(,)
+                      listener: endRecordTypeEntry()
+                    listener: endRecordType((, null, 2, false)
+                  listener: beginVariablesDeclaration(emptyRecord5, null, null)
+                  parseVariablesDeclarationRest(), true)
+                    parseOptionallyInitializedIdentifier())
+                      ensureIdentifier(), localVariableDeclaration)
+                        listener: handleIdentifier(emptyRecord5, localVariableDeclaration)
+                      listener: beginInitializedIdentifier(emptyRecord5)
+                      parseVariableInitializerOpt(emptyRecord5)
+                        listener: beginVariableInitializer(=)
+                        parseExpression(=)
+                          parsePrecedenceExpression(=, 1, true)
+                            parseUnaryExpression(=, true)
+                              parsePrimary(=, expression)
+                                parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=)
+                                  parseParenthesizedExpressionOrRecordLiteral(=, null)
+                                    listener: beginParenthesizedExpressionOrRecordLiteral(()
+                                    parseExpression(()
+                                      parsePrecedenceExpression((, 1, true)
+                                        parseUnaryExpression((, true)
+                                          parsePrimary((, expression)
+                                            parseLiteralInt(()
+                                              listener: handleLiteralInt(42)
+                                    parseExpression(,)
+                                      parsePrecedenceExpression(,, 1, true)
+                                        parseUnaryExpression(,, true)
+                                          parsePrimary(,, expression)
+                                            parseLiteralInt(,)
+                                              listener: handleLiteralInt(42)
+                                    parseExpression(,)
+                                      parsePrecedenceExpression(,, 1, true)
+                                        parseUnaryExpression(,, true)
+                                          parsePrimary(,, expression)
+                                            parseSend(,, expression)
+                                              isNextIdentifier(,)
+                                              ensureIdentifier(,, expression)
+                                                reportRecoverableErrorWithToken(,, Instance of 'Template<(Token) => Message>')
+                                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ','., Try inserting an identifier before ','., {lexeme: ,}], ,, ,)
+                                                rewriter()
+                                                listener: handleIdentifier(, expression)
+                                              listener: handleNoTypeArguments(,)
+                                              parseArgumentsOpt()
+                                                listener: handleNoArguments(,)
+                                              listener: handleSend(, ,)
+                                    ensureCloseParen(,, ()
+                                    listener: endRecordLiteral((, 3, null)
+                        listener: endVariableInitializer(=)
+                      listener: endInitializedIdentifier(emptyRecord5)
+                    ensureSemicolon())
+                    listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, ()
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclaration(;, false)
+                parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                  looksLikeLocalFunction(emptyRecord6)
+                  listener: beginMetadataStar(()
+                  listener: endMetadataStar(0)
+                  parseRecordType((, ;)
+                    listener: beginRecordType(()
+                    parseRecordTypeField((, identifierIsOptional: true)
+                      listener: beginRecordTypeEntry()
+                      parseMetadataStar(()
+                        listener: beginMetadataStar(int)
+                        listener: endMetadataStar(0)
+                      listener: handleIdentifier(int, typeReference)
+                      listener: handleNoTypeArguments(,)
+                      listener: handleType(int, null)
+                      listener: handleNoName(,)
+                      listener: endRecordTypeEntry()
+                    parseRecordTypeField(,, identifierIsOptional: true)
+                      listener: beginRecordTypeEntry()
+                      parseMetadataStar(,)
+                        listener: beginMetadataStar(int)
+                        listener: endMetadataStar(0)
+                      listener: handleIdentifier(int, typeReference)
+                      listener: handleNoTypeArguments(,)
+                      listener: handleType(int, null)
+                      listener: handleNoName(,)
+                      listener: endRecordTypeEntry()
+                    parseRecordTypeField(,, identifierIsOptional: true)
+                      listener: beginRecordTypeEntry()
+                      parseMetadataStar(,)
+                        listener: beginMetadataStar(,)
+                        listener: endMetadataStar(0)
+                      reportRecoverableErrorWithToken(,, Instance of 'Template<(Token) => Message>')
+                        listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got ','., null, {lexeme: ,}], ,, ,)
+                      rewriter()
+                      listener: handleIdentifier(, typeReference)
+                      listener: handleNoTypeArguments(,)
+                      listener: handleType(, null)
+                      listener: handleNoName(,)
+                      listener: endRecordTypeEntry()
+                    listener: endRecordType((, null, 3, false)
+                  listener: beginVariablesDeclaration(emptyRecord6, null, null)
+                  parseVariablesDeclarationRest(), true)
+                    parseOptionallyInitializedIdentifier())
+                      ensureIdentifier(), localVariableDeclaration)
+                        listener: handleIdentifier(emptyRecord6, localVariableDeclaration)
+                      listener: beginInitializedIdentifier(emptyRecord6)
+                      parseVariableInitializerOpt(emptyRecord6)
+                        listener: beginVariableInitializer(=)
+                        parseExpression(=)
+                          parsePrecedenceExpression(=, 1, true)
+                            parseUnaryExpression(=, true)
+                              parsePrimary(=, expression)
+                                parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=)
+                                  parseParenthesizedExpressionOrRecordLiteral(=, null)
+                                    listener: beginParenthesizedExpressionOrRecordLiteral(()
+                                    parseExpression(()
+                                      parsePrecedenceExpression((, 1, true)
+                                        parseUnaryExpression((, true)
+                                          parsePrimary((, expression)
+                                            parseLiteralInt(()
+                                              listener: handleLiteralInt(42)
+                                    parseExpression(,)
+                                      parsePrecedenceExpression(,, 1, true)
+                                        parseUnaryExpression(,, true)
+                                          parsePrimary(,, expression)
+                                            parseLiteralInt(,)
+                                              listener: handleLiteralInt(42)
+                                    parseExpression(,)
+                                      parsePrecedenceExpression(,, 1, true)
+                                        parseUnaryExpression(,, true)
+                                          parsePrimary(,, expression)
+                                            parseSend(,, expression)
+                                              isNextIdentifier(,)
+                                              ensureIdentifier(,, expression)
+                                                reportRecoverableErrorWithToken(,, Instance of 'Template<(Token) => Message>')
+                                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ','., Try inserting an identifier before ','., {lexeme: ,}], ,, ,)
+                                                rewriter()
+                                                listener: handleIdentifier(, expression)
+                                              listener: handleNoTypeArguments(,)
+                                              parseArgumentsOpt()
+                                                listener: handleNoArguments(,)
+                                              listener: handleSend(, ,)
+                                    ensureCloseParen(,, ()
+                                    listener: endRecordLiteral((, 3, null)
+                        listener: endVariableInitializer(=)
+                      listener: endInitializedIdentifier(emptyRecord6)
+                    ensureSemicolon())
+                    listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, ()
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclaration(;, false)
+                parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                  looksLikeLocalFunction(emptyRecord7)
+                  listener: beginMetadataStar(()
+                  listener: endMetadataStar(0)
+                  parseRecordType((, ;)
+                    listener: beginRecordType(()
+                    parseRecordTypeField((, identifierIsOptional: true)
+                      listener: beginRecordTypeEntry()
+                      parseMetadataStar(()
+                        listener: beginMetadataStar(int)
+                        listener: endMetadataStar(0)
+                      listener: handleIdentifier(int, typeReference)
+                      listener: handleNoTypeArguments(,)
+                      listener: handleType(int, null)
+                      listener: handleNoName(,)
+                      listener: endRecordTypeEntry()
+                    parseRecordTypeField(,, identifierIsOptional: true)
+                      listener: beginRecordTypeEntry()
+                      parseMetadataStar(,)
+                        listener: beginMetadataStar(,)
+                        listener: endMetadataStar(0)
+                      reportRecoverableErrorWithToken(,, Instance of 'Template<(Token) => Message>')
+                        listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got ','., null, {lexeme: ,}], ,, ,)
+                      rewriter()
+                      listener: handleIdentifier(, typeReference)
+                      listener: handleNoTypeArguments(,)
+                      listener: handleType(, null)
+                      listener: handleNoName(,)
+                      listener: endRecordTypeEntry()
+                    parseRecordTypeField(,, identifierIsOptional: true)
+                      listener: beginRecordTypeEntry()
+                      parseMetadataStar(,)
+                        listener: beginMetadataStar(,)
+                        listener: endMetadataStar(0)
+                      reportRecoverableErrorWithToken(,, Instance of 'Template<(Token) => Message>')
+                        listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got ','., null, {lexeme: ,}], ,, ,)
+                      rewriter()
+                      listener: handleIdentifier(, typeReference)
+                      listener: handleNoTypeArguments(,)
+                      listener: handleType(, null)
+                      listener: handleNoName(,)
+                      listener: endRecordTypeEntry()
+                    listener: endRecordType((, null, 3, false)
+                  listener: beginVariablesDeclaration(emptyRecord7, null, null)
+                  parseVariablesDeclarationRest(), true)
+                    parseOptionallyInitializedIdentifier())
+                      ensureIdentifier(), localVariableDeclaration)
+                        listener: handleIdentifier(emptyRecord7, localVariableDeclaration)
+                      listener: beginInitializedIdentifier(emptyRecord7)
+                      parseVariableInitializerOpt(emptyRecord7)
+                        listener: beginVariableInitializer(=)
+                        parseExpression(=)
+                          parsePrecedenceExpression(=, 1, true)
+                            parseUnaryExpression(=, true)
+                              parsePrimary(=, expression)
+                                parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=)
+                                  parseParenthesizedExpressionOrRecordLiteral(=, null)
+                                    listener: beginParenthesizedExpressionOrRecordLiteral(()
+                                    parseExpression(()
+                                      parsePrecedenceExpression((, 1, true)
+                                        parseUnaryExpression((, true)
+                                          parsePrimary((, expression)
+                                            parseLiteralInt(()
+                                              listener: handleLiteralInt(42)
+                                    parseExpression(,)
+                                      parsePrecedenceExpression(,, 1, true)
+                                        parseUnaryExpression(,, true)
+                                          parsePrimary(,, expression)
+                                            parseLiteralInt(,)
+                                              listener: handleLiteralInt(42)
+                                    parseExpression(,)
+                                      parsePrecedenceExpression(,, 1, true)
+                                        parseUnaryExpression(,, true)
+                                          parsePrimary(,, expression)
+                                            parseSend(,, expression)
+                                              isNextIdentifier(,)
+                                              ensureIdentifier(,, expression)
+                                                reportRecoverableErrorWithToken(,, Instance of 'Template<(Token) => Message>')
+                                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ','., Try inserting an identifier before ','., {lexeme: ,}], ,, ,)
+                                                rewriter()
+                                                listener: handleIdentifier(, expression)
+                                              listener: handleNoTypeArguments(,)
+                                              parseArgumentsOpt()
+                                                listener: handleNoArguments(,)
+                                              listener: handleSend(, ,)
+                                    parseExpression(,)
+                                      parsePrecedenceExpression(,, 1, true)
+                                        parseUnaryExpression(,, true)
+                                          parsePrimary(,, expression)
+                                            parseSend(,, expression)
+                                              isNextIdentifier(,)
+                                              ensureIdentifier(,, expression)
+                                                reportRecoverableErrorWithToken(,, Instance of 'Template<(Token) => Message>')
+                                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ','., Try inserting an identifier before ','., {lexeme: ,}], ,, ,)
+                                                rewriter()
+                                                listener: handleIdentifier(, expression)
+                                              listener: handleNoTypeArguments(,)
+                                              parseArgumentsOpt()
+                                                listener: handleNoArguments(,)
+                                              listener: handleSend(, ,)
+                                    ensureCloseParen(,, ()
+                                    listener: endRecordLiteral((, 4, null)
+                        listener: endVariableInitializer(=)
+                      listener: endInitializedIdentifier(emptyRecord7)
+                    ensureSemicolon())
+                    listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, ()
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclaration(;, false)
+                parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                  looksLikeLocalFunction(emptyRecord8)
+                  listener: beginMetadataStar(()
+                  listener: endMetadataStar(0)
+                  parseRecordType((, ;)
+                    listener: beginRecordType(()
+                    parseRecordTypeField((, identifierIsOptional: true)
+                      listener: beginRecordTypeEntry()
+                      parseMetadataStar(()
+                        listener: beginMetadataStar(int)
+                        listener: endMetadataStar(0)
+                      listener: handleIdentifier(int, typeReference)
+                      listener: handleNoTypeArguments(,)
+                      listener: handleType(int, null)
+                      listener: handleNoName(,)
+                      listener: endRecordTypeEntry()
+                    parseRecordTypeField(,, identifierIsOptional: true)
+                      listener: beginRecordTypeEntry()
+                      parseMetadataStar(,)
+                        listener: beginMetadataStar(int)
+                        listener: endMetadataStar(0)
+                      listener: handleIdentifier(int, typeReference)
+                      listener: handleNoTypeArguments(,)
+                      listener: handleType(int, null)
+                      listener: handleNoName(,)
+                      listener: endRecordTypeEntry()
+                    parseRecordTypeField(,, identifierIsOptional: true)
+                      listener: beginRecordTypeEntry()
+                      parseMetadataStar(,)
+                        listener: beginMetadataStar(,)
+                        listener: endMetadataStar(0)
+                      reportRecoverableErrorWithToken(,, Instance of 'Template<(Token) => Message>')
+                        listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got ','., null, {lexeme: ,}], ,, ,)
+                      rewriter()
+                      listener: handleIdentifier(, typeReference)
+                      listener: handleNoTypeArguments(,)
+                      listener: handleType(, null)
+                      listener: handleNoName(,)
+                      listener: endRecordTypeEntry()
+                    parseRecordTypeField(,, identifierIsOptional: true)
+                      listener: beginRecordTypeEntry()
+                      parseMetadataStar(,)
+                        listener: beginMetadataStar(,)
+                        listener: endMetadataStar(0)
+                      reportRecoverableErrorWithToken(,, Instance of 'Template<(Token) => Message>')
+                        listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got ','., null, {lexeme: ,}], ,, ,)
+                      rewriter()
+                      listener: handleIdentifier(, typeReference)
+                      listener: handleNoTypeArguments(,)
+                      listener: handleType(, null)
+                      listener: handleNoName(,)
+                      listener: endRecordTypeEntry()
+                    listener: endRecordType((, null, 4, false)
+                  listener: beginVariablesDeclaration(emptyRecord8, null, null)
+                  parseVariablesDeclarationRest(), true)
+                    parseOptionallyInitializedIdentifier())
+                      ensureIdentifier(), localVariableDeclaration)
+                        listener: handleIdentifier(emptyRecord8, localVariableDeclaration)
+                      listener: beginInitializedIdentifier(emptyRecord8)
+                      parseVariableInitializerOpt(emptyRecord8)
+                        listener: beginVariableInitializer(=)
+                        parseExpression(=)
+                          parsePrecedenceExpression(=, 1, true)
+                            parseUnaryExpression(=, true)
+                              parsePrimary(=, expression)
+                                parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=)
+                                  parseParenthesizedExpressionOrRecordLiteral(=, null)
+                                    listener: beginParenthesizedExpressionOrRecordLiteral(()
+                                    parseExpression(()
+                                      parsePrecedenceExpression((, 1, true)
+                                        parseUnaryExpression((, true)
+                                          parsePrimary((, expression)
+                                            parseLiteralInt(()
+                                              listener: handleLiteralInt(42)
+                                    parseExpression(,)
+                                      parsePrecedenceExpression(,, 1, true)
+                                        parseUnaryExpression(,, true)
+                                          parsePrimary(,, expression)
+                                            parseLiteralInt(,)
+                                              listener: handleLiteralInt(42)
+                                    parseExpression(,)
+                                      parsePrecedenceExpression(,, 1, true)
+                                        parseUnaryExpression(,, true)
+                                          parsePrimary(,, expression)
+                                            parseSend(,, expression)
+                                              isNextIdentifier(,)
+                                              ensureIdentifier(,, expression)
+                                                reportRecoverableErrorWithToken(,, Instance of 'Template<(Token) => Message>')
+                                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ','., Try inserting an identifier before ','., {lexeme: ,}], ,, ,)
+                                                rewriter()
+                                                listener: handleIdentifier(, expression)
+                                              listener: handleNoTypeArguments(,)
+                                              parseArgumentsOpt()
+                                                listener: handleNoArguments(,)
+                                              listener: handleSend(, ,)
+                                    parseExpression(,)
+                                      parsePrecedenceExpression(,, 1, true)
+                                        parseUnaryExpression(,, true)
+                                          parsePrimary(,, expression)
+                                            parseSend(,, expression)
+                                              isNextIdentifier(,)
+                                              ensureIdentifier(,, expression)
+                                                reportRecoverableErrorWithToken(,, Instance of 'Template<(Token) => Message>')
+                                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ','., Try inserting an identifier before ','., {lexeme: ,}], ,, ,)
+                                                rewriter()
+                                                listener: handleIdentifier(, expression)
+                                              listener: handleNoTypeArguments(,)
+                                              parseArgumentsOpt()
+                                                listener: handleNoArguments(,)
+                                              listener: handleSend(, ,)
+                                    ensureCloseParen(,, ()
+                                    listener: endRecordLiteral((, 4, null)
+                        listener: endVariableInitializer(=)
+                      listener: endInitializedIdentifier(emptyRecord8)
+                    ensureSemicolon())
+                    listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(8, {, })
+        listener: endTopLevelMethod(main, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(main)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/record/record_and_commas.dart.parser.expect b/pkg/front_end/parser_testcases/record/record_and_commas.dart.parser.expect
new file mode 100644
index 0000000..21fec6a
--- /dev/null
+++ b/pkg/front_end/parser_testcases/record/record_and_commas.dart.parser.expect
@@ -0,0 +1,33 @@
+NOTICE: Stream was rewritten by parser!
+
+main() {
+
+() emptyRecord1 = ();
+
+
+(,) emptyRecord2 = ();
+() emptyRecord3 = (,);
+(,) emptyRecord4 = (,);
+
+
+(int, *synthetic*,) emptyRecord5 = (42, 42, *synthetic*,);
+(int, int, *synthetic*,) emptyRecord6 = (42, 42, *synthetic*,);
+(int, *synthetic*, *synthetic*,) emptyRecord7 = (42, 42, *synthetic*, *synthetic*,);
+(int, int, *synthetic*, *synthetic*,) emptyRecord8 = (42, 42, *synthetic*, *synthetic*,);
+}
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+
+([BeginToken])[SimpleToken] emptyRecord1[StringToken] =[SimpleToken] ([BeginToken])[SimpleToken];[SimpleToken]
+
+
+([BeginToken],[SimpleToken])[SimpleToken] emptyRecord2[StringToken] =[SimpleToken] ([BeginToken])[SimpleToken];[SimpleToken]
+([BeginToken])[SimpleToken] emptyRecord3[StringToken] =[SimpleToken] ([BeginToken],[SimpleToken])[SimpleToken];[SimpleToken]
+([BeginToken],[SimpleToken])[SimpleToken] emptyRecord4[StringToken] =[SimpleToken] ([BeginToken],[SimpleToken])[SimpleToken];[SimpleToken]
+
+
+([BeginToken]int[StringToken],[SimpleToken] [SyntheticStringToken],[SimpleToken])[SimpleToken] emptyRecord5[StringToken] =[SimpleToken] ([BeginToken]42[StringToken],[SimpleToken] 42[StringToken],[SimpleToken] [SyntheticStringToken],[SimpleToken])[SimpleToken];[SimpleToken]
+([BeginToken]int[StringToken],[SimpleToken] int[StringToken],[SimpleToken] [SyntheticStringToken],[SimpleToken])[SimpleToken] emptyRecord6[StringToken] =[SimpleToken] ([BeginToken]42[StringToken],[SimpleToken] 42[StringToken],[SimpleToken] [SyntheticStringToken],[SimpleToken])[SimpleToken];[SimpleToken]
+([BeginToken]int[StringToken],[SimpleToken] [SyntheticStringToken],[SimpleToken] [SyntheticStringToken],[SimpleToken])[SimpleToken] emptyRecord7[StringToken] =[SimpleToken] ([BeginToken]42[StringToken],[SimpleToken] 42[StringToken],[SimpleToken] [SyntheticStringToken],[SimpleToken] [SyntheticStringToken],[SimpleToken])[SimpleToken];[SimpleToken]
+([BeginToken]int[StringToken],[SimpleToken] int[StringToken],[SimpleToken] [SyntheticStringToken],[SimpleToken] [SyntheticStringToken],[SimpleToken])[SimpleToken] emptyRecord8[StringToken] =[SimpleToken] ([BeginToken]42[StringToken],[SimpleToken] 42[StringToken],[SimpleToken] [SyntheticStringToken],[SimpleToken] [SyntheticStringToken],[SimpleToken])[SimpleToken];[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/record/record_and_commas.dart.scanner.expect b/pkg/front_end/parser_testcases/record/record_and_commas.dart.scanner.expect
new file mode 100644
index 0000000..314dff3
--- /dev/null
+++ b/pkg/front_end/parser_testcases/record/record_and_commas.dart.scanner.expect
@@ -0,0 +1,31 @@
+main() {
+
+() emptyRecord1 = ();
+
+
+(,) emptyRecord2 = ();
+() emptyRecord3 = (,);
+(,) emptyRecord4 = (,);
+
+
+(int, ,) emptyRecord5 = (42, 42, ,);
+(int, int, ,) emptyRecord6 = (42, 42, ,);
+(int, , ,) emptyRecord7 = (42, 42, , ,);
+(int, int, , ,) emptyRecord8 = (42, 42, , ,);
+}
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+
+([BeginToken])[SimpleToken] emptyRecord1[StringToken] =[SimpleToken] ([BeginToken])[SimpleToken];[SimpleToken]
+
+
+([BeginToken],[SimpleToken])[SimpleToken] emptyRecord2[StringToken] =[SimpleToken] ([BeginToken])[SimpleToken];[SimpleToken]
+([BeginToken])[SimpleToken] emptyRecord3[StringToken] =[SimpleToken] ([BeginToken],[SimpleToken])[SimpleToken];[SimpleToken]
+([BeginToken],[SimpleToken])[SimpleToken] emptyRecord4[StringToken] =[SimpleToken] ([BeginToken],[SimpleToken])[SimpleToken];[SimpleToken]
+
+
+([BeginToken]int[StringToken],[SimpleToken] ,[SimpleToken])[SimpleToken] emptyRecord5[StringToken] =[SimpleToken] ([BeginToken]42[StringToken],[SimpleToken] 42[StringToken],[SimpleToken] ,[SimpleToken])[SimpleToken];[SimpleToken]
+([BeginToken]int[StringToken],[SimpleToken] int[StringToken],[SimpleToken] ,[SimpleToken])[SimpleToken] emptyRecord6[StringToken] =[SimpleToken] ([BeginToken]42[StringToken],[SimpleToken] 42[StringToken],[SimpleToken] ,[SimpleToken])[SimpleToken];[SimpleToken]
+([BeginToken]int[StringToken],[SimpleToken] ,[SimpleToken] ,[SimpleToken])[SimpleToken] emptyRecord7[StringToken] =[SimpleToken] ([BeginToken]42[StringToken],[SimpleToken] 42[StringToken],[SimpleToken] ,[SimpleToken] ,[SimpleToken])[SimpleToken];[SimpleToken]
+([BeginToken]int[StringToken],[SimpleToken] int[StringToken],[SimpleToken] ,[SimpleToken] ,[SimpleToken])[SimpleToken] emptyRecord8[StringToken] =[SimpleToken] ([BeginToken]42[StringToken],[SimpleToken] 42[StringToken],[SimpleToken] ,[SimpleToken] ,[SimpleToken])[SimpleToken];[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/record/record_literal_04.dart b/pkg/front_end/parser_testcases/record/record_literal_04.dart
index 80a2b50..470e3a8 100644
--- a/pkg/front_end/parser_testcases/record/record_literal_04.dart
+++ b/pkg/front_end/parser_testcases/record/record_literal_04.dart
@@ -8,7 +8,7 @@
   // Error: Const makes it a record (I guess), but there's no trailing comma.
   var r5 = const (42);
 
-  // Error: A record needs at least one element.
+  // OK: A record can have 0 elements.
   var r6 = const ();
 }
 
diff --git a/pkg/front_end/parser_testcases/record/record_literal_04.dart.expect b/pkg/front_end/parser_testcases/record/record_literal_04.dart.expect
index d56b116..51e51f6 100644
--- a/pkg/front_end/parser_testcases/record/record_literal_04.dart.expect
+++ b/pkg/front_end/parser_testcases/record/record_literal_04.dart.expect
@@ -4,10 +4,6 @@
   var r5 = const (42);
                     ^
 
-parser/record/record_literal_04:12:19: Record literal can't be empty.
-  var r6 = const ();
-                  ^
-
 beginCompilationUnit(void)
   beginMetadataStar(void)
   endMetadataStar(0)
@@ -121,7 +117,6 @@
             beginVariableInitializer(=)
               beginConstLiteral(()
                 beginParenthesizedExpressionOrRecordLiteral(()
-                  handleRecoverableError(RecordLiteralEmpty, ), ))
                 endRecordLiteral((, 0, const)
               endConstLiteral(;)
             endVariableInitializer(=)
diff --git a/pkg/front_end/parser_testcases/record/record_literal_04.dart.intertwined.expect b/pkg/front_end/parser_testcases/record/record_literal_04.dart.intertwined.expect
index 87a505b..049c77b 100644
--- a/pkg/front_end/parser_testcases/record/record_literal_04.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/record/record_literal_04.dart.intertwined.expect
@@ -288,8 +288,6 @@
                                 parseParenthesizedExpressionOrRecordLiteral(const, const)
                                   listener: beginParenthesizedExpressionOrRecordLiteral(()
                                   ensureCloseParen((, ()
-                                  reportRecoverableError(), RecordLiteralEmpty)
-                                    listener: handleRecoverableError(RecordLiteralEmpty, ), ))
                                   listener: endRecordLiteral((, 0, const)
                                 listener: endConstLiteral(;)
                       listener: endVariableInitializer(=)
diff --git a/pkg/front_end/parser_testcases/record/record_type_02.dart b/pkg/front_end/parser_testcases/record/record_type_02.dart
index 3ef1eac..cd20603 100644
--- a/pkg/front_end/parser_testcases/record/record_type_02.dart
+++ b/pkg/front_end/parser_testcases/record/record_type_02.dart
@@ -6,5 +6,5 @@
 void ok() {
   (int, ) record1 = (1, );
   ({int ok}) record2 = (ok: 1);
-  () record3 = Record.empty;
+  () record3 = ();
 }
diff --git a/pkg/front_end/parser_testcases/record/record_type_02.dart.expect b/pkg/front_end/parser_testcases/record/record_type_02.dart.expect
index fb6031a..d485df1 100644
--- a/pkg/front_end/parser_testcases/record/record_type_02.dart.expect
+++ b/pkg/front_end/parser_testcases/record/record_type_02.dart.expect
@@ -147,15 +147,8 @@
           handleIdentifier(record3, localVariableDeclaration)
           beginInitializedIdentifier(record3)
             beginVariableInitializer(=)
-              handleIdentifier(Record, expression)
-              handleNoTypeArguments(.)
-              handleNoArguments(.)
-              handleSend(Record, .)
-              handleIdentifier(empty, expressionContinuation)
-              handleNoTypeArguments(;)
-              handleNoArguments(;)
-              handleSend(empty, ;)
-              handleEndingBinaryExpression(.)
+              beginParenthesizedExpressionOrRecordLiteral(()
+              endRecordLiteral((, 0, null)
             endVariableInitializer(=)
           endInitializedIdentifier(record3)
         endVariablesDeclaration(1, ;)
diff --git a/pkg/front_end/parser_testcases/record/record_type_02.dart.intertwined.expect b/pkg/front_end/parser_testcases/record/record_type_02.dart.intertwined.expect
index 6ffd80e..8d7bed4 100644
--- a/pkg/front_end/parser_testcases/record/record_type_02.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/record/record_type_02.dart.intertwined.expect
@@ -299,29 +299,14 @@
                           parsePrecedenceExpression(=, 1, true)
                             parseUnaryExpression(=, true)
                               parsePrimary(=, expression)
-                                parseSendOrFunctionLiteral(=, expression)
-                                  parseSend(=, expression)
-                                    isNextIdentifier(=)
-                                    ensureIdentifier(=, expression)
-                                      listener: handleIdentifier(Record, expression)
-                                    listener: handleNoTypeArguments(.)
-                                    parseArgumentsOpt(Record)
-                                      listener: handleNoArguments(.)
-                                    listener: handleSend(Record, .)
-                            parsePrimary(., expressionContinuation)
-                              parseSendOrFunctionLiteral(., expressionContinuation)
-                                parseSend(., expressionContinuation)
-                                  isNextIdentifier(.)
-                                  ensureIdentifier(., expressionContinuation)
-                                    listener: handleIdentifier(empty, expressionContinuation)
-                                  listener: handleNoTypeArguments(;)
-                                  parseArgumentsOpt(empty)
-                                    listener: handleNoArguments(;)
-                                  listener: handleSend(empty, ;)
-                            listener: handleEndingBinaryExpression(.)
+                                parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=)
+                                  parseParenthesizedExpressionOrRecordLiteral(=, null)
+                                    listener: beginParenthesizedExpressionOrRecordLiteral(()
+                                    ensureCloseParen((, ()
+                                    listener: endRecordLiteral((, 0, null)
                         listener: endVariableInitializer(=)
                       listener: endInitializedIdentifier(record3)
-                    ensureSemicolon(empty)
+                    ensureSemicolon())
                     listener: endVariablesDeclaration(1, ;)
           notEofOrValue(}, })
           listener: endBlockFunctionBody(3, {, })
diff --git a/pkg/front_end/parser_testcases/record/record_type_02.dart.parser.expect b/pkg/front_end/parser_testcases/record/record_type_02.dart.parser.expect
index 92d366c..245b8d2 100644
--- a/pkg/front_end/parser_testcases/record/record_type_02.dart.parser.expect
+++ b/pkg/front_end/parser_testcases/record/record_type_02.dart.parser.expect
@@ -6,7 +6,7 @@
 void ok() {
 (int, ) record1 = (1, );
 ({int ok}) record2 = (ok: 1);
-() record3 = Record.empty;
+() record3 = ();
 }
 
 
@@ -18,6 +18,6 @@
 void[KeywordToken] ok[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
 ([BeginToken]int[StringToken],[SimpleToken] )[SimpleToken] record1[StringToken] =[SimpleToken] ([BeginToken]1[StringToken],[SimpleToken] )[SimpleToken];[SimpleToken]
 ([BeginToken]{[BeginToken]int[StringToken] ok[StringToken]}[SimpleToken])[SimpleToken] record2[StringToken] =[SimpleToken] ([BeginToken]ok[StringToken]:[SimpleToken] 1[StringToken])[SimpleToken];[SimpleToken]
-([BeginToken])[SimpleToken] record3[StringToken] =[SimpleToken] Record[StringToken].[SimpleToken]empty[StringToken];[SimpleToken]
+([BeginToken])[SimpleToken] record3[StringToken] =[SimpleToken] ([BeginToken])[SimpleToken];[SimpleToken]
 }[SimpleToken]
 [SimpleToken]
diff --git a/pkg/front_end/parser_testcases/record/record_type_02.dart.scanner.expect b/pkg/front_end/parser_testcases/record/record_type_02.dart.scanner.expect
index 92d366c..245b8d2 100644
--- a/pkg/front_end/parser_testcases/record/record_type_02.dart.scanner.expect
+++ b/pkg/front_end/parser_testcases/record/record_type_02.dart.scanner.expect
@@ -6,7 +6,7 @@
 void ok() {
 (int, ) record1 = (1, );
 ({int ok}) record2 = (ok: 1);
-() record3 = Record.empty;
+() record3 = ();
 }
 
 
@@ -18,6 +18,6 @@
 void[KeywordToken] ok[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
 ([BeginToken]int[StringToken],[SimpleToken] )[SimpleToken] record1[StringToken] =[SimpleToken] ([BeginToken]1[StringToken],[SimpleToken] )[SimpleToken];[SimpleToken]
 ([BeginToken]{[BeginToken]int[StringToken] ok[StringToken]}[SimpleToken])[SimpleToken] record2[StringToken] =[SimpleToken] ([BeginToken]ok[StringToken]:[SimpleToken] 1[StringToken])[SimpleToken];[SimpleToken]
-([BeginToken])[SimpleToken] record3[StringToken] =[SimpleToken] Record[StringToken].[SimpleToken]empty[StringToken];[SimpleToken]
+([BeginToken])[SimpleToken] record3[StringToken] =[SimpleToken] ([BeginToken])[SimpleToken];[SimpleToken]
 }[SimpleToken]
 [SimpleToken]
diff --git a/pkg/front_end/test/spell_checking_list_messages.txt b/pkg/front_end/test/spell_checking_list_messages.txt
index 575ec3d..ce82309 100644
--- a/pkg/front_end/test/spell_checking_list_messages.txt
+++ b/pkg/front_end/test/spell_checking_list_messages.txt
@@ -73,7 +73,6 @@
 pubspec.yaml
 r
 re
-record.empty
 sdksummary
 size
 solutions
diff --git a/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.expect b/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.expect
index a97af90..caee8d2 100644
--- a/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.expect
+++ b/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.expect
@@ -315,10 +315,13 @@
 //   C.this();
 //     ^^^^
 //
-// pkg/front_end/testcases/general/duplicated_declarations.dart:40:6: Error: Expected an identifier, but got ')'.
-// Try inserting an identifier before ')'.
+// pkg/front_end/testcases/general/duplicated_declarations.dart:40:5: Error: The 'records' language feature is disabled for this library.
+// Try removing the `@dart=` annotation or setting the language version to 2.19 or higher.
 //   C.();
-//      ^
+//     ^
+// pkg/front_end/testcases/general/duplicated_declarations.dart:5:1: Context: This is the annotation that opts out this library from the 'records' language feature.
+// // @dart=2.16
+// ^^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/general/duplicated_declarations.dart:40:5: Error: Expected an identifier, but got '('.
 // Try inserting an identifier before '('.
diff --git a/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.modular.expect b/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.modular.expect
index a97af90..caee8d2 100644
--- a/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.modular.expect
@@ -315,10 +315,13 @@
 //   C.this();
 //     ^^^^
 //
-// pkg/front_end/testcases/general/duplicated_declarations.dart:40:6: Error: Expected an identifier, but got ')'.
-// Try inserting an identifier before ')'.
+// pkg/front_end/testcases/general/duplicated_declarations.dart:40:5: Error: The 'records' language feature is disabled for this library.
+// Try removing the `@dart=` annotation or setting the language version to 2.19 or higher.
 //   C.();
-//      ^
+//     ^
+// pkg/front_end/testcases/general/duplicated_declarations.dart:5:1: Context: This is the annotation that opts out this library from the 'records' language feature.
+// // @dart=2.16
+// ^^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/general/duplicated_declarations.dart:40:5: Error: Expected an identifier, but got '('.
 // Try inserting an identifier before '('.
diff --git a/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.transformed.expect b/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.transformed.expect
index a97af90..caee8d2 100644
--- a/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/duplicated_declarations.dart.weak.transformed.expect
@@ -315,10 +315,13 @@
 //   C.this();
 //     ^^^^
 //
-// pkg/front_end/testcases/general/duplicated_declarations.dart:40:6: Error: Expected an identifier, but got ')'.
-// Try inserting an identifier before ')'.
+// pkg/front_end/testcases/general/duplicated_declarations.dart:40:5: Error: The 'records' language feature is disabled for this library.
+// Try removing the `@dart=` annotation or setting the language version to 2.19 or higher.
 //   C.();
-//      ^
+//     ^
+// pkg/front_end/testcases/general/duplicated_declarations.dart:5:1: Context: This is the annotation that opts out this library from the 'records' language feature.
+// // @dart=2.16
+// ^^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/general/duplicated_declarations.dart:40:5: Error: Expected an identifier, but got '('.
 // Try inserting an identifier before '('.
diff --git a/pkg/front_end/testcases/general/issue44347.dart.weak.expect b/pkg/front_end/testcases/general/issue44347.dart.weak.expect
index bd718d5..c8486b3 100644
--- a/pkg/front_end/testcases/general/issue44347.dart.weak.expect
+++ b/pkg/front_end/testcases/general/issue44347.dart.weak.expect
@@ -2,11 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/issue44347.dart:6:13: Error: Expected an identifier, but got ')'.
-// Try inserting an identifier before ')'.
-//   Set<int>.();
-//             ^
-//
 // pkg/front_end/testcases/general/issue44347.dart:6:12: Error: Expected an identifier, but got '('.
 // Try inserting an identifier before '('.
 //   Set<int>.();
diff --git a/pkg/front_end/testcases/general/issue44347.dart.weak.modular.expect b/pkg/front_end/testcases/general/issue44347.dart.weak.modular.expect
index bd718d5..c8486b3 100644
--- a/pkg/front_end/testcases/general/issue44347.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/general/issue44347.dart.weak.modular.expect
@@ -2,11 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/issue44347.dart:6:13: Error: Expected an identifier, but got ')'.
-// Try inserting an identifier before ')'.
-//   Set<int>.();
-//             ^
-//
 // pkg/front_end/testcases/general/issue44347.dart:6:12: Error: Expected an identifier, but got '('.
 // Try inserting an identifier before '('.
 //   Set<int>.();
diff --git a/pkg/front_end/testcases/general/issue44347.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue44347.dart.weak.transformed.expect
index bd718d5..c8486b3 100644
--- a/pkg/front_end/testcases/general/issue44347.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/issue44347.dart.weak.transformed.expect
@@ -2,11 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/issue44347.dart:6:13: Error: Expected an identifier, but got ')'.
-// Try inserting an identifier before ')'.
-//   Set<int>.();
-//             ^
-//
 // pkg/front_end/testcases/general/issue44347.dart:6:12: Error: Expected an identifier, but got '('.
 // Try inserting an identifier before '('.
 //   Set<int>.();
diff --git a/pkg/front_end/testcases/records/record_literal.dart.strong.expect b/pkg/front_end/testcases/records/record_literal.dart.strong.expect
index 4aebeca..f6467d6 100644
--- a/pkg/front_end/testcases/records/record_literal.dart.strong.expect
+++ b/pkg/front_end/testcases/records/record_literal.dart.strong.expect
@@ -1,12 +1,4 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/records/record_literal.dart:6:4: Error: Expected an identifier, but got ')'.
-// Try inserting an identifier before ')'.
-//   ();
-//    ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -19,14 +11,12 @@
   }
 }
 static method method() → dynamic {
-  invalid-expression "pkg/front_end/testcases/records/record_literal.dart:6:4: Error: This couldn't be parsed.
-  ();
-   ^";
+  #C1;
   (0, 1);
   (0, {b: 1});
   ({a: 0, b: 1});
   let final core::int #t1 = 0 in (1, {a: #t1});
-  #C3;
+  #C4;
 }
 static method sorting() → dynamic {
   ({a: 0, b: 1, c: 2, d: 3});
@@ -42,7 +32,8 @@
 }
 
 constants  {
-  #C1 = TypeLiteralConstant(core::int)
-  #C2 = TypeLiteralConstant(core::String)
-  #C3 = (#C1, #C2)
+  #C1 = ()
+  #C2 = TypeLiteralConstant(core::int)
+  #C3 = TypeLiteralConstant(core::String)
+  #C4 = (#C2, #C3)
 }
diff --git a/pkg/front_end/testcases/records/record_literal.dart.strong.transformed.expect b/pkg/front_end/testcases/records/record_literal.dart.strong.transformed.expect
index 2ae1669..3b66c78 100644
--- a/pkg/front_end/testcases/records/record_literal.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/records/record_literal.dart.strong.transformed.expect
@@ -1,12 +1,4 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/records/record_literal.dart:6:4: Error: Expected an identifier, but got ')'.
-// Try inserting an identifier before ')'.
-//   ();
-//    ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -19,14 +11,12 @@
   }
 }
 static method method() → dynamic {
-  invalid-expression "pkg/front_end/testcases/records/record_literal.dart:6:4: Error: This couldn't be parsed.
-  ();
-   ^";
+  #C1;
   (0, 1);
   (0, {b: 1});
   ({a: 0, b: 1});
   let final core::int #t1 = 0 in (1, {a: #t1});
-  #C3;
+  #C4;
 }
 static method sorting() → dynamic {
   ({a: 0, b: 1, c: 2, d: 3});
@@ -42,9 +32,10 @@
 }
 
 constants  {
-  #C1 = TypeLiteralConstant(core::int)
-  #C2 = TypeLiteralConstant(core::String)
-  #C3 = (#C1, #C2)
+  #C1 = ()
+  #C2 = TypeLiteralConstant(core::int)
+  #C3 = TypeLiteralConstant(core::String)
+  #C4 = (#C2, #C3)
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/records/record_literal.dart.weak.expect b/pkg/front_end/testcases/records/record_literal.dart.weak.expect
index da16fca..5772679e 100644
--- a/pkg/front_end/testcases/records/record_literal.dart.weak.expect
+++ b/pkg/front_end/testcases/records/record_literal.dart.weak.expect
@@ -1,12 +1,4 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/records/record_literal.dart:6:4: Error: Expected an identifier, but got ')'.
-// Try inserting an identifier before ')'.
-//   ();
-//    ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -19,14 +11,12 @@
   }
 }
 static method method() → dynamic {
-  invalid-expression "pkg/front_end/testcases/records/record_literal.dart:6:4: Error: This couldn't be parsed.
-  ();
-   ^";
+  #C1;
   (0, 1);
   (0, {b: 1});
   ({a: 0, b: 1});
   let final core::int #t1 = 0 in (1, {a: #t1});
-  #C3;
+  #C4;
 }
 static method sorting() → dynamic {
   ({a: 0, b: 1, c: 2, d: 3});
@@ -42,7 +32,8 @@
 }
 
 constants  {
-  #C1 = TypeLiteralConstant(core::int*)
-  #C2 = TypeLiteralConstant(core::String*)
-  #C3 = (#C1, #C2)
+  #C1 = ()
+  #C2 = TypeLiteralConstant(core::int*)
+  #C3 = TypeLiteralConstant(core::String*)
+  #C4 = (#C2, #C3)
 }
diff --git a/pkg/front_end/testcases/records/record_literal.dart.weak.modular.expect b/pkg/front_end/testcases/records/record_literal.dart.weak.modular.expect
index da16fca..5772679e 100644
--- a/pkg/front_end/testcases/records/record_literal.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/records/record_literal.dart.weak.modular.expect
@@ -1,12 +1,4 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/records/record_literal.dart:6:4: Error: Expected an identifier, but got ')'.
-// Try inserting an identifier before ')'.
-//   ();
-//    ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -19,14 +11,12 @@
   }
 }
 static method method() → dynamic {
-  invalid-expression "pkg/front_end/testcases/records/record_literal.dart:6:4: Error: This couldn't be parsed.
-  ();
-   ^";
+  #C1;
   (0, 1);
   (0, {b: 1});
   ({a: 0, b: 1});
   let final core::int #t1 = 0 in (1, {a: #t1});
-  #C3;
+  #C4;
 }
 static method sorting() → dynamic {
   ({a: 0, b: 1, c: 2, d: 3});
@@ -42,7 +32,8 @@
 }
 
 constants  {
-  #C1 = TypeLiteralConstant(core::int*)
-  #C2 = TypeLiteralConstant(core::String*)
-  #C3 = (#C1, #C2)
+  #C1 = ()
+  #C2 = TypeLiteralConstant(core::int*)
+  #C3 = TypeLiteralConstant(core::String*)
+  #C4 = (#C2, #C3)
 }
diff --git a/pkg/front_end/testcases/records/record_literal.dart.weak.transformed.expect b/pkg/front_end/testcases/records/record_literal.dart.weak.transformed.expect
index 430692b..f6c3936 100644
--- a/pkg/front_end/testcases/records/record_literal.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/records/record_literal.dart.weak.transformed.expect
@@ -1,12 +1,4 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/records/record_literal.dart:6:4: Error: Expected an identifier, but got ')'.
-// Try inserting an identifier before ')'.
-//   ();
-//    ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -19,14 +11,12 @@
   }
 }
 static method method() → dynamic {
-  invalid-expression "pkg/front_end/testcases/records/record_literal.dart:6:4: Error: This couldn't be parsed.
-  ();
-   ^";
+  #C1;
   (0, 1);
   (0, {b: 1});
   ({a: 0, b: 1});
   let final core::int #t1 = 0 in (1, {a: #t1});
-  #C3;
+  #C4;
 }
 static method sorting() → dynamic {
   ({a: 0, b: 1, c: 2, d: 3});
@@ -42,9 +32,10 @@
 }
 
 constants  {
-  #C1 = TypeLiteralConstant(core::int*)
-  #C2 = TypeLiteralConstant(core::String*)
-  #C3 = (#C1, #C2)
+  #C1 = ()
+  #C2 = TypeLiteralConstant(core::int*)
+  #C3 = TypeLiteralConstant(core::String*)
+  #C4 = (#C2, #C3)
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/regress/issue_31198.dart.weak.expect b/pkg/front_end/testcases/regress/issue_31198.dart.weak.expect
index 63411d2..c773bb3 100644
--- a/pkg/front_end/testcases/regress/issue_31198.dart.weak.expect
+++ b/pkg/front_end/testcases/regress/issue_31198.dart.weak.expect
@@ -2,11 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_31198.dart:10:24: Error: Expected an identifier, but got ')'.
-// Try inserting an identifier before ')'.
-//   B.named2(): super().() {}
-//                        ^
-//
 // pkg/front_end/testcases/regress/issue_31198.dart:8:8: Error: Can't use 'super' as an expression.
 // To delegate a constructor to a super constructor, put the super call as an initializer.
 //   B(): super().foo() {}
diff --git a/pkg/front_end/testcases/regress/issue_31198.dart.weak.modular.expect b/pkg/front_end/testcases/regress/issue_31198.dart.weak.modular.expect
index 63411d2..c773bb3 100644
--- a/pkg/front_end/testcases/regress/issue_31198.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/regress/issue_31198.dart.weak.modular.expect
@@ -2,11 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_31198.dart:10:24: Error: Expected an identifier, but got ')'.
-// Try inserting an identifier before ')'.
-//   B.named2(): super().() {}
-//                        ^
-//
 // pkg/front_end/testcases/regress/issue_31198.dart:8:8: Error: Can't use 'super' as an expression.
 // To delegate a constructor to a super constructor, put the super call as an initializer.
 //   B(): super().foo() {}
diff --git a/pkg/front_end/testcases/regress/issue_31198.dart.weak.outline.expect b/pkg/front_end/testcases/regress/issue_31198.dart.weak.outline.expect
index b6f2598b..de40fe0 100644
--- a/pkg/front_end/testcases/regress/issue_31198.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_31198.dart.weak.outline.expect
@@ -1,12 +1,4 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/regress/issue_31198.dart:10:24: Error: Expected an identifier, but got ')'.
-// Try inserting an identifier before ')'.
-//   B.named2(): super().() {}
-//                        ^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/regress/issue_31198.dart.weak.transformed.expect b/pkg/front_end/testcases/regress/issue_31198.dart.weak.transformed.expect
index 63411d2..c773bb3 100644
--- a/pkg/front_end/testcases/regress/issue_31198.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31198.dart.weak.transformed.expect
@@ -2,11 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_31198.dart:10:24: Error: Expected an identifier, but got ')'.
-// Try inserting an identifier before ')'.
-//   B.named2(): super().() {}
-//                        ^
-//
 // pkg/front_end/testcases/regress/issue_31198.dart:8:8: Error: Can't use 'super' as an expression.
 // To delegate a constructor to a super constructor, put the super call as an initializer.
 //   B(): super().foo() {}
diff --git a/tests/language/record_literal_problems_test.dart b/tests/language/record_literal_problems_test.dart
index ab279df..aafbefd 100644
--- a/tests/language/record_literal_problems_test.dart
+++ b/tests/language/record_literal_problems_test.dart
@@ -11,7 +11,4 @@
   // [cfe] Record literal with one field requires a trailing comma.
 
   var r2 = const ();
-  //              ^
-  // [analyzer] SYNTACTIC_ERROR.RECORD_LITERAL_EMPTY
-  // [cfe] Record literal can't be empty.
 }
diff --git a/tests/language_2/record_literal_problems_test.dart b/tests/language_2/record_literal_problems_test.dart
index f089d7c..292cfeb 100644
--- a/tests/language_2/record_literal_problems_test.dart
+++ b/tests/language_2/record_literal_problems_test.dart
@@ -19,7 +19,4 @@
   //             ^
   // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
   // [cfe] The 'records' language feature is disabled for this library.
-  //              ^
-  // [analyzer] SYNTACTIC_ERROR.RECORD_LITERAL_EMPTY
-  // [cfe] Record literal can't be empty.
 }
diff --git a/tests/language_2/record_type_problems_test.dart b/tests/language_2/record_type_problems_test.dart
index a82a271..eb45432 100644
--- a/tests/language_2/record_type_problems_test.dart
+++ b/tests/language_2/record_type_problems_test.dart
@@ -29,13 +29,12 @@
 // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
 // [cfe] The 'records' language feature is disabled for this library.
 
-  () emptyRecord = Record.empty;
+  () emptyRecord = ();
 //^
 // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
 // [cfe] This requires the experimental 'records' language feature to be enabled.
-//                 ^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
-//                        ^
-// [cfe] Member not found: 'empty'.
+//                 ^
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
+// [cfe] The 'records' language feature is disabled for this library.
   print(emptyRecord);
 }