Skip to content

Commit 667d235

Browse files
authored
Merge pull request #15716 from xedin/rdar-38625824
[CSSolver] Clarify generic disjunction choice favoring conditions
2 parents 306e878 + 8688dde commit 667d235

File tree

2 files changed

+70
-22
lines changed

2 files changed

+70
-22
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,64 @@ ConstraintSystem::getTypeOfMemberReference(
13761376
return { openedType, type };
13771377
}
13781378

1379+
// Performance hack: if there are two generic overloads, and one is
1380+
// more specialized than the other, prefer the more-specialized one.
1381+
static void tryOptimizeGenericDisjunction(ConstraintSystem &cs,
1382+
ArrayRef<OverloadChoice> choices,
1383+
OverloadChoice *&favoredChoice) {
1384+
if (favoredChoice || choices.size() != 2)
1385+
return;
1386+
1387+
const auto &choiceA = choices[0];
1388+
const auto &choiceB = choices[1];
1389+
1390+
if (!choiceA.isDecl() || !choiceB.isDecl())
1391+
return;
1392+
1393+
auto isViable = [](ValueDecl *decl) -> bool {
1394+
assert(decl);
1395+
1396+
auto *AFD = dyn_cast<AbstractFunctionDecl>(decl);
1397+
if (!AFD || !AFD->isGeneric())
1398+
return false;
1399+
1400+
auto funcType = AFD->getInterfaceType();
1401+
auto hasAny = funcType.findIf([](Type type) -> bool {
1402+
if (auto objType = type->getOptionalObjectType())
1403+
return objType->isAny();
1404+
1405+
return type->isAny();
1406+
});
1407+
1408+
// If function declaration references `Any` or `Any?` type
1409+
// let's not attempt it, because it's unclear
1410+
// without solving which overload is going to be better.
1411+
return !hasAny;
1412+
};
1413+
1414+
auto *declA = choiceA.getDecl();
1415+
auto *declB = choiceB.getDecl();
1416+
1417+
if (!isViable(declA) || !isViable(declB))
1418+
return;
1419+
1420+
auto &TC = cs.TC;
1421+
auto *DC = cs.DC;
1422+
1423+
switch (TC.compareDeclarations(DC, declA, declB)) {
1424+
case Comparison::Better:
1425+
favoredChoice = const_cast<OverloadChoice *>(&choiceA);
1426+
break;
1427+
1428+
case Comparison::Worse:
1429+
favoredChoice = const_cast<OverloadChoice *>(&choiceB);
1430+
break;
1431+
1432+
case Comparison::Unordered:
1433+
break;
1434+
}
1435+
}
1436+
13791437
void ConstraintSystem::addOverloadSet(Type boundType,
13801438
ArrayRef<OverloadChoice> choices,
13811439
DeclContext *useDC,
@@ -1389,28 +1447,7 @@ void ConstraintSystem::addOverloadSet(Type boundType,
13891447
return;
13901448
}
13911449

1392-
// Performance hack: if there are two generic overloads, and one is
1393-
// more specialized than the other, prefer the more-specialized one.
1394-
if (!favoredChoice && choices.size() == 2 &&
1395-
choices[0].isDecl() && choices[1].isDecl() &&
1396-
isa<AbstractFunctionDecl>(choices[0].getDecl()) &&
1397-
cast<AbstractFunctionDecl>(choices[0].getDecl())->isGeneric() &&
1398-
isa<AbstractFunctionDecl>(choices[1].getDecl()) &&
1399-
cast<AbstractFunctionDecl>(choices[1].getDecl())->isGeneric()) {
1400-
switch (TC.compareDeclarations(DC, choices[0].getDecl(),
1401-
choices[1].getDecl())) {
1402-
case Comparison::Better:
1403-
favoredChoice = const_cast<OverloadChoice *>(&choices[0]);
1404-
break;
1405-
1406-
case Comparison::Worse:
1407-
favoredChoice = const_cast<OverloadChoice *>(&choices[1]);
1408-
break;
1409-
1410-
case Comparison::Unordered:
1411-
break;
1412-
}
1413-
}
1450+
tryOptimizeGenericDisjunction(*this, choices, favoredChoice);
14141451

14151452
SmallVector<Constraint *, 4> overloads;
14161453

test/Constraints/rdar38625824.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-swift-frontend -emit-sil -verify %s | %FileCheck %s
2+
func foo<T>(_: Any) -> T {
3+
fatalError()
4+
}
5+
6+
func foo<T>(_: Any?) -> T {
7+
fatalError()
8+
}
9+
10+
// CHECK: function_ref @$S12rdar386258243fooyxyplF : $@convention(thin) <τ_0_0> (@in_guaranteed Any) -> @out τ_0_0
11+
var _: String = foo("hello")

0 commit comments

Comments
 (0)