Skip to content

Commit badffdc

Browse files
committed
[Constraint solver] Tune the "skip generic operators" heuristic.
The "skip generic operators" heuristic within the constraint solver is fairly awful, because it is known to miss reasonable solutions. Make is slightly more narrow by only skipping generic operators when the concrete operator we found was symmetric.
1 parent ecdc993 commit badffdc

File tree

1 file changed

+25
-1
lines changed

1 file changed

+25
-1
lines changed

lib/Sema/CSSolver.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//===----------------------------------------------------------------------===//
1616
#include "ConstraintSystem.h"
1717
#include "ConstraintGraph.h"
18+
#include "swift/AST/ParameterList.h"
1819
#include "swift/AST/TypeWalker.h"
1920
#include "llvm/ADT/Statistic.h"
2021
#include "llvm/Support/Compiler.h"
@@ -2480,6 +2481,28 @@ static bool isGenericOperatorOrUnavailable(Constraint *constraint) {
24802481
decl->getAttrs().isUnavailable(ctx);
24812482
}
24822483

2484+
/// Whether this constraint refers to a symmetric operator.
2485+
static bool isSymmetricOperator(Constraint *constraint) {
2486+
if (constraint->getKind() != ConstraintKind::BindOverload ||
2487+
constraint->getOverloadChoice().getKind() != OverloadChoiceKind::Decl ||
2488+
!constraint->getOverloadChoice().getDecl()->isOperator())
2489+
return false;
2490+
2491+
// If it's a binary operator, check that the types on both sides are the
2492+
// same. Otherwise, don't perform this optimization.
2493+
auto func = dyn_cast<FuncDecl>(constraint->getOverloadChoice().getDecl());
2494+
auto paramList =
2495+
func->getParameterList(func->getDeclContext()->isTypeContext());
2496+
if (paramList->size() != 2)
2497+
return true;
2498+
2499+
auto firstType =
2500+
paramList->get(0)->getInterfaceType()->getLValueOrInOutObjectType();
2501+
auto secondType =
2502+
paramList->get(1)->getInterfaceType()->getLValueOrInOutObjectType();
2503+
return firstType->isEqual(secondType);
2504+
}
2505+
24832506
bool ConstraintSystem::solveSimplified(
24842507
SmallVectorImpl<Solution> &solutions,
24852508
FreeTypeVariableBinding allowFreeTypeVariables) {
@@ -2694,7 +2717,8 @@ bool ConstraintSystem::solveSimplified(
26942717

26952718
if (!solveRec(solutions, allowFreeTypeVariables)) {
26962719
if (!firstNonGenericOperatorSolution &&
2697-
!isGenericOperatorOrUnavailable(constraint))
2720+
!isGenericOperatorOrUnavailable(constraint) &&
2721+
isSymmetricOperator(constraint))
26982722
firstNonGenericOperatorSolution = constraint;
26992723

27002724
firstSolvedConstraint = constraint;

0 commit comments

Comments
 (0)