Skip to content

Commit 3e7e9f3

Browse files
authored
Merge pull request #19132 from xedin/add-binding-producer
[ConstraintSystem] Add `BindingProducer` base type
2 parents 6591626 + e4252a5 commit 3e7e9f3

File tree

2 files changed

+249
-161
lines changed

2 files changed

+249
-161
lines changed

lib/Sema/CSSolver.cpp

Lines changed: 101 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -527,13 +527,6 @@ bool ConstraintSystem::tryTypeVariableBindings(
527527
bool anySolved = false;
528528
bool sawFirstLiteralConstraint = false;
529529

530-
auto attemptTypeVarBinding = [&](TypeVariableBinding &binding) -> bool {
531-
// Try to solve the system with typeVar := type
532-
ConstraintSystem::SolverScope scope(*this);
533-
binding.attempt(*this);
534-
return !solveRec(solutions);
535-
};
536-
537530
if (TC.getLangOpts().DebugConstraintSolver) {
538531
auto &log = getASTContext().TypeCheckerDebug->getStream();
539532
log.indent(solverState->depth * 2) << "Initial bindings: ";
@@ -556,7 +549,7 @@ bool ConstraintSystem::tryTypeVariableBindings(
556549
if (anySolved) {
557550
// If this is a defaultable binding and we have found solutions,
558551
// don't explore the default binding.
559-
if (binding->isDefaultableBinding())
552+
if (binding->isDefaultable())
560553
continue;
561554

562555
// If we were able to solve this without considering
@@ -567,16 +560,20 @@ bool ConstraintSystem::tryTypeVariableBindings(
567560

568561
if (TC.getLangOpts().DebugConstraintSolver) {
569562
auto &log = getASTContext().TypeCheckerDebug->getStream();
570-
log.indent(solverState->depth * 2)
571-
<< "(trying " << typeVar->getString()
572-
<< " := " << binding->getType()->getString() << '\n';
563+
log.indent(solverState->depth * 2) << "(trying ";
564+
binding->print(log, &getASTContext().SourceMgr);
565+
log << '\n';
573566
}
574567

575568
if (binding->hasDefaultedProtocol())
576569
sawFirstLiteralConstraint = true;
577570

578-
if (attemptTypeVarBinding(*binding))
579-
anySolved = true;
571+
{
572+
// Try to solve the system with typeVar := type
573+
ConstraintSystem::SolverScope scope(*this);
574+
binding->attempt(*this);
575+
anySolved |= !solveRec(solutions);
576+
}
580577

581578
if (TC.getLangOpts().DebugConstraintSolver) {
582579
auto &log = getASTContext().TypeCheckerDebug->getStream();
@@ -1617,17 +1614,17 @@ void ConstraintSystem::collectDisjunctions(
16171614
}
16181615

16191616
/// \brief Check if the given disjunction choice should be attempted by solver.
1620-
static bool shouldSkipDisjunctionChoice(DisjunctionChoice &choice,
1617+
static bool shouldSkipDisjunctionChoice(ConstraintSystem &cs,
1618+
const TypeBinding &choice,
16211619
Optional<Score> &bestNonGenericScore) {
1622-
auto &cs = choice.getCS();
16231620
auto &TC = cs.TC;
16241621

1625-
if (choice->isDisabled()) {
1622+
if (choice.isDisabled()) {
16261623
if (TC.getLangOpts().DebugConstraintSolver) {
16271624
auto &log = cs.getASTContext().TypeCheckerDebug->getStream();
16281625
log.indent(cs.solverState->depth)
16291626
<< "(skipping ";
1630-
choice->print(log, &TC.Context.SourceMgr);
1627+
choice.print(log, &TC.Context.SourceMgr);
16311628
log << '\n';
16321629
}
16331630

@@ -1746,22 +1743,68 @@ Constraint *ConstraintSystem::selectDisjunction() {
17461743
return nullptr;
17471744
}
17481745

1749-
bool ConstraintSystem::solveForDisjunctionChoices(
1750-
DisjunctionChoiceProducer &disjunction,
1746+
Optional<Score> ConstraintSystem::solveForDisjunctionChoice(
1747+
const TypeBinding &choice, ConstraintLocator *disjunctionLocator,
17511748
SmallVectorImpl<Solution> &solutions) {
1749+
SolverScope scope(*this);
1750+
++solverState->NumDisjunctionTerms;
1751+
1752+
// If the disjunction requested us to, remember which choice we
1753+
// took for it.
1754+
if (disjunctionLocator) {
1755+
auto index = choice.getIndex();
1756+
DisjunctionChoices.push_back({disjunctionLocator, index});
1757+
1758+
// Implicit unwraps of optionals are worse solutions than those
1759+
// not involving implicit unwraps.
1760+
if (!disjunctionLocator->getPath().empty()) {
1761+
auto kind = disjunctionLocator->getPath().back().getKind();
1762+
if (kind == ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice ||
1763+
kind == ConstraintLocator::DynamicLookupResult) {
1764+
assert(index == 0 || index == 1);
1765+
if (index == 1)
1766+
increaseScore(SK_ForceUnchecked);
1767+
}
1768+
}
1769+
}
1770+
1771+
choice.attempt(*this);
1772+
if (solveRec(solutions))
1773+
return None;
1774+
1775+
assert(!solutions.empty());
1776+
Score bestScore = solutions.front().getFixedScore();
1777+
if (solutions.size() == 1)
1778+
return bestScore;
1779+
1780+
for (unsigned i = 1, n = solutions.size(); i != n; ++i) {
1781+
auto &score = solutions[i].getFixedScore();
1782+
if (score < bestScore)
1783+
bestScore = score;
1784+
}
1785+
1786+
return bestScore;
1787+
}
1788+
1789+
bool ConstraintSystem::solveForDisjunctionChoices(
1790+
ArrayRef<Constraint *> choices, ConstraintLocator *disjunctionLocator,
1791+
bool isExplicitConversion, SmallVectorImpl<Solution> &solutions) {
17521792
Optional<Score> bestNonGenericScore;
1753-
Optional<std::pair<DisjunctionChoice, Score>> lastSolvedChoice;
1793+
Optional<std::pair<Constraint *, Score>> lastSolvedChoice;
1794+
1795+
DisjunctionChoiceProducer producer(*this, choices, disjunctionLocator,
1796+
isExplicitConversion);
17541797

17551798
// Try each of the constraints within the disjunction.
1756-
while (auto binding = disjunction()) {
1757-
auto &currentChoice = *binding;
1758-
if (shouldSkipDisjunctionChoice(currentChoice, bestNonGenericScore))
1799+
while (auto currentChoice = producer()) {
1800+
if (shouldSkipDisjunctionChoice(*this, *currentChoice, bestNonGenericScore))
17591801
continue;
17601802

17611803
// We already have a solution; check whether we should
17621804
// short-circuit the disjunction.
17631805
if (lastSolvedChoice) {
1764-
Constraint *lastChoice = lastSolvedChoice->first;
1806+
auto *choice = choices[currentChoice->getIndex()];
1807+
auto *lastChoice = lastSolvedChoice->first;
17651808
auto delta = lastSolvedChoice->second - CurrentScore;
17661809
bool hasUnavailableOverloads = delta.Data[SK_Unavailable] > 0;
17671810
bool hasFixes = delta.Data[SK_Fix] > 0;
@@ -1771,13 +1814,10 @@ bool ConstraintSystem::solveForDisjunctionChoices(
17711814
// selecting unavailable overloads or result in fixes being
17721815
// applied to reach a solution.
17731816
if (!hasUnavailableOverloads && !hasFixes &&
1774-
shortCircuitDisjunctionAt(currentChoice, lastChoice, getASTContext()))
1817+
shortCircuitDisjunctionAt(choice, lastChoice, getASTContext()))
17751818
break;
17761819
}
17771820

1778-
// Try to solve the system with this option in the disjunction.
1779-
SolverScope scope(*this);
1780-
++solverState->NumDisjunctionTerms;
17811821
if (TC.getLangOpts().DebugConstraintSolver) {
17821822
auto &log = getASTContext().TypeCheckerDebug->getStream();
17831823
log.indent(solverState->depth)
@@ -1786,34 +1826,16 @@ bool ConstraintSystem::solveForDisjunctionChoices(
17861826
log << '\n';
17871827
}
17881828

1789-
// If the disjunction requested us to, remember which choice we
1790-
// took for it.
1791-
1792-
if (auto *disjunctionLocator = disjunction.getLocator()) {
1793-
auto index = currentChoice.getIndex();
1794-
DisjunctionChoices.push_back({disjunctionLocator, index});
1795-
1796-
// Implicit unwraps of optionals are worse solutions than those
1797-
// not involving implicit unwraps.
1798-
if (!disjunctionLocator->getPath().empty()) {
1799-
auto kind = disjunctionLocator->getPath().back().getKind();
1800-
if (kind == ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice ||
1801-
kind == ConstraintLocator::DynamicLookupResult) {
1802-
assert(index == 0 || index == 1);
1803-
if (index == 1)
1804-
increaseScore(SK_ForceUnchecked);
1805-
}
1806-
}
1807-
}
1808-
1809-
if (auto score = binding->attempt(solutions)) {
1810-
if (!currentChoice.isGenericOperator() &&
1811-
currentChoice.isSymmetricOperator()) {
1829+
// Try to solve the system with this option in the disjunction.
1830+
if (auto score = solveForDisjunctionChoice(*currentChoice,
1831+
disjunctionLocator, solutions)) {
1832+
if (!currentChoice->isGenericOperator() &&
1833+
currentChoice->isSymmetricOperator()) {
18121834
if (!bestNonGenericScore || score < bestNonGenericScore)
18131835
bestNonGenericScore = score;
18141836
}
18151837

1816-
lastSolvedChoice = {currentChoice, *score};
1838+
lastSolvedChoice = {choices[currentChoice->getIndex()], *score};
18171839
}
18181840

18191841
if (TC.getLangOpts().DebugConstraintSolver) {
@@ -1882,11 +1904,9 @@ bool ConstraintSystem::solveForDisjunction(
18821904
disjunction->shouldRememberChoice() ? disjunction->getLocator() : nullptr;
18831905
assert(!disjunction->shouldRememberChoice() || disjunction->getLocator());
18841906

1885-
auto choices =
1886-
DisjunctionChoiceProducer(*this, disjunction->getNestedConstraints(),
1887-
locator, disjunction->isExplicitConversion());
1888-
1889-
auto noSolutions = solveForDisjunctionChoices(choices, solutions);
1907+
auto noSolutions = solveForDisjunctionChoices(
1908+
disjunction->getNestedConstraints(), locator,
1909+
disjunction->isExplicitConversion(), solutions);
18901910

18911911
if (hasDisabledChoices) {
18921912
// Re-enable previously disabled overload choices.
@@ -1956,46 +1976,23 @@ bool ConstraintSystem::solveSimplified(SmallVectorImpl<Solution> &solutions) {
19561976
}
19571977

19581978
void DisjunctionChoice::attempt(ConstraintSystem &cs) const {
1959-
CS->simplifyDisjunctionChoice(Choice);
1979+
cs.simplifyDisjunctionChoice(Choice);
19601980

19611981
if (ExplicitConversion)
1962-
propagateConversionInfo();
1963-
}
1964-
1965-
Optional<Score>
1966-
DisjunctionChoice::attempt(SmallVectorImpl<Solution> &solutions) {
1967-
attempt(*CS);
1968-
1969-
if (CS->solveRec(solutions))
1970-
return None;
1971-
1972-
assert (!solutions.empty());
1973-
1974-
Score bestScore = solutions.front().getFixedScore();
1975-
1976-
if (solutions.size() == 1)
1977-
return bestScore;
1978-
1979-
for (unsigned i = 1, n = solutions.size(); i != n; ++i) {
1980-
auto &score = solutions[i].getFixedScore();
1981-
if (score < bestScore)
1982-
bestScore = score;
1983-
}
1984-
1985-
return bestScore;
1982+
propagateConversionInfo(cs);
19861983
}
19871984

1988-
bool DisjunctionChoice::isGenericOperator() const {
1989-
auto *decl = getOperatorDecl();
1985+
bool DisjunctionChoice::isGenericOp(Constraint *choice) {
1986+
auto *decl = getOperatorDecl(choice);
19901987
if (!decl)
19911988
return false;
19921989

19931990
auto interfaceType = decl->getInterfaceType();
19941991
return interfaceType->is<GenericFunctionType>();
19951992
}
19961993

1997-
bool DisjunctionChoice::isSymmetricOperator() const {
1998-
auto *decl = getOperatorDecl();
1994+
bool DisjunctionChoice::isSymmetricOp(Constraint *choice) {
1995+
auto *decl = getOperatorDecl(choice);
19991996
if (!decl)
20001997
return false;
20011998

@@ -2009,7 +2006,7 @@ bool DisjunctionChoice::isSymmetricOperator() const {
20092006
return firstType->isEqual(secondType);
20102007
}
20112008

2012-
void DisjunctionChoice::propagateConversionInfo() const {
2009+
void DisjunctionChoice::propagateConversionInfo(ConstraintSystem &cs) const {
20132010
assert(ExplicitConversion);
20142011

20152012
auto LHS = Choice->getFirstType();
@@ -2026,28 +2023,28 @@ void DisjunctionChoice::propagateConversionInfo() const {
20262023
if (typeVar->getImpl().getFixedType(nullptr))
20272024
return;
20282025

2029-
auto bindings = CS->getPotentialBindings(typeVar);
2026+
auto bindings = cs.getPotentialBindings(typeVar);
20302027
if (bindings.InvolvesTypeVariables || bindings.Bindings.size() != 1)
20312028
return;
20322029

20332030
auto conversionType = bindings.Bindings[0].BindingType;
20342031
llvm::SetVector<Constraint *> constraints;
2035-
CS->CG.gatherConstraints(typeVar, constraints,
2036-
ConstraintGraph::GatheringKind::EquivalenceClass,
2037-
[](Constraint *constraint) -> bool {
2038-
switch (constraint->getKind()) {
2039-
case ConstraintKind::Conversion:
2040-
case ConstraintKind::Defaultable:
2041-
case ConstraintKind::ConformsTo:
2042-
case ConstraintKind::LiteralConformsTo:
2043-
return false;
2044-
2045-
default:
2046-
return true;
2047-
}
2048-
});
2032+
cs.CG.gatherConstraints(typeVar, constraints,
2033+
ConstraintGraph::GatheringKind::EquivalenceClass,
2034+
[](Constraint *constraint) -> bool {
2035+
switch (constraint->getKind()) {
2036+
case ConstraintKind::Conversion:
2037+
case ConstraintKind::Defaultable:
2038+
case ConstraintKind::ConformsTo:
2039+
case ConstraintKind::LiteralConformsTo:
2040+
return false;
2041+
2042+
default:
2043+
return true;
2044+
}
2045+
});
20492046

20502047
if (constraints.empty())
2051-
CS->addConstraint(ConstraintKind::Bind, typeVar, conversionType,
2052-
Choice->getLocator());
2048+
cs.addConstraint(ConstraintKind::Bind, typeVar, conversionType,
2049+
Choice->getLocator());
20532050
}

0 commit comments

Comments
 (0)