Skip to content

Commit bc14f00

Browse files
committed
[CSClosure] Link closure conjunction with referenced outer parameters
If one or more outer closure parameters used in the body of an inner closure have not been resolved when conjunction is created, let's reference them in the conjunction constraint to avoid disconnecting conjunction from its context.
1 parent dfe6c34 commit bc14f00

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

lib/Sema/CSClosure.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,38 @@ class TypeVariableRefFinder : public ASTWalker {
9494
}
9595
};
9696

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+
97129
// MARK: Constraint generation
98130

99131
/// Check whether it makes sense to convert this element into a constrant.
@@ -143,6 +175,8 @@ static void createConjunction(ConstraintSystem &cs,
143175
isIsolated = true;
144176
}
145177

178+
UnresolvedClosureParameterCollector paramCollector(cs);
179+
146180
for (const auto &entry : elements) {
147181
ASTNode element = std::get<0>(entry);
148182
ContextualTypeInfo context = std::get<1>(entry);
@@ -151,6 +185,12 @@ static void createConjunction(ConstraintSystem &cs,
151185
if (!isViableElement(element))
152186
continue;
153187

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+
154194
constraints.push_back(
155195
Constraint::createClosureBodyElement(cs, element, context, elementLoc));
156196
}
@@ -162,6 +202,9 @@ static void createConjunction(ConstraintSystem &cs,
162202
if (constraints.empty())
163203
return;
164204

205+
for (auto *externalVar : paramCollector.getVariables())
206+
referencedVars.push_back(externalVar);
207+
165208
cs.addUnsolvedConstraint(Constraint::createConjunction(
166209
cs, constraints, isIsolated, locator, referencedVars));
167210
}

0 commit comments

Comments
 (0)