@@ -1210,25 +1210,48 @@ ConstraintSystem::SolutionKind
1210
1210
ConstraintSystem::matchTypes (Type type1, Type type2, ConstraintKind kind,
1211
1211
TypeMatchOptions flags,
1212
1212
ConstraintLocatorBuilder locator) {
1213
- // If we have type variables that have been bound to fixed types, look through
1214
- // to the fixed type.
1215
1213
bool isArgumentTupleConversion
1216
1214
= kind == ConstraintKind::ArgumentTupleConversion ||
1217
1215
kind == ConstraintKind::OperatorArgumentTupleConversion;
1218
- type1 = getFixedTypeRecursive (type1, flags, kind == ConstraintKind::Equal,
1219
- isArgumentTupleConversion);
1220
1216
1221
- auto desugar1 = type1->getDesugaredType ();
1222
- TypeVariableType *typeVar1 = desugar1->getAs <TypeVariableType>();
1217
+ // If we're doing an argument tuple conversion, or just matching the input
1218
+ // types of two function types, we have to be careful to preserve
1219
+ // ParenType sugar.
1220
+ bool isArgumentTupleMatch = isArgumentTupleConversion;
1221
+ bool isSwiftVersion3 = getASTContext ().isSwiftVersion3 ();
1222
+
1223
+ // ... but not in Swift 3 mode, where this behavior was broken.
1224
+ if (!isSwiftVersion3)
1225
+ if (auto elt = locator.last ())
1226
+ if (elt->getKind () == ConstraintLocator::FunctionArgument)
1227
+ isArgumentTupleMatch = true ;
1223
1228
1229
+ // If we have type variables that have been bound to fixed types, look through
1230
+ // to the fixed type.
1231
+ type1 = getFixedTypeRecursive (type1, flags, kind == ConstraintKind::Equal,
1232
+ isArgumentTupleMatch);
1224
1233
type2 = getFixedTypeRecursive (type2, flags, kind == ConstraintKind::Equal,
1225
- isArgumentTupleConversion);
1234
+ isArgumentTupleMatch);
1235
+
1236
+ auto desugar1 = type1->getDesugaredType ();
1226
1237
auto desugar2 = type2->getDesugaredType ();
1227
- TypeVariableType *typeVar2 = desugar2->getAs <TypeVariableType>();
1238
+ TypeVariableType *typeVar1, *typeVar2;
1239
+ if (isArgumentTupleMatch &&
1240
+ !isSwiftVersion3) {
1241
+ typeVar1 = dyn_cast<TypeVariableType>(type1.getPointer ());
1242
+ typeVar2 = dyn_cast<TypeVariableType>(type2.getPointer ());
1243
+
1244
+ // If the types are obviously equivalent, we're done.
1245
+ if (type1.getPointer () == type2.getPointer ())
1246
+ return SolutionKind::Solved;
1247
+ } else {
1248
+ typeVar1 = desugar1->getAs <TypeVariableType>();
1249
+ typeVar2 = desugar2->getAs <TypeVariableType>();
1228
1250
1229
- // If the types are obviously equivalent, we're done.
1230
- if (desugar1->isEqual (desugar2))
1231
- return SolutionKind::Solved;
1251
+ // If the types are obviously equivalent, we're done.
1252
+ if (desugar1->isEqual (desugar2))
1253
+ return SolutionKind::Solved;
1254
+ }
1232
1255
1233
1256
// Local function that should be used to produce the return value whenever
1234
1257
// this function was unable to resolve the constraint. It should be used
@@ -1435,12 +1458,6 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
1435
1458
}
1436
1459
}
1437
1460
1438
- bool isTypeVarOrMember1 = desugar1->isTypeVariableOrMember ();
1439
- bool isTypeVarOrMember2 = desugar2->isTypeVariableOrMember ();
1440
-
1441
- llvm::SmallVector<RestrictionOrFix, 4 > conversionsOrFixes;
1442
- bool concrete = !isTypeVarOrMember1 && !isTypeVarOrMember2;
1443
-
1444
1461
// If this is an argument conversion, handle it directly. The rules are
1445
1462
// different from normal conversions.
1446
1463
if (kind == ConstraintKind::ArgumentTupleConversion ||
@@ -1452,6 +1469,22 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
1452
1469
return formUnsolvedResult ();
1453
1470
}
1454
1471
1472
+ if (isArgumentTupleMatch &&
1473
+ !isSwiftVersion3) {
1474
+ if (!typeVar1 && !typeVar2) {
1475
+ if (isa<ParenType>(type1.getPointer ()) !=
1476
+ isa<ParenType>(type2.getPointer ())) {
1477
+ return SolutionKind::Error;
1478
+ }
1479
+ }
1480
+ }
1481
+
1482
+ bool isTypeVarOrMember1 = desugar1->isTypeVariableOrMember ();
1483
+ bool isTypeVarOrMember2 = desugar2->isTypeVariableOrMember ();
1484
+
1485
+ llvm::SmallVector<RestrictionOrFix, 4 > conversionsOrFixes;
1486
+ bool concrete = !isTypeVarOrMember1 && !isTypeVarOrMember2;
1487
+
1455
1488
// Decompose parallel structure.
1456
1489
TypeMatchOptions subflags =
1457
1490
getDefaultDecompositionOptions (flags) - TMF_ApplyingFix;
0 commit comments