mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #5300 from DougGregor/constraint-solver-cleanups
This commit is contained in:
@@ -1178,6 +1178,31 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind,
|
||||
if (kind != TypeMatchKind::ConformsTo && desugar1->isEqual(desugar2))
|
||||
return SolutionKind::Solved;
|
||||
|
||||
// Local function that should be used to produce the return value whenever
|
||||
// this function was unable to resolve the constraint. It should be used
|
||||
// within \c matchTypes() as
|
||||
//
|
||||
// return formUnsolvedResult();
|
||||
//
|
||||
// along any unsolved path. No other returns should produce
|
||||
// SolutionKind::Unsolved or inspect TMF_GenerateConstraints.
|
||||
auto formUnsolvedResult = [&] {
|
||||
// If we're supposed to generate constraints (i.e., this is a
|
||||
// newly-generated constraint), do so now.
|
||||
if (flags & TMF_GenerateConstraints) {
|
||||
// Add a new constraint between these types. We consider the current
|
||||
// type-matching problem to the "solved" by this addition, because
|
||||
// this new constraint will be solved at a later point.
|
||||
// Obviously, this must not happen at the top level, or the
|
||||
// algorithm would not terminate.
|
||||
addConstraint(getConstraintKind(kind), type1, type2,
|
||||
getConstraintLocator(locator));
|
||||
return SolutionKind::Solved;
|
||||
}
|
||||
|
||||
return SolutionKind::Unsolved;
|
||||
};
|
||||
|
||||
// If either (or both) types are type variables, unify the type variables.
|
||||
if (typeVar1 || typeVar2) {
|
||||
switch (kind) {
|
||||
@@ -1196,24 +1221,8 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind,
|
||||
// If exactly one of the type variables can bind to an lvalue, we
|
||||
// can't merge these two type variables.
|
||||
if (rep1->getImpl().canBindToLValue()
|
||||
!= rep2->getImpl().canBindToLValue()) {
|
||||
if (flags & TMF_GenerateConstraints) {
|
||||
if (kind == TypeMatchKind::BindToPointerType) {
|
||||
increaseScore(ScoreKind::SK_ScalarPointerConversion);
|
||||
}
|
||||
|
||||
// Add a new constraint between these types. We consider the current
|
||||
// type-matching problem to the "solved" by this addition, because
|
||||
// this new constraint will be solved at a later point.
|
||||
// Obviously, this must not happen at the top level, or the
|
||||
// algorithm would not terminate.
|
||||
addConstraint(getConstraintKind(kind), rep1, rep2,
|
||||
getConstraintLocator(locator));
|
||||
return SolutionKind::Solved;
|
||||
}
|
||||
|
||||
return SolutionKind::Unsolved;
|
||||
}
|
||||
!= rep2->getImpl().canBindToLValue())
|
||||
return formUnsolvedResult();
|
||||
|
||||
// Merge the equivalence classes corresponding to these two variables.
|
||||
mergeEquivalenceClasses(rep1, rep2);
|
||||
@@ -1246,8 +1255,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind,
|
||||
|
||||
// A constraint that binds any pointer to a void pointer is
|
||||
// ineffective, since any pointer can be converted to a void pointer.
|
||||
if (kind == TypeMatchKind::BindToPointerType && desugar2->isVoid() &&
|
||||
(flags & TMF_GenerateConstraints)) {
|
||||
if (kind == TypeMatchKind::BindToPointerType && desugar2->isVoid()) {
|
||||
// Bind type1 to Void only as a last resort.
|
||||
addConstraint(ConstraintKind::Defaultable, typeVar1, type2,
|
||||
getConstraintLocator(locator));
|
||||
@@ -1301,7 +1309,8 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind,
|
||||
return SolutionKind::Solved;
|
||||
}
|
||||
}
|
||||
return SolutionKind::Unsolved;
|
||||
|
||||
return formUnsolvedResult();
|
||||
}
|
||||
|
||||
case TypeMatchKind::ArgumentTupleConversion:
|
||||
@@ -1323,22 +1332,13 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind,
|
||||
case TypeMatchKind::ArgumentConversion:
|
||||
case TypeMatchKind::OperatorArgumentTupleConversion:
|
||||
case TypeMatchKind::OperatorArgumentConversion:
|
||||
if (flags & TMF_GenerateConstraints) {
|
||||
// Add a new constraint between these types. We consider the current
|
||||
// type-matching problem to the "solved" by this addition, because
|
||||
// this new constraint will be solved at a later point.
|
||||
// Obviously, this must not happen at the top level, or the algorithm
|
||||
// would not terminate.
|
||||
addConstraint(getConstraintKind(kind), type1, type2,
|
||||
getConstraintLocator(locator));
|
||||
return SolutionKind::Solved;
|
||||
}
|
||||
|
||||
// We couldn't solve this constraint. If only one of the types is a type
|
||||
// variable, perhaps we can do something with it below.
|
||||
if (typeVar1 && typeVar2)
|
||||
return typeVar1 == typeVar2 ? SolutionKind::Solved
|
||||
: SolutionKind::Unsolved;
|
||||
if (typeVar1 && typeVar2) {
|
||||
if (typeVar1 == typeVar2) return SolutionKind::Solved;
|
||||
|
||||
return formUnsolvedResult();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1355,18 +1355,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind,
|
||||
return ::matchCallArguments(*this, kind, type1, type2, locator);
|
||||
}
|
||||
|
||||
if (flags & TMF_GenerateConstraints) {
|
||||
// Add a new constraint between these types. We consider the current
|
||||
// type-matching problem to the "solved" by this addition, because
|
||||
// this new constraint will be solved at a later point.
|
||||
// Obviously, this must not happen at the top level, or the algorithm
|
||||
// would not terminate.
|
||||
addConstraint(getConstraintKind(kind), type1, type2,
|
||||
getConstraintLocator(locator));
|
||||
return SolutionKind::Solved;
|
||||
}
|
||||
|
||||
return SolutionKind::Unsolved;
|
||||
return formUnsolvedResult();
|
||||
}
|
||||
|
||||
// Decompose parallel structure.
|
||||
@@ -2067,8 +2056,7 @@ commit_to_conversions:
|
||||
|
||||
if (conversionsOrFixes.empty()) {
|
||||
// If one of the types is a type variable, we leave this unsolved.
|
||||
if (typeVar1 || typeVar2)
|
||||
return SolutionKind::Unsolved;
|
||||
if (typeVar1 || typeVar2) return formUnsolvedResult();
|
||||
|
||||
return SolutionKind::Error;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user