Skip to content

Commit b9646da

Browse files
committed
[Sema] Refactor repairTupleOrAssociatedValuePatternIfApplicable
Avoid relying on the modeling of single unlabeled associated values as ParenType, instead check the case constructor parameters. Also refactor to early return in more cases.
1 parent 3c8921a commit b9646da

File tree

1 file changed

+62
-54
lines changed

1 file changed

+62
-54
lines changed

lib/Sema/TypeCheckPattern.cpp

Lines changed: 62 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -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

10051013
NullablePtr<Pattern> TypeChecker::trySimplifyExprPattern(ExprPattern *EP,

0 commit comments

Comments
 (0)