Skip to content

Commit 3100088

Browse files
authored
Merge pull request #12198 from xedin/rdar-22898292
[ConstraintSolver] Prioritize certain type variables while looking for bindings
2 parents 71015dc + 001b097 commit 3100088

File tree

4 files changed

+62
-7
lines changed

4 files changed

+62
-7
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,10 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
361361
ConstraintClassification::Relational &&
362362
"only relational constraints handled here");
363363

364+
// Record constraint which contributes to the
365+
// finding of pontential bindings.
366+
result.Sources.insert(constraint);
367+
364368
auto first = simplifyType(constraint->getFirstType());
365369
auto second = simplifyType(constraint->getSecondType());
366370

lib/Sema/CSSimplify.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,13 +1695,14 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
16951695
}
16961696

16971697
// If we have a binding for the right-hand side
1698-
// (argument type) don't try to bind it to the left-hand
1699-
// side (parameter type) directly, because their
1700-
// relationship is contravariant and the actual
1701-
// binding can only come from the left-hand side.
1698+
// (argument type used in the body) don't try
1699+
// to bind it to the left-hand side (parameter type)
1700+
// directly, because there could be an implicit
1701+
// conversion between them, and actual binding
1702+
// can only come from the left-hand side.
17021703
addUnsolvedConstraint(
1703-
Constraint::create(*this, ConstraintKind::ArgumentConversion, type2,
1704-
typeVar1, getConstraintLocator(locator)));
1704+
Constraint::create(*this, ConstraintKind::Equal, typeVar1, type2,
1705+
getConstraintLocator(locator)));
17051706
return SolutionKind::Solved;
17061707
}
17071708

lib/Sema/ConstraintSystem.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "swift/AST/TypeCheckerDebugConsumer.h"
3434
#include "llvm/ADT/ilist.h"
3535
#include "llvm/ADT/PointerUnion.h"
36+
#include "llvm/ADT/SetOperations.h"
3637
#include "llvm/ADT/SetVector.h"
3738
#include "llvm/ADT/SmallPtrSet.h"
3839
#include "llvm/Support/ErrorHandling.h"
@@ -2577,6 +2578,9 @@ class ConstraintSystem {
25772578
/// Tracks the position of the last known supertype in the group.
25782579
Optional<unsigned> lastSupertypeIndex;
25792580

2581+
/// A set of all constraints which contribute to pontential bindings.
2582+
llvm::SmallPtrSet<Constraint *, 8> Sources;
2583+
25802584
PotentialBindings(TypeVariableType *typeVar) : TypeVar(typeVar) {}
25812585

25822586
/// Determine whether the set of bindings is non-empty.
@@ -2600,7 +2604,29 @@ class ConstraintSystem {
26002604
/// \c x is a better set of bindings that \c y.
26012605
friend bool operator<(const PotentialBindings &x,
26022606
const PotentialBindings &y) {
2603-
return formBindingScore(x) < formBindingScore(y);
2607+
if (formBindingScore(x) < formBindingScore(y))
2608+
return true;
2609+
2610+
if (!x.hasNonDefaultableBindings())
2611+
return false;
2612+
2613+
llvm::SmallPtrSet<Constraint *, 8> intersection(x.Sources);
2614+
llvm::set_intersect(intersection, y.Sources);
2615+
2616+
// Some relational constraints dictate certain
2617+
// ordering when it comes to attempting binding
2618+
// of type variables, where left-hand side is
2619+
// always more preferrable than right-hand side.
2620+
for (const auto *constraint : intersection) {
2621+
if (constraint->getKind() != ConstraintKind::Subtype)
2622+
continue;
2623+
2624+
auto lhs = constraint->getFirstType();
2625+
if (auto *typeVar = lhs->getAs<TypeVariableType>())
2626+
return x.TypeVar == typeVar;
2627+
}
2628+
2629+
return false;
26042630
}
26052631

26062632
void foundLiteralBinding(ProtocolDecl *proto) {

test/Constraints/generics.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,3 +504,27 @@ func rdar27700622<E: Comparable>(_ input: [E]) -> [E] {
504504

505505
return rdar27700622(lhs) + [pivot] + rdar27700622(rhs) // Ok
506506
}
507+
508+
// rdar://problem/22898292 - Type inference failure with constrained subclass
509+
protocol P_22898292 {}
510+
511+
do {
512+
func construct_generic<T: P_22898292>(_ construct: () -> T) -> T { return construct() }
513+
514+
class A {}
515+
class B : A, P_22898292 {}
516+
517+
func foo() -> B { return B() }
518+
func bar(_ value: A) {}
519+
func baz<T: A>(_ value: T) {}
520+
521+
func rdar_22898292_1() {
522+
let x = construct_generic { foo() } // returns A
523+
bar(x) // Ok
524+
bar(construct_generic { foo() }) // Ok
525+
}
526+
527+
func rdar22898292_2<T: B>(_ d: T) {
528+
_ = { baz($0) }(construct_generic { d }) // Ok
529+
}
530+
}

0 commit comments

Comments
 (0)