@@ -1204,17 +1204,25 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern,
1204
1204
// TODO: permit implicit conversions?
1205
1205
case PatternKind::Tuple: {
1206
1206
TuplePattern *TP = cast<TuplePattern>(P);
1207
- bool hadError = type->hasError ();
1208
-
1207
+
1208
+ TupleType *tupleTy = type->getAs <TupleType>();
1209
+
1209
1210
// Sometimes a paren is just a paren. If the tuple pattern has a single
1210
1211
// element, we can reduce it to a paren pattern.
1211
- bool canDecayToParen = TP->getNumElements () == 1 ;
1212
- auto decayToParen = [&]() -> Pattern * {
1213
- assert (canDecayToParen);
1214
- Pattern *sub = TP->getElement (0 ).getPattern ();
1215
- sub = TypeChecker::coercePatternToType (
1216
- pattern.forSubPattern (sub, /* retainTopLevel=*/ false ), type,
1217
- subOptions);
1212
+ //
1213
+ // FIXME: This condition is rather loose, e.g. it makes the following compile:
1214
+ // switch 0 {
1215
+ // case (int: 0): break
1216
+ // default: break
1217
+ // }
1218
+ // Do we really want/need to support this?
1219
+ //
1220
+ if (TP->getNumElements () == 1 &&
1221
+ (!tupleTy || tupleTy->getNumElements () != 1 )) {
1222
+ auto *sub = TypeChecker::coercePatternToType (
1223
+ pattern.forSubPattern (TP->getElement (0 ).getPattern (),
1224
+ /* retainTopLevel=*/ false ),
1225
+ type, subOptions);
1218
1226
if (!sub)
1219
1227
return nullptr ;
1220
1228
@@ -1225,63 +1233,50 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern,
1225
1233
} else {
1226
1234
P = sub;
1227
1235
}
1228
- return P;
1229
- };
1236
+ } else {
1237
+ if (!tupleTy) {
1238
+ diags.diagnose (TP->getStartLoc (),
1239
+ diag::tuple_pattern_in_non_tuple_context, type);
1230
1240
1231
- // The context type must be a tuple.
1232
- TupleType *tupleTy = type->getAs <TupleType>();
1233
- if (!tupleTy && !hadError) {
1234
- if (canDecayToParen)
1235
- return decayToParen ();
1236
- diags.diagnose (TP->getStartLoc (),
1237
- diag::tuple_pattern_in_non_tuple_context, type);
1238
- hadError = true ;
1239
- }
1241
+ return nullptr ;
1242
+ }
1240
1243
1241
- // The number of elements must match exactly.
1242
- if (!hadError && tupleTy->getNumElements () != TP->getNumElements ()) {
1243
- if (canDecayToParen)
1244
- return decayToParen ();
1245
-
1246
- diags.diagnose (TP->getStartLoc (), diag::tuple_pattern_length_mismatch,
1247
- type);
1248
- hadError = true ;
1249
- }
1244
+ // The number of elements must match exactly.
1245
+ if (tupleTy->getNumElements () != TP->getNumElements ()) {
1246
+ diags.diagnose (TP->getStartLoc (), diag::tuple_pattern_length_mismatch,
1247
+ type);
1250
1248
1251
- // Coerce each tuple element to the respective type.
1252
- P-> setType (type);
1249
+ return nullptr ;
1250
+ }
1253
1251
1254
- for (unsigned i = 0 , e = TP->getNumElements (); i != e; ++i) {
1255
- TuplePatternElt &elt = TP->getElement (i);
1252
+ // Coerce each tuple element to the respective type.
1253
+ for (unsigned i = 0 , e = TP->getNumElements (); i != e; ++i) {
1254
+ TuplePatternElt &patternElt = TP->getElement (i);
1255
+ const auto &typeElt = tupleTy->getElement (i);
1256
+
1257
+ // If the tuple pattern had a label for the tuple element, it must match
1258
+ // the label for the tuple type being matched.
1259
+ if (!patternElt.getLabel ().empty () &&
1260
+ patternElt.getLabel () != typeElt.getName ()) {
1261
+ diags.diagnose (patternElt.getLabelLoc (),
1262
+ diag::tuple_pattern_label_mismatch,
1263
+ patternElt.getLabel (), typeElt.getName ());
1264
+ return nullptr ;
1265
+ }
1256
1266
1257
- Type CoercionType;
1258
- if (hadError)
1259
- CoercionType = ErrorType::get (Context);
1260
- else
1261
- CoercionType = tupleTy->getElement (i).getType ();
1262
-
1263
- // If the tuple pattern had a label for the tuple element, it must match
1264
- // the label for the tuple type being matched.
1265
- if (!hadError && !elt.getLabel ().empty () &&
1266
- elt.getLabel () != tupleTy->getElement (i).getName ()) {
1267
- diags.diagnose (elt.getLabelLoc (), diag::tuple_pattern_label_mismatch,
1268
- elt.getLabel (), tupleTy->getElement (i).getName ());
1269
- hadError = true ;
1270
- }
1267
+ auto *sub =
1268
+ coercePatternToType (pattern.forSubPattern (patternElt.getPattern (),
1269
+ /* retainTopLevel=*/ false ),
1270
+ typeElt.getType (), subOptions);
1271
+ if (!sub)
1272
+ return nullptr ;
1271
1273
1272
- auto sub = coercePatternToType (
1273
- pattern.forSubPattern (elt.getPattern (), /* retainTopLevel=*/ false ),
1274
- CoercionType, subOptions);
1275
- if (!sub)
1276
- return nullptr ;
1274
+ patternElt.setPattern (sub);
1275
+ }
1277
1276
1278
- if (!hadError)
1279
- elt.setPattern (sub);
1277
+ P->setType (type);
1280
1278
}
1281
1279
1282
- if (hadError)
1283
- return nullptr ;
1284
-
1285
1280
return P;
1286
1281
}
1287
1282
0 commit comments