@@ -942,64 +942,72 @@ void repairTupleOrAssociatedValuePatternIfApplicable(
942942 Type enumPayloadType,
943943 const EnumElementDecl *enumCase) {
944944 auto &DE = Ctx.Diags ;
945- bool addDeclNote = false ;
946- if (auto *tupleType = dyn_cast<TupleType>(enumPayloadType.getPointer ())) {
947- if (tupleType->getNumElements () >= 2
948- && enumElementInnerPat->getKind () == PatternKind::Paren) {
949- auto *semantic = enumElementInnerPat->getSemanticsProvidingPattern ();
950- if (auto *tuplePattern = dyn_cast<TuplePattern>(semantic)) {
951- if (tuplePattern->getNumElements () >= 2 ) {
952- auto diag = DE.diagnose (tuplePattern->getLoc (),
953- diag::converting_tuple_into_several_associated_values,
954- enumCase->getNameStr (), tupleType->getNumElements ());
955- auto subPattern =
956- dyn_cast<ParenPattern>(enumElementInnerPat)->getSubPattern ();
957-
958- // We might also have code like
959- //
960- // enum Upair { case upair(Int, Int) }
961- // func f(u: Upair) { switch u { case .upair(let (x, y)): () } }
962- //
963- // This needs a more complex rearrangement to fix the code. So only
964- // apply the fix-it if we have a tuple immediately inside.
965- if (subPattern->getKind () == PatternKind::Tuple) {
966- auto leadingParen = SourceRange (enumElementInnerPat->getStartLoc ());
967- auto trailingParen = SourceRange (enumElementInnerPat->getEndLoc ());
968- diag.fixItRemove (leadingParen)
969- .fixItRemove (trailingParen);
970- }
971-
972- addDeclNote = true ;
973- enumElementInnerPat = semantic;
974- }
975- } else {
976- DE.diagnose (enumElementInnerPat->getLoc (),
977- diag::found_one_pattern_for_several_associated_values,
978- enumCase->getNameStr (),
979- tupleType->getNumElements ());
980- addDeclNote = true ;
981- }
982- }
983- } else if (auto *tupleType = enumPayloadType->getAs <TupleType>()) {
984- if (tupleType->getNumElements () >= 2 ) {
985- if (auto *tuplePattern = dyn_cast<TuplePattern>(enumElementInnerPat)) {
986- DE.diagnose (enumElementInnerPat->getLoc (),
987- diag::converting_several_associated_values_into_tuple,
988- enumCase->getNameStr (),
989- tupleType->getNumElements ())
990- .fixItInsert (enumElementInnerPat->getStartLoc (), " (" )
991- .fixItInsertAfter (enumElementInnerPat->getEndLoc (), " )" );
992- addDeclNote = true ;
993- enumElementInnerPat =
994- new (Ctx) ParenPattern (enumElementInnerPat->getStartLoc (),
995- enumElementInnerPat,
996- enumElementInnerPat->getEndLoc ());
945+ auto addDeclNote = [&]() {
946+ DE.diagnose (enumCase->getStartLoc (), diag::decl_declared_here, enumCase);
947+ };
948+ auto payloadParams = enumCase->getCaseConstructorParams ();
949+
950+ // First check to see whether we need to untuple a pattern.
951+ if (payloadParams.size () >= 2 ) {
952+ if (enumElementInnerPat->getKind () != PatternKind::Paren)
953+ return ;
954+
955+ auto *semantic = enumElementInnerPat->getSemanticsProvidingPattern ();
956+ if (auto *tuplePattern = dyn_cast<TuplePattern>(semantic)) {
957+ if (tuplePattern->getNumElements () < 2 )
958+ return ;
959+
960+ auto diag =
961+ DE.diagnose (tuplePattern->getLoc (),
962+ diag::converting_tuple_into_several_associated_values,
963+ enumCase->getNameStr (), payloadParams.size ());
964+ auto subPattern =
965+ dyn_cast<ParenPattern>(enumElementInnerPat)->getSubPattern ();
966+
967+ // We might also have code like
968+ //
969+ // enum Upair { case upair(Int, Int) }
970+ // func f(u: Upair) { switch u { case .upair(let (x, y)): () } }
971+ //
972+ // This needs a more complex rearrangement to fix the code. So only
973+ // apply the fix-it if we have a tuple immediately inside.
974+ if (subPattern->getKind () == PatternKind::Tuple) {
975+ auto leadingParen = SourceRange (enumElementInnerPat->getStartLoc ());
976+ auto trailingParen = SourceRange (enumElementInnerPat->getEndLoc ());
977+ diag.fixItRemove (leadingParen).fixItRemove (trailingParen);
997978 }
979+ diag.flush ();
980+ addDeclNote ();
981+ enumElementInnerPat = semantic;
982+ } else {
983+ DE.diagnose (enumElementInnerPat->getLoc (),
984+ diag::found_one_pattern_for_several_associated_values,
985+ enumCase->getNameStr (), payloadParams.size ());
986+ addDeclNote ();
998987 }
988+ return ;
999989 }
1000990
1001- if (addDeclNote)
1002- DE.diagnose (enumCase->getStartLoc (), diag::decl_declared_here, enumCase);
991+ // Then check to see whether we need to tuple a pattern.
992+ if (payloadParams.size () == 1 && !payloadParams[0 ].hasLabel ()) {
993+ auto *tupleType = enumPayloadType->getAs <TupleType>();
994+ if (!tupleType || tupleType->getNumElements () < 2 )
995+ return ;
996+
997+ auto *tuplePattern = dyn_cast<TuplePattern>(enumElementInnerPat);
998+ if (!tuplePattern)
999+ return ;
1000+
1001+ DE.diagnose (enumElementInnerPat->getLoc (),
1002+ diag::converting_several_associated_values_into_tuple,
1003+ enumCase->getNameStr (), tupleType->getNumElements ())
1004+ .fixItInsert (enumElementInnerPat->getStartLoc (), " (" )
1005+ .fixItInsertAfter (enumElementInnerPat->getEndLoc (), " )" );
1006+ addDeclNote ();
1007+ enumElementInnerPat = new (Ctx)
1008+ ParenPattern (enumElementInnerPat->getStartLoc (), enumElementInnerPat,
1009+ enumElementInnerPat->getEndLoc ());
1010+ }
10031011}
10041012
10051013NullablePtr<Pattern> TypeChecker::trySimplifyExprPattern (ExprPattern *EP,
0 commit comments