Skip to content

Commit 94f14d4

Browse files
authored
Merge pull request #18386 from rudkx/simplify-state-for-disjunction-choice
[ConstraintSystem] Split the main loop attempting disjunction choices…
2 parents 4dc0cc5 + e84b372 commit 94f14d4

File tree

2 files changed

+95
-74
lines changed

2 files changed

+95
-74
lines changed

lib/Sema/CSSolver.cpp

Lines changed: 77 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,64 +1957,12 @@ Constraint *ConstraintSystem::selectDisjunction() {
19571957
}
19581958

19591959
bool ConstraintSystem::solveForDisjunctionChoices(
1960-
Constraint *disjunction, SmallVectorImpl<Solution> &solutions,
1961-
FreeTypeVariableBinding allowFreeTypeVariables) {
1962-
assert(disjunction->getKind() == ConstraintKind::Disjunction);
1963-
1964-
// Remove this disjunction constraint from the list.
1965-
auto afterDisjunction = InactiveConstraints.erase(disjunction);
1966-
CG.removeConstraint(disjunction);
1967-
1968-
// Check if selected disjunction has a representative
1969-
// this might happen when there are multiple binary operators
1970-
// chained together. If so, disable choices which differ
1971-
// from currently selected representative.
1972-
auto pruneOverloadSet = [&](Constraint *disjunction) -> bool {
1973-
auto *choice = disjunction->getNestedConstraints().front();
1974-
auto *typeVar = choice->getFirstType()->getAs<TypeVariableType>();
1975-
if (!typeVar)
1976-
return false;
1977-
1978-
auto *repr = typeVar->getImpl().getRepresentative(nullptr);
1979-
if (!repr || repr == typeVar)
1980-
return false;
1981-
1982-
bool isPruned = false;
1983-
for (auto resolved = resolvedOverloadSets; resolved;
1984-
resolved = resolved->Previous) {
1985-
if (!resolved->BoundType->isEqual(repr))
1986-
continue;
1987-
1988-
auto &representative = resolved->Choice;
1989-
if (!representative.isDecl())
1990-
return false;
1991-
1992-
// Disable all of the overload choices which are different from
1993-
// the one which is currently picked for representative.
1994-
for (auto *constraint : disjunction->getNestedConstraints()) {
1995-
auto choice = constraint->getOverloadChoice();
1996-
if (!choice.isDecl())
1997-
continue;
1998-
1999-
if (choice.getDecl() != representative.getDecl()) {
2000-
constraint->setDisabled();
2001-
isPruned = true;
2002-
}
2003-
}
2004-
break;
2005-
}
2006-
2007-
return isPruned;
2008-
};
2009-
2010-
bool hasDisabledChoices = pruneOverloadSet(disjunction);
2011-
2012-
Optional<std::pair<DisjunctionChoice, Score>> lastSolvedChoice;
1960+
ArrayRef<Constraint *> constraints, ConstraintLocator *disjunctionLocator,
1961+
SmallVectorImpl<Solution> &solutions,
1962+
FreeTypeVariableBinding allowFreeTypeVariables, bool explicitConversion) {
20131963
Optional<Score> bestNonGenericScore;
1964+
Optional<std::pair<DisjunctionChoice, Score>> lastSolvedChoice;
20141965

2015-
++solverState->NumDisjunctions;
2016-
bool explicitConversion = isExplicitConversionConstraint(disjunction);
2017-
auto constraints = disjunction->getNestedConstraints();
20181966
// Try each of the constraints within the disjunction.
20191967
for (auto index : indices(constraints)) {
20201968
auto currentChoice =
@@ -2052,15 +2000,14 @@ bool ConstraintSystem::solveForDisjunctionChoices(
20522000

20532001
// If the disjunction requested us to, remember which choice we
20542002
// took for it.
2055-
if (disjunction->shouldRememberChoice()) {
2056-
auto locator = disjunction->getLocator();
2057-
assert(locator && "remembered disjunction doesn't have a locator?");
2058-
DisjunctionChoices.push_back({locator, index});
2003+
2004+
if (disjunctionLocator) {
2005+
DisjunctionChoices.push_back({disjunctionLocator, index});
20592006

20602007
// Implicit unwraps of optionals are worse solutions than those
20612008
// not involving implicit unwraps.
2062-
if (!locator->getPath().empty()) {
2063-
auto kind = locator->getPath().back().getKind();
2009+
if (!disjunctionLocator->getPath().empty()) {
2010+
auto kind = disjunctionLocator->getPath().back().getKind();
20642011
if (kind == ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice ||
20652012
kind == ConstraintLocator::DynamicLookupResult) {
20662013
assert(index == 0 || index == 1);
@@ -2086,6 +2033,71 @@ bool ConstraintSystem::solveForDisjunctionChoices(
20862033
}
20872034
}
20882035

2036+
return !bool(lastSolvedChoice.hasValue());
2037+
}
2038+
2039+
bool ConstraintSystem::solveForDisjunction(
2040+
Constraint *disjunction, SmallVectorImpl<Solution> &solutions,
2041+
FreeTypeVariableBinding allowFreeTypeVariables) {
2042+
assert(disjunction->getKind() == ConstraintKind::Disjunction);
2043+
2044+
// Remove this disjunction constraint from the list.
2045+
auto afterDisjunction = InactiveConstraints.erase(disjunction);
2046+
CG.removeConstraint(disjunction);
2047+
2048+
// Check if selected disjunction has a representative
2049+
// this might happen when there are multiple binary operators
2050+
// chained together. If so, disable choices which differ
2051+
// from currently selected representative.
2052+
auto pruneOverloadSet = [&](Constraint *disjunction) -> bool {
2053+
auto *choice = disjunction->getNestedConstraints().front();
2054+
auto *typeVar = choice->getFirstType()->getAs<TypeVariableType>();
2055+
if (!typeVar)
2056+
return false;
2057+
2058+
auto *repr = typeVar->getImpl().getRepresentative(nullptr);
2059+
if (!repr || repr == typeVar)
2060+
return false;
2061+
2062+
bool isPruned = false;
2063+
for (auto resolved = resolvedOverloadSets; resolved;
2064+
resolved = resolved->Previous) {
2065+
if (!resolved->BoundType->isEqual(repr))
2066+
continue;
2067+
2068+
auto &representative = resolved->Choice;
2069+
if (!representative.isDecl())
2070+
return false;
2071+
2072+
// Disable all of the overload choices which are different from
2073+
// the one which is currently picked for representative.
2074+
for (auto *constraint : disjunction->getNestedConstraints()) {
2075+
auto choice = constraint->getOverloadChoice();
2076+
if (!choice.isDecl())
2077+
continue;
2078+
2079+
if (choice.getDecl() != representative.getDecl()) {
2080+
constraint->setDisabled();
2081+
isPruned = true;
2082+
}
2083+
}
2084+
break;
2085+
}
2086+
2087+
return isPruned;
2088+
};
2089+
2090+
bool hasDisabledChoices = pruneOverloadSet(disjunction);
2091+
2092+
++solverState->NumDisjunctions;
2093+
auto *locator =
2094+
disjunction->shouldRememberChoice() ? disjunction->getLocator() : nullptr;
2095+
assert(!disjunction->shouldRememberChoice() || disjunction->getLocator());
2096+
2097+
auto noSolutions = solveForDisjunctionChoices(
2098+
disjunction->getNestedConstraints(), locator, solutions,
2099+
allowFreeTypeVariables, isExplicitConversionConstraint(disjunction));
2100+
20892101
if (hasDisabledChoices) {
20902102
// Re-enable previously disabled overload choices.
20912103
for (auto *choice : disjunction->getNestedConstraints()) {
@@ -2098,7 +2110,7 @@ bool ConstraintSystem::solveForDisjunctionChoices(
20982110
InactiveConstraints.insert(afterDisjunction, disjunction);
20992111
CG.addConstraint(disjunction);
21002112

2101-
return bool(lastSolvedChoice.hasValue());
2113+
return noSolutions;
21022114
}
21032115

21042116
bool ConstraintSystem::solveSimplified(
@@ -2123,10 +2135,8 @@ bool ConstraintSystem::solveSimplified(
21232135
allowFreeTypeVariables);
21242136
}
21252137

2126-
if (disjunction) {
2127-
return !solveForDisjunctionChoices(disjunction, solutions,
2128-
allowFreeTypeVariables);
2129-
}
2138+
if (disjunction)
2139+
return solveForDisjunction(disjunction, solutions, allowFreeTypeVariables);
21302140

21312141
// If there are no disjunctions we can't solve this system unless we have
21322142
// free type variables and are allowing them in the solution.

lib/Sema/ConstraintSystem.h

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2975,13 +2975,24 @@ class ConstraintSystem {
29752975
/// \brief Collect the current inactive disjunction constraints.
29762976
void collectDisjunctions(SmallVectorImpl<Constraint *> &disjunctions);
29772977

2978-
/// \brief Attempt to solve for the choices in the given disjunction.
2979-
///
2980-
/// \returns true if we found at least one solution.
2981-
bool
2982-
solveForDisjunctionChoices(Constraint *disjunction,
2983-
SmallVectorImpl<Solution> &solutions,
2984-
FreeTypeVariableBinding allowFreeTypeVariables);
2978+
/// \brief Attempt find a solution involving the options in a
2979+
/// disjunction.
2980+
///
2981+
/// \returns true if we failed to find any solutions, false otherwise.
2982+
bool solveForDisjunction(Constraint *disjunction,
2983+
SmallVectorImpl<Solution> &solutions,
2984+
FreeTypeVariableBinding allowFreeTypeVariables);
2985+
2986+
/// \brief Attempt to solve for some subset of the constraints in a
2987+
/// disjunction, skipping constraints that we decide do not
2988+
/// need to be solved for because they would not result in
2989+
/// the best solution to the constraint system.
2990+
///
2991+
/// \returns true if we failed to find any solutions, false otherwise.
2992+
bool solveForDisjunctionChoices(
2993+
ArrayRef<Constraint *> constraints, ConstraintLocator *disjunctionLocator,
2994+
SmallVectorImpl<Solution> &solutions,
2995+
FreeTypeVariableBinding allowFreeTypeVariables, bool explicitConversion);
29852996

29862997
/// \brief Solve the system of constraints after it has already been
29872998
/// simplified.

0 commit comments

Comments
 (0)