Skip to content

[4.0] [ConstraintSolver] Use a flag to prevent solver from removing possible solutions #10522

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
Jun 23, 2017
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
3 changes: 3 additions & 0 deletions lib/Sema/CSRanking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ void ConstraintSystem::increaseScore(ScoreKind kind, unsigned value) {
}

bool ConstraintSystem::worseThanBestSolution() const {
if (retainAllSolutions())
return false;

if (!solverState || !solverState->BestScore ||
CurrentScore <= *solverState->BestScore)
return false;
Expand Down
28 changes: 10 additions & 18 deletions lib/Sema/CSSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ Solution ConstraintSystem::finalize(
Solution solution(*this, CurrentScore);

// Update the best score we've seen so far.
if (solverState) {
if (solverState && !retainAllSolutions()) {
assert(!solverState->BestScore || CurrentScore <= *solverState->BestScore);
solverState->BestScore = CurrentScore;
}
Expand Down Expand Up @@ -1499,7 +1499,8 @@ bool ConstraintSystem::Candidate::solve(
};

// Allocate new constraint system for sub-expression.
ConstraintSystem cs(TC, DC, None);
ConstraintSystem cs(TC, DC,
ConstraintSystemFlags::ReturnAllDiscoveredSolutions);

// Cleanup after constraint system generation/solving,
// because it would assign types to expressions, which
Expand Down Expand Up @@ -2066,17 +2067,11 @@ bool ConstraintSystem::solve(SmallVectorImpl<Solution> &solutions,
// Solve the system.
solveRec(solutions, allowFreeTypeVariables);

// If there is more than one viable system, attempt to pick the best
// solution.
auto size = solutions.size();
if (size > 1 &&
!Options.contains(ConstraintSystemFlags::ReturnAllDiscoveredSolutions)) {
if (auto best = findBestSolution(solutions, /*minimize=*/false)) {
if (*best != 0)
solutions[0] = std::move(solutions[*best]);
solutions.erase(solutions.begin() + 1, solutions.end());
}
}
// Filter deduced solutions, try to figure out if there is
// a single best solution to use, if not explicitly disabled
// by constraint system options.
if (!retainAllSolutions())
filterSolutions(solutions);

// We fail if there is no solution.
return solutions.empty();
Expand Down Expand Up @@ -2289,11 +2284,8 @@ bool ConstraintSystem::solveRec(SmallVectorImpl<Solution> &solutions,
auto &solutions = partialSolutions[component];
// If there's a single best solution, keep only that one.
// Otherwise, the set of solutions will at least have been minimized.
if (auto best = findBestSolution(solutions, /*minimize=*/true)) {
if (*best > 0)
solutions[0] = std::move(solutions[*best]);
solutions.erase(solutions.begin() + 1, solutions.end());
}
if (!retainAllSolutions())
filterSolutions(solutions, /*minimize=*/true);
}

// Produce all combinations of partial solutions.
Expand Down
31 changes: 29 additions & 2 deletions lib/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -1386,6 +1386,13 @@ class ConstraintSystem {
bool hasFreeTypeVariables();

private:
/// \brief Indicates if the constraint system should retain all of the
/// solutions it has deduced regardless of their score.
bool retainAllSolutions() const {
return Options.contains(
ConstraintSystemFlags::ReturnAllDiscoveredSolutions);
}

/// \brief Finalize this constraint system; we're done attempting to solve
/// it.
///
Expand All @@ -1407,8 +1414,28 @@ class ConstraintSystem {
/// diagnostic for it and returning true. If the fixit hint turned out to be
/// bogus, this returns false and doesn't emit anything.
bool applySolutionFix(Expr *expr, const Solution &solution, unsigned fixNo);



/// \brief If there is more than one viable solution,
/// attempt to pick the best solution and remove all of the rest.
///
/// \param solutions The set of solutions to filter.
///
/// \param minimize The flag which idicates if the
/// set of solutions should be filtered even if there is
/// no single best solution, see `findBestSolution` for
/// more details.
void filterSolutions(SmallVectorImpl<Solution> &solutions,
bool minimize = false) {
if (solutions.size() < 2)
return;

if (auto best = findBestSolution(solutions, minimize)) {
if (*best != 0)
solutions[0] = std::move(solutions[*best]);
solutions.erase(solutions.begin() + 1, solutions.end());
}
}

/// \brief Restore the type variable bindings to what they were before
/// we attempted to solve this constraint system.
///
Expand Down
21 changes: 20 additions & 1 deletion test/Constraints/diagnostics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -977,4 +977,23 @@ let _: KeyPath<R32101765, Float> = \R32101765.prop32101765
let _: KeyPath<R32101765, Float> = \.prop32101765.unknown
// expected-error@-1 {{type 'Int' has no member 'unknown'}}
let _: KeyPath<R32101765, Float> = \R32101765.prop32101765.unknown
// expected-error@-1 {{type 'Int' has no member 'unknown'}}
// expected-error@-1 {{type 'Int' has no member 'unknown'}}

// rdar://problem/32726044 - shrink reduced domains too far

public protocol P_32726044 {}

extension Int: P_32726044 {}
extension Float: P_32726044 {}

public func *(lhs: P_32726044, rhs: P_32726044) -> Double {
fatalError()
}

func rdar32726044() -> Float {
var f: Float = 0
f = Float(1) * 100 // Ok
let _: Float = Float(42) + 0 // Ok
return f
}