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