[stable] [parser] Support nullable record types in patterns

Not fixed for nullable record types in
https://dart-review.googlesource.com/c/sdk/+/280106.

Fixes: https://github.com/dart-lang/sdk/issues/52518

Cherry-pick: https://dart-review.googlesource.com/c/sdk/+/304642
Change-Id: I5861b9fa7a0a6b8dce1b8965f6f4ef58123133a6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/305824
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
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 92d622d..c483831 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -7921,7 +7921,6 @@
         typeInfo.isNullable &&
         typeInfo.couldBeExpression) {
       assert(optional('?', token));
-      assert(next.isKeywordOrIdentifier);
       if (!looksLikeName(next)) {
         reportRecoverableError(
             next, codes.templateExpectedIdentifier.withArguments(next));
@@ -9775,8 +9774,12 @@
         return parseVariablePattern(token, patternContext);
       case '(':
         // "(" could start a record type (which has to be followed by an
-        // identifier though), e.g. `(int, int) foo`.
-        if (next.endGroup!.next!.isIdentifier) {
+        // identifier (or ? identifier) though), e.g. `(int, int) foo`
+        // or `(int, int)? bar`.
+        Token afterEndGroup = next.endGroup!.next!;
+        if (afterEndGroup.isIdentifier ||
+            (optional("?", afterEndGroup) &&
+                afterEndGroup.next!.isIdentifier)) {
           TypeInfo typeInfo = computeVariablePatternType(token);
           if (typeInfo is ComplexTypeInfo &&
               typeInfo.isRecordType &&
diff --git a/pkg/front_end/parser_testcases/patterns/issue_51169.dart b/pkg/front_end/parser_testcases/patterns/issue_51169.dart
index 4a55399..8e1ea43 100644
--- a/pkg/front_end/parser_testcases/patterns/issue_51169.dart
+++ b/pkg/front_end/parser_testcases/patterns/issue_51169.dart
@@ -15,3 +15,12 @@
       print(b);
   }
 }
+
+testNullable(a) {
+  switch (a) {
+    case (foo: (int, int)? b) when b != (2, 3):
+      print(b);
+    case Class(field: (int, int)? b) when b != (2, 3):
+      print(b);
+  }
+}
diff --git a/pkg/front_end/parser_testcases/patterns/issue_51169.dart.expect b/pkg/front_end/parser_testcases/patterns/issue_51169.dart.expect
index e04d78c..9ac2d3e 100644
--- a/pkg/front_end/parser_testcases/patterns/issue_51169.dart.expect
+++ b/pkg/front_end/parser_testcases/patterns/issue_51169.dart.expect
@@ -235,5 +235,133 @@
         endSwitchStatement(switch, })
       endBlockFunctionBody(1, {, })
     endTopLevelMethod(test, null, })
+  endTopLevelDeclaration(testNullable)
+  beginMetadataStar(testNullable)
+  endMetadataStar(0)
+  beginTopLevelMember(testNullable)
+    beginTopLevelMethod(}, null, null)
+      handleNoType(})
+      handleIdentifier(testNullable, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(a)
+        endMetadataStar(0)
+        beginFormalParameter(a, MemberKind.TopLevelMethod, null, null, null)
+          handleNoType(()
+          handleIdentifier(a, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, null, a, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginSwitchStatement(switch)
+          handleIdentifier(a, expression)
+          handleNoTypeArguments())
+          handleNoArguments())
+          handleSend(a, ))
+          handleParenthesizedCondition((, null, null)
+          beginSwitchBlock({)
+            beginCaseExpression(case)
+              handleIdentifier(foo, namedRecordFieldReference)
+              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()
+              endRecordType((, ?, 2, false)
+              handleDeclaredVariablePattern(null, b, false)
+              handlePatternField(:)
+              handleRecordPattern((, 1)
+              beginSwitchCaseWhenClause(when)
+                handleIdentifier(b, expression)
+                handleNoTypeArguments(!=)
+                handleNoArguments(!=)
+                handleSend(b, !=)
+                beginBinaryExpression(!=)
+                  beginParenthesizedExpressionOrRecordLiteral(()
+                    handleLiteralInt(2)
+                    handleLiteralInt(3)
+                  endRecordLiteral((, 2, null)
+                endBinaryExpression(!=)
+              endSwitchCaseWhenClause())
+            endCaseExpression(case, when, :)
+            beginSwitchCase(0, 1, case)
+              handleIdentifier(print, expression)
+              handleNoTypeArguments(()
+              beginArguments(()
+                handleIdentifier(b, expression)
+                handleNoTypeArguments())
+                handleNoArguments())
+                handleSend(b, ))
+              endArguments(1, (, ))
+              handleSend(print, ;)
+              handleExpressionStatement(;)
+            endSwitchCase(0, 1, null, null, 1, case, case)
+            beginCaseExpression(case)
+              handleNoTypeArguments(()
+              handleIdentifier(field, namedArgumentReference)
+              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()
+              endRecordType((, ?, 2, false)
+              handleDeclaredVariablePattern(null, b, false)
+              handlePatternField(:)
+              handleObjectPatternFields(1, (, ))
+              handleObjectPattern(Class, null, null)
+              beginSwitchCaseWhenClause(when)
+                handleIdentifier(b, expression)
+                handleNoTypeArguments(!=)
+                handleNoArguments(!=)
+                handleSend(b, !=)
+                beginBinaryExpression(!=)
+                  beginParenthesizedExpressionOrRecordLiteral(()
+                    handleLiteralInt(2)
+                    handleLiteralInt(3)
+                  endRecordLiteral((, 2, null)
+                endBinaryExpression(!=)
+              endSwitchCaseWhenClause())
+            endCaseExpression(case, when, :)
+            beginSwitchCase(0, 1, case)
+              handleIdentifier(print, expression)
+              handleNoTypeArguments(()
+              beginArguments(()
+                handleIdentifier(b, expression)
+                handleNoTypeArguments())
+                handleNoArguments())
+                handleSend(b, ))
+              endArguments(1, (, ))
+              handleSend(print, ;)
+              handleExpressionStatement(;)
+            endSwitchCase(0, 1, null, null, 1, case, })
+          endSwitchBlock(2, {, })
+        endSwitchStatement(switch, })
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(testNullable, null, })
   endTopLevelDeclaration()
-endCompilationUnit(2, )
+endCompilationUnit(3, )
diff --git a/pkg/front_end/parser_testcases/patterns/issue_51169.dart.intertwined.expect b/pkg/front_end/parser_testcases/patterns/issue_51169.dart.intertwined.expect
index 66e6407..6d508db 100644
--- a/pkg/front_end/parser_testcases/patterns/issue_51169.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/patterns/issue_51169.dart.intertwined.expect
@@ -606,6 +606,340 @@
           notEofOrValue(}, })
           listener: endBlockFunctionBody(1, {, })
         listener: endTopLevelMethod(test, null, })
