[Constraint solver] Start lazily building relational constraints.

Start migrating the main ConstraintSolver::addConstraint() entrypoint
for relational constraints over to the model where it simplifies
first, then only creates a new constraint if the constraint it built
cannot be solved. This covers only the main relational
constraints--there are a number of other relational constraint kinds
to handle this way.
This commit is contained in:
Doug Gregor
2016-10-20 23:39:00 -07:00
parent bdd27e9982
commit 7519d83007
2 changed files with 63 additions and 14 deletions

View File

@@ -4030,7 +4030,8 @@ bool ConstraintSystem::recordFix(Fix fix, ConstraintLocatorBuilder locator) {
ConstraintSystem::SolutionKind ConstraintSystem::SolutionKind
ConstraintSystem::simplifyFixConstraint(Fix fix, Type type1, Type type2, ConstraintSystem::simplifyFixConstraint(Fix fix, Type type1, Type type2,
TypeMatchKind matchKind, TypeMatchOptions flags, TypeMatchKind matchKind,
TypeMatchOptions flags,
ConstraintLocatorBuilder locator) { ConstraintLocatorBuilder locator) {
if (recordFix(fix, locator)) if (recordFix(fix, locator))
return SolutionKind::Error; return SolutionKind::Error;
@@ -4063,6 +4064,62 @@ ConstraintSystem::simplifyFixConstraint(Fix fix, Type type1, Type type2,
} }
} }
void ConstraintSystem::addConstraint(ConstraintKind kind, Type first,
Type second,
ConstraintLocatorBuilder locator,
bool isFavored) {
assert(first && "Missing first type");
assert(second && "Missing second type");
// Local function to record failures if necessary.
auto failed = [&] {
// Add a failing constraint, if needed.
if (shouldAddNewFailingConstraint()) {
auto c = Constraint::create(*this, kind, first, second, DeclName(),
FunctionRefKind::Compound,
getConstraintLocator(locator));
if (isFavored) c->setFavored();
addNewFailingConstraint(c);
}
};
TypeMatchOptions subflags = TMF_GenerateConstraints;
switch (kind) {
case ConstraintKind::Equal:
case ConstraintKind::BindParam:
case ConstraintKind::Subtype:
case ConstraintKind::Conversion:
case ConstraintKind::ExplicitConversion:
case ConstraintKind::ArgumentConversion:
case ConstraintKind::ArgumentTupleConversion:
case ConstraintKind::OperatorArgumentTupleConversion:
case ConstraintKind::OperatorArgumentConversion:
switch (matchTypes(first, second, getTypeMatchKind(kind), subflags,
locator)) {
case SolutionKind::Error:
return failed();
case SolutionKind::Unsolved:
llvm_unreachable("should have generated constraints");
case SolutionKind::Solved:
return;
}
case ConstraintKind::Bind: // FIXME: This should go through matchTypes() above
default: {
// FALLBACK CASE: do the slow thing.
auto c = Constraint::create(*this, kind, first, second, DeclName(),
FunctionRefKind::Compound,
getConstraintLocator(locator));
if (isFavored) c->setFavored();
addConstraint(c);
break;
}
}
}
ConstraintSystem::SolutionKind ConstraintSystem::SolutionKind
ConstraintSystem::simplifyConstraint(const Constraint &constraint) { ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
switch (constraint.getKind()) { switch (constraint.getKind()) {
@@ -4076,16 +4133,14 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
case ConstraintKind::ArgumentTupleConversion: case ConstraintKind::ArgumentTupleConversion:
case ConstraintKind::OperatorArgumentTupleConversion: case ConstraintKind::OperatorArgumentTupleConversion:
case ConstraintKind::OperatorArgumentConversion: { case ConstraintKind::OperatorArgumentConversion: {
// For relational constraints, match up the types. // Relational constraints.
auto matchKind = getTypeMatchKind(constraint.getKind()); auto matchKind = getTypeMatchKind(constraint.getKind());
// If there is a fix associated with this constraint, apply it before // If there is a fix associated with this constraint, apply it.
// we continue.
if (auto fix = constraint.getFix()) { if (auto fix = constraint.getFix()) {
return simplifyFixConstraint(*fix, constraint.getFirstType(), return simplifyFixConstraint(*fix, constraint.getFirstType(),
constraint.getSecondType(), matchKind, constraint.getSecondType(), matchKind,
TMF_GenerateConstraints, None, constraint.getLocator());
constraint.getLocator());
} }
// If there is a restriction on this constraint, apply it directly rather // If there is a restriction on this constraint, apply it directly rather

View File

@@ -1384,14 +1384,8 @@ public:
/// \brief Add a constraint to the constraint system. /// \brief Add a constraint to the constraint system.
void addConstraint(ConstraintKind kind, Type first, Type second, void addConstraint(ConstraintKind kind, Type first, Type second,
ConstraintLocator *locator, bool isFavored = false) { ConstraintLocatorBuilder locator,
assert(first && "Missing first type"); bool isFavored = false);
assert(second && "Missing second type");
auto c = Constraint::create(*this, kind, first, second, DeclName(),
FunctionRefKind::Compound, locator);
if (isFavored) c->setFavored();
addConstraint(c);
}
/// Add a new constraint with a restriction on its application. /// Add a new constraint with a restriction on its application.
void addRestrictedConstraint(ConstraintKind kind, void addRestrictedConstraint(ConstraintKind kind,