@@ -94,6 +94,38 @@ class TypeVariableRefFinder : public ASTWalker {
94
94
}
95
95
};
96
96
97
+ // / Find any references to not yet resolved outer closure parameters
98
+ // / used in the body of the inner closure. This is required because
99
+ // / isolated conjunctions, just like single-expression closures, have
100
+ // / to be connected to type variables they are going to use, otherwise
101
+ // / they'll get placed in a separate solver component and would never
102
+ // / produce a solution.
103
+ class UnresolvedClosureParameterCollector : public ASTWalker {
104
+ ConstraintSystem &CS;
105
+
106
+ llvm::SmallSetVector<TypeVariableType *, 4 > Vars;
107
+
108
+ public:
109
+ UnresolvedClosureParameterCollector (ConstraintSystem &cs) : CS(cs) {}
110
+
111
+ std::pair<bool , Expr *> walkToExprPre (Expr *expr) override {
112
+ if (auto *DRE = dyn_cast<DeclRefExpr>(expr)) {
113
+ auto *decl = DRE->getDecl ();
114
+ if (isa<ParamDecl>(decl)) {
115
+ if (auto type = CS.getTypeIfAvailable (decl)) {
116
+ if (auto *typeVar = type->getAs <TypeVariableType>())
117
+ Vars.insert (typeVar);
118
+ }
119
+ }
120
+ }
121
+ return {true , expr};
122
+ }
123
+
124
+ ArrayRef<TypeVariableType *> getVariables () const {
125
+ return Vars.getArrayRef ();
126
+ }
127
+ };
128
+
97
129
// MARK: Constraint generation
98
130
99
131
// / Check whether it makes sense to convert this element into a constrant.
@@ -143,6 +175,8 @@ static void createConjunction(ConstraintSystem &cs,
143
175
isIsolated = true ;
144
176
}
145
177
178
+ UnresolvedClosureParameterCollector paramCollector (cs);
179
+
146
180
for (const auto &entry : elements) {
147
181
ASTNode element = std::get<0 >(entry);
148
182
ContextualTypeInfo context = std::get<1 >(entry);
@@ -151,6 +185,12 @@ static void createConjunction(ConstraintSystem &cs,
151
185
if (!isViableElement (element))
152
186
continue ;
153
187
188
+ // If this conjunction going to represent a body of a closure,
189
+ // let's collect references to not yet resolved outer
190
+ // closure parameters.
191
+ if (isIsolated)
192
+ element.walk (paramCollector);
193
+
154
194
constraints.push_back (
155
195
Constraint::createClosureBodyElement (cs, element, context, elementLoc));
156
196
}
@@ -162,6 +202,9 @@ static void createConjunction(ConstraintSystem &cs,
162
202
if (constraints.empty ())
163
203
return ;
164
204
205
+ for (auto *externalVar : paramCollector.getVariables ())
206
+ referencedVars.push_back (externalVar);
207
+
165
208
cs.addUnsolvedConstraint (Constraint::createConjunction (
166
209
cs, constraints, isIsolated, locator, referencedVars));
167
210
}
0 commit comments