Skip to content

Commit 2d851ff

Browse files
authored
Merge pull request #38700 from hborla/improve-transitive-conformance-heuristic
[ConstraintSystem] Improve the "transitive conformance" heuristic and remove early conformance checking from `DisjunctionStep::shouldSkip`
2 parents 6e288bd + 241c1e4 commit 2d851ff

File tree

2 files changed

+6
-53
lines changed

2 files changed

+6
-53
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6485,6 +6485,12 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyTransitivelyConformsTo(
64856485
// If the type doesn't conform, let's check whether
64866486
// an Optional or Unsafe{Mutable}Pointer from it would.
64876487

6488+
// If the current score is equal to the best score, fail without checking
6489+
// implicit conversions, because an implicit conversion would lead to a
6490+
// worse score anyway.
6491+
if (solverState && solverState->BestScore && CurrentScore == *solverState->BestScore)
6492+
return SolutionKind::Error;
6493+
64886494
SmallVector<Type, 4> typesToCheck;
64896495

64906496
// T -> Optional<T>

lib/Sema/CSStep.cpp

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -639,59 +639,6 @@ bool DisjunctionStep::shouldSkip(const DisjunctionChoice &choice) const {
639639
}
640640
}
641641

642-
// If the solver already found a solution with a choice that did not
643-
// introduce any conversions (i.e., the score is not worse than the
644-
// current score), we can skip any generic operators with conformance
645-
// requirements that are not satisfied by any known argument types.
646-
auto argFnType = CS.getAppliedDisjunctionArgumentFunction(Disjunction);
647-
auto checkRequirementsEarly = [&]() -> bool {
648-
auto bestScore = getBestScore(Solutions);
649-
if (!(bestScore && choice.isGenericOperator() && argFnType))
650-
return false;
651-
652-
auto currentScore = getCurrentScore();
653-
for (unsigned i = 0; i < NumScoreKinds; ++i) {
654-
if (i == SK_NonDefaultLiteral)
655-
continue;
656-
657-
if (bestScore->Data[i] > currentScore.Data[i])
658-
return false;
659-
}
660-
661-
return true;
662-
};
663-
if (checkRequirementsEarly()) {
664-
Constraint *constraint = choice;
665-
auto *decl = constraint->getOverloadChoice().getDecl();
666-
if (decl->getBaseIdentifier().isArithmeticOperator()) {
667-
auto *useDC = constraint->getOverloadUseDC();
668-
auto choiceType = CS.getEffectiveOverloadType(
669-
constraint->getLocator(), constraint->getOverloadChoice(),
670-
/*allowMembers=*/true, useDC);
671-
auto choiceFnType = choiceType->getAs<FunctionType>();
672-
auto genericFnType = decl->getInterfaceType()->getAs<GenericFunctionType>();
673-
auto signature = genericFnType->getGenericSignature();
674-
675-
for (auto argParamPair : llvm::zip(argFnType->getParams(),
676-
choiceFnType->getParams())) {
677-
auto argType = std::get<0>(argParamPair).getPlainType();
678-
auto paramType = std::get<1>(argParamPair).getPlainType();
679-
680-
// Only check argument types with no type variables that will be matched
681-
// against a plain type parameter.
682-
argType = argType->getCanonicalType()->getWithoutSpecifierType();
683-
if (argType->hasTypeVariable() || !paramType->isTypeParameter())
684-
continue;
685-
686-
for (auto *protocol : signature->getRequiredProtocols(paramType)) {
687-
if (!TypeChecker::conformsToProtocol(argType, protocol,
688-
useDC->getParentModule()))
689-
return skip("unsatisfied");
690-
}
691-
}
692-
}
693-
}
694-
695642
// Don't attempt to solve for generic operators if we already have
696643
// a non-generic solution.
697644

0 commit comments

Comments
 (0)