@@ -37,6 +37,9 @@ Expr *getVoidExpr(ASTContext &ctx) {
37
37
38
38
// / Find any type variable references inside of an AST node.
39
39
class TypeVariableRefFinder : public ASTWalker {
40
+ // / A stack of all closures the walker encountered so far.
41
+ SmallVector<DeclContext *> ClosureDCs;
42
+
40
43
ConstraintSystem &CS;
41
44
ASTNode Parent;
42
45
@@ -46,9 +49,16 @@ class TypeVariableRefFinder : public ASTWalker {
46
49
TypeVariableRefFinder (
47
50
ConstraintSystem &cs, ASTNode parent,
48
51
llvm::SmallPtrSetImpl<TypeVariableType *> &referencedVars)
49
- : CS(cs), Parent(parent), ReferencedVars(referencedVars) {}
52
+ : CS(cs), Parent(parent), ReferencedVars(referencedVars) {
53
+ if (auto *closure = getAsExpr<ClosureExpr>(Parent))
54
+ ClosureDCs.push_back (closure);
55
+ }
50
56
51
57
std::pair<bool , Expr *> walkToExprPre (Expr *expr) override {
58
+ if (auto *closure = dyn_cast<ClosureExpr>(expr)) {
59
+ ClosureDCs.push_back (closure);
60
+ }
61
+
52
62
if (auto *DRE = dyn_cast<DeclRefExpr>(expr)) {
53
63
auto *decl = DRE->getDecl ();
54
64
@@ -81,20 +91,33 @@ class TypeVariableRefFinder : public ASTWalker {
81
91
return {true , expr};
82
92
}
83
93
94
+ Expr *walkToExprPost (Expr *expr) override {
95
+ if (auto *closure = dyn_cast<ClosureExpr>(expr)) {
96
+ ClosureDCs.pop_back ();
97
+ }
98
+ return expr;
99
+ }
100
+
84
101
std::pair<bool , Stmt *> walkToStmtPre (Stmt *stmt) override {
85
102
// Return statements have to reference outside result type
86
103
// since all of them are joined by it if it's not specified
87
104
// explicitly.
88
105
if (isa<ReturnStmt>(stmt)) {
89
106
if (auto *closure = getAsExpr<ClosureExpr>(Parent)) {
90
- inferVariables (CS.getClosureType (closure)->getResult ());
107
+ // Return is only viable if it belongs to a parent closure.
108
+ if (currentClosureDC () == closure)
109
+ inferVariables (CS.getClosureType (closure)->getResult ());
91
110
}
92
111
}
93
112
94
113
return {true , stmt};
95
114
}
96
115
97
116
private:
117
+ DeclContext *currentClosureDC () const {
118
+ return ClosureDCs.empty () ? nullptr : ClosureDCs.back ();
119
+ }
120
+
98
121
void inferVariables (Type type) {
99
122
type = type->getWithoutSpecifierType ();
100
123
// Record the type variable itself because it has to
0 commit comments