@@ -983,64 +983,72 @@ void repairTupleOrAssociatedValuePatternIfApplicable(
983
983
Type enumPayloadType,
984
984
const EnumElementDecl *enumCase) {
985
985
auto &DE = Ctx.Diags ;
986
- bool addDeclNote = false ;
987
- if (auto *tupleType = dyn_cast<TupleType>(enumPayloadType.getPointer ())) {
988
- if (tupleType->getNumElements () >= 2
989
- && enumElementInnerPat->getKind () == PatternKind::Paren) {
990
- auto *semantic = enumElementInnerPat->getSemanticsProvidingPattern ();
991
- if (auto *tuplePattern = dyn_cast<TuplePattern>(semantic)) {
992
- if (tuplePattern->getNumElements () >= 2 ) {
993
- auto diag = DE.diagnose (tuplePattern->getLoc (),
994
- diag::converting_tuple_into_several_associated_values,
995
- enumCase->getNameStr (), tupleType->getNumElements ());
996
- auto subPattern =
997
- dyn_cast<ParenPattern>(enumElementInnerPat)->getSubPattern ();
998
-
999
- // We might also have code like
1000
- //
1001
- // enum Upair { case upair(Int, Int) }
1002
- // func f(u: Upair) { switch u { case .upair(let (x, y)): () } }
1003
- //
1004
- // This needs a more complex rearrangement to fix the code. So only
1005
- // apply the fix-it if we have a tuple immediately inside.
1006
- if (subPattern->getKind () == PatternKind::Tuple) {
1007
- auto leadingParen = SourceRange (enumElementInnerPat->getStartLoc ());
1008
- auto trailingParen = SourceRange (enumElementInnerPat->getEndLoc ());
1009
- diag.fixItRemove (leadingParen)
1010
- .fixItRemove (trailingParen);
1011
- }
1012
-
1013
- addDeclNote = true ;
1014
- enumElementInnerPat = semantic;
1015
- }
1016
- } else {
1017
- DE.diagnose (enumElementInnerPat->getLoc (),
1018
- diag::found_one_pattern_for_several_associated_values,
1019
- enumCase->getNameStr (),
1020
- tupleType->getNumElements ());
1021
- addDeclNote = true ;
1022
- }
1023
- }
1024
- } else if (auto *tupleType = enumPayloadType->getAs <TupleType>()) {
1025
- if (tupleType->getNumElements () >= 2 ) {
1026
- if (auto *tuplePattern = dyn_cast<TuplePattern>(enumElementInnerPat)) {
1027
- DE.diagnose (enumElementInnerPat->getLoc (),
1028
- diag::converting_several_associated_values_into_tuple,
1029
- enumCase->getNameStr (),
1030
- tupleType->getNumElements ())
1031
- .fixItInsert (enumElementInnerPat->getStartLoc (), " (" )
1032
- .fixItInsertAfter (enumElementInnerPat->getEndLoc (), " )" );
1033
- addDeclNote = true ;
1034
- enumElementInnerPat =
1035
- new (Ctx) ParenPattern (enumElementInnerPat->getStartLoc (),
1036
- enumElementInnerPat,
1037
- enumElementInnerPat->getEndLoc ());
986
+ auto addDeclNote = [&]() {
987
+ DE.diagnose (enumCase->getStartLoc (), diag::decl_declared_here, enumCase);
988
+ };
989
+ auto payloadParams = enumCase->getCaseConstructorParams ();
990
+
991
+ // First check to see whether we need to untuple a pattern.
992
+ if (payloadParams.size () >= 2 ) {
993
+ if (enumElementInnerPat->getKind () != PatternKind::Paren)
994
+ return ;
995
+
996
+ auto *semantic = enumElementInnerPat->getSemanticsProvidingPattern ();
997
+ if (auto *tuplePattern = dyn_cast<TuplePattern>(semantic)) {
998
+ if (tuplePattern->getNumElements () < 2 )
999
+ return ;
1000
+
1001
+ auto diag =
1002
+ DE.diagnose (tuplePattern->getLoc (),
1003
+ diag::converting_tuple_into_several_associated_values,
1004
+ enumCase->getNameStr (), payloadParams.size ());
1005
+ auto subPattern =
1006
+ dyn_cast<ParenPattern>(enumElementInnerPat)->getSubPattern ();
1007
+
1008
+ // We might also have code like
1009
+ //
1010
+ // enum Upair { case upair(Int, Int) }
1011
+ // func f(u: Upair) { switch u { case .upair(let (x, y)): () } }
1012
+ //
1013
+ // This needs a more complex rearrangement to fix the code. So only
1014
+ // apply the fix-it if we have a tuple immediately inside.
1015
+ if (subPattern->getKind () == PatternKind::Tuple) {
1016
+ auto leadingParen = SourceRange (enumElementInnerPat->getStartLoc ());
1017
+ auto trailingParen = SourceRange (enumElementInnerPat->getEndLoc ());
1018
+ diag.fixItRemove (leadingParen).fixItRemove (trailingParen);
1038
1019
}
1020
+ diag.flush ();
1021
+ addDeclNote ();
1022
+ enumElementInnerPat = semantic;
1023
+ } else {
1024
+ DE.diagnose (enumElementInnerPat->getLoc (),
1025
+ diag::found_one_pattern_for_several_associated_values,
1026
+ enumCase->getNameStr (), payloadParams.size ());
1027
+ addDeclNote ();
1039
1028
}
1029
+ return ;
1040
1030
}
1041
1031
1042
- if (addDeclNote)
1043
- DE.diagnose (enumCase->getStartLoc (), diag::decl_declared_here, enumCase);
1032
+ // Then check to see whether we need to tuple a pattern.
1033
+ if (payloadParams.size () == 1 && !payloadParams[0 ].hasLabel ()) {
1034
+ auto *tupleType = enumPayloadType->getAs <TupleType>();
1035
+ if (!tupleType || tupleType->getNumElements () < 2 )
1036
+ return ;
1037
+
1038
+ auto *tuplePattern = dyn_cast<TuplePattern>(enumElementInnerPat);
1039
+ if (!tuplePattern)
1040
+ return ;
1041
+
1042
+ DE.diagnose (enumElementInnerPat->getLoc (),
1043
+ diag::converting_several_associated_values_into_tuple,
1044
+ enumCase->getNameStr (), tupleType->getNumElements ())
1045
+ .fixItInsert (enumElementInnerPat->getStartLoc (), " (" )
1046
+ .fixItInsertAfter (enumElementInnerPat->getEndLoc (), " )" );
1047
+ addDeclNote ();
1048
+ enumElementInnerPat = new (Ctx)
1049
+ ParenPattern (enumElementInnerPat->getStartLoc (), enumElementInnerPat,
1050
+ enumElementInnerPat->getEndLoc ());
1051
+ }
1044
1052
}
1045
1053
1046
1054
NullablePtr<Pattern> TypeChecker::trySimplifyExprPattern (ExprPattern *EP,
0 commit comments