Skip to content

Commit 39dc184

Browse files
authored
Merge pull request #15009 from xedin/rdar-38159133
[CSBindings] Try to infer bindings from related type variables
2 parents f3b7b8c + 380ea4a commit 39dc184

File tree

3 files changed

+62
-22
lines changed

3 files changed

+62
-22
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,58 @@ Optional<ConstraintSystem::PotentialBindings>
2424
ConstraintSystem::determineBestBindings() {
2525
// Look for potential type variable bindings.
2626
Optional<PotentialBindings> bestBindings;
27-
for (auto typeVar : getTypeVariables()) {
28-
// Skip any type variables that are bound.
27+
llvm::SmallDenseMap<TypeVariableType *, PotentialBindings> cache;
28+
29+
// First, let's collect all of the possible bindings.
30+
for (auto *typeVar : getTypeVariables()) {
2931
if (typeVar->getImpl().hasRepresentativeOrFixed())
3032
continue;
3133

32-
// Get potential bindings.
33-
auto bindings = getPotentialBindings(typeVar);
34-
if (!bindings)
34+
if (auto bindings = getPotentialBindings(typeVar))
35+
cache.insert({typeVar, std::move(bindings)});
36+
}
37+
38+
// Now let's see if we could infer something for related type
39+
// variables based on other bindings.
40+
for (auto *typeVar : getTypeVariables()) {
41+
auto cachedBindings = cache.find(typeVar);
42+
if (cachedBindings == cache.end())
3543
continue;
3644

45+
auto &bindings = cachedBindings->getSecond();
46+
// All of the relevant relational constraints associated with
47+
// current type variable should be recored by its potential bindings.
48+
for (auto *constraint : bindings.Sources) {
49+
if (constraint->getKind() != ConstraintKind::Subtype)
50+
continue;
51+
52+
auto lhs = simplifyType(constraint->getFirstType());
53+
auto rhs = simplifyType(constraint->getSecondType());
54+
55+
// We are only interested in 'subtype' constraints which have
56+
// type variable on the left-hand side.
57+
if (rhs->getAs<TypeVariableType>() != typeVar)
58+
continue;
59+
60+
auto *tv = lhs->getAs<TypeVariableType>();
61+
if (!tv)
62+
continue;
63+
64+
auto relatedBindings = cache.find(tv);
65+
if (relatedBindings == cache.end())
66+
continue;
67+
68+
for (auto &binding : relatedBindings->getSecond().Bindings) {
69+
auto type = binding.BindingType;
70+
71+
if (ConstraintSystem::typeVarOccursInType(typeVar, type))
72+
continue;
73+
74+
bindings.addPotentialBinding(
75+
{type, AllowedBindingKind::Supertypes, binding.BindingSource});
76+
}
77+
}
78+
3779
if (TC.getLangOpts().DebugConstraintSolver) {
3880
auto &log = getASTContext().TypeCheckerDebug->getStream();
3981
bindings.dump(typeVar, log, solverState->depth * 2);
@@ -42,7 +84,7 @@ ConstraintSystem::determineBestBindings() {
4284
// If these are the first bindings, or they are better than what
4385
// we saw before, use them instead.
4486
if (!bestBindings || bindings < *bestBindings)
45-
bestBindings = std::move(bindings);
87+
bestBindings = bindings;
4688
}
4789

4890
return bestBindings;

lib/Sema/ConstraintSystem.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2776,22 +2776,6 @@ class ConstraintSystem {
27762776
if (x.FullyBound || x.SubtypeOfExistentialType)
27772777
return false;
27782778

2779-
llvm::SmallPtrSet<Constraint *, 8> intersection(x.Sources);
2780-
llvm::set_intersect(intersection, y.Sources);
2781-
2782-
// Some relational constraints dictate certain
2783-
// ordering when it comes to attempting binding
2784-
// of type variables, where left-hand side is
2785-
// always more preferrable than right-hand side.
2786-
for (const auto *constraint : intersection) {
2787-
if (constraint->getKind() != ConstraintKind::Subtype)
2788-
continue;
2789-
2790-
auto lhs = constraint->getFirstType();
2791-
if (auto *typeVar = lhs->getAs<TypeVariableType>())
2792-
return x.TypeVar == typeVar;
2793-
}
2794-
27952779
// If the only difference is default types,
27962780
// prioritize bindings with fewer of them.
27972781
return x.NumDefaultableBindings < y.NumDefaultableBindings;

test/Constraints/generics.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,3 +543,17 @@ func rdar35541153() {
543543
foo(x) // Ok
544544
bar(y, "ultimate question", 42) // Ok
545545
}
546+
547+
// rdar://problem/38159133 - [SR-7125]: Swift 4.1 Xcode 9.3b4 regression
548+
549+
protocol P_38159133 {}
550+
551+
do {
552+
class Super {}
553+
class A: Super, P_38159133 {}
554+
class B: Super, P_38159133 {}
555+
556+
func rdar38159133(_ a: A?, _ b: B?) {
557+
let _: [P_38159133] = [a, b].compactMap { $0 } // Ok
558+
}
559+
}

0 commit comments

Comments
 (0)