Skip to content

Commit 3ede1ab

Browse files
committed
Sema: New implementation of SE-0110
Fix matchTypes() to be more careful about stripping off ParenType sugar, in order to match the behavior outlined in SE-0110. Note that the new logic only executes in Swift 4 mode; there's no functional change here in Swift 3 mode. This makes a second copy of the tuple_arguments test: - Compatibility/tuple_arguments is a test for Swift 3, updated to note differences with Swift 3. - Constraints/tuple_arguments has been updated for the new Swift 4 mode behavior. Fixes <rdar://problem/27383557>.
1 parent 321edbf commit 3ede1ab

File tree

3 files changed

+1424
-118
lines changed

3 files changed

+1424
-118
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,25 +1210,48 @@ ConstraintSystem::SolutionKind
12101210
ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
12111211
TypeMatchOptions flags,
12121212
ConstraintLocatorBuilder locator) {
1213-
// If we have type variables that have been bound to fixed types, look through
1214-
// to the fixed type.
12151213
bool isArgumentTupleConversion
12161214
= kind == ConstraintKind::ArgumentTupleConversion ||
12171215
kind == ConstraintKind::OperatorArgumentTupleConversion;
1218-
type1 = getFixedTypeRecursive(type1, flags, kind == ConstraintKind::Equal,
1219-
isArgumentTupleConversion);
12201216

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;
12231228

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);
12241233
type2 = getFixedTypeRecursive(type2, flags, kind == ConstraintKind::Equal,
1225-
isArgumentTupleConversion);
1234+
isArgumentTupleMatch);
1235+
1236+
auto desugar1 = type1->getDesugaredType();
12261237
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>();
12281250

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+
}
12321255

12331256
// Local function that should be used to produce the return value whenever
12341257
// this function was unable to resolve the constraint. It should be used
@@ -1435,12 +1458,6 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
14351458
}
14361459
}
14371460

1438-
bool isTypeVarOrMember1 = desugar1->isTypeVariableOrMember();
1439-
bool isTypeVarOrMember2 = desugar2->isTypeVariableOrMember();
1440-
1441-
llvm::SmallVector<RestrictionOrFix, 4> conversionsOrFixes;
1442-
bool concrete = !isTypeVarOrMember1 && !isTypeVarOrMember2;
1443-
14441461
// If this is an argument conversion, handle it directly. The rules are
14451462
// different from normal conversions.
14461463
if (kind == ConstraintKind::ArgumentTupleConversion ||
@@ -1452,6 +1469,22 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
14521469
return formUnsolvedResult();
14531470
}
14541471

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+
14551488
// Decompose parallel structure.
14561489
TypeMatchOptions subflags =
14571490
getDefaultDecompositionOptions(flags) - TMF_ApplyingFix;

0 commit comments

Comments
 (0)