Skip to content

Commit 40b4eda

Browse files
authored
Merge pull request #17352 from rudkx/reenable-perf-hack-attempt-2
[ConstraintSystem] Reinstate favoring more specialized of two generic…
2 parents 8abaaea + 1a2d7f5 commit 40b4eda

File tree

3 files changed

+61
-1
lines changed

3 files changed

+61
-1
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1486,6 +1486,64 @@ ConstraintSystem::getTypeOfMemberReference(
14861486
return { openedType, type };
14871487
}
14881488

1489+
// Performance hack: if there are two generic overloads, and one is
1490+
// more specialized than the other, prefer the more-specialized one.
1491+
static void tryOptimizeGenericDisjunction(ConstraintSystem &cs,
1492+
ArrayRef<OverloadChoice> choices,
1493+
OverloadChoice *&favoredChoice) {
1494+
if (favoredChoice || choices.size() != 2)
1495+
return;
1496+
1497+
const auto &choiceA = choices[0];
1498+
const auto &choiceB = choices[1];
1499+
1500+
if (!choiceA.isDecl() || !choiceB.isDecl())
1501+
return;
1502+
1503+
auto isViable = [](ValueDecl *decl) -> bool {
1504+
assert(decl);
1505+
1506+
auto *AFD = dyn_cast<AbstractFunctionDecl>(decl);
1507+
if (!AFD || !AFD->isGeneric())
1508+
return false;
1509+
1510+
auto funcType = AFD->getInterfaceType();
1511+
auto hasAnyOrOptional = funcType.findIf([](Type type) -> bool {
1512+
if (auto objType = type->getOptionalObjectType())
1513+
return true;
1514+
1515+
return type->isAny();
1516+
});
1517+
1518+
// If function declaration references `Any` or `Any?` type
1519+
// let's not attempt it, because it's unclear
1520+
// without solving which overload is going to be better.
1521+
return !hasAnyOrOptional;
1522+
};
1523+
1524+
auto *declA = choiceA.getDecl();
1525+
auto *declB = choiceB.getDecl();
1526+
1527+
if (!isViable(declA) || !isViable(declB))
1528+
return;
1529+
1530+
auto &TC = cs.TC;
1531+
auto *DC = cs.DC;
1532+
1533+
switch (TC.compareDeclarations(DC, declA, declB)) {
1534+
case Comparison::Better:
1535+
favoredChoice = const_cast<OverloadChoice *>(&choiceA);
1536+
break;
1537+
1538+
case Comparison::Worse:
1539+
favoredChoice = const_cast<OverloadChoice *>(&choiceB);
1540+
break;
1541+
1542+
case Comparison::Unordered:
1543+
break;
1544+
}
1545+
}
1546+
14891547
void ConstraintSystem::addOverloadSet(Type boundType,
14901548
ArrayRef<OverloadChoice> choices,
14911549
DeclContext *useDC,
@@ -1500,6 +1558,8 @@ void ConstraintSystem::addOverloadSet(Type boundType,
15001558
return;
15011559
}
15021560

1561+
tryOptimizeGenericDisjunction(*this, choices, favoredChoice);
1562+
15031563
SmallVector<Constraint *, 4> overloads;
15041564

15051565
// As we do for other favored constraints, if a favored overload has been

validation-test/Sema/type_checker_perf/slow/more_specialized_generic_func.swift.gyb renamed to validation-test/Sema/type_checker_perf/fast/more_specialized_generic_func.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %scale-test --invert-result --begin 1 --end 10 --step 1 --select incrementScopeCounter %s --expected-exit-code 0
1+
// RUN: %scale-test --begin 1 --end 10 --step 1 --select incrementScopeCounter %s --expected-exit-code 0
22
// REQUIRES: OS=macosx
33
// REQUIRES: asserts
44

0 commit comments

Comments
 (0)