Skip to content

Commit 0140bf7

Browse files
authored
Merge pull request #10522 from xedin/rdar-32726044-4.0
[4.0] [ConstraintSolver] Use a flag to prevent solver from removing possible solutions
2 parents e1303a3 + f176e30 commit 0140bf7

File tree

4 files changed

+62
-21
lines changed

4 files changed

+62
-21
lines changed

lib/Sema/CSRanking.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ void ConstraintSystem::increaseScore(ScoreKind kind, unsigned value) {
9393
}
9494

9595
bool ConstraintSystem::worseThanBestSolution() const {
96+
if (retainAllSolutions())
97+
return false;
98+
9699
if (!solverState || !solverState->BestScore ||
97100
CurrentScore <= *solverState->BestScore)
98101
return false;

lib/Sema/CSSolver.cpp

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ Solution ConstraintSystem::finalize(
110110
Solution solution(*this, CurrentScore);
111111

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

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

15041505
// Cleanup after constraint system generation/solving,
15051506
// because it would assign types to expressions, which
@@ -2070,17 +2071,11 @@ bool ConstraintSystem::solve(SmallVectorImpl<Solution> &solutions,
20702071
// Solve the system.
20712072
solveRec(solutions, allowFreeTypeVariables);
20722073

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

20852080
// We fail if there is no solution.
20862081
return solutions.empty();
@@ -2293,11 +2288,8 @@ bool ConstraintSystem::solveRec(SmallVectorImpl<Solution> &solutions,
22932288
auto &solutions = partialSolutions[component];
22942289
// If there's a single best solution, keep only that one.
22952290
// Otherwise, the set of solutions will at least have been minimized.
2296-
if (auto best = findBestSolution(solutions, /*minimize=*/true)) {
2297-
if (*best > 0)
2298-
solutions[0] = std::move(solutions[*best]);
2299-
solutions.erase(solutions.begin() + 1, solutions.end());
2300-
}
2291+
if (!retainAllSolutions())
2292+
filterSolutions(solutions, /*minimize=*/true);
23012293
}
23022294

23032295
// Produce all combinations of partial solutions.

lib/Sema/ConstraintSystem.h

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,6 +1417,13 @@ class ConstraintSystem {
14171417
bool hasFreeTypeVariables();
14181418

14191419
private:
1420+
/// \brief Indicates if the constraint system should retain all of the
1421+
/// solutions it has deduced regardless of their score.
1422+
bool retainAllSolutions() const {
1423+
return Options.contains(
1424+
ConstraintSystemFlags::ReturnAllDiscoveredSolutions);
1425+
}
1426+
14201427
/// \brief Finalize this constraint system; we're done attempting to solve
14211428
/// it.
14221429
///
@@ -1438,8 +1445,28 @@ class ConstraintSystem {
14381445
/// diagnostic for it and returning true. If the fixit hint turned out to be
14391446
/// bogus, this returns false and doesn't emit anything.
14401447
bool applySolutionFix(Expr *expr, const Solution &solution, unsigned fixNo);
1441-
1442-
1448+
1449+
/// \brief If there is more than one viable solution,
1450+
/// attempt to pick the best solution and remove all of the rest.
1451+
///
1452+
/// \param solutions The set of solutions to filter.
1453+
///
1454+
/// \param minimize The flag which idicates if the
1455+
/// set of solutions should be filtered even if there is
1456+
/// no single best solution, see `findBestSolution` for
1457+
/// more details.
1458+
void filterSolutions(SmallVectorImpl<Solution> &solutions,
1459+
bool minimize = false) {
1460+
if (solutions.size() < 2)
1461+
return;
1462+
1463+
if (auto best = findBestSolution(solutions, minimize)) {
1464+
if (*best != 0)
1465+
solutions[0] = std::move(solutions[*best]);
1466+
solutions.erase(solutions.begin() + 1, solutions.end());
1467+
}
1468+
}
1469+
14431470
/// \brief Restore the type variable bindings to what they were before
14441471
/// we attempted to solve this constraint system.
14451472
///

test/Constraints/diagnostics.swift

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -977,4 +977,23 @@ let _: KeyPath<R32101765, Float> = \R32101765.prop32101765
977977
let _: KeyPath<R32101765, Float> = \.prop32101765.unknown
978978
// expected-error@-1 {{type 'Int' has no member 'unknown'}}
979979
let _: KeyPath<R32101765, Float> = \R32101765.prop32101765.unknown
980-
// expected-error@-1 {{type 'Int' has no member 'unknown'}}
980+
// expected-error@-1 {{type 'Int' has no member 'unknown'}}
981+
982+
// rdar://problem/32726044 - shrink reduced domains too far
983+
984+
public protocol P_32726044 {}
985+
986+
extension Int: P_32726044 {}
987+
extension Float: P_32726044 {}
988+
989+
public func *(lhs: P_32726044, rhs: P_32726044) -> Double {
990+
fatalError()
991+
}
992+
993+
func rdar32726044() -> Float {
994+
var f: Float = 0
995+
f = Float(1) * 100 // Ok
996+
let _: Float = Float(42) + 0 // Ok
997+
return f
998+
}
999+

0 commit comments

Comments
 (0)