Skip to content

Commit f2404fe

Browse files
committed
[CS] Factor out BindingSet::favoredOverConjunction
And refactor the way we select the next step for a ComponentStep. This should be NFC.
1 parent 1846276 commit f2404fe

File tree

3 files changed

+48
-24
lines changed

3 files changed

+48
-24
lines changed

include/swift/Sema/CSBindings.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,9 @@ class BindingSet {
480480
/// if it has only concrete types or would resolve a closure.
481481
bool favoredOverDisjunction(Constraint *disjunction) const;
482482

483+
/// Check if this binding is favored over a conjunction.
484+
bool favoredOverConjunction(Constraint *conjunction) const;
485+
483486
/// Detect `subtype` relationship between two type variables and
484487
/// attempt to infer supertype bindings transitively e.g.
485488
///

lib/Sema/CSBindings.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,6 +1065,14 @@ bool BindingSet::favoredOverDisjunction(Constraint *disjunction) const {
10651065
return !involvesTypeVariables();
10661066
}
10671067

1068+
bool BindingSet::favoredOverConjunction(Constraint *conjunction) const {
1069+
if (CS.shouldAttemptFixes() && isHole()) {
1070+
if (forClosureResult() || forGenericParameter())
1071+
return false;
1072+
}
1073+
return true;
1074+
}
1075+
10681076
BindingSet ConstraintSystem::getBindingsFor(TypeVariableType *typeVar,
10691077
bool finalize) {
10701078
assert(typeVar->getImpl().getRepresentative(nullptr) == typeVar &&

lib/Sema/CSStep.cpp

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ StepResult ComponentStep::take(bool prevFailed) {
359359
});
360360

361361
auto *disjunction = CS.selectDisjunction();
362+
auto *conjunction = CS.selectConjunction();
362363

363364
if (CS.isDebugMode()) {
364365
if (!potentialBindings.empty()) {
@@ -393,33 +394,45 @@ StepResult ComponentStep::take(bool prevFailed) {
393394
}
394395
}
395396

396-
if (CS.shouldAttemptFixes()) {
397-
if ((bestBindings &&
398-
(bestBindings->forClosureResult() ||
399-
bestBindings->forGenericParameter()) &&
400-
bestBindings->isHole()) &&
401-
!disjunction) {
402-
if (auto *conjunction = CS.selectConjunction()) {
403-
return suspend(
404-
std::make_unique<ConjunctionStep>(CS, conjunction, Solutions));
405-
}
397+
enum class StepKind { Binding, Disjunction, Conjunction };
398+
399+
auto chooseStep = [&]() -> Optional<StepKind> {
400+
// Bindings usually happen first, but sometimes we want to prioritize a
401+
// disjunction or conjunction.
402+
if (bestBindings) {
403+
if (disjunction && !bestBindings->favoredOverDisjunction(disjunction))
404+
return StepKind::Disjunction;
405+
406+
if (conjunction && !bestBindings->favoredOverConjunction(conjunction))
407+
return StepKind::Conjunction;
408+
409+
return StepKind::Binding;
410+
}
411+
if (disjunction)
412+
return StepKind::Disjunction;
413+
414+
if (conjunction)
415+
return StepKind::Conjunction;
416+
417+
return None;
418+
};
419+
420+
if (auto step = chooseStep()) {
421+
switch (*step) {
422+
case StepKind::Binding:
423+
return suspend(
424+
std::make_unique<TypeVariableStep>(*bestBindings, Solutions));
425+
case StepKind::Disjunction:
426+
return suspend(
427+
std::make_unique<DisjunctionStep>(CS, disjunction, Solutions));
428+
case StepKind::Conjunction:
429+
return suspend(
430+
std::make_unique<ConjunctionStep>(CS, conjunction, Solutions));
406431
}
432+
llvm_unreachable("Unhandled case in switch!");
407433
}
408434

409-
if (bestBindings &&
410-
(!disjunction || bestBindings->favoredOverDisjunction(disjunction))) {
411-
// Produce a type variable step.
412-
return suspend(
413-
std::make_unique<TypeVariableStep>(*bestBindings, Solutions));
414-
} else if (disjunction) {
415-
// Produce a disjunction step.
416-
return suspend(
417-
std::make_unique<DisjunctionStep>(CS, disjunction, Solutions));
418-
} else if (auto *conjunction = CS.selectConjunction()) {
419-
return suspend(
420-
std::make_unique<ConjunctionStep>(CS, conjunction, Solutions));
421-
} else if (!CS.solverState->allowsFreeTypeVariables() &&
422-
CS.hasFreeTypeVariables()) {
435+
if (!CS.solverState->allowsFreeTypeVariables() && CS.hasFreeTypeVariables()) {
423436
// If there are no disjunctions or type variables to bind
424437
// we can't solve this system unless we have free type variables
425438
// allowed in the solution.

0 commit comments

Comments
 (0)