Skip to content

Commit b5e17fb

Browse files
authored
Merge pull request swiftlang#35744 from hborla/solver-disjunction-selection
[ConstraintSystem] Tweak disjunction selection
2 parents 60c562c + 752cf7f commit b5e17fb

File tree

5 files changed

+38
-6
lines changed

5 files changed

+38
-6
lines changed

include/swift/Sema/Constraint.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,11 @@ class Constraint final : public llvm::ilist_node<Constraint>,
686686
});
687687
}
688688

689+
/// Returns the number of resolved argument types for an applied disjunction
690+
/// constriant. This is always zero for disjunctions that do not represent
691+
/// an applied overload.
692+
unsigned countResolvedArgumentTypes(ConstraintSystem &cs) const;
693+
689694
/// Determine if this constraint represents explicit conversion,
690695
/// e.g. coercion constraint "as X" which forms a disjunction.
691696
bool isExplicitConversion() const;

include/swift/Sema/ConstraintSystem.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4983,7 +4983,7 @@ class ConstraintSystem {
49834983

49844984
// If the given constraint is an applied disjunction, get the argument function
49854985
// that the disjunction is applied to.
4986-
const FunctionType *getAppliedDisjunctionArgumentFunction(Constraint *disjunction) {
4986+
const FunctionType *getAppliedDisjunctionArgumentFunction(const Constraint *disjunction) {
49874987
assert(disjunction->getKind() == ConstraintKind::Disjunction);
49884988
return AppliedDisjunctions[disjunction->getLocator()];
49894989
}

lib/Sema/CSSolver.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2295,20 +2295,27 @@ Constraint *ConstraintSystem::selectDisjunction() {
22952295
return first->countActiveNestedConstraints() < second->countActiveNestedConstraints();
22962296

22972297
if (firstFavored == secondFavored) {
2298-
// Look for additional choices to favor
2298+
// Look for additional choices that are "favored"
22992299
SmallVector<unsigned, 4> firstExisting;
23002300
SmallVector<unsigned, 4> secondExisting;
23012301

23022302
existingOperatorBindingsForDisjunction(*cs, first->getNestedConstraints(), firstExisting);
2303-
firstFavored = firstExisting.size() ? firstExisting.size() : first->countActiveNestedConstraints();
2303+
firstFavored += firstExisting.size();
23042304
existingOperatorBindingsForDisjunction(*cs, second->getNestedConstraints(), secondExisting);
2305-
secondFavored = secondExisting.size() ? secondExisting.size() : second->countActiveNestedConstraints();
2306-
2307-
return firstFavored < secondFavored;
2305+
secondFavored += secondExisting.size();
23082306
}
23092307

23102308
firstFavored = firstFavored ? firstFavored : first->countActiveNestedConstraints();
23112309
secondFavored = secondFavored ? secondFavored : second->countActiveNestedConstraints();
2310+
2311+
// Everything else equal, choose the disjunction with the greatest
2312+
// number of resoved argument types. The number of resolved argument
2313+
// types is always zero for disjunctions that don't represent applied
2314+
// overloads.
2315+
if (firstFavored == secondFavored) {
2316+
return first->countResolvedArgumentTypes(*this) > second->countResolvedArgumentTypes(*this);
2317+
}
2318+
23122319
return firstFavored < secondFavored;
23132320
});
23142321

lib/Sema/Constraint.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,17 @@ gatherReferencedTypeVars(Constraint *constraint,
606606
}
607607
}
608608

609+
unsigned Constraint::countResolvedArgumentTypes(ConstraintSystem &cs) const {
610+
auto *argumentFuncType = cs.getAppliedDisjunctionArgumentFunction(this);
611+
if (!argumentFuncType)
612+
return 0;
613+
614+
return llvm::count_if(argumentFuncType->getParams(), [&](const AnyFunctionType::Param arg) {
615+
auto argType = cs.getFixedTypeRecursive(arg.getPlainType(), /*wantRValue=*/true);
616+
return !argType->isTypeVariableOrMember();
617+
});
618+
}
619+
609620
bool Constraint::isExplicitConversion() const {
610621
assert(Kind == ConstraintKind::Disjunction);
611622

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %scale-test --begin 10 --end 20 --step 1 --select NumLeafScopes %s
2+
// REQUIRES: asserts,no_asan
3+
4+
func test(_ arr: [Int]) -> [Int] {
5+
%for i in range(0, N):
6+
arr +
7+
%end
8+
(arr.isEmpty ? arr : [Int]())
9+
}

0 commit comments

Comments
 (0)