Skip to content

Commit d2c7c8d

Browse files
committed
[Constraint solver] Enable favoring of disjunction constraints during solving
Allow constraints to be favored during solving, and unwound after exiting that particular solver scope. We're not using this yet.
1 parent 4c16107 commit d2c7c8d

File tree

4 files changed

+42
-17
lines changed

4 files changed

+42
-17
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4903,7 +4903,6 @@ Type ConstraintSystem::simplifyAppliedOverloads(
49034903
break;
49044904
}
49054905

4906-
49074906
// If there was a constraint that we couldn't reason about, don't use the
49084907
// results of any common-type computations.
49094908
if (hasUnhandledConstraints)

lib/Sema/CSSolver.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ ConstraintSystem::SolverScope::SolverScope(ConstraintSystem &cs)
424424
numCheckedConformances = cs.CheckedConformances.size();
425425
numMissingMembers = cs.MissingMembers.size();
426426
numDisabledConstraints = cs.solverState->getNumDisabledConstraints();
427+
numFavoredConstraints = cs.solverState->getNumFavoredConstraints();
427428

428429
PreviousScore = cs.CurrentScore;
429430

lib/Sema/ConstraintSystem.cpp

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,17 +1373,16 @@ ConstraintSystem::getTypeOfMemberReference(
13731373

13741374
// Performance hack: if there are two generic overloads, and one is
13751375
// more specialized than the other, prefer the more-specialized one.
1376-
static void tryOptimizeGenericDisjunction(ConstraintSystem &cs,
1377-
ArrayRef<OverloadChoice> choices,
1378-
OverloadChoice *&favoredChoice) {
1379-
if (favoredChoice || choices.size() != 2)
1380-
return;
1376+
OverloadChoice *ConstraintSystem::tryOptimizeGenericDisjunction(
1377+
ArrayRef<OverloadChoice> choices) {
1378+
if (choices.size() != 2)
1379+
return nullptr;
13811380

13821381
const auto &choiceA = choices[0];
13831382
const auto &choiceB = choices[1];
13841383

13851384
if (!choiceA.isDecl() || !choiceB.isDecl())
1386-
return;
1385+
return nullptr;
13871386

13881387
auto isViable = [](ValueDecl *decl) -> bool {
13891388
assert(decl);
@@ -1410,22 +1409,17 @@ static void tryOptimizeGenericDisjunction(ConstraintSystem &cs,
14101409
auto *declB = choiceB.getDecl();
14111410

14121411
if (!isViable(declA) || !isViable(declB))
1413-
return;
1414-
1415-
auto &TC = cs.TC;
1416-
auto *DC = cs.DC;
1412+
return nullptr;
14171413

14181414
switch (TC.compareDeclarations(DC, declA, declB)) {
14191415
case Comparison::Better:
1420-
favoredChoice = const_cast<OverloadChoice *>(&choiceA);
1421-
break;
1416+
return const_cast<OverloadChoice *>(&choiceA);
14221417

14231418
case Comparison::Worse:
1424-
favoredChoice = const_cast<OverloadChoice *>(&choiceB);
1425-
break;
1419+
return const_cast<OverloadChoice *>(&choiceB);
14261420

14271421
case Comparison::Unordered:
1428-
break;
1422+
return nullptr;
14291423
}
14301424
}
14311425

@@ -1582,7 +1576,8 @@ void ConstraintSystem::addOverloadSet(Type boundType,
15821576
return;
15831577
}
15841578

1585-
tryOptimizeGenericDisjunction(*this, choices, favoredChoice);
1579+
if (!favoredChoice)
1580+
favoredChoice = tryOptimizeGenericDisjunction(choices);
15861581

15871582
SmallVector<OverloadChoice, 4> scratchChoices;
15881583
choices = partitionSIMDOperators(choices, scratchChoices);

lib/Sema/ConstraintSystem.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,6 +1317,15 @@ class ConstraintSystem {
13171317
disabledConstraints.erase(
13181318
disabledConstraints.begin() + scope->numDisabledConstraints,
13191319
disabledConstraints.end());
1320+
1321+
for (unsigned constraintIdx :
1322+
range(scope->numFavoredConstraints, favoredConstraints.size())) {
1323+
if (favoredConstraints[constraintIdx]->isFavored())
1324+
favoredConstraints[constraintIdx]->setFavored(false);
1325+
}
1326+
favoredConstraints.erase(
1327+
favoredConstraints.begin() + scope->numFavoredConstraints,
1328+
favoredConstraints.end());
13201329
}
13211330

13221331
/// Check whether constraint system is allowed to form solutions
@@ -1336,6 +1345,19 @@ class ConstraintSystem {
13361345
disabledConstraints.push_back(constraint);
13371346
}
13381347

1348+
unsigned getNumFavoredConstraints() const {
1349+
return favoredConstraints.size();
1350+
}
1351+
1352+
/// Favor the given constraint; this change will be rolled back
1353+
/// when we exit the current solver scope.
1354+
void favorConstraint(Constraint *constraint) {
1355+
if (!constraint->isFavored()) {
1356+
constraint->setFavored();
1357+
favoredConstraints.push_back(constraint);
1358+
}
1359+
}
1360+
13391361
private:
13401362
/// The list of constraints that have been retired along the
13411363
/// current path, this list is used in LIFO fashion when constraints
@@ -1358,6 +1380,7 @@ class ConstraintSystem {
13581380
std::tuple<SolverScope *, ConstraintList::iterator, unsigned>, 4> scopes;
13591381

13601382
SmallVector<Constraint *, 4> disabledConstraints;
1383+
SmallVector<Constraint *, 4> favoredConstraints;
13611384
};
13621385

13631386
class CacheExprTypes : public ASTWalker {
@@ -1518,6 +1541,8 @@ class ConstraintSystem {
15181541

15191542
unsigned numDisabledConstraints;
15201543

1544+
unsigned numFavoredConstraints;
1545+
15211546
/// The previous score.
15221547
Score PreviousScore;
15231548

@@ -3162,6 +3187,11 @@ class ConstraintSystem {
31623187

31633188
Constraint *selectApplyDisjunction();
31643189

3190+
/// Look at the set of overload choices to determine if there is a best
3191+
/// generic overload to favor.
3192+
OverloadChoice *tryOptimizeGenericDisjunction(
3193+
ArrayRef<OverloadChoice> choices);
3194+
31653195
/// Solve the system of constraints generated from provided expression.
31663196
///
31673197
/// \param expr The expression to generate constraints from.

0 commit comments

Comments
 (0)