@@ -24,16 +24,58 @@ Optional<ConstraintSystem::PotentialBindings>
24
24
ConstraintSystem::determineBestBindings () {
25
25
// Look for potential type variable bindings.
26
26
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 ()) {
29
31
if (typeVar->getImpl ().hasRepresentativeOrFixed ())
30
32
continue ;
31
33
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 ())
35
43
continue ;
36
44
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
+
37
79
if (TC.getLangOpts ().DebugConstraintSolver ) {
38
80
auto &log = getASTContext ().TypeCheckerDebug ->getStream ();
39
81
bindings.dump (typeVar, log, solverState->depth * 2 );
@@ -42,7 +84,7 @@ ConstraintSystem::determineBestBindings() {
42
84
// If these are the first bindings, or they are better than what
43
85
// we saw before, use them instead.
44
86
if (!bestBindings || bindings < *bestBindings)
45
- bestBindings = std::move ( bindings) ;
87
+ bestBindings = bindings;
46
88
}
47
89
48
90
return bestBindings;
0 commit comments