+  listener: endTopLevelDeclaration(testNullable)
+  parseTopLevelDeclarationImpl(}, Instance of 'DirectiveContext')
+    parseMetadataStar(})
+      listener: beginMetadataStar(testNullable)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(})
+      listener: beginTopLevelMember(testNullable)
+      isReservedKeyword(()
+      parseTopLevelMethod(}, null, null, }, Instance of 'NoType', null, testNullable, false)
+        listener: beginTopLevelMethod(}, null, null)
+        listener: handleNoType(})
+        ensureIdentifierPotentiallyRecovered(}, topLevelFunctionDeclaration, false)
+          listener: handleIdentifier(testNullable, topLevelFunctionDeclaration)
+        parseMethodTypeVar(testNullable)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(testNullable, testNullable, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(testNullable, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(a)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(a, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleNoType(()
+                ensureIdentifier((, formalParameterDeclaration)
+                  listener: handleIdentifier(a, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, null, a, null, null, FormalParameterKind.requiredPositional, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, switch)
+          parseStatement({)
+            parseStatementX({)
+              parseSwitchStatement({)
+                listener: beginSwitchStatement(switch)
+                ensureParenthesizedCondition(switch, allowCase: false)
+                  parseExpressionInParenthesisRest((, allowCase: false)
+                    parseExpression(()
+                      looksLikeOuterPatternEquals(()
+                        skipOuterPattern(()
+                          skipObjectPatternRest(a)
+                      parsePrecedenceExpression((, 1, true, ConstantPatternContext.none)
+                        parseUnaryExpression((, true, ConstantPatternContext.none)
+                          parsePrimary((, expression, ConstantPatternContext.none)
+                            parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none)
+                              parseSend((, expression, ConstantPatternContext.none)
+                                isNextIdentifier(()
+                                ensureIdentifier((, expression)
+                                  listener: handleIdentifier(a, expression)
+                                listener: handleNoTypeArguments())
+                                parseArgumentsOpt(a)
+                                  listener: handleNoArguments())
+                                listener: handleSend(a, ))
+                    ensureCloseParen(a, ()
+                    listener: handleParenthesizedCondition((, null, null)
+                parseSwitchBlock())
+                  ensureBlock(), null, switch statement)
+                  listener: beginSwitchBlock({)
+                  notEofOrValue(}, case)
+                  peekPastLabels(case)
+                  listener: beginCaseExpression(case)
+                  parsePattern(case, PatternContext.matching, precedence: 1)
+                    parsePrimaryPattern(case, PatternContext.matching)
+                      parseParenthesizedPatternOrRecordPattern(case, PatternContext.matching)
+                        ensureIdentifier((, namedRecordFieldReference)
+                          listener: handleIdentifier(foo, namedRecordFieldReference)
+                        parsePattern(:, PatternContext.matching, precedence: 1)
+                          parsePrimaryPattern(:, PatternContext.matching)
+                            parseVariablePattern(:, PatternContext.matching, typeInfo: Instance of 'ComplexTypeInfo')
+                              parseRecordType((, :, true)
+                                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()
+                                listener: endRecordType((, ?, 2, false)
+                              listener: handleDeclaredVariablePattern(null, b, false)
+                        listener: handlePatternField(:)
+                        ensureCloseParen(b, ()
+                        listener: handleRecordPattern((, 1)
+                  listener: beginSwitchCaseWhenClause(when)
+                  parseExpression(when)
+                    looksLikeOuterPatternEquals(when)
+                      skipOuterPattern(when)
+                        skipObjectPatternRest(b)
+                    parsePrecedenceExpression(when, 1, true, ConstantPatternContext.none)
+                      parseUnaryExpression(when, true, ConstantPatternContext.none)
+                        parsePrimary(when, expression, ConstantPatternContext.none)
+                          parseSendOrFunctionLiteral(when, expression, ConstantPatternContext.none)
+                            parseSend(when, expression, ConstantPatternContext.none)
+                              isNextIdentifier(when)
+                              ensureIdentifier(when, expression)
+                                listener: handleIdentifier(b, expression)
+                              listener: handleNoTypeArguments(!=)
+                              parseArgumentsOpt(b)
+                                listener: handleNoArguments(!=)
+                              listener: handleSend(b, !=)
+                      listener: beginBinaryExpression(!=)
+                      parsePrecedenceExpression(!=, 8, true, ConstantPatternContext.none)
+                        parseUnaryExpression(!=, true, ConstantPatternContext.none)
+                          parsePrimary(!=, expression, ConstantPatternContext.none)
+                            parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(!=, ConstantPatternContext.none)
+                              parseParenthesizedExpressionOrRecordLiteral(!=, null, ConstantPatternContext.none)
+                                listener: beginParenthesizedExpressionOrRecordLiteral(()
+                                parseExpression(()
+                                  looksLikeOuterPatternEquals(()
+                                    skipOuterPattern(()
+                                  parsePrecedenceExpression((, 1, true, ConstantPatternContext.none)
+                                    parseUnaryExpression((, true, ConstantPatternContext.none)
+                                      parsePrimary((, expression, ConstantPatternContext.none)
+                                        parseLiteralInt(()
+                                          listener: handleLiteralInt(2)
+                                parseExpression(,)
+                                  looksLikeOuterPatternEquals(,)
+                                    skipOuterPattern(,)
+                                  parsePrecedenceExpression(,, 1, true, ConstantPatternContext.none)
+                                    parseUnaryExpression(,, true, ConstantPatternContext.none)
+                                      parsePrimary(,, expression, ConstantPatternContext.none)
+                                        parseLiteralInt(,)
+                                          listener: handleLiteralInt(3)
+                                ensureCloseParen(3, ()
+                                listener: endRecordLiteral((, 2, null)
+                      listener: endBinaryExpression(!=)
+                  listener: endSwitchCaseWhenClause())
+                  ensureColon())
+                  listener: endCaseExpression(case, when, :)
+                  peekPastLabels(print)
+                  parseStatementsInSwitchCase(:, print, case, 0, 1, null, null)
+                    listener: beginSwitchCase(0, 1, case)
+                    parseStatement(:)
+                      parseStatementX(:)
+                        parseExpressionStatementOrDeclarationAfterModifiers(:, :, null, null, null, null)
+                          looksLikeLocalFunction(print)
+                          parseExpressionStatement(:)
+                            parseExpression(:)
+                              looksLikeOuterPatternEquals(:)
+                                skipOuterPattern(:)
+                                  skipObjectPatternRest(print)
+                              parsePrecedenceExpression(:, 1, true, ConstantPatternContext.none)
+                                parseUnaryExpression(:, true, ConstantPatternContext.none)
+                                  parsePrimary(:, expression, ConstantPatternContext.none)
+                                    parseSendOrFunctionLiteral(:, expression, ConstantPatternContext.none)
+                                      looksLikeFunctionBody(;)
+                                      parseSend(:, expression, ConstantPatternContext.none)
+                                        isNextIdentifier(:)
+                                        ensureIdentifier(:, expression)
+                                          listener: handleIdentifier(print, expression)
+                                        listener: handleNoTypeArguments(()
+                                        parseArgumentsOpt(print)
+                                          parseArguments(print)
+                                            parseArgumentsRest(()
+                                              listener: beginArguments(()
+                                              parseExpression(()
+                                                looksLikeOuterPatternEquals(()
+                                                  skipOuterPattern(()
+                                                    skipObjectPatternRest(b)
+                                                parsePrecedenceExpression((, 1, true, ConstantPatternContext.none)
+                                                  parseUnaryExpression((, true, ConstantPatternContext.none)
+                                                    parsePrimary((, expression, ConstantPatternContext.none)
+                                                      parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none)
+                                                        parseSend((, expression, ConstantPatternContext.none)
+                                                          isNextIdentifier(()
+                                                          ensureIdentifier((, expression)
+                                                            listener: handleIdentifier(b, expression)
+                                                          listener: handleNoTypeArguments())
+                                                          parseArgumentsOpt(b)
+                                                            listener: handleNoArguments())
+                                                          listener: handleSend(b, ))
+                                              listener: endArguments(1, (, ))
+                                        listener: handleSend(print, ;)
+                            ensureSemicolon())
+                            listener: handleExpressionStatement(;)
+                    peekPastLabels(case)
+                    listener: endSwitchCase(0, 1, null, null, 1, case, case)
+                  notEofOrValue(}, case)
+                  peekPastLabels(case)
+                  listener: beginCaseExpression(case)
+                  parsePattern(case, PatternContext.matching, precedence: 1)
+                    parsePrimaryPattern(case, PatternContext.matching)
+                      listener: handleNoTypeArguments(()
+                      parseObjectPatternRest(Class, PatternContext.matching)
+                        ensureIdentifier((, namedArgumentReference)
+                          listener: handleIdentifier(field, namedArgumentReference)
+                        parsePattern(:, PatternContext.matching, precedence: 1)
+                          parsePrimaryPattern(:, PatternContext.matching)
+                            parseVariablePattern(:, PatternContext.matching, typeInfo: Instance of 'ComplexTypeInfo')
+                              parseRecordType((, :, true)
+                                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()
+                                listener: endRecordType((, ?, 2, false)
+                              listener: handleDeclaredVariablePattern(null, b, false)
+                        listener: handlePatternField(:)
+                        listener: handleObjectPatternFields(1, (, ))
+                      listener: handleObjectPattern(Class, null, null)
+                  listener: beginSwitchCaseWhenClause(when)
+                  parseExpression(when)
+                    looksLikeOuterPatternEquals(when)
+                      skipOuterPattern(when)
+                        skipObjectPatternRest(b)
+                    parsePrecedenceExpression(when, 1, true, ConstantPatternContext.none)
+                      parseUnaryExpression(when, true, ConstantPatternContext.none)
+                        parsePrimary(when, expression, ConstantPatternContext.none)
+                          parseSendOrFunctionLiteral(when, expression, ConstantPatternContext.none)
+                            parseSend(when, expression, ConstantPatternContext.none)
+                              isNextIdentifier(when)
+                              ensureIdentifier(when, expression)
+                                listener: handleIdentifier(b, expression)
+                              listener: handleNoTypeArguments(!=)
+                              parseArgumentsOpt(b)
+                                listener: handleNoArguments(!=)
+                              listener: handleSend(b, !=)
+                      listener: beginBinaryExpression(!=)
+                      parsePrecedenceExpression(!=, 8, true, ConstantPatternContext.none)
+                        parseUnaryExpression(!=, true, ConstantPatternContext.none)
+                          parsePrimary(!=, expression, ConstantPatternContext.none)
+                            parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(!=, ConstantPatternContext.none)
+                              parseParenthesizedExpressionOrRecordLiteral(!=, null, ConstantPatternContext.none)
+                                listener: beginParenthesizedExpressionOrRecordLiteral(()
+                                parseExpression(()
+                                  looksLikeOuterPatternEquals(()
+                                    skipOuterPattern(()
+                                  parsePrecedenceExpression((, 1, true, ConstantPatternContext.none)
+                                    parseUnaryExpression((, true, ConstantPatternContext.none)
+                                      parsePrimary((, expression, ConstantPatternContext.none)
+                                        parseLiteralInt(()
+                                          listener: handleLiteralInt(2)
+                                parseExpression(,)
+                                  looksLikeOuterPatternEquals(,)
+                                    skipOuterPattern(,)
+                                  parsePrecedenceExpression(,, 1, true, ConstantPatternContext.none)
+                                    parseUnaryExpression(,, true, ConstantPatternContext.none)
+                                      parsePrimary(,, expression, ConstantPatternContext.none)
+                                        parseLiteralInt(,)
+                                          listener: handleLiteralInt(3)
+                                ensureCloseParen(3, ()
+                                listener: endRecordLiteral((, 2, null)
+                      listener: endBinaryExpression(!=)
+                  listener: endSwitchCaseWhenClause())
+                  ensureColon())
+                  listener: endCaseExpression(case, when, :)
+                  peekPastLabels(print)
+                  parseStatementsInSwitchCase(:, print, case, 0, 1, null, null)
+                    listener: beginSwitchCase(0, 1, case)
+                    parseStatement(:)
+                      parseStatementX(:)
+                        parseExpressionStatementOrDeclarationAfterModifiers(:, :, null, null, null, null)
+                          looksLikeLocalFunction(print)
+                          parseExpressionStatement(:)
+                            parseExpression(:)
+                              looksLikeOuterPatternEquals(:)
+                                skipOuterPattern(:)
+                                  skipObjectPatternRest(print)
+                              parsePrecedenceExpression(:, 1, true, ConstantPatternContext.none)
+                                parseUnaryExpression(:, true, ConstantPatternContext.none)
+                                  parsePrimary(:, expression, ConstantPatternContext.none)
+                                    parseSendOrFunctionLiteral(:, expression, ConstantPatternContext.none)
+                                      looksLikeFunctionBody(;)
+                                      parseSend(:, expression, ConstantPatternContext.none)
+                                        isNextIdentifier(:)
+                                        ensureIdentifier(:, expression)
+                                          listener: handleIdentifier(print, expression)
+                                        listener: handleNoTypeArguments(()
+                                        parseArgumentsOpt(print)
+                                          parseArguments(print)
+                                            parseArgumentsRest(()
+                                              listener: beginArguments(()
+                                              parseExpression(()
+                                                looksLikeOuterPatternEquals(()
+                                                  skipOuterPattern(()
+                                                    skipObjectPatternRest(b)
+                                                parsePrecedenceExpression((, 1, true, ConstantPatternContext.none)
+                                                  parseUnaryExpression((, true, ConstantPatternContext.none)
+                                                    parsePrimary((, expression, ConstantPatternContext.none)
+                                                      parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none)
+                                                        parseSend((, expression, ConstantPatternContext.none)
+                                                          isNextIdentifier(()
+                                                          ensureIdentifier((, expression)
+                                                            listener: handleIdentifier(b, expression)
+                                                          listener: handleNoTypeArguments())
+                                                          parseArgumentsOpt(b)
+                                                            listener: handleNoArguments())
+                                                          listener: handleSend(b, ))
+                                              listener: endArguments(1, (, ))
+                                        listener: handleSend(print, ;)
+                            ensureSemicolon())
+                            listener: handleExpressionStatement(;)
+                    peekPastLabels(})
+                    listener: endSwitchCase(0, 1, null, null, 1, case, })
+                  notEofOrValue(}, })
+                  listener: endSwitchBlock(2, {, })
+                listener: endSwitchStatement(switch, })
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(testNullable, null, })
   listener: endTopLevelDeclaration()
   reportAllErrorTokens(class)
-  listener: endCompilationUnit(2, )
+  listener: endCompilationUnit(3, )
diff --git a/pkg/front_end/parser_testcases/patterns/issue_51169.dart.parser.expect b/pkg/front_end/parser_testcases/patterns/issue_51169.dart.parser.expect
index bc3e020..29dd81d 100644
--- a/pkg/front_end/parser_testcases/patterns/issue_51169.dart.parser.expect
+++ b/pkg/front_end/parser_testcases/patterns/issue_51169.dart.parser.expect
@@ -16,6 +16,15 @@
 }
 }
 
+testNullable(a) {
+switch (a) {
+case (foo: (int, int)? b) when b != (2, 3):
+print(b);
+case Class(field: (int, int)? b) when b != (2, 3):
+print(b);
+}
+}
+
 
 class[KeywordToken] Class[StringToken] {[BeginToken]
 dynamic[KeywordToken] field[StringToken];[SimpleToken]
@@ -34,4 +43,13 @@
 print[StringToken]([BeginToken]b[StringToken])[SimpleToken];[SimpleToken]
 }[SimpleToken]
 }[SimpleToken]
+
+testNullable[StringToken]([BeginToken]a[StringToken])[SimpleToken] {[BeginToken]
+switch[KeywordToken] ([BeginToken]a[StringToken])[SimpleToken] {[BeginToken]
+case[KeywordToken] ([BeginToken]foo[StringToken]:[SimpleToken] ([BeginToken]int[StringToken],[SimpleToken] int[StringToken])[SimpleToken]?[SimpleToken] b[StringToken])[SimpleToken] when[KeywordToken] b[StringToken] !=[SimpleToken] ([BeginToken]2[StringToken],[SimpleToken] 3[StringToken])[SimpleToken]:[SimpleToken]
+print[StringToken]([BeginToken]b[StringToken])[SimpleToken];[SimpleToken]
+case[KeywordToken] Class[StringToken]([BeginToken]field[StringToken]:[SimpleToken] ([BeginToken]int[StringToken],[SimpleToken] int[StringToken])[SimpleToken]?[SimpleToken] b[StringToken])[SimpleToken] when[KeywordToken] b[StringToken] !=[SimpleToken] ([BeginToken]2[StringToken],[SimpleToken] 3[StringToken])[SimpleToken]:[SimpleToken]
+print[StringToken]([BeginToken]b[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
 [SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/issue_51169.dart.scanner.expect b/pkg/front_end/parser_testcases/patterns/issue_51169.dart.scanner.expect
index bc3e020..29dd81d 100644
--- a/pkg/front_end/parser_testcases/patterns/issue_51169.dart.scanner.expect
+++ b/pkg/front_end/parser_testcases/patterns/issue_51169.dart.scanner.expect
@@ -16,6 +16,15 @@
 }
 }
 
+testNullable(a) {
+switch (a) {
+case (foo: (int, int)? b) when b != (2, 3):
+print(b);
+case Class(field: (int, int)? b) when b != (2, 3):
+print(b);
+}
+}
+
 
 class[KeywordToken] Class[StringToken] {[BeginToken]
 dynamic[KeywordToken] field[StringToken];[SimpleToken]
@@ -34,4 +43,13 @@
 print[StringToken]([BeginToken]b[StringToken])[SimpleToken];[SimpleToken]
 }[SimpleToken]
 }[SimpleToken]
+
+testNullable[StringToken]([BeginToken]a[StringToken])[SimpleToken] {[BeginToken]
+switch[KeywordToken] ([BeginToken]a[StringToken])[SimpleToken] {[BeginToken]
+case[KeywordToken] ([BeginToken]foo[StringToken]:[SimpleToken] ([BeginToken]int[StringToken],[SimpleToken] int[StringToken])[SimpleToken]?[SimpleToken] b[StringToken])[SimpleToken] when[KeywordToken] b[StringToken] !=[SimpleToken] ([BeginToken]2[StringToken],[SimpleToken] 3[StringToken])[SimpleToken]:[SimpleToken]
+print[StringToken]([BeginToken]b[StringToken])[SimpleToken];[SimpleToken]
+case[KeywordToken] Class[StringToken]([BeginToken]field[StringToken]:[SimpleToken] ([BeginToken]int[StringToken],[SimpleToken] int[StringToken])[SimpleToken]?[SimpleToken] b[StringToken])[SimpleToken] when[KeywordToken] b[StringToken] !=[SimpleToken] ([BeginToken]2[StringToken],[SimpleToken] 3[StringToken])[SimpleToken]:[SimpleToken]
+print[StringToken]([BeginToken]b[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
 [SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/issue_51176.dart b/pkg/front_end/parser_testcases/patterns/issue_51176.dart
index f34ab34..4d85b08 100644
--- a/pkg/front_end/parser_testcases/patterns/issue_51176.dart
+++ b/pkg/front_end/parser_testcases/patterns/issue_51176.dart
@@ -14,4 +14,20 @@
 
   var (n: (int, {int x}) a10, (int z, {int y}) b10)
       = (n: (x: 42, -1), (y: 1, 0));
+
+  var ((a1,)?,) = (null,);
+  var (n: (x: a2)?) = (n: null);
+  var (n: (x: a3, b3)?, (y: c3, d3)?) = (n: null, null);
+
+  final ((a4,)?,) = (null,);
+  final (n: (x: a5)?) = (n: null);
+  final (n: (x: a6, b6)?, (y: c6, d6)?) = (n: null, null);
+
+  var ((int a7,)?,) = (null,);
+  var (n: (x: int a8)?) = (n: null);
+  var (n: (x: int a9, int b9)?, (y: int c9, int d9)?)
+      = (n: null, null);
+
+  var (n: (int, {int x})? a10, (int z, {int y})? b10)
+      = (n: null, null);
 }
diff --git a/pkg/front_end/parser_testcases/patterns/issue_51176.dart.expect b/pkg/front_end/parser_testcases/patterns/issue_51176.dart.expect
index 4d8bd96..337be13 100644
--- a/pkg/front_end/parser_testcases/patterns/issue_51176.dart.expect
+++ b/pkg/front_end/parser_testcases/patterns/issue_51176.dart.expect
@@ -313,7 +313,257 @@
           endRecordLiteral((, 2, null)
         endRecordLiteral((, 2, null)
         handlePatternVariableDeclarationStatement(var, =, ;)
-      endBlockFunctionBody(10, {, })
+        beginMetadataStar(var)
+        endMetadataStar(0)
+        handleNoType(a1)
+        handleDeclaredVariablePattern(null, a1, false)
+        handlePatternField(null)
+        handleRecordPattern((, 1)
+        handleNullCheckPattern(?)
+        handlePatternField(null)
+        handleRecordPattern((, 1)
+        beginParenthesizedExpressionOrRecordLiteral(()
+          handleLiteralNull(null)
+        endRecordLiteral((, 1, null)
+        handlePatternVariableDeclarationStatement(var, =, ;)
+        beginMetadataStar(var)
+        endMetadataStar(0)
+        handleIdentifier(n, namedRecordFieldReference)
+        handleIdentifier(x, namedRecordFieldReference)
+        handleNoType(a2)
+        handleDeclaredVariablePattern(null, a2, false)
+        handlePatternField(:)
+        handleRecordPattern((, 1)
+        handleNullCheckPattern(?)
+        handlePatternField(:)
+        handleRecordPattern((, 1)
+        beginParenthesizedExpressionOrRecordLiteral(()
+          handleIdentifier(n, namedRecordFieldReference)
+          handleLiteralNull(null)
+          handleNamedRecordField(:)
+        endRecordLiteral((, 1, null)
+        handlePatternVariableDeclarationStatement(var, =, ;)
+        beginMetadataStar(var)
+        endMetadataStar(0)
+        handleIdentifier(n, namedRecordFieldReference)
+        handleIdentifier(x, namedRecordFieldReference)
+        handleNoType(a3)
+        handleDeclaredVariablePattern(null, a3, false)
+        handlePatternField(:)
+        handleNoType(b3)
+        handleDeclaredVariablePattern(null, b3, false)
+        handlePatternField(null)
+        handleRecordPattern((, 2)
+        handleNullCheckPattern(?)
+        handlePatternField(:)
+        handleIdentifier(y, namedRecordFieldReference)
+        handleNoType(c3)
+        handleDeclaredVariablePattern(null, c3, false)
+        handlePatternField(:)
+        handleNoType(d3)
+        handleDeclaredVariablePattern(null, d3, false)
+        handlePatternField(null)
+        handleRecordPattern((, 2)
+        handleNullCheckPattern(?)
+        handlePatternField(null)
+        handleRecordPattern((, 2)
+        beginParenthesizedExpressionOrRecordLiteral(()
+          handleIdentifier(n, namedRecordFieldReference)
+          handleLiteralNull(null)
+          handleNamedRecordField(:)
+          handleLiteralNull(null)
+        endRecordLiteral((, 2, null)
+        handlePatternVariableDeclarationStatement(var, =, ;)
+        beginMetadataStar(final)
+        endMetadataStar(0)
+        handleNoType(a4)
+        handleDeclaredVariablePattern(null, a4, false)
+        handlePatternField(null)
+        handleRecordPattern((, 1)
+        handleNullCheckPattern(?)
+        handlePatternField(null)
+        handleRecordPattern((, 1)
+        beginParenthesizedExpressionOrRecordLiteral(()
+          handleLiteralNull(null)
+        endRecordLiteral((, 1, null)
+        handlePatternVariableDeclarationStatement(final, =, ;)
+        beginMetadataStar(final)
+        endMetadataStar(0)
+        handleIdentifier(n, namedRecordFieldReference)
+        handleIdentifier(x, namedRecordFieldReference)
+        handleNoType(a5)
+        handleDeclaredVariablePattern(null, a5, false)
+        handlePatternField(:)
+        handleRecordPattern((, 1)
+        handleNullCheckPattern(?)
+        handlePatternField(:)
+        handleRecordPattern((, 1)
+        beginParenthesizedExpressionOrRecordLiteral(()
+          handleIdentifier(n, namedRecordFieldReference)
+          handleLiteralNull(null)
+          handleNamedRecordField(:)
+        endRecordLiteral((, 1, null)
+        handlePatternVariableDeclarationStatement(final, =, ;)
+        beginMetadataStar(final)
+        endMetadataStar(0)
+        handleIdentifier(n, namedRecordFieldReference)
+        handleIdentifier(x, namedRecordFieldReference)
+        handleNoType(a6)
+        handleDeclaredVariablePattern(null, a6, false)
+        handlePatternField(:)
+        handleNoType(b6)
+        handleDeclaredVariablePattern(null, b6, false)
+        handlePatternField(null)
+        handleRecordPattern((, 2)
+        handleNullCheckPattern(?)
+        handlePatternField(:)
+        handleIdentifier(y, namedRecordFieldReference)
+        handleNoType(c6)
+        handleDeclaredVariablePattern(null, c6, false)
+        handlePatternField(:)
+        handleNoType(d6)
+        handleDeclaredVariablePattern(null, d6, false)
+        handlePatternField(null)
+        handleRecordPattern((, 2)
+        handleNullCheckPattern(?)
+        handlePatternField(null)
+        handleRecordPattern((, 2)
+        beginParenthesizedExpressionOrRecordLiteral(()
+          handleIdentifier(n, namedRecordFieldReference)
+          handleLiteralNull(null)
+          handleNamedRecordField(:)
+          handleLiteralNull(null)
+        endRecordLiteral((, 2, null)
+        handlePatternVariableDeclarationStatement(final, =, ;)
+        beginMetadataStar(var)
+        endMetadataStar(0)
+        handleIdentifier(int, typeReference)
+        handleNoTypeArguments(a7)
+        handleType(int, null)
+        handleDeclaredVariablePattern(null, a7, false)
+        handlePatternField(null)
+        handleRecordPattern((, 1)
+        handleNullCheckPattern(?)
+        handlePatternField(null)
+        handleRecordPattern((, 1)
+        beginParenthesizedExpressionOrRecordLiteral(()
+          handleLiteralNull(null)
+        endRecordLiteral((, 1, null)
+        handlePatternVariableDeclarationStatement(var, =, ;)
+        beginMetadataStar(var)
+        endMetadataStar(0)
+        handleIdentifier(n, namedRecordFieldReference)
+        handleIdentifier(x, namedRecordFieldReference)
+        handleIdentifier(int, typeReference)
+        handleNoTypeArguments(a8)
+        handleType(int, null)
+        handleDeclaredVariablePattern(null, a8, false)
+        handlePatternField(:)
+        handleRecordPattern((, 1)
+        handleNullCheckPattern(?)
+        handlePatternField(:)
+        handleRecordPattern((, 1)
+        beginParenthesizedExpressionOrRecordLiteral(()
+          handleIdentifier(n, namedRecordFieldReference)
+          handleLiteralNull(null)
+          handleNamedRecordField(:)
+        endRecordLiteral((, 1, null)
+        handlePatternVariableDeclarationStatement(var, =, ;)
+        beginMetadataStar(var)
+        endMetadataStar(0)
+        handleIdentifier(n, namedRecordFieldReference)
+        handleIdentifier(x, namedRecordFieldReference)
+        handleIdentifier(int, typeReference)
+        handleNoTypeArguments(a9)
+        handleType(int, null)
+        handleDeclaredVariablePattern(null, a9, false)
+        handlePatternField(:)
+        handleIdentifier(int, typeReference)
+        handleNoTypeArguments(b9)
+        handleType(int, null)
+        handleDeclaredVariablePattern(null, b9, false)
+        handlePatternField(null)
+        handleRecordPattern((, 2)
+        handleNullCheckPattern(?)
+        handlePatternField(:)
+        handleIdentifier(y, namedRecordFieldReference)
+        handleIdentifier(int, typeReference)
+        handleNoTypeArguments(c9)
+        handleType(int, null)
+        handleDeclaredVariablePattern(null, c9, false)
+        handlePatternField(:)
+        handleIdentifier(int, typeReference)
+        handleNoTypeArguments(d9)
+        handleType(int, null)
+        handleDeclaredVariablePattern(null, d9, false)
+        handlePatternField(null)
+        handleRecordPattern((, 2)
+        handleNullCheckPattern(?)
+        handlePatternField(null)
+        handleRecordPattern((, 2)
+        beginParenthesizedExpressionOrRecordLiteral(()
+          handleIdentifier(n, namedRecordFieldReference)
+          handleLiteralNull(null)
+          handleNamedRecordField(:)
+          handleLiteralNull(null)
+        endRecordLiteral((, 2, null)
+        handlePatternVariableDeclarationStatement(var, =, ;)
+        beginMetadataStar(var)
+        endMetadataStar(0)
+        handleIdentifier(n, namedRecordFieldReference)
+        beginRecordType(()
+          beginRecordTypeEntry()
+            beginMetadataStar(int)
+            endMetadataStar(0)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(,)
+            handleType(int, null)
+            handleNoName(,)
+          endRecordTypeEntry()
+          beginRecordTypeNamedFields({)
+            beginRecordTypeEntry()
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              handleIdentifier(int, typeReference)
+              handleNoTypeArguments(x)
+              handleType(int, null)
+              handleIdentifier(x, recordFieldDeclaration)
+            endRecordTypeEntry()
+          endRecordTypeNamedFields(1, {)
+        endRecordType((, ?, 2, true)
+        handleDeclaredVariablePattern(null, a10, false)
+        handlePatternField(:)
+        beginRecordType(()
+          beginRecordTypeEntry()
+            beginMetadataStar(int)
+            endMetadataStar(0)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(z)
+            handleType(int, null)
+            handleIdentifier(z, recordFieldDeclaration)
+          endRecordTypeEntry()
+          beginRecordTypeNamedFields({)
+            beginRecordTypeEntry()
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              handleIdentifier(int, typeReference)
+              handleNoTypeArguments(y)
+              handleType(int, null)
+              handleIdentifier(y, recordFieldDeclaration)
+            endRecordTypeEntry()
+          endRecordTypeNamedFields(1, {)
+        endRecordType((, ?, 2, true)
+        handleDeclaredVariablePattern(null, b10, false)
+        handlePatternField(null)
+        handleRecordPattern((, 2)
+        beginParenthesizedExpressionOrRecordLiteral(()
+          handleIdentifier(n, namedRecordFieldReference)
+          handleLiteralNull(null)
+          handleNamedRecordField(:)
+          handleLiteralNull(null)
+        endRecordLiteral((, 2, null)
+        handlePatternVariableDeclarationStatement(var, =, ;)
+      endBlockFunctionBody(20, {, })
     endTopLevelMethod(main, null, })
   endTopLevelDeclaration()
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/issue_51176.dart.intertwined.expect b/pkg/front_end/parser_testcases/patterns/issue_51176.dart.intertwined.expect
index 457e412..bd2eeb7 100644
--- a/pkg/front_end/parser_testcases/patterns/issue_51176.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/patterns/issue_51176.dart.intertwined.expect
@@ -982,8 +982,704 @@
                               listener: endRecordLiteral((, 2, null)
                   ensureSemicolon())
                   listener: handlePatternVariableDeclarationStatement(var, =, ;)
+          notEofOrValue(}, var)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(var, ;, null, var, null, null)
+                skipOuterPattern(var)
+                listener: beginMetadataStar(var)
+                listener: endMetadataStar(0)
+                parsePatternVariableDeclarationStatement(var, ;, var)
+                  parsePattern(var, PatternContext.declaration, precedence: 1)
+                    parsePrimaryPattern(var, PatternContext.declaration)
+                      parseParenthesizedPatternOrRecordPattern(var, PatternContext.declaration)
+                        parsePattern((, PatternContext.declaration, precedence: 1)
+                          parsePrimaryPattern((, PatternContext.declaration)
+                            parseParenthesizedPatternOrRecordPattern((, PatternContext.declaration)
+                              parsePattern((, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern((, PatternContext.declaration)
+                                  parseVariablePattern((, PatternContext.declaration, typeInfo: Instance of 'NoType')
+                                    listener: handleNoType(a1)
+                                    listener: handleDeclaredVariablePattern(null, a1, false)
+                              listener: handlePatternField(null)
+                              ensureCloseParen(,, ()
+                              listener: handleRecordPattern((, 1)
+                          listener: handleNullCheckPattern(?)
+                        listener: handlePatternField(null)
+                        ensureCloseParen(,, ()
+                        listener: handleRecordPattern((, 1)
+                  parseExpression(=)
+                    looksLikeOuterPatternEquals(=)
+                      skipOuterPattern(=)
+                    parsePrecedenceExpression(=, 1, true, ConstantPatternContext.none)
+                      parseUnaryExpression(=, true, ConstantPatternContext.none)
+                        parsePrimary(=, expression, ConstantPatternContext.none)
+                          parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=, ConstantPatternContext.none)
+                            parseParenthesizedExpressionOrRecordLiteral(=, null, ConstantPatternContext.none)
+                              listener: beginParenthesizedExpressionOrRecordLiteral(()
+                              parseExpression(()
+                                looksLikeOuterPatternEquals(()
+                                  skipOuterPattern(()
+                                parsePrecedenceExpression((, 1, true, ConstantPatternContext.none)
+                                  parseUnaryExpression((, true, ConstantPatternContext.none)
+                                    parsePrimary((, expression, ConstantPatternContext.none)
+                                      parseLiteralNull(()
+                                        listener: handleLiteralNull(null)
+                              ensureCloseParen(,, ()
+                              listener: endRecordLiteral((, 1, null)
+                  ensureSemicolon())
+                  listener: handlePatternVariableDeclarationStatement(var, =, ;)
+          notEofOrValue(}, var)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(var, ;, null, var, null, null)
+                skipOuterPattern(var)
+                listener: beginMetadataStar(var)
+                listener: endMetadataStar(0)
+                parsePatternVariableDeclarationStatement(var, ;, var)
+                  parsePattern(var, PatternContext.declaration, precedence: 1)
+                    parsePrimaryPattern(var, PatternContext.declaration)
+                      parseParenthesizedPatternOrRecordPattern(var, PatternContext.declaration)
+                        ensureIdentifier((, namedRecordFieldReference)
+                          listener: handleIdentifier(n, namedRecordFieldReference)
+                        parsePattern(:, PatternContext.declaration, precedence: 1)
+                          parsePrimaryPattern(:, PatternContext.declaration)
+                            parseParenthesizedPatternOrRecordPattern(:, PatternContext.declaration)
+                              ensureIdentifier((, namedRecordFieldReference)
+                                listener: handleIdentifier(x, namedRecordFieldReference)
+                              parsePattern(:, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern(:, PatternContext.declaration)
+                                  parseVariablePattern(:, PatternContext.declaration, typeInfo: Instance of 'NoType')
+                                    listener: handleNoType(a2)
+                                    listener: handleDeclaredVariablePattern(null, a2, false)
+                              listener: handlePatternField(:)
+                              ensureCloseParen(a2, ()
+                              listener: handleRecordPattern((, 1)
+                          listener: handleNullCheckPattern(?)
+                        listener: handlePatternField(:)
+                        ensureCloseParen(?, ()
+                        listener: handleRecordPattern((, 1)
+                  parseExpression(=)
+                    looksLikeOuterPatternEquals(=)
+                      skipOuterPattern(=)
+                    parsePrecedenceExpression(=, 1, true, ConstantPatternContext.none)
+                      parseUnaryExpression(=, true, ConstantPatternContext.none)
+                        parsePrimary(=, expression, ConstantPatternContext.none)
+                          parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=, ConstantPatternContext.none)
+                            parseParenthesizedExpressionOrRecordLiteral(=, null, ConstantPatternContext.none)
+                              listener: beginParenthesizedExpressionOrRecordLiteral(()
+                              ensureIdentifier((, namedRecordFieldReference)
+                                listener: handleIdentifier(n, namedRecordFieldReference)
+                              parseExpression(:)
+                                looksLikeOuterPatternEquals(:)
+                                  skipOuterPattern(:)
+                                parsePrecedenceExpression(:, 1, true, ConstantPatternContext.none)
+                                  parseUnaryExpression(:, true, ConstantPatternContext.none)
+                                    parsePrimary(:, expression, ConstantPatternContext.none)
+                                      parseLiteralNull(:)
+                                        listener: handleLiteralNull(null)
+                              listener: handleNamedRecordField(:)
+                              ensureCloseParen(null, ()
+                              listener: endRecordLiteral((, 1, null)
+                  ensureSemicolon())
+                  listener: handlePatternVariableDeclarationStatement(var, =, ;)
+          notEofOrValue(}, var)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(var, ;, null, var, null, null)
+                skipOuterPattern(var)
+                listener: beginMetadataStar(var)
+                listener: endMetadataStar(0)
+                parsePatternVariableDeclarationStatement(var, ;, var)
+                  parsePattern(var, PatternContext.declaration, precedence: 1)
+                    parsePrimaryPattern(var, PatternContext.declaration)
+                      parseParenthesizedPatternOrRecordPattern(var, PatternContext.declaration)
+                        ensureIdentifier((, namedRecordFieldReference)
+                          listener: handleIdentifier(n, namedRecordFieldReference)
+                        parsePattern(:, PatternContext.declaration, precedence: 1)
+                          parsePrimaryPattern(:, PatternContext.declaration)
+                            parseParenthesizedPatternOrRecordPattern(:, PatternContext.declaration)
+                              ensureIdentifier((, namedRecordFieldReference)
+                                listener: handleIdentifier(x, namedRecordFieldReference)
+                              parsePattern(:, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern(:, PatternContext.declaration)
+                                  parseVariablePattern(:, PatternContext.declaration, typeInfo: Instance of 'NoType')
+                                    listener: handleNoType(a3)
+                                    listener: handleDeclaredVariablePattern(null, a3, false)
+                              listener: handlePatternField(:)
+                              parsePattern(,, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern(,, PatternContext.declaration)
+                                  parseVariablePattern(,, PatternContext.declaration, typeInfo: Instance of 'NoType')
+                                    listener: handleNoType(b3)
+                                    listener: handleDeclaredVariablePattern(null, b3, false)
+                              listener: handlePatternField(null)
+                              ensureCloseParen(b3, ()
+                              listener: handleRecordPattern((, 2)
+                          listener: handleNullCheckPattern(?)
+                        listener: handlePatternField(:)
+                        parsePattern(,, PatternContext.declaration, precedence: 1)
+                          parsePrimaryPattern(,, PatternContext.declaration)
+                            parseParenthesizedPatternOrRecordPattern(,, PatternContext.declaration)
+                              ensureIdentifier((, namedRecordFieldReference)
+                                listener: handleIdentifier(y, namedRecordFieldReference)
+                              parsePattern(:, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern(:, PatternContext.declaration)
+                                  parseVariablePattern(:, PatternContext.declaration, typeInfo: Instance of 'NoType')
+                                    listener: handleNoType(c3)
+                                    listener: handleDeclaredVariablePattern(null, c3, false)
+                              listener: handlePatternField(:)
+                              parsePattern(,, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern(,, PatternContext.declaration)
+                                  parseVariablePattern(,, PatternContext.declaration, typeInfo: Instance of 'NoType')
+                                    listener: handleNoType(d3)
+                                    listener: handleDeclaredVariablePattern(null, d3, false)
+                              listener: handlePatternField(null)
+                              ensureCloseParen(d3, ()
+                              listener: handleRecordPattern((, 2)
+                          listener: handleNullCheckPattern(?)
+                        listener: handlePatternField(null)
+                        ensureCloseParen(?, ()
+                        listener: handleRecordPattern((, 2)
+                  parseExpression(=)
+                    looksLikeOuterPatternEquals(=)
+                      skipOuterPattern(=)
+                    parsePrecedenceExpression(=, 1, true, ConstantPatternContext.none)
+                      parseUnaryExpression(=, true, ConstantPatternContext.none)
+                        parsePrimary(=, expression, ConstantPatternContext.none)
+                          parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=, ConstantPatternContext.none)
+                            parseParenthesizedExpressionOrRecordLiteral(=, null, ConstantPatternContext.none)
+                              listener: beginParenthesizedExpressionOrRecordLiteral(()
+                              ensureIdentifier((, namedRecordFieldReference)
+                                listener: handleIdentifier(n, namedRecordFieldReference)
+                              parseExpression(:)
+                                looksLikeOuterPatternEquals(:)
+                                  skipOuterPattern(:)
+                                parsePrecedenceExpression(:, 1, true, ConstantPatternContext.none)
+                                  parseUnaryExpression(:, true, ConstantPatternContext.none)
+                                    parsePrimary(:, expression, ConstantPatternContext.none)
+                                      parseLiteralNull(:)
+                                        listener: handleLiteralNull(null)
+                              listener: handleNamedRecordField(:)
+                              parseExpression(,)
+                                looksLikeOuterPatternEquals(,)
+                                  skipOuterPattern(,)
+                                parsePrecedenceExpression(,, 1, true, ConstantPatternContext.none)
+                                  parseUnaryExpression(,, true, ConstantPatternContext.none)
+                                    parsePrimary(,, expression, ConstantPatternContext.none)
+                                      parseLiteralNull(,)
+                                        listener: handleLiteralNull(null)
+                              ensureCloseParen(null, ()
+                              listener: endRecordLiteral((, 2, null)
+                  ensureSemicolon())
+                  listener: handlePatternVariableDeclarationStatement(var, =, ;)
+          notEofOrValue(}, final)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(final, ;, null, final, null, null)
+                skipOuterPattern(final)
+                listener: beginMetadataStar(final)
+                listener: endMetadataStar(0)
+                parsePatternVariableDeclarationStatement(final, ;, final)
+                  parsePattern(final, PatternContext.declaration, precedence: 1)
+                    parsePrimaryPattern(final, PatternContext.declaration)
+                      parseParenthesizedPatternOrRecordPattern(final, PatternContext.declaration)
+                        parsePattern((, PatternContext.declaration, precedence: 1)
+                          parsePrimaryPattern((, PatternContext.declaration)
+                            parseParenthesizedPatternOrRecordPattern((, PatternContext.declaration)
+                              parsePattern((, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern((, PatternContext.declaration)
+                                  parseVariablePattern((, PatternContext.declaration, typeInfo: Instance of 'NoType')
+                                    listener: handleNoType(a4)
+                                    listener: handleDeclaredVariablePattern(null, a4, false)
+                              listener: handlePatternField(null)
+                              ensureCloseParen(,, ()
+                              listener: handleRecordPattern((, 1)
+                          listener: handleNullCheckPattern(?)
+                        listener: handlePatternField(null)
+                        ensureCloseParen(,, ()
+                        listener: handleRecordPattern((, 1)
+                  parseExpression(=)
+                    looksLikeOuterPatternEquals(=)
+                      skipOuterPattern(=)
+                    parsePrecedenceExpression(=, 1, true, ConstantPatternContext.none)
+                      parseUnaryExpression(=, true, ConstantPatternContext.none)
+                        parsePrimary(=, expression, ConstantPatternContext.none)
+                          parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=, ConstantPatternContext.none)
+                            parseParenthesizedExpressionOrRecordLiteral(=, null, ConstantPatternContext.none)
+                              listener: beginParenthesizedExpressionOrRecordLiteral(()
+                              parseExpression(()
+                                looksLikeOuterPatternEquals(()
+                                  skipOuterPattern(()
+                                parsePrecedenceExpression((, 1, true, ConstantPatternContext.none)
+                                  parseUnaryExpression((, true, ConstantPatternContext.none)
+                                    parsePrimary((, expression, ConstantPatternContext.none)
+                                      parseLiteralNull(()
+                                        listener: handleLiteralNull(null)
+                              ensureCloseParen(,, ()
+                              listener: endRecordLiteral((, 1, null)
+                  ensureSemicolon())
+                  listener: handlePatternVariableDeclarationStatement(final, =, ;)
+          notEofOrValue(}, final)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(final, ;, null, final, null, null)
+                skipOuterPattern(final)
+                listener: beginMetadataStar(final)
+                listener: endMetadataStar(0)
+                parsePatternVariableDeclarationStatement(final, ;, final)
+                  parsePattern(final, PatternContext.declaration, precedence: 1)
+                    parsePrimaryPattern(final, PatternContext.declaration)
+                      parseParenthesizedPatternOrRecordPattern(final, PatternContext.declaration)
+                        ensureIdentifier((, namedRecordFieldReference)
+                          listener: handleIdentifier(n, namedRecordFieldReference)
+                        parsePattern(:, PatternContext.declaration, precedence: 1)
+                          parsePrimaryPattern(:, PatternContext.declaration)
+                            parseParenthesizedPatternOrRecordPattern(:, PatternContext.declaration)
+                              ensureIdentifier((, namedRecordFieldReference)
+                                listener: handleIdentifier(x, namedRecordFieldReference)
+                              parsePattern(:, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern(:, PatternContext.declaration)
+                                  parseVariablePattern(:, PatternContext.declaration, typeInfo: Instance of 'NoType')
+                                    listener: handleNoType(a5)
+                                    listener: handleDeclaredVariablePattern(null, a5, false)
+                              listener: handlePatternField(:)
+                              ensureCloseParen(a5, ()
+                              listener: handleRecordPattern((, 1)
+                          listener: handleNullCheckPattern(?)
+                        listener: handlePatternField(:)
+                        ensureCloseParen(?, ()
+                        listener: handleRecordPattern((, 1)
+                  parseExpression(=)
+                    looksLikeOuterPatternEquals(=)
+                      skipOuterPattern(=)
+                    parsePrecedenceExpression(=, 1, true, ConstantPatternContext.none)
+                      parseUnaryExpression(=, true, ConstantPatternContext.none)
+                        parsePrimary(=, expression, ConstantPatternContext.none)
+                          parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=, ConstantPatternContext.none)
+                            parseParenthesizedExpressionOrRecordLiteral(=, null, ConstantPatternContext.none)
+                              listener: beginParenthesizedExpressionOrRecordLiteral(()
+                              ensureIdentifier((, namedRecordFieldReference)
+                                listener: handleIdentifier(n, namedRecordFieldReference)
+                              parseExpression(:)
+                                looksLikeOuterPatternEquals(:)
+                                  skipOuterPattern(:)
+                                parsePrecedenceExpression(:, 1, true, ConstantPatternContext.none)
+                                  parseUnaryExpression(:, true, ConstantPatternContext.none)
+                                    parsePrimary(:, expression, ConstantPatternContext.none)
+                                      parseLiteralNull(:)
+                                        listener: handleLiteralNull(null)
+                              listener: handleNamedRecordField(:)
+                              ensureCloseParen(null, ()
+                              listener: endRecordLiteral((, 1, null)
+                  ensureSemicolon())
+                  listener: handlePatternVariableDeclarationStatement(final, =, ;)
+          notEofOrValue(}, final)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(final, ;, null, final, null, null)
+                skipOuterPattern(final)
+                listener: beginMetadataStar(final)
+                listener: endMetadataStar(0)
+                parsePatternVariableDeclarationStatement(final, ;, final)
+                  parsePattern(final, PatternContext.declaration, precedence: 1)
+                    parsePrimaryPattern(final, PatternContext.declaration)
+                      parseParenthesizedPatternOrRecordPattern(final, PatternContext.declaration)
+                        ensureIdentifier((, namedRecordFieldReference)
+                          listener: handleIdentifier(n, namedRecordFieldReference)
+                        parsePattern(:, PatternContext.declaration, precedence: 1)
+                          parsePrimaryPattern(:, PatternContext.declaration)
+                            parseParenthesizedPatternOrRecordPattern(:, PatternContext.declaration)
+                              ensureIdentifier((, namedRecordFieldReference)
+                                listener: handleIdentifier(x, namedRecordFieldReference)
+                              parsePattern(:, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern(:, PatternContext.declaration)
+                                  parseVariablePattern(:, PatternContext.declaration, typeInfo: Instance of 'NoType')
+                                    listener: handleNoType(a6)
+                                    listener: handleDeclaredVariablePattern(null, a6, false)
+                              listener: handlePatternField(:)
+                              parsePattern(,, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern(,, PatternContext.declaration)
+                                  parseVariablePattern(,, PatternContext.declaration, typeInfo: Instance of 'NoType')
+                                    listener: handleNoType(b6)
+                                    listener: handleDeclaredVariablePattern(null, b6, false)
+                              listener: handlePatternField(null)
+                              ensureCloseParen(b6, ()
+                              listener: handleRecordPattern((, 2)
+                          listener: handleNullCheckPattern(?)
+                        listener: handlePatternField(:)
+                        parsePattern(,, PatternContext.declaration, precedence: 1)
+                          parsePrimaryPattern(,, PatternContext.declaration)
+                            parseParenthesizedPatternOrRecordPattern(,, PatternContext.declaration)
+                              ensureIdentifier((, namedRecordFieldReference)
+                                listener: handleIdentifier(y, namedRecordFieldReference)
+                              parsePattern(:, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern(:, PatternContext.declaration)
+                                  parseVariablePattern(:, PatternContext.declaration, typeInfo: Instance of 'NoType')
+                                    listener: handleNoType(c6)
+                                    listener: handleDeclaredVariablePattern(null, c6, false)
+                              listener: handlePatternField(:)
+                              parsePattern(,, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern(,, PatternContext.declaration)
+                                  parseVariablePattern(,, PatternContext.declaration, typeInfo: Instance of 'NoType')
+                                    listener: handleNoType(d6)
+                                    listener: handleDeclaredVariablePattern(null, d6, false)
+                              listener: handlePatternField(null)
+                              ensureCloseParen(d6, ()
+                              listener: handleRecordPattern((, 2)
+                          listener: handleNullCheckPattern(?)
+                        listener: handlePatternField(null)
+                        ensureCloseParen(?, ()
+                        listener: handleRecordPattern((, 2)
+                  parseExpression(=)
+                    looksLikeOuterPatternEquals(=)
+                      skipOuterPattern(=)
+                    parsePrecedenceExpression(=, 1, true, ConstantPatternContext.none)
+                      parseUnaryExpression(=, true, ConstantPatternContext.none)
+                        parsePrimary(=, expression, ConstantPatternContext.none)
+                          parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=, ConstantPatternContext.none)
+                            parseParenthesizedExpressionOrRecordLiteral(=, null, ConstantPatternContext.none)
+                              listener: beginParenthesizedExpressionOrRecordLiteral(()
+                              ensureIdentifier((, namedRecordFieldReference)
+                                listener: handleIdentifier(n, namedRecordFieldReference)
+                              parseExpression(:)
+                                looksLikeOuterPatternEquals(:)
+                                  skipOuterPattern(:)
+                                parsePrecedenceExpression(:, 1, true, ConstantPatternContext.none)
+                                  parseUnaryExpression(:, true, ConstantPatternContext.none)
+                                    parsePrimary(:, expression, ConstantPatternContext.none)
+                                      parseLiteralNull(:)
+                                        listener: handleLiteralNull(null)
+                              listener: handleNamedRecordField(:)
+                              parseExpression(,)
+                                looksLikeOuterPatternEquals(,)
+                                  skipOuterPattern(,)
+                                parsePrecedenceExpression(,, 1, true, ConstantPatternContext.none)
+                                  parseUnaryExpression(,, true, ConstantPatternContext.none)
+                                    parsePrimary(,, expression, ConstantPatternContext.none)
+                                      parseLiteralNull(,)
+                                        listener: handleLiteralNull(null)
+                              ensureCloseParen(null, ()
+                              listener: endRecordLiteral((, 2, null)
+                  ensureSemicolon())
+                  listener: handlePatternVariableDeclarationStatement(final, =, ;)
+          notEofOrValue(}, var)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(var, ;, null, var, null, null)
+                skipOuterPattern(var)
+                listener: beginMetadataStar(var)
+                listener: endMetadataStar(0)
+                parsePatternVariableDeclarationStatement(var, ;, var)
+                  parsePattern(var, PatternContext.declaration, precedence: 1)
+                    parsePrimaryPattern(var, PatternContext.declaration)
+                      parseParenthesizedPatternOrRecordPattern(var, PatternContext.declaration)
+                        parsePattern((, PatternContext.declaration, precedence: 1)
+                          parsePrimaryPattern((, PatternContext.declaration)
+                            parseParenthesizedPatternOrRecordPattern((, PatternContext.declaration)
+                              parsePattern((, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern((, PatternContext.declaration)
+                                  parseVariablePattern((, PatternContext.declaration, typeInfo: Instance of 'SimpleType')
+                                    listener: handleIdentifier(int, typeReference)
+                                    listener: handleNoTypeArguments(a7)
+                                    listener: handleType(int, null)
+                                    listener: handleDeclaredVariablePattern(null, a7, false)
+                              listener: handlePatternField(null)
+                              ensureCloseParen(,, ()
+                              listener: handleRecordPattern((, 1)
+                          listener: handleNullCheckPattern(?)
+                        listener: handlePatternField(null)
+                        ensureCloseParen(,, ()
+                        listener: handleRecordPattern((, 1)
+                  parseExpression(=)
+                    looksLikeOuterPatternEquals(=)
+                      skipOuterPattern(=)
+                    parsePrecedenceExpression(=, 1, true, ConstantPatternContext.none)
+                      parseUnaryExpression(=, true, ConstantPatternContext.none)
+                        parsePrimary(=, expression, ConstantPatternContext.none)
+                          parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=, ConstantPatternContext.none)
+                            parseParenthesizedExpressionOrRecordLiteral(=, null, ConstantPatternContext.none)
+                              listener: beginParenthesizedExpressionOrRecordLiteral(()
+                              parseExpression(()
+                                looksLikeOuterPatternEquals(()
+                                  skipOuterPattern(()
+                                parsePrecedenceExpression((, 1, true, ConstantPatternContext.none)
+                                  parseUnaryExpression((, true, ConstantPatternContext.none)
+                                    parsePrimary((, expression, ConstantPatternContext.none)
+                                      parseLiteralNull(()
+                                        listener: handleLiteralNull(null)
+                              ensureCloseParen(,, ()
+                              listener: endRecordLiteral((, 1, null)
+                  ensureSemicolon())
+                  listener: handlePatternVariableDeclarationStatement(var, =, ;)
+          notEofOrValue(}, var)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(var, ;, null, var, null, null)
+                skipOuterPattern(var)
+                listener: beginMetadataStar(var)
+                listener: endMetadataStar(0)
+                parsePatternVariableDeclarationStatement(var, ;, var)
+                  parsePattern(var, PatternContext.declaration, precedence: 1)
+                    parsePrimaryPattern(var, PatternContext.declaration)
+                      parseParenthesizedPatternOrRecordPattern(var, PatternContext.declaration)
+                        ensureIdentifier((, namedRecordFieldReference)
+                          listener: handleIdentifier(n, namedRecordFieldReference)
+                        parsePattern(:, PatternContext.declaration, precedence: 1)
+                          parsePrimaryPattern(:, PatternContext.declaration)
+                            parseParenthesizedPatternOrRecordPattern(:, PatternContext.declaration)
+                              ensureIdentifier((, namedRecordFieldReference)
+                                listener: handleIdentifier(x, namedRecordFieldReference)
+                              parsePattern(:, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern(:, PatternContext.declaration)
+                                  parseVariablePattern(:, PatternContext.declaration, typeInfo: Instance of 'SimpleType')
+                                    listener: handleIdentifier(int, typeReference)
+                                    listener: handleNoTypeArguments(a8)
+                                    listener: handleType(int, null)
+                                    listener: handleDeclaredVariablePattern(null, a8, false)
+                              listener: handlePatternField(:)
+                              ensureCloseParen(a8, ()
+                              listener: handleRecordPattern((, 1)
+                          listener: handleNullCheckPattern(?)
+                        listener: handlePatternField(:)
+                        ensureCloseParen(?, ()
+                        listener: handleRecordPattern((, 1)
+                  parseExpression(=)
+                    looksLikeOuterPatternEquals(=)
+                      skipOuterPattern(=)
+                    parsePrecedenceExpression(=, 1, true, ConstantPatternContext.none)
+                      parseUnaryExpression(=, true, ConstantPatternContext.none)
+                        parsePrimary(=, expression, ConstantPatternContext.none)
+                          parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=, ConstantPatternContext.none)
+                            parseParenthesizedExpressionOrRecordLiteral(=, null, ConstantPatternContext.none)
+                              listener: beginParenthesizedExpressionOrRecordLiteral(()
+                              ensureIdentifier((, namedRecordFieldReference)
+                                listener: handleIdentifier(n, namedRecordFieldReference)
+                              parseExpression(:)
+                                looksLikeOuterPatternEquals(:)
+                                  skipOuterPattern(:)
+                                parsePrecedenceExpression(:, 1, true, ConstantPatternContext.none)
+                                  parseUnaryExpression(:, true, ConstantPatternContext.none)
+                                    parsePrimary(:, expression, ConstantPatternContext.none)
+                                      parseLiteralNull(:)
+                                        listener: handleLiteralNull(null)
+                              listener: handleNamedRecordField(:)
+                              ensureCloseParen(null, ()
+                              listener: endRecordLiteral((, 1, null)
+                  ensureSemicolon())
+                  listener: handlePatternVariableDeclarationStatement(var, =, ;)
+          notEofOrValue(}, var)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(var, ;, null, var, null, null)
+                skipOuterPattern(var)
+                listener: beginMetadataStar(var)
+                listener: endMetadataStar(0)
+                parsePatternVariableDeclarationStatement(var, ;, var)
+                  parsePattern(var, PatternContext.declaration, precedence: 1)
+                    parsePrimaryPattern(var, PatternContext.declaration)
+                      parseParenthesizedPatternOrRecordPattern(var, PatternContext.declaration)
+                        ensureIdentifier((, namedRecordFieldReference)
+                          listener: handleIdentifier(n, namedRecordFieldReference)
+                        parsePattern(:, PatternContext.declaration, precedence: 1)
+                          parsePrimaryPattern(:, PatternContext.declaration)
+                            parseParenthesizedPatternOrRecordPattern(:, PatternContext.declaration)
+                              ensureIdentifier((, namedRecordFieldReference)
+                                listener: handleIdentifier(x, namedRecordFieldReference)
+                              parsePattern(:, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern(:, PatternContext.declaration)
+                                  parseVariablePattern(:, PatternContext.declaration, typeInfo: Instance of 'SimpleType')
+                                    listener: handleIdentifier(int, typeReference)
+                                    listener: handleNoTypeArguments(a9)
+                                    listener: handleType(int, null)
+                                    listener: handleDeclaredVariablePattern(null, a9, false)
+                              listener: handlePatternField(:)
+                              parsePattern(,, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern(,, PatternContext.declaration)
+                                  parseVariablePattern(,, PatternContext.declaration, typeInfo: Instance of 'SimpleType')
+                                    listener: handleIdentifier(int, typeReference)
+                                    listener: handleNoTypeArguments(b9)
+                                    listener: handleType(int, null)
+                                    listener: handleDeclaredVariablePattern(null, b9, false)
+                              listener: handlePatternField(null)
+                              ensureCloseParen(b9, ()
+                              listener: handleRecordPattern((, 2)
+                          listener: handleNullCheckPattern(?)
+                        listener: handlePatternField(:)
+                        parsePattern(,, PatternContext.declaration, precedence: 1)
+                          parsePrimaryPattern(,, PatternContext.declaration)
+                            parseParenthesizedPatternOrRecordPattern(,, PatternContext.declaration)
+                              ensureIdentifier((, namedRecordFieldReference)
+                                listener: handleIdentifier(y, namedRecordFieldReference)
+                              parsePattern(:, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern(:, PatternContext.declaration)
+                                  parseVariablePattern(:, PatternContext.declaration, typeInfo: Instance of 'SimpleType')
+                                    listener: handleIdentifier(int, typeReference)
+                                    listener: handleNoTypeArguments(c9)
+                                    listener: handleType(int, null)
+                                    listener: handleDeclaredVariablePattern(null, c9, false)
+                              listener: handlePatternField(:)
+                              parsePattern(,, PatternContext.declaration, precedence: 1)
+                                parsePrimaryPattern(,, PatternContext.declaration)
+                                  parseVariablePattern(,, PatternContext.declaration, typeInfo: Instance of 'SimpleType')
+                                    listener: handleIdentifier(int, typeReference)
+                                    listener: handleNoTypeArguments(d9)
+                                    listener: handleType(int, null)
+                                    listener: handleDeclaredVariablePattern(null, d9, false)
+                              listener: handlePatternField(null)
+                              ensureCloseParen(d9, ()
+                              listener: handleRecordPattern((, 2)
+                          listener: handleNullCheckPattern(?)
+                        listener: handlePatternField(null)
+                        ensureCloseParen(?, ()
+                        listener: handleRecordPattern((, 2)
+                  parseExpression(=)
+                    looksLikeOuterPatternEquals(=)
+                      skipOuterPattern(=)
+                    parsePrecedenceExpression(=, 1, true, ConstantPatternContext.none)
+                      parseUnaryExpression(=, true, ConstantPatternContext.none)
+                        parsePrimary(=, expression, ConstantPatternContext.none)
+                          parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=, ConstantPatternContext.none)
+                            parseParenthesizedExpressionOrRecordLiteral(=, null, ConstantPatternContext.none)
+                              listener: beginParenthesizedExpressionOrRecordLiteral(()
+                              ensureIdentifier((, namedRecordFieldReference)
+                                listener: handleIdentifier(n, namedRecordFieldReference)
+                              parseExpression(:)
+                                looksLikeOuterPatternEquals(:)
+                                  skipOuterPattern(:)
+                                parsePrecedenceExpression(:, 1, true, ConstantPatternContext.none)
+                                  parseUnaryExpression(:, true, ConstantPatternContext.none)
+                                    parsePrimary(:, expression, ConstantPatternContext.none)
+                                      parseLiteralNull(:)
+                                        listener: handleLiteralNull(null)
+                              listener: handleNamedRecordField(:)
+                              parseExpression(,)
+                                looksLikeOuterPatternEquals(,)
+                                  skipOuterPattern(,)
+                                parsePrecedenceExpression(,, 1, true, ConstantPatternContext.none)
+                                  parseUnaryExpression(,, true, ConstantPatternContext.none)
+                                    parsePrimary(,, expression, ConstantPatternContext.none)
+                                      parseLiteralNull(,)
+                                        listener: handleLiteralNull(null)
+                              ensureCloseParen(null, ()
+                              listener: endRecordLiteral((, 2, null)
+                  ensureSemicolon())
+                  listener: handlePatternVariableDeclarationStatement(var, =, ;)
+          notEofOrValue(}, var)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(var, ;, null, var, null, null)
+                skipOuterPattern(var)
+                listener: beginMetadataStar(var)
+                listener: endMetadataStar(0)
+                parsePatternVariableDeclarationStatement(var, ;, var)
+                  parsePattern(var, PatternContext.declaration, precedence: 1)
+                    parsePrimaryPattern(var, PatternContext.declaration)
+                      parseParenthesizedPatternOrRecordPattern(var, PatternContext.declaration)
+                        ensureIdentifier((, namedRecordFieldReference)
+                          listener: handleIdentifier(n, namedRecordFieldReference)
+                        parsePattern(:, PatternContext.declaration, precedence: 1)
+                          parsePrimaryPattern(:, PatternContext.declaration)
+                            parseVariablePattern(:, PatternContext.declaration, typeInfo: Instance of 'ComplexTypeInfo')
+                              parseRecordType((, :, true)
+                                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()
+                                parseRecordTypeNamedFields(,)
+                                  listener: beginRecordTypeNamedFields({)
+                                  parseRecordTypeField({, identifierIsOptional: false)
+                                    listener: beginRecordTypeEntry()
+                                    parseMetadataStar({)
+                                      listener: beginMetadataStar(int)
+                                      listener: endMetadataStar(0)
+                                    listener: handleIdentifier(int, typeReference)
+                                    listener: handleNoTypeArguments(x)
+                                    listener: handleType(int, null)
+                                    ensureIdentifier(int, recordFieldDeclaration)
+                                      listener: handleIdentifier(x, recordFieldDeclaration)
+                                    listener: endRecordTypeEntry()
+                                  listener: endRecordTypeNamedFields(1, {)
+                                ensureCloseParen(}, ()
+                                listener: endRecordType((, ?, 2, true)
+                              listener: handleDeclaredVariablePattern(null, a10, false)
+                        listener: handlePatternField(:)
+                        parsePattern(,, PatternContext.declaration, precedence: 1)
+                          parsePrimaryPattern(,, PatternContext.declaration)
+                            parseVariablePattern(,, PatternContext.declaration, typeInfo: Instance of 'ComplexTypeInfo')
+                              parseRecordType((, ,, true)
+                                listener: beginRecordType(()
+                                parseRecordTypeField((, identifierIsOptional: true)
+                                  listener: beginRecordTypeEntry()
+                                  parseMetadataStar(()
+                                    listener: beginMetadataStar(int)
+                                    listener: endMetadataStar(0)
+                                  listener: handleIdentifier(int, typeReference)
+                                  listener: handleNoTypeArguments(z)
+                                  listener: handleType(int, null)
+                                  ensureIdentifier(int, recordFieldDeclaration)
+                                    listener: handleIdentifier(z, recordFieldDeclaration)
+                                  listener: endRecordTypeEntry()
+                                parseRecordTypeNamedFields(,)
+                                  listener: beginRecordTypeNamedFields({)
+                                  parseRecordTypeField({, identifierIsOptional: false)
+                                    listener: beginRecordTypeEntry()
+                                    parseMetadataStar({)
+                                      listener: beginMetadataStar(int)
+                                      listener: endMetadataStar(0)
+                                    listener: handleIdentifier(int, typeReference)
+                                    listener: handleNoTypeArguments(y)
+                                    listener: handleType(int, null)
+                                    ensureIdentifier(int, recordFieldDeclaration)
+                                      listener: handleIdentifier(y, recordFieldDeclaration)
+                                    listener: endRecordTypeEntry()
+                                  listener: endRecordTypeNamedFields(1, {)
+                                ensureCloseParen(}, ()
+                                listener: endRecordType((, ?, 2, true)
+                              listener: handleDeclaredVariablePattern(null, b10, false)
+                        listener: handlePatternField(null)
+                        ensureCloseParen(b10, ()
+                        listener: handleRecordPattern((, 2)
+                  parseExpression(=)
+                    looksLikeOuterPatternEquals(=)
+                      skipOuterPattern(=)
+                    parsePrecedenceExpression(=, 1, true, ConstantPatternContext.none)
+                      parseUnaryExpression(=, true, ConstantPatternContext.none)
+                        parsePrimary(=, expression, ConstantPatternContext.none)
+                          parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=, ConstantPatternContext.none)
+                            parseParenthesizedExpressionOrRecordLiteral(=, null, ConstantPatternContext.none)
+                              listener: beginParenthesizedExpressionOrRecordLiteral(()
+                              ensureIdentifier((, namedRecordFieldReference)
+                                listener: handleIdentifier(n, namedRecordFieldReference)
+                              parseExpression(:)
+                                looksLikeOuterPatternEquals(:)
+                                  skipOuterPattern(:)
+                                parsePrecedenceExpression(:, 1, true, ConstantPatternContext.none)
+                                  parseUnaryExpression(:, true, ConstantPatternContext.none)
+                                    parsePrimary(:, expression, ConstantPatternContext.none)
+                                      parseLiteralNull(:)
+                                        listener: handleLiteralNull(null)
+                              listener: handleNamedRecordField(:)
+                              parseExpression(,)
+                                looksLikeOuterPatternEquals(,)
+                                  skipOuterPattern(,)
+                                parsePrecedenceExpression(,, 1, true, ConstantPatternContext.none)
+                                  parseUnaryExpression(,, true, ConstantPatternContext.none)
+                                    parsePrimary(,, expression, ConstantPatternContext.none)
+                                      parseLiteralNull(,)
+                                        listener: handleLiteralNull(null)
+                              ensureCloseParen(null, ()
+                              listener: endRecordLiteral((, 2, null)
+                  ensureSemicolon())
+                  listener: handlePatternVariableDeclarationStatement(var, =, ;)
           notEofOrValue(}, })
-          listener: endBlockFunctionBody(10, {, })
+          listener: endBlockFunctionBody(20, {, })
         listener: endTopLevelMethod(main, null, })
   listener: endTopLevelDeclaration()
   reportAllErrorTokens(main)
diff --git a/pkg/front_end/parser_testcases/patterns/issue_51176.dart.parser.expect b/pkg/front_end/parser_testcases/patterns/issue_51176.dart.parser.expect
index ce2b87a..183fa4e 100644
--- a/pkg/front_end/parser_testcases/patterns/issue_51176.dart.parser.expect
+++ b/pkg/front_end/parser_testcases/patterns/issue_51176.dart.parser.expect
@@ -14,6 +14,22 @@
 
 var (n: (int, {int x}) a10, (int z, {int y}) b10)
 = (n: (x: 42, -1), (y: 1, 0));
+
+var ((a1,)?,) = (null,);
+var (n: (x: a2)?) = (n: null);
+var (n: (x: a3, b3)?, (y: c3, d3)?) = (n: null, null);
+
+final ((a4,)?,) = (null,);
+final (n: (x: a5)?) = (n: null);
+final (n: (x: a6, b6)?, (y: c6, d6)?) = (n: null, null);
+
+var ((int a7,)?,) = (null,);
+var (n: (x: int a8)?) = (n: null);
+var (n: (x: int a9, int b9)?, (y: int c9, int d9)?)
+= (n: null, null);
+
+var (n: (int, {int x})? a10, (int z, {int y})? b10)
+= (n: null, null);
 }
 
 
@@ -33,5 +49,21 @@
 
 var[KeywordToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]int[StringToken],[SimpleToken] {[BeginToken]int[StringToken] x[StringToken]}[SimpleToken])[SimpleToken] a10[StringToken],[SimpleToken] ([BeginToken]int[StringToken] z[StringToken],[SimpleToken] {[BeginToken]int[StringToken] y[StringToken]}[SimpleToken])[SimpleToken] b10[StringToken])[SimpleToken]
 =[SimpleToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]x[StringToken]:[SimpleToken] 42[StringToken],[SimpleToken] -[SimpleToken]1[StringToken])[SimpleToken],[SimpleToken] ([BeginToken]y[StringToken]:[SimpleToken] 1[StringToken],[SimpleToken] 0[StringToken])[SimpleToken])[SimpleToken];[SimpleToken]
+
+var[KeywordToken] ([BeginToken]([BeginToken]a1[StringToken],[SimpleToken])[SimpleToken]?[SimpleToken],[SimpleToken])[SimpleToken] =[SimpleToken] ([BeginToken]null[KeywordToken],[SimpleToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]x[StringToken]:[SimpleToken] a2[StringToken])[SimpleToken]?[SimpleToken])[SimpleToken] =[SimpleToken] ([BeginToken]n[StringToken]:[SimpleToken] null[KeywordToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]x[StringToken]:[SimpleToken] a3[StringToken],[SimpleToken] b3[StringToken])[SimpleToken]?[SimpleToken],[SimpleToken] ([BeginToken]y[StringToken]:[SimpleToken] c3[StringToken],[SimpleToken] d3[StringToken])[SimpleToken]?[SimpleToken])[SimpleToken] =[SimpleToken] ([BeginToken]n[StringToken]:[SimpleToken] null[KeywordToken],[SimpleToken] null[KeywordToken])[SimpleToken];[SimpleToken]
+
+final[KeywordToken] ([BeginToken]([BeginToken]a4[StringToken],[SimpleToken])[SimpleToken]?[SimpleToken],[SimpleToken])[SimpleToken] =[SimpleToken] ([BeginToken]null[KeywordToken],[SimpleToken])[SimpleToken];[SimpleToken]
+final[KeywordToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]x[StringToken]:[SimpleToken] a5[StringToken])[SimpleToken]?[SimpleToken])[SimpleToken] =[SimpleToken] ([BeginToken]n[StringToken]:[SimpleToken] null[KeywordToken])[SimpleToken];[SimpleToken]
+final[KeywordToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]x[StringToken]:[SimpleToken] a6[StringToken],[SimpleToken] b6[StringToken])[SimpleToken]?[SimpleToken],[SimpleToken] ([BeginToken]y[StringToken]:[SimpleToken] c6[StringToken],[SimpleToken] d6[StringToken])[SimpleToken]?[SimpleToken])[SimpleToken] =[SimpleToken] ([BeginToken]n[StringToken]:[SimpleToken] null[KeywordToken],[SimpleToken] null[KeywordToken])[SimpleToken];[SimpleToken]
+
+var[KeywordToken] ([BeginToken]([BeginToken]int[StringToken] a7[StringToken],[SimpleToken])[SimpleToken]?[SimpleToken],[SimpleToken])[SimpleToken] =[SimpleToken] ([BeginToken]null[KeywordToken],[SimpleToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]x[StringToken]:[SimpleToken] int[StringToken] a8[StringToken])[SimpleToken]?[SimpleToken])[SimpleToken] =[SimpleToken] ([BeginToken]n[StringToken]:[SimpleToken] null[KeywordToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]x[StringToken]:[SimpleToken] int[StringToken] a9[StringToken],[SimpleToken] int[StringToken] b9[StringToken])[SimpleToken]?[SimpleToken],[SimpleToken] ([BeginToken]y[StringToken]:[SimpleToken] int[StringToken] c9[StringToken],[SimpleToken] int[StringToken] d9[StringToken])[SimpleToken]?[SimpleToken])[SimpleToken]
+=[SimpleToken] ([BeginToken]n[StringToken]:[SimpleToken] null[KeywordToken],[SimpleToken] null[KeywordToken])[SimpleToken];[SimpleToken]
+
+var[KeywordToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]int[StringToken],[SimpleToken] {[BeginToken]int[StringToken] x[StringToken]}[SimpleToken])[SimpleToken]?[SimpleToken] a10[StringToken],[SimpleToken] ([BeginToken]int[StringToken] z[StringToken],[SimpleToken] {[BeginToken]int[StringToken] y[StringToken]}[SimpleToken])[SimpleToken]?[SimpleToken] b10[StringToken])[SimpleToken]
+=[SimpleToken] ([BeginToken]n[StringToken]:[SimpleToken] null[KeywordToken],[SimpleToken] null[KeywordToken])[SimpleToken];[SimpleToken]
 }[SimpleToken]
 [SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/issue_51176.dart.scanner.expect b/pkg/front_end/parser_testcases/patterns/issue_51176.dart.scanner.expect
index ce2b87a..183fa4e 100644
--- a/pkg/front_end/parser_testcases/patterns/issue_51176.dart.scanner.expect
+++ b/pkg/front_end/parser_testcases/patterns/issue_51176.dart.scanner.expect
@@ -14,6 +14,22 @@
 
 var (n: (int, {int x}) a10, (int z, {int y}) b10)
 = (n: (x: 42, -1), (y: 1, 0));
+
+var ((a1,)?,) = (null,);
+var (n: (x: a2)?) = (n: null);
+var (n: (x: a3, b3)?, (y: c3, d3)?) = (n: null, null);
+
+final ((a4,)?,) = (null,);
+final (n: (x: a5)?) = (n: null);
+final (n: (x: a6, b6)?, (y: c6, d6)?) = (n: null, null);
+
+var ((int a7,)?,) = (null,);
+var (n: (x: int a8)?) = (n: null);
+var (n: (x: int a9, int b9)?, (y: int c9, int d9)?)
+= (n: null, null);
+
+var (n: (int, {int x})? a10, (int z, {int y})? b10)
+= (n: null, null);
 }
 
 
@@ -33,5 +49,21 @@
 
 var[KeywordToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]int[StringToken],[SimpleToken] {[BeginToken]int[StringToken] x[StringToken]}[SimpleToken])[SimpleToken] a10[StringToken],[SimpleToken] ([BeginToken]int[StringToken] z[StringToken],[SimpleToken] {[BeginToken]int[StringToken] y[StringToken]}[SimpleToken])[SimpleToken] b10[StringToken])[SimpleToken]
 =[SimpleToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]x[StringToken]:[SimpleToken] 42[StringToken],[SimpleToken] -[SimpleToken]1[StringToken])[SimpleToken],[SimpleToken] ([BeginToken]y[StringToken]:[SimpleToken] 1[StringToken],[SimpleToken] 0[StringToken])[SimpleToken])[SimpleToken];[SimpleToken]
+
+var[KeywordToken] ([BeginToken]([BeginToken]a1[StringToken],[SimpleToken])[SimpleToken]?[SimpleToken],[SimpleToken])[SimpleToken] =[SimpleToken] ([BeginToken]null[KeywordToken],[SimpleToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]x[StringToken]:[SimpleToken] a2[StringToken])[SimpleToken]?[SimpleToken])[SimpleToken] =[SimpleToken] ([BeginToken]n[StringToken]:[SimpleToken] null[KeywordToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]x[StringToken]:[SimpleToken] a3[StringToken],[SimpleToken] b3[StringToken])[SimpleToken]?[SimpleToken],[SimpleToken] ([BeginToken]y[StringToken]:[SimpleToken] c3[StringToken],[SimpleToken] d3[StringToken])[SimpleToken]?[SimpleToken])[SimpleToken] =[SimpleToken] ([BeginToken]n[StringToken]:[SimpleToken] null[KeywordToken],[SimpleToken] null[KeywordToken])[SimpleToken];[SimpleToken]
+
+final[KeywordToken] ([BeginToken]([BeginToken]a4[StringToken],[SimpleToken])[SimpleToken]?[SimpleToken],[SimpleToken])[SimpleToken] =[SimpleToken] ([BeginToken]null[KeywordToken],[SimpleToken])[SimpleToken];[SimpleToken]
+final[KeywordToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]x[StringToken]:[SimpleToken] a5[StringToken])[SimpleToken]?[SimpleToken])[SimpleToken] =[SimpleToken] ([BeginToken]n[StringToken]:[SimpleToken] null[KeywordToken])[SimpleToken];[SimpleToken]
+final[KeywordToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]x[StringToken]:[SimpleToken] a6[StringToken],[SimpleToken] b6[StringToken])[SimpleToken]?[SimpleToken],[SimpleToken] ([BeginToken]y[StringToken]:[SimpleToken] c6[StringToken],[SimpleToken] d6[StringToken])[SimpleToken]?[SimpleToken])[SimpleToken] =[SimpleToken] ([BeginToken]n[StringToken]:[SimpleToken] null[KeywordToken],[SimpleToken] null[KeywordToken])[SimpleToken];[SimpleToken]
+
+var[KeywordToken] ([BeginToken]([BeginToken]int[StringToken] a7[StringToken],[SimpleToken])[SimpleToken]?[SimpleToken],[SimpleToken])[SimpleToken] =[SimpleToken] ([BeginToken]null[KeywordToken],[SimpleToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]x[StringToken]:[SimpleToken] int[StringToken] a8[StringToken])[SimpleToken]?[SimpleToken])[SimpleToken] =[SimpleToken] ([BeginToken]n[StringToken]:[SimpleToken] null[KeywordToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]x[StringToken]:[SimpleToken] int[StringToken] a9[StringToken],[SimpleToken] int[StringToken] b9[StringToken])[SimpleToken]?[SimpleToken],[SimpleToken] ([BeginToken]y[StringToken]:[SimpleToken] int[StringToken] c9[StringToken],[SimpleToken] int[StringToken] d9[StringToken])[SimpleToken]?[SimpleToken])[SimpleToken]
+=[SimpleToken] ([BeginToken]n[StringToken]:[SimpleToken] null[KeywordToken],[SimpleToken] null[KeywordToken])[SimpleToken];[SimpleToken]
+
+var[KeywordToken] ([BeginToken]n[StringToken]:[SimpleToken] ([BeginToken]int[StringToken],[SimpleToken] {[BeginToken]int[StringToken] x[StringToken]}[SimpleToken])[SimpleToken]?[SimpleToken] a10[StringToken],[SimpleToken] ([BeginToken]int[StringToken] z[StringToken],[SimpleToken] {[BeginToken]int[StringToken] y[StringToken]}[SimpleToken])[SimpleToken]?[SimpleToken] b10[StringToken])[SimpleToken]
+=[SimpleToken] ([BeginToken]n[StringToken]:[SimpleToken] null[KeywordToken],[SimpleToken] null[KeywordToken])[SimpleToken];[SimpleToken]
 }[SimpleToken]
 [SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/issue_52439.dart b/pkg/front_end/parser_testcases/patterns/issue_52439.dart
new file mode 100644
index 0000000..d06090a
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/issue_52439.dart
@@ -0,0 +1,5 @@
+void main() {
+  var (int x, (int, )? y) = switch (foo) {
+    _ => (42, null),
+  };
+}
diff --git a/pkg/front_end/parser_testcases/patterns/issue_52439.dart.expect b/pkg/front_end/parser_testcases/patterns/issue_52439.dart.expect
new file mode 100644
index 0000000..e6eca06
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/issue_52439.dart.expect
@@ -0,0 +1,55 @@
+beginCompilationUnit(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(, null, null)
+      handleVoidKeyword(void)
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginMetadataStar(var)
+        endMetadataStar(0)
+        handleIdentifier(int, typeReference)
+        handleNoTypeArguments(x)
+        handleType(int, null)
+        handleDeclaredVariablePattern(null, x, false)
+        handlePatternField(null)
+        beginRecordType(()
+          beginRecordTypeEntry()
+            beginMetadataStar(int)
+            endMetadataStar(0)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(,)
+            handleType(int, null)
+            handleNoName(,)
+          endRecordTypeEntry()
+        endRecordType((, ?, 1, false)
+        handleDeclaredVariablePattern(null, y, false)
+        handlePatternField(null)
+        handleRecordPattern((, 2)
+        beginSwitchExpression(switch)
+          handleIdentifier(foo, expression)
+          handleNoTypeArguments())
+          handleNoArguments())
+          handleSend(foo, ))
+          handleParenthesizedCondition((, null, null)
+          beginSwitchExpressionBlock({)
+            beginSwitchExpressionCase()
+              handleNoType(_)
+              handleWildcardPattern(null, _)
+              handleSwitchExpressionCasePattern(_)
+              beginParenthesizedExpressionOrRecordLiteral(()
+                handleLiteralInt(42)
+                handleLiteralNull(null)
+              endRecordLiteral((, 2, null)
+            endSwitchExpressionCase(null, =>, ))
+          endSwitchExpressionBlock(1, {, })
+        endSwitchExpression(switch, })
+        handlePatternVariableDeclarationStatement(var, =, ;)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(void, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/issue_52439.dart.intertwined.expect b/pkg/front_end/parser_testcases/patterns/issue_52439.dart.intertwined.expect
new file mode 100644
index 0000000..6d7b50a
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/issue_52439.dart.intertwined.expect
@@ -0,0 +1,143 @@
+parseUnit(void)
+  skipErrorTokens(void)
+  listener: beginCompilationUnit(void)
+  syntheticPreviousToken(void)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, main, false)
+        listener: beginTopLevelMethod(, null, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifierPotentiallyRecovered(void, 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(}, var)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers(var, {, null, var, null, null)
+                skipOuterPattern(var)
+                listener: beginMetadataStar(var)
+                listener: endMetadataStar(0)
+                parsePatternVariableDeclarationStatement(var, {, var)
+                  parsePattern(var, PatternContext.declaration, precedence: 1)
+                    parsePrimaryPattern(var, PatternContext.declaration)
+                      parseParenthesizedPatternOrRecordPattern(var, PatternContext.declaration)
+                        parsePattern((, PatternContext.declaration, precedence: 1)
+                          parsePrimaryPattern((, PatternContext.declaration)
+                            parseVariablePattern((, PatternContext.declaration, typeInfo: Instance of 'SimpleType')
+                              listener: handleIdentifier(int, typeReference)
+                              listener: handleNoTypeArguments(x)
+                              listener: handleType(int, null)
+                              listener: handleDeclaredVariablePattern(null, x, false)
+                        listener: handlePatternField(null)
+                        parsePattern(,, PatternContext.declaration, precedence: 1)
+                          parsePrimaryPattern(,, PatternContext.declaration)
+                            parseVariablePattern(,, PatternContext.declaration, typeInfo: Instance of 'ComplexTypeInfo')
+                              parseRecordType((, ,, true)
+                                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()
+                                listener: endRecordType((, ?, 1, false)
+                              listener: handleDeclaredVariablePattern(null, y, false)
+                        listener: handlePatternField(null)
+                        ensureCloseParen(y, ()
+                        listener: handleRecordPattern((, 2)
+                  parseExpression(=)
+                    looksLikeOuterPatternEquals(=)
+                      skipOuterPattern(=)
+                    parsePrecedenceExpression(=, 1, true, ConstantPatternContext.none)
+                      parseUnaryExpression(=, true, ConstantPatternContext.none)
+                        parsePrimary(=, expression, ConstantPatternContext.none)
+                          inPlainSync()
+                          parseSwitchExpression(=)
+                            listener: beginSwitchExpression(switch)
+                            ensureParenthesizedCondition(switch, allowCase: false)
+                              parseExpressionInParenthesisRest((, allowCase: false)
+                                parseExpression(()
+                                  looksLikeOuterPatternEquals(()
+                                    skipOuterPattern(()
+                                      skipObjectPatternRest(foo)
+                                  parsePrecedenceExpression((, 1, true, ConstantPatternContext.none)
+                                    parseUnaryExpression((, true, ConstantPatternContext.none)
+                                      parsePrimary((, expression, ConstantPatternContext.none)
+                                        parseSendOrFunctionLiteral((, expression, ConstantPatternContext.none)
+                                          parseSend((, expression, ConstantPatternContext.none)
+                                            isNextIdentifier(()
+                                            ensureIdentifier((, expression)
+                                              listener: handleIdentifier(foo, expression)
+                                            listener: handleNoTypeArguments())
+                                            parseArgumentsOpt(foo)
+                                              listener: handleNoArguments())
+                                            listener: handleSend(foo, ))
+                                ensureCloseParen(foo, ()
+                                listener: handleParenthesizedCondition((, null, null)
+                            ensureBlock(), null, switch expression)
+                            listener: beginSwitchExpressionBlock({)
+                            listener: beginSwitchExpressionCase()
+                            parsePattern({, PatternContext.matching, precedence: 1)
+                              parsePrimaryPattern({, PatternContext.matching)
+                                parseVariablePattern({, PatternContext.matching, typeInfo: Instance of 'NoType')
+                                  listener: handleNoType(_)
+                                  listener: handleWildcardPattern(null, _)
+                            listener: handleSwitchExpressionCasePattern(_)
+                            ensureFunctionArrow(_)
+                            parseExpression(=>)
+                              looksLikeOuterPatternEquals(=>)
+                                skipOuterPattern(=>)
+                              parsePrecedenceExpression(=>, 1, true, ConstantPatternContext.none)
+                                parseUnaryExpression(=>, true, ConstantPatternContext.none)
+                                  parsePrimary(=>, expression, ConstantPatternContext.none)
+                                    parseParenthesizedExpressionFunctionLiteralOrRecordLiteral(=>, ConstantPatternContext.none)
+                                      parseParenthesizedExpressionOrRecordLiteral(=>, null, ConstantPatternContext.none)
+                                        listener: beginParenthesizedExpressionOrRecordLiteral(()
+                                        parseExpression(()
+                                          looksLikeOuterPatternEquals(()
+                                            skipOuterPattern(()
+                                          parsePrecedenceExpression((, 1, true, ConstantPatternContext.none)
+                                            parseUnaryExpression((, true, ConstantPatternContext.none)
+                                              parsePrimary((, expression, ConstantPatternContext.none)
+                                                parseLiteralInt(()
+                                                  listener: handleLiteralInt(42)
+                                        parseExpression(,)
+                                          looksLikeOuterPatternEquals(,)
+                                            skipOuterPattern(,)
+                                          parsePrecedenceExpression(,, 1, true, ConstantPatternContext.none)
+                                            parseUnaryExpression(,, true, ConstantPatternContext.none)
+                                              parsePrimary(,, expression, ConstantPatternContext.none)
+                                                parseLiteralNull(,)
+                                                  listener: handleLiteralNull(null)
+                                        ensureCloseParen(null, ()
+                                        listener: endRecordLiteral((, 2, null)
+                            listener: endSwitchExpressionCase(null, =>, ))
+                            listener: endSwitchExpressionBlock(1, {, })
+                            listener: endSwitchExpression(switch, })
+                  ensureSemicolon(})
+                  listener: handlePatternVariableDeclarationStatement(var, =, ;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(void)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/patterns/issue_52439.dart.parser.expect b/pkg/front_end/parser_testcases/patterns/issue_52439.dart.parser.expect
new file mode 100644
index 0000000..add3432
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/issue_52439.dart.parser.expect
@@ -0,0 +1,13 @@
+void main() {
+var (int x, (int, )? y) = switch (foo) {
+_ => (42, null),
+};
+}
+
+
+void[KeywordToken] main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+var[KeywordToken] ([BeginToken]int[StringToken] x[StringToken],[SimpleToken] ([BeginToken]int[StringToken],[SimpleToken] )[SimpleToken]?[SimpleToken] y[StringToken])[SimpleToken] =[SimpleToken] switch[KeywordToken] ([BeginToken]foo[StringToken])[SimpleToken] {[BeginToken]
+_[StringToken] =>[SimpleToken] ([BeginToken]42[StringToken],[SimpleToken] null[KeywordToken])[SimpleToken],[SimpleToken]
+}[SimpleToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/patterns/issue_52439.dart.scanner.expect b/pkg/front_end/parser_testcases/patterns/issue_52439.dart.scanner.expect
new file mode 100644
index 0000000..add3432
--- /dev/null
+++ b/pkg/front_end/parser_testcases/patterns/issue_52439.dart.scanner.expect
@@ -0,0 +1,13 @@
+void main() {
+var (int x, (int, )? y) = switch (foo) {
+_ => (42, null),
+};
+}
+
+
+void[KeywordToken] main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+var[KeywordToken] ([BeginToken]int[StringToken] x[StringToken],[SimpleToken] ([BeginToken]int[StringToken],[SimpleToken] )[SimpleToken]?[SimpleToken] y[StringToken])[SimpleToken] =[SimpleToken] switch[KeywordToken] ([BeginToken]foo[StringToken])[SimpleToken] {[BeginToken]
+_[StringToken] =>[SimpleToken] ([BeginToken]42[StringToken],[SimpleToken] null[KeywordToken])[SimpleToken],[SimpleToken]
+}[SimpleToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/tests/language/patterns/issue_52439.dart b/tests/language/patterns/issue_52439.dart
new file mode 100644
index 0000000..53858de
--- /dev/null
+++ b/tests/language/patterns/issue_52439.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=records,patterns
+
+import "package:expect/expect.dart";
+
+void main() {
+  dynamic foo = 84;
+  var (int x, (int, )? y) = switch (foo) {
+    _ => (42, null),
+  };
+  Expect.equals(42, x);
+  Expect.equals(null, y);
+}
+