Skip to content

Commit e7cc51b

Browse files
committed
[NFC] Sema: Tidy up tuple pattern handling in coercePatternToType
1 parent 75c1b6e commit e7cc51b

File tree

1 file changed

+52
-57
lines changed

1 file changed

+52
-57
lines changed

lib/Sema/TypeCheckPattern.cpp

Lines changed: 52 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,17 +1165,25 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern,
11651165
// TODO: permit implicit conversions?
11661166
case PatternKind::Tuple: {
11671167
TuplePattern *TP = cast<TuplePattern>(P);
1168-
bool hadError = type->hasError();
1169-
1168+
1169+
TupleType *tupleTy = type->getAs<TupleType>();
1170+
11701171
// Sometimes a paren is just a paren. If the tuple pattern has a single
11711172
// element, we can reduce it to a paren pattern.
1172-
bool canDecayToParen = TP->getNumElements() == 1;
1173-
auto decayToParen = [&]() -> Pattern * {
1174-
assert(canDecayToParen);
1175-
Pattern *sub = TP->getElement(0).getPattern();
1176-
sub = TypeChecker::coercePatternToType(
1177-
pattern.forSubPattern(sub, /*retainTopLevel=*/false), type,
1178-
subOptions);
1173+
//
1174+
// FIXME: This condition is rather loose, e.g. it makes the following compile:
1175+
// switch 0 {
1176+
// case (int: 0): break
1177+
// default: break
1178+
// }
1179+
// Do we really want/need to support this?
1180+
//
1181+
if (TP->getNumElements() == 1 &&
1182+
(!tupleTy || tupleTy->getNumElements() != 1)) {
1183+
auto *sub = TypeChecker::coercePatternToType(
1184+
pattern.forSubPattern(TP->getElement(0).getPattern(),
1185+
/*retainTopLevel=*/false),
1186+
type, subOptions);
11791187
if (!sub)
11801188
return nullptr;
11811189

@@ -1186,63 +1194,50 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern,
11861194
} else {
11871195
P = sub;
11881196
}
1189-
return P;
1190-
};
1197+
} else {
1198+
if (!tupleTy) {
1199+
diags.diagnose(TP->getStartLoc(),
1200+
diag::tuple_pattern_in_non_tuple_context, type);
11911201

1192-
// The context type must be a tuple.
1193-
TupleType *tupleTy = type->getAs<TupleType>();
1194-
if (!tupleTy && !hadError) {
1195-
if (canDecayToParen)
1196-
return decayToParen();
1197-
diags.diagnose(TP->getStartLoc(),
1198-
diag::tuple_pattern_in_non_tuple_context, type);
1199-
hadError = true;
1200-
}
1202+
return nullptr;
1203+
}
12011204

1202-
// The number of elements must match exactly.
1203-
if (!hadError && tupleTy->getNumElements() != TP->getNumElements()) {
1204-
if (canDecayToParen)
1205-
return decayToParen();
1206-
1207-
diags.diagnose(TP->getStartLoc(), diag::tuple_pattern_length_mismatch,
1208-
type);
1209-
hadError = true;
1210-
}
1205+
// The number of elements must match exactly.
1206+
if (tupleTy->getNumElements() != TP->getNumElements()) {
1207+
diags.diagnose(TP->getStartLoc(), diag::tuple_pattern_length_mismatch,
1208+
type);
12111209

1212-
// Coerce each tuple element to the respective type.
1213-
P->setType(type);
1210+
return nullptr;
1211+
}
12141212

1215-
for (unsigned i = 0, e = TP->getNumElements(); i != e; ++i) {
1216-
TuplePatternElt &elt = TP->getElement(i);
1213+
// Coerce each tuple element to the respective type.
1214+
for (unsigned i = 0, e = TP->getNumElements(); i != e; ++i) {
1215+
TuplePatternElt &patternElt = TP->getElement(i);
1216+
const auto &typeElt = tupleTy->getElement(i);
1217+
1218+
// If the tuple pattern had a label for the tuple element, it must match
1219+
// the label for the tuple type being matched.
1220+
if (!patternElt.getLabel().empty() &&
1221+
patternElt.getLabel() != typeElt.getName()) {
1222+
diags.diagnose(patternElt.getLabelLoc(),
1223+
diag::tuple_pattern_label_mismatch,
1224+
patternElt.getLabel(), typeElt.getName());
1225+
return nullptr;
1226+
}
12171227

1218-
Type CoercionType;
1219-
if (hadError)
1220-
CoercionType = ErrorType::get(Context);
1221-
else
1222-
CoercionType = tupleTy->getElement(i).getType();
1223-
1224-
// If the tuple pattern had a label for the tuple element, it must match
1225-
// the label for the tuple type being matched.
1226-
if (!hadError && !elt.getLabel().empty() &&
1227-
elt.getLabel() != tupleTy->getElement(i).getName()) {
1228-
diags.diagnose(elt.getLabelLoc(), diag::tuple_pattern_label_mismatch,
1229-
elt.getLabel(), tupleTy->getElement(i).getName());
1230-
hadError = true;
1231-
}
1228+
auto *sub =
1229+
coercePatternToType(pattern.forSubPattern(patternElt.getPattern(),
1230+
/*retainTopLevel=*/false),
1231+
typeElt.getType(), subOptions);
1232+
if (!sub)
1233+
return nullptr;
12321234

1233-
auto sub = coercePatternToType(
1234-
pattern.forSubPattern(elt.getPattern(), /*retainTopLevel=*/false),
1235-
CoercionType, subOptions);
1236-
if (!sub)
1237-
return nullptr;
1235+
patternElt.setPattern(sub);
1236+
}
12381237

1239-
if (!hadError)
1240-
elt.setPattern(sub);
1238+
P->setType(type);
12411239
}
12421240

1243-
if (hadError)
1244-
return nullptr;
1245-
12461241
return P;
12471242
}
12481243

0 commit comments

Comments
 (0)