Skip to content

[ConstraintSystem] NFC: Move allowFreeTypeVariableBindings into `So… #19101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 32 additions & 45 deletions lib/Sema/CSSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,14 @@ Optional<Type> ConstraintSystem::checkTypeOfBinding(TypeVariableType *typeVar,
return type;
}

Solution ConstraintSystem::finalize(
FreeTypeVariableBinding allowFreeTypeVariables) {
Solution ConstraintSystem::finalize() {
assert(solverState);

// Create the solution.
Solution solution(*this, CurrentScore);

// Update the best score we've seen so far.
if (solverState && !retainAllSolutions()) {
if (!retainAllSolutions()) {
assert(TC.getLangOpts().DisableConstraintSolverPerformanceHacks ||
!solverState->BestScore || CurrentScore <= *solverState->BestScore);

Expand All @@ -142,7 +143,7 @@ Solution ConstraintSystem::finalize(
if (getFixedType(tv))
continue;

switch (allowFreeTypeVariables) {
switch (solverState->AllowFreeTypeVariables) {
case FreeTypeVariableBinding::Disallow:
llvm_unreachable("Solver left free type variables");

Expand Down Expand Up @@ -386,9 +387,10 @@ void truncate(SmallVectorImpl<T> &vec, unsigned newSize) {

} // end anonymous namespace

ConstraintSystem::SolverState::SolverState(Expr *const expr,
ConstraintSystem &cs)
: CS(cs) {
ConstraintSystem::SolverState::SolverState(
Expr *const expr, ConstraintSystem &cs,
FreeTypeVariableBinding allowFreeTypeVariables)
: CS(cs), AllowFreeTypeVariables(allowFreeTypeVariables) {
assert(!CS.solverState &&
"Constraint system should not already have solver state!");
CS.solverState = this;
Expand Down Expand Up @@ -520,8 +522,7 @@ ConstraintSystem::SolverScope::~SolverScope() {
bool ConstraintSystem::tryTypeVariableBindings(
TypeVariableType *typeVar,
ArrayRef<ConstraintSystem::PotentialBinding> initialBindings,
SmallVectorImpl<Solution> &solutions,
FreeTypeVariableBinding allowFreeTypeVariables) {
SmallVectorImpl<Solution> &solutions) {
auto &TC = getTypeChecker();
bool anySolved = false;
bool sawFirstLiteralConstraint = false;
Expand Down Expand Up @@ -558,7 +559,7 @@ bool ConstraintSystem::tryTypeVariableBindings(
if (binding.isDefaultableBinding())
DefaultedConstraints.push_back(binding.DefaultableBinding);

return !solveRec(solutions, allowFreeTypeVariables);
return !solveRec(solutions);
};

if (TC.getLangOpts().DebugConstraintSolver) {
Expand Down Expand Up @@ -713,12 +714,12 @@ bool ConstraintSystem::Candidate::solve(
// Try to solve the system and record all available solutions.
llvm::SmallVector<Solution, 2> solutions;
{
SolverState state(E, cs);
SolverState state(E, cs, FreeTypeVariableBinding::Allow);

// Use solveRec() instead of solve() in here, because solve()
// would try to deduce the best solution, which we don't
// really want. Instead, we want the reduced set of domain choices.
cs.solveRec(solutions, FreeTypeVariableBinding::Allow);
cs.solveRec(solutions);
}

if (TC.getLangOpts().DebugConstraintSolver) {
Expand Down Expand Up @@ -1302,10 +1303,10 @@ bool ConstraintSystem::solve(Expr *const expr,
SmallVectorImpl<Solution> &solutions,
FreeTypeVariableBinding allowFreeTypeVariables) {
// Set up solver state.
SolverState state(expr, *this);
SolverState state(expr, *this, allowFreeTypeVariables);

// Solve the system.
solveRec(solutions, allowFreeTypeVariables);
solveRec(solutions);

if (TC.getLangOpts().DebugConstraintSolver) {
auto &log = getASTContext().TypeCheckerDebug->getStream();
Expand All @@ -1330,8 +1331,7 @@ bool ConstraintSystem::solve(Expr *const expr,
return solutions.empty() || getExpressionTooComplex(solutions);
}

bool ConstraintSystem::solveRec(SmallVectorImpl<Solution> &solutions,
FreeTypeVariableBinding allowFreeTypeVariables){
bool ConstraintSystem::solveRec(SmallVectorImpl<Solution> &solutions) {
// If we already failed, or simplification fails, we're done.
if (failedConstraint || simplify())
return true;
Expand All @@ -1347,11 +1347,10 @@ bool ConstraintSystem::solveRec(SmallVectorImpl<Solution> &solutions,

// If any free type variables remain and we're not allowed to have them,
// fail.
if (allowFreeTypeVariables == FreeTypeVariableBinding::Disallow &&
hasFreeTypeVariables())
if (!solverState->allowsFreeTypeVariables() && hasFreeTypeVariables())
return true;

auto solution = finalize(allowFreeTypeVariables);
auto solution = finalize();
if (TC.getLangOpts().DebugConstraintSolver) {
auto &log = getASTContext().TypeCheckerDebug->getStream();
log.indent(solverState->depth * 2)
Expand All @@ -1376,7 +1375,7 @@ bool ConstraintSystem::solveRec(SmallVectorImpl<Solution> &solutions,
// If we don't have more than one component, just solve the whole
// system.
if (numComponents < 2)
return solveSimplified(solutions, allowFreeTypeVariables);
return solveSimplified(solutions);

if (TC.Context.LangOpts.DebugConstraintSolver) {
auto &log = getASTContext().TypeCheckerDebug->getStream();
Expand Down Expand Up @@ -1487,8 +1486,7 @@ bool ConstraintSystem::solveRec(SmallVectorImpl<Solution> &solutions,
}

// Solve for this component. If it fails, we're done.
bool failed = bucket.solve(*this, partialSolutions[component],
allowFreeTypeVariables);
bool failed = bucket.solve(*this, partialSolutions[component]);

if (failed) {
if (TC.getLangOpts().DebugConstraintSolver) {
Expand Down Expand Up @@ -1553,7 +1551,7 @@ bool ConstraintSystem::solveRec(SmallVectorImpl<Solution> &solutions,
// skip it.
if (!worseThanBestSolution()) {
// Finalize this solution.
auto solution = finalize(allowFreeTypeVariables);
auto solution = finalize();
if (TC.getLangOpts().DebugConstraintSolver) {
auto &log = getASTContext().TypeCheckerDebug->getStream();
log.indent(solverState->depth * 2)
Expand Down Expand Up @@ -1777,8 +1775,7 @@ Constraint *ConstraintSystem::selectDisjunction() {
}

bool ConstraintSystem::solveForDisjunctionChoices(
Disjunction &disjunction, SmallVectorImpl<Solution> &solutions,
FreeTypeVariableBinding allowFreeTypeVariables) {
Disjunction &disjunction, SmallVectorImpl<Solution> &solutions) {
Optional<Score> bestNonGenericScore;
Optional<std::pair<DisjunctionChoice, Score>> lastSolvedChoice;

Expand Down Expand Up @@ -1835,7 +1832,7 @@ bool ConstraintSystem::solveForDisjunctionChoices(
}
}

if (auto score = currentChoice.solve(solutions, allowFreeTypeVariables)) {
if (auto score = currentChoice.solve(solutions)) {
if (!currentChoice.isGenericOperator() &&
currentChoice.isSymmetricOperator()) {
if (!bestNonGenericScore || score < bestNonGenericScore)
Expand All @@ -1855,8 +1852,7 @@ bool ConstraintSystem::solveForDisjunctionChoices(
}

bool ConstraintSystem::solveForDisjunction(
Constraint *disjunction, SmallVectorImpl<Solution> &solutions,
FreeTypeVariableBinding allowFreeTypeVariables) {
Constraint *disjunction, SmallVectorImpl<Solution> &solutions) {
assert(disjunction->getKind() == ConstraintKind::Disjunction);

// Remove this disjunction constraint from the list.
Expand Down Expand Up @@ -1915,8 +1911,7 @@ bool ConstraintSystem::solveForDisjunction(
auto choices = Disjunction(*this, disjunction->getNestedConstraints(),
locator, disjunction->isExplicitConversion());

auto noSolutions =
solveForDisjunctionChoices(choices, solutions, allowFreeTypeVariables);
auto noSolutions = solveForDisjunctionChoices(choices, solutions);

if (hasDisabledChoices) {
// Re-enable previously disabled overload choices.
Expand All @@ -1933,12 +1928,8 @@ bool ConstraintSystem::solveForDisjunction(
return noSolutions;
}

bool ConstraintSystem::solveSimplified(
SmallVectorImpl<Solution> &solutions,
FreeTypeVariableBinding allowFreeTypeVariables) {

bool ConstraintSystem::solveSimplified(SmallVectorImpl<Solution> &solutions) {
auto *disjunction = selectDisjunction();

auto bestBindings = determineBestBindings();

// If we've already explored a lot of potential solutions, bail.
Expand All @@ -1951,17 +1942,15 @@ bool ConstraintSystem::solveSimplified(
if (bestBindings && (!disjunction || (!bestBindings->InvolvesTypeVariables &&
!bestBindings->FullyBound))) {
return tryTypeVariableBindings(bestBindings->TypeVar,
bestBindings->Bindings, solutions,
allowFreeTypeVariables);
bestBindings->Bindings, solutions);
}

if (disjunction)
return solveForDisjunction(disjunction, solutions, allowFreeTypeVariables);
return solveForDisjunction(disjunction, solutions);

// If there are no disjunctions we can't solve this system unless we have
// free type variables and are allowing them in the solution.
if (allowFreeTypeVariables == FreeTypeVariableBinding::Disallow ||
!hasFreeTypeVariables())
if (!solverState->allowsFreeTypeVariables() || !hasFreeTypeVariables())
return true;

// If this solution is worse than the best solution we've seen so far,
Expand All @@ -1981,7 +1970,7 @@ bool ConstraintSystem::solveSimplified(
}
}

auto solution = finalize(allowFreeTypeVariables);
auto solution = finalize();
if (TC.getLangOpts().DebugConstraintSolver) {
auto &log = getASTContext().TypeCheckerDebug->getStream();
log.indent(solverState->depth * 2) << "(found solution)\n";
Expand All @@ -1991,15 +1980,13 @@ bool ConstraintSystem::solveSimplified(
return false;
}

Optional<Score>
DisjunctionChoice::solve(SmallVectorImpl<Solution> &solutions,
FreeTypeVariableBinding allowFreeTypeVariables) {
Optional<Score> DisjunctionChoice::solve(SmallVectorImpl<Solution> &solutions) {
CS->simplifyDisjunctionChoice(Choice);

if (ExplicitConversion)
propagateConversionInfo();

if (CS->solveRec(solutions, allowFreeTypeVariables))
if (CS->solveRec(solutions))
return None;

assert (!solutions.empty());
Expand Down
4 changes: 2 additions & 2 deletions lib/Sema/ConstraintSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2081,11 +2081,11 @@ bool ConstraintSystem::salvage(SmallVectorImpl<Solution> &viable, Expr *expr) {

{
// Set up solver state.
SolverState state(expr, *this);
SolverState state(expr, *this, FreeTypeVariableBinding::Disallow);
state.recordFixes = true;

// Solve the system.
solveRec(viable, FreeTypeVariableBinding::Disallow);
solveRec(viable);

// Check whether we have a best solution; this can happen if we found
// a series of fixes that worked.
Expand Down
45 changes: 20 additions & 25 deletions lib/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -1139,14 +1139,17 @@ class ConstraintSystem {

/// \brief Describes the current solver state.
struct SolverState {
SolverState(Expr *const expr, ConstraintSystem &cs);
SolverState(Expr *const expr, ConstraintSystem &cs,
FreeTypeVariableBinding allowFreeTypeVariables);
~SolverState();

llvm::DenseMap<Expr *, unsigned> ExprWeights;

/// The constraint system.
ConstraintSystem &CS;

FreeTypeVariableBinding AllowFreeTypeVariables;

/// Old value of DebugConstraintSolver.
/// FIXME: Move the "debug constraint solver" bit into the constraint
/// system itself.
Expand Down Expand Up @@ -1288,6 +1291,12 @@ class ConstraintSystem {
generatedConstraints.erase(genStart, genEnd);
}

/// Check whether constraint system is allowed to form solutions
/// even with unbound type variables present.
bool allowsFreeTypeVariables() const {
return AllowFreeTypeVariables != FreeTypeVariableBinding::Disallow;
}

private:
/// The list of constraints that have been retired along the
/// current path, this list is used in LIFO fashion when constraints
Expand Down Expand Up @@ -1507,7 +1516,7 @@ class ConstraintSystem {
/// it.
///
/// \returns the solution.
Solution finalize(FreeTypeVariableBinding allowFreeTypeVariables);
Solution finalize();

/// \brief Apply the given solution to the current constraint system.
///
Expand Down Expand Up @@ -2950,8 +2959,7 @@ class ConstraintSystem {
bool
tryTypeVariableBindings(TypeVariableType *typeVar,
ArrayRef<ConstraintSystem::PotentialBinding> bindings,
SmallVectorImpl<Solution> &solutions,
FreeTypeVariableBinding allowFreeTypeVariables);
SmallVectorImpl<Solution> &solutions);

private:
/// \brief Add a constraint to the constraint system.
Expand All @@ -2967,31 +2975,24 @@ class ConstraintSystem {
///
/// \returns true if we failed to find any solutions, false otherwise.
bool solveForDisjunction(Constraint *disjunction,
SmallVectorImpl<Solution> &solutions,
FreeTypeVariableBinding allowFreeTypeVariables);
SmallVectorImpl<Solution> &solutions);

/// \brief Attempt to solve for some subset of the constraints in a
/// disjunction, skipping constraints that we decide do not
/// need to be solved for because they would not result in
/// the best solution to the constraint system.
///
/// \returns true if we failed to find any solutions, false otherwise.
bool
solveForDisjunctionChoices(Disjunction &disjunction,
SmallVectorImpl<Solution> &solutions,
FreeTypeVariableBinding allowFreeTypeVariables);
bool solveForDisjunctionChoices(Disjunction &disjunction,
SmallVectorImpl<Solution> &solutions);

/// \brief Solve the system of constraints after it has already been
/// simplified.
///
/// \param solutions The set of solutions to this system of constraints.
///
/// \param allowFreeTypeVariables How to bind free type variables in
/// the solution.
///
/// \returns true if an error occurred, false otherwise.
bool solveSimplified(SmallVectorImpl<Solution> &solutions,
FreeTypeVariableBinding allowFreeTypeVariables);
bool solveSimplified(SmallVectorImpl<Solution> &solutions);

/// \brief Find reduced domains of disjunction constraints for given
/// expression, this is achieved to solving individual sub-expressions
Expand Down Expand Up @@ -3075,12 +3076,8 @@ class ConstraintSystem {
///
/// \param solutions The set of solutions to this system of constraints.
///
/// \param allowFreeTypeVariables How to bind free type variables in
/// the solution.
///
/// \returns true if there are no solutions
bool solveRec(SmallVectorImpl<Solution> &solutions,
FreeTypeVariableBinding allowFreeTypeVariables);
bool solveRec(SmallVectorImpl<Solution> &solutions);

/// \brief Solve the system of constraints.
///
Expand Down Expand Up @@ -3402,8 +3399,7 @@ class DisjunctionChoice {
bool isSymmetricOperator() const;

/// \brief Apply given choice to the system and try to solve it.
Optional<Score> solve(SmallVectorImpl<Solution> &solutions,
FreeTypeVariableBinding allowFreeTypeVariables);
Optional<Score> solve(SmallVectorImpl<Solution> &solutions);

operator Constraint *() { return Choice; }

Expand Down Expand Up @@ -3536,8 +3532,7 @@ class Component {
Disjunctions.push_back(constraint);
}

bool solve(ConstraintSystem &cs, SmallVectorImpl<Solution> &solutions,
FreeTypeVariableBinding allowFreeTypeVariables) {
bool solve(ConstraintSystem &cs, SmallVectorImpl<Solution> &solutions) {
// Return constraints from the bucket back into circulation.
reinstateTo(cs.InactiveConstraints);

Expand All @@ -3550,7 +3545,7 @@ class Component {
llvm::SaveAndRestore<ConstraintSystem::SolverScope *>
partialSolutionScope(cs.solverState->PartialSolutionScope, &scope);

failed = cs.solveSimplified(solutions, allowFreeTypeVariables);
failed = cs.solveSimplified(solutions);
}

// Put the constraints back into their original bucket.
Expand Down