mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user