@@ -1165,17 +1165,25 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern,
1165
1165
// TODO: permit implicit conversions?
1166
1166
case PatternKind::Tuple: {
1167
1167
TuplePattern *TP = cast<TuplePattern>(P);
1168
- bool hadError = type->hasError ();
1169
-
1168
+
1169
+ TupleType *tupleTy = type->getAs <TupleType>();
1170
+
1170
1171
// Sometimes a paren is just a paren. If the tuple pattern has a single
1171
1172
// 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);
1179
1187
if (!sub)
1180
1188
return nullptr ;
1181
1189
@@ -1186,63 +1194,50 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern,
1186
1194
} else {
1187
1195
P = sub;
1188
1196
}
1189
- return P;
1190
- };
1197
+ } else {
1198
+ if (!tupleTy) {
1199
+ diags.diagnose (TP->getStartLoc (),
1200
+ diag::tuple_pattern_in_non_tuple_context, type);
1191
1201
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
+ }
1201
1204
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);
1211
1209
1212
- // Coerce each tuple element to the respective type.
1213
- P-> setType (type);
1210
+ return nullptr ;
1211
+ }
1214
1212
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
+ }
1217
1227
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 ;
1232
1234
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
+ }
1238
1237
1239
- if (!hadError)
1240
- elt.setPattern (sub);
1238
+ P->setType (type);
1241
1239
}
1242
1240
1243
- if (hadError)
1244
- return nullptr ;
1245
-
1246
1241
return P;
1247
1242
}
1248
1243
0 commit comments