21
21
using namespace swift ;
22
22
using namespace constraints ;
23
23
24
+ void ConstraintSystem::inferTransitiveSupertypeBindings (
25
+ const llvm::SmallDenseMap<TypeVariableType *, PotentialBindings>
26
+ &inferredBindings,
27
+ PotentialBindings &bindings) {
28
+ auto *typeVar = bindings.TypeVar ;
29
+
30
+ llvm::SmallVector<Constraint *, 4 > subtypeOf;
31
+ // First, let's collect all of the `subtype` constraints associated
32
+ // with this type variable.
33
+ llvm::copy_if (bindings.Sources , std::back_inserter (subtypeOf),
34
+ [&](const Constraint *constraint) -> bool {
35
+ if (constraint->getKind () != ConstraintKind::Subtype)
36
+ return false ;
37
+
38
+ auto rhs = simplifyType (constraint->getSecondType ());
39
+ return rhs->getAs <TypeVariableType>() == typeVar;
40
+ });
41
+
42
+ if (subtypeOf.empty ())
43
+ return ;
44
+
45
+ // We need to make sure that there are no duplicate bindings in the
46
+ // set, other we'll produce multiple identical solutions.
47
+ llvm::SmallPtrSet<CanType, 4 > existingTypes;
48
+ for (const auto &binding : bindings.Bindings )
49
+ existingTypes.insert (binding.BindingType ->getCanonicalType ());
50
+
51
+ for (auto *constraint : subtypeOf) {
52
+ auto *tv =
53
+ simplifyType (constraint->getFirstType ())->getAs <TypeVariableType>();
54
+ if (!tv)
55
+ continue ;
56
+
57
+ auto relatedBindings = inferredBindings.find (tv);
58
+ if (relatedBindings == inferredBindings.end ())
59
+ continue ;
60
+
61
+ for (auto &binding : relatedBindings->getSecond ().Bindings ) {
62
+ // We need the binding kind for the potential binding to
63
+ // either be Exact or Supertypes in order for it to make sense
64
+ // to add Supertype bindings based on the relationship between
65
+ // our type variables.
66
+ if (binding.Kind != AllowedBindingKind::Exact &&
67
+ binding.Kind != AllowedBindingKind::Supertypes)
68
+ continue ;
69
+
70
+ auto type = binding.BindingType ;
71
+
72
+ if (!existingTypes.insert (type->getCanonicalType ()).second )
73
+ continue ;
74
+
75
+ if (ConstraintSystem::typeVarOccursInType (typeVar, type))
76
+ continue ;
77
+
78
+ bindings.addPotentialBinding (
79
+ binding.withSameSource (type, AllowedBindingKind::Supertypes));
80
+ }
81
+ }
82
+ }
83
+
24
84
Optional<ConstraintSystem::PotentialBindings>
25
85
ConstraintSystem::determineBestBindings () {
26
86
// Look for potential type variable bindings.
@@ -44,46 +104,8 @@ ConstraintSystem::determineBestBindings() {
44
104
continue ;
45
105
46
106
auto &bindings = cachedBindings->getSecond ();
47
- // All of the relevant relational constraints associated with
48
- // current type variable should be recored by its potential bindings.
49
- for (auto *constraint : bindings.Sources ) {
50
- if (constraint->getKind () != ConstraintKind::Subtype)
51
- continue ;
52
-
53
- auto lhs = simplifyType (constraint->getFirstType ());
54
- auto rhs = simplifyType (constraint->getSecondType ());
55
-
56
- // We are only interested in 'subtype' constraints which have
57
- // type variable on the left-hand side.
58
- if (rhs->getAs <TypeVariableType>() != typeVar)
59
- continue ;
60
-
61
- auto *tv = lhs->getAs <TypeVariableType>();
62
- if (!tv)
63
- continue ;
64
-
65
- auto relatedBindings = cache.find (tv);
66
- if (relatedBindings == cache.end ())
67
- continue ;
68
-
69
- for (auto &binding : relatedBindings->getSecond ().Bindings ) {
70
- // We need the binding kind for the potential binding to
71
- // either be Exact or Supertypes in order for it to make sense
72
- // to add Supertype bindings based on the relationship between
73
- // our type variables.
74
- if (binding.Kind != AllowedBindingKind::Exact &&
75
- binding.Kind != AllowedBindingKind::Supertypes)
76
- continue ;
77
-
78
- auto type = binding.BindingType ;
79
107
80
- if (ConstraintSystem::typeVarOccursInType (typeVar, type))
81
- continue ;
82
-
83
- bindings.addPotentialBinding (
84
- binding.withSameSource (type, AllowedBindingKind::Supertypes));
85
- }
86
- }
108
+ inferTransitiveSupertypeBindings (cache, bindings);
87
109
88
110
if (getASTContext ().TypeCheckerOpts .DebugConstraintSolver ) {
89
111
auto &log = getASTContext ().TypeCheckerDebug ->getStream ();
0 commit comments