[Constraint solver] Favor more-specialized overload among two generics.

When we form an overload set containing two generic functions, where
one is more specialized than the other, "favor" the more-specialized
function in the constraint system so we won't explore any paths
involving the less-specialized function when the more-specialized
version applies. This should be a strict improvement, because
previously we would have always gone down both paths.

Fixes rdar://problem/37371815, taking this exponential example linear.
This commit is contained in:
Doug Gregor
2018-02-08 16:56:14 -08:00
parent 43435af7ee
commit 3d32e89e33
2 changed files with 50 additions and 0 deletions

View File

@@ -1389,6 +1389,29 @@ void ConstraintSystem::addOverloadSet(Type boundType,
return;
}
// Performance hack: if there are two generic overloads, and one is
// more specialized than the other, prefer the more-specialized one.
if (!favoredChoice && choices.size() == 2 &&
choices[0].isDecl() && choices[1].isDecl() &&
isa<AbstractFunctionDecl>(choices[0].getDecl()) &&
cast<AbstractFunctionDecl>(choices[0].getDecl())->isGeneric() &&
isa<AbstractFunctionDecl>(choices[1].getDecl()) &&
cast<AbstractFunctionDecl>(choices[1].getDecl())->isGeneric()) {
switch (TC.compareDeclarations(DC, choices[0].getDecl(),
choices[1].getDecl())) {
case Comparison::Better:
favoredChoice = const_cast<OverloadChoice *>(&choices[0]);
break;
case Comparison::Worse:
favoredChoice = const_cast<OverloadChoice *>(&choices[1]);
break;
case Comparison::Unordered:
break;
}
}
SmallVector<Constraint *, 4> overloads;
// As we do for other favored constraints, if a favored overload has been