[Constraint solver] Move tryOptimizeGenericDisjunction() into partitioning

This narrow favoring rule makes more sense as part of disjunction
partitioning, because it is not dependent on the use site at all and
should only kick in when other options fail.
This commit is contained in:
Doug Gregor
2019-03-05 13:41:25 -08:00
parent fae2d1b2ac
commit b993c6e076
4 changed files with 82 additions and 92 deletions

View File

@@ -1371,58 +1371,6 @@ ConstraintSystem::getTypeOfMemberReference(
return { openedType, type };
}
// Performance hack: if there are two generic overloads, and one is
// more specialized than the other, prefer the more-specialized one.
OverloadChoice *ConstraintSystem::tryOptimizeGenericDisjunction(
ArrayRef<OverloadChoice> choices) {
if (choices.size() != 2)
return nullptr;
const auto &choiceA = choices[0];
const auto &choiceB = choices[1];
if (!choiceA.isDecl() || !choiceB.isDecl())
return nullptr;
auto isViable = [](ValueDecl *decl) -> bool {
assert(decl);
auto *AFD = dyn_cast<AbstractFunctionDecl>(decl);
if (!AFD || !AFD->isGeneric())
return false;
auto funcType = AFD->getInterfaceType();
auto hasAnyOrOptional = funcType.findIf([](Type type) -> bool {
if (type->getOptionalObjectType())
return true;
return type->isAny();
});
// If function declaration references `Any` or `Any?` type
// let's not attempt it, because it's unclear
// without solving which overload is going to be better.
return !hasAnyOrOptional;
};
auto *declA = choiceA.getDecl();
auto *declB = choiceB.getDecl();
if (!isViable(declA) || !isViable(declB))
return nullptr;
switch (TC.compareDeclarations(DC, declA, declB)) {
case Comparison::Better:
return const_cast<OverloadChoice *>(&choiceA);
case Comparison::Worse:
return const_cast<OverloadChoice *>(&choiceB);
case Comparison::Unordered:
return nullptr;
}
}
/// If there are any SIMD operators in the overload set, partition the set so
/// that the SIMD operators come at the end.
static ArrayRef<OverloadChoice> partitionSIMDOperators(
@@ -1576,9 +1524,6 @@ void ConstraintSystem::addOverloadSet(Type boundType,
return;
}
if (!favoredChoice)
favoredChoice = tryOptimizeGenericDisjunction(choices);
SmallVector<OverloadChoice, 4> scratchChoices;
choices = partitionSIMDOperators(choices, scratchChoices);