@@ -947,6 +947,75 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
947
947
return S;
948
948
}
949
949
950
+ void checkCaseLabelItem (CaseStmt *caseBlock, CaseLabelItem &labelItem,
951
+ bool &limitExhaustivityChecks, Type subjectType) {
952
+ SWIFT_DEFER {
953
+ // Check the guard expression, if present.
954
+ if (auto *guard = labelItem.getGuardExpr ()) {
955
+ limitExhaustivityChecks |= TC.typeCheckCondition (guard, DC);
956
+ labelItem.setGuardExpr (guard);
957
+ }
958
+ };
959
+
960
+ Pattern *pattern = labelItem.getPattern ();
961
+ auto *newPattern = TC.resolvePattern (pattern, DC,
962
+ /* isStmtCondition*/ false );
963
+ if (!newPattern)
964
+ return ;
965
+ pattern = newPattern;
966
+ // Coerce the pattern to the subject's type.
967
+ TypeResolutionOptions patternOptions (TypeResolverContext::InExpression);
968
+ if (!subjectType ||
969
+ TC.coercePatternToType (pattern, TypeResolution::forContextual (DC),
970
+ subjectType, patternOptions)) {
971
+ limitExhaustivityChecks = true ;
972
+
973
+ // If that failed, mark any variables binding pieces of the pattern
974
+ // as invalid to silence follow-on errors.
975
+ pattern->forEachVariable ([&](VarDecl *VD) { VD->markInvalid (); });
976
+ }
977
+ labelItem.setPattern (pattern);
978
+
979
+ // For each variable in the pattern, make sure its type is identical to what
980
+ // it was in the first label item's pattern.
981
+ auto *firstPattern = caseBlock->getCaseLabelItems ()[0 ].getPattern ();
982
+ SmallVector<VarDecl *, 4 > vars;
983
+ firstPattern->collectVariables (vars);
984
+ pattern->forEachVariable ([&](VarDecl *vd) {
985
+ if (!vd->hasName ())
986
+ return ;
987
+ for (auto *expected : vars) {
988
+ if (expected->hasName () && expected->getName () == vd->getName ()) {
989
+ if (vd->hasType () && expected->hasType () && !expected->isInvalid () &&
990
+ !vd->getType ()->isEqual (expected->getType ())) {
991
+ TC.diagnose (vd->getLoc (), diag::type_mismatch_multiple_pattern_list,
992
+ vd->getType (), expected->getType ());
993
+ vd->markInvalid ();
994
+ expected->markInvalid ();
995
+ }
996
+ if (expected->isLet () != vd->isLet ()) {
997
+ auto diag = TC.diagnose (
998
+ vd->getLoc (), diag::mutability_mismatch_multiple_pattern_list,
999
+ vd->isLet (), expected->isLet ());
1000
+
1001
+ VarPattern *foundVP = nullptr ;
1002
+ vd->getParentPattern ()->forEachNode ([&](Pattern *P) {
1003
+ if (auto *VP = dyn_cast<VarPattern>(P))
1004
+ if (VP->getSingleVar () == vd)
1005
+ foundVP = VP;
1006
+ });
1007
+ if (foundVP)
1008
+ diag.fixItReplace (foundVP->getLoc (),
1009
+ expected->isLet () ? " let" : " var" );
1010
+ vd->markInvalid ();
1011
+ expected->markInvalid ();
1012
+ }
1013
+ return ;
1014
+ }
1015
+ }
1016
+ });
1017
+ }
1018
+
950
1019
Stmt *visitSwitchStmt (SwitchStmt *switchStmt) {
951
1020
// Type-check the subject expression.
952
1021
Expr *subjectExpr = switchStmt->getSubjectExpr ();
@@ -979,73 +1048,10 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
979
1048
FallthroughDest = std::next (i) == e ? nullptr : *std::next (i);
980
1049
981
1050
for (auto &labelItem : caseBlock->getMutableCaseLabelItems ()) {
982
- // Resolve the pattern in the label.
983
- Pattern *pattern = labelItem.getPattern ();
984
- if (auto *newPattern = TC.resolvePattern (pattern, DC,
985
- /* isStmtCondition*/ false )) {
986
- pattern = newPattern;
987
- // Coerce the pattern to the subject's type.
988
- TypeResolutionOptions patternOptions (TypeResolverContext::InExpression);
989
- if (!subjectType ||
990
- TC.coercePatternToType (pattern, TypeResolution::forContextual (DC),
991
- subjectType, patternOptions)) {
992
- limitExhaustivityChecks = true ;
993
-
994
- // If that failed, mark any variables binding pieces of the pattern
995
- // as invalid to silence follow-on errors.
996
- pattern->forEachVariable ([&](VarDecl *VD) {
997
- VD->markInvalid ();
998
- });
999
- }
1000
- labelItem.setPattern (pattern);
1001
-
1002
- // For each variable in the pattern, make sure its type is identical to what it
1003
- // was in the first label item's pattern.
1004
- auto *firstPattern = caseBlock->getCaseLabelItems ()[0 ].getPattern ();
1005
- SmallVector<VarDecl *, 4 > vars;
1006
- firstPattern->collectVariables (vars);
1007
- pattern->forEachVariable ([&](VarDecl *vd) {
1008
- if (!vd->hasName ())
1009
- return ;
1010
- for (auto *expected : vars) {
1011
- if (expected->hasName () && expected->getName () == vd->getName ()) {
1012
- if (vd->hasType () && expected->hasType () &&
1013
- !expected->isInvalid () &&
1014
- !vd->getType ()->isEqual (expected->getType ())) {
1015
- TC.diagnose (vd->getLoc (),
1016
- diag::type_mismatch_multiple_pattern_list,
1017
- vd->getType (), expected->getType ());
1018
- vd->markInvalid ();
1019
- expected->markInvalid ();
1020
- }
1021
- if (expected->isLet () != vd->isLet ()) {
1022
- auto diag = TC.diagnose (
1023
- vd->getLoc (),
1024
- diag::mutability_mismatch_multiple_pattern_list,
1025
- vd->isLet (), expected->isLet ());
1026
-
1027
- VarPattern *foundVP = nullptr ;
1028
- vd->getParentPattern ()->forEachNode ([&](Pattern *P) {
1029
- if (auto *VP = dyn_cast<VarPattern>(P))
1030
- if (VP->getSingleVar () == vd)
1031
- foundVP = VP;
1032
- });
1033
- if (foundVP)
1034
- diag.fixItReplace (foundVP->getLoc (),
1035
- expected->isLet () ? " let" : " var" );
1036
- vd->markInvalid ();
1037
- expected->markInvalid ();
1038
- }
1039
- return ;
1040
- }
1041
- }
1042
- });
1043
- }
1044
- // Check the guard expression, if present.
1045
- if (auto *guard = labelItem.getGuardExpr ()) {
1046
- limitExhaustivityChecks |= TC.typeCheckCondition (guard, DC);
1047
- labelItem.setGuardExpr (guard);
1048
- }
1051
+ // Resolve the pattern in our case label if it has not been resolved
1052
+ // and check that our var decls follow invariants.
1053
+ checkCaseLabelItem (caseBlock, labelItem, limitExhaustivityChecks,
1054
+ subjectType);
1049
1055
}
1050
1056
1051
1057
// Check restrictions on '@unknown'.
0 commit comments