@@ -858,7 +858,8 @@ namespace {
858
858
static void parseGuardedPattern (Parser &P, GuardedPattern &result,
859
859
ParserStatus &status,
860
860
SmallVectorImpl<VarDecl *> &boundDecls,
861
- GuardedPatternContext parsingContext) {
861
+ GuardedPatternContext parsingContext,
862
+ bool isFirstPattern) {
862
863
ParserResult<Pattern> patternResult;
863
864
auto setErrorResult = [&] () {
864
865
patternResult = makeParserErrorResult (new (P.Context )
@@ -945,14 +946,64 @@ static void parseGuardedPattern(Parser &P, GuardedPattern &result,
945
946
status |= patternResult;
946
947
result.ThePattern = patternResult.get ();
947
948
948
- // Add variable bindings from the pattern to the case scope. We have
949
- // to do this with a full AST walk, because the freshly parsed pattern
950
- // represents tuples and var patterns as tupleexprs and
951
- // unresolved_pattern_expr nodes, instead of as proper pattern nodes.
952
- patternResult.get ()->forEachVariable ([&](VarDecl *VD) {
953
- if (VD->hasName ()) P.addToScope (VD);
954
- boundDecls.push_back (VD);
955
- });
949
+ if (isFirstPattern) {
950
+ // Add variable bindings from the pattern to the case scope. We have
951
+ // to do this with a full AST walk, because the freshly parsed pattern
952
+ // represents tuples and var patterns as tupleexprs and
953
+ // unresolved_pattern_expr nodes, instead of as proper pattern nodes.
954
+ patternResult.get ()->forEachVariable ([&](VarDecl *VD) {
955
+ if (VD->hasName ()) P.addToScope (VD);
956
+ boundDecls.push_back (VD);
957
+ });
958
+ } else {
959
+ // If boundDecls already contains variables, then we must match the
960
+ // same number and same names in this pattern as were declared in a
961
+ // previous pattern (and later we will make sure they have the same
962
+ // types).
963
+ SmallVector<VarDecl*, 4 > repeatedDecls;
964
+ patternResult.get ()->forEachVariable ([&](VarDecl *VD) {
965
+ if (!VD->hasName ())
966
+ return ;
967
+
968
+ for (auto repeat : repeatedDecls)
969
+ if (repeat->getName () == VD->getName ())
970
+ P.addToScope (VD); // will diagnose a duplicate declaration
971
+
972
+ bool found = false ;
973
+ for (auto previous : boundDecls) {
974
+ if (previous->hasName () && previous->getName () == VD->getName ()) {
975
+ found = true ;
976
+ break ;
977
+ }
978
+ }
979
+ if (!found) {
980
+ // Diagnose a declaration that doesn't match a previous pattern.
981
+ P.diagnose (VD->getLoc (), diag::extra_var_in_multiple_pattern_list, VD->getName ());
982
+ status.setIsParseError ();
983
+ }
984
+ repeatedDecls.push_back (VD);
985
+ });
986
+
987
+ for (auto previous : boundDecls) {
988
+ bool found = false ;
989
+ for (auto repeat : repeatedDecls) {
990
+ if (previous->hasName () && previous->getName () == repeat->getName ()) {
991
+ found = true ;
992
+ break ;
993
+ }
994
+ }
995
+ if (!found) {
996
+ // Diagnose a previous declaration that is missing in this pattern.
997
+ P.diagnose (previous->getLoc (), diag::extra_var_in_multiple_pattern_list, previous->getName ());
998
+ status.setIsParseError ();
999
+ }
1000
+ }
1001
+
1002
+ for (auto VD : repeatedDecls) {
1003
+ VD->setHasNonPatternBindingInit ();
1004
+ VD->setImplicit ();
1005
+ }
1006
+ }
956
1007
957
1008
// Now that we have them, mark them as being initialized without a PBD.
958
1009
for (auto VD : boundDecls)
@@ -2004,7 +2055,7 @@ ParserResult<CatchStmt> Parser::parseStmtCatch() {
2004
2055
ParserStatus status;
2005
2056
GuardedPattern pattern;
2006
2057
parseGuardedPattern (*this , pattern, status, boundDecls,
2007
- GuardedPatternContext::Catch);
2058
+ GuardedPatternContext::Catch, /* isFirst */ true );
2008
2059
if (status.hasCodeCompletion ()) {
2009
2060
return makeParserCodeCompletionResult<CatchStmt>();
2010
2061
}
@@ -2509,17 +2560,19 @@ static ParserStatus parseStmtCase(Parser &P, SourceLoc &CaseLoc,
2509
2560
SmallVectorImpl<VarDecl *> &BoundDecls,
2510
2561
SourceLoc &ColonLoc) {
2511
2562
ParserStatus Status;
2512
-
2563
+ bool isFirst = true ;
2564
+
2513
2565
CaseLoc = P.consumeToken (tok::kw_case);
2514
2566
2515
2567
do {
2516
2568
GuardedPattern PatternResult;
2517
2569
parseGuardedPattern (P, PatternResult, Status, BoundDecls,
2518
- GuardedPatternContext::Case);
2570
+ GuardedPatternContext::Case, isFirst );
2519
2571
LabelItems.push_back (CaseLabelItem (/* IsDefault=*/ false ,
2520
2572
PatternResult.ThePattern ,
2521
2573
PatternResult.WhereLoc ,
2522
2574
PatternResult.Guard ));
2575
+ isFirst = false ;
2523
2576
} while (P.consumeIf (tok::comma));
2524
2577
2525
2578
ColonLoc = P.Tok .getLoc ();
@@ -2586,11 +2639,6 @@ ParserResult<CaseStmt> Parser::parseStmtCase() {
2586
2639
2587
2640
assert (!CaseLabelItems.empty () && " did not parse any labels?!" );
2588
2641
2589
- // Case blocks with multiple patterns cannot bind variables.
2590
- if (!BoundDecls.empty () && CaseLabelItems.size () > 1 )
2591
- diagnose (BoundDecls[0 ]->getLoc (),
2592
- diag::var_binding_with_multiple_case_patterns);
2593
-
2594
2642
SmallVector<ASTNode, 8 > BodyItems;
2595
2643
2596
2644
SourceLoc StartOfBody = Tok.getLoc ();
0 commit comments