@@ -1004,6 +1004,9 @@ class ClosureConstraintApplication
1004
1004
RewriteTargetFn rewriteTarget;
1005
1005
bool isSingleExpression;
1006
1006
1007
+ // / All `func`s declared in the body of the closure.
1008
+ SmallVector<FuncDecl *, 4 > LocalFuncs;
1009
+
1007
1010
public:
1008
1011
// / Whether an error was encountered while generating constraints.
1009
1012
bool hadError = false ;
@@ -1048,6 +1051,14 @@ class ClosureConstraintApplication
1048
1051
// information e.g. accessors and do access/availability checks.
1049
1052
}
1050
1053
1054
+ // Local functions cannot be type-checked in-order because they can
1055
+ // capture variables declared after them. Let's save them to be
1056
+ // processed after the solution has been applied to the body.
1057
+ if (auto *func = dyn_cast<FuncDecl>(decl)) {
1058
+ LocalFuncs.push_back (func);
1059
+ return ;
1060
+ }
1061
+
1051
1062
TypeChecker::typeCheckDecl (decl);
1052
1063
}
1053
1064
@@ -1456,6 +1467,19 @@ class ClosureConstraintApplication
1456
1467
UNSUPPORTED_STMT(Fail)
1457
1468
#undef UNSUPPORTED_STMT
1458
1469
1470
+ public:
1471
+ // / Apply solution to the closure and return updated body.
1472
+ ASTNode apply () {
1473
+ auto body = visit (closure->getBody ());
1474
+
1475
+ // Since local functions can capture variables that are declared
1476
+ // after them, let's type-check them after all of the pattern
1477
+ // bindings have been resolved by applying solution to the body.
1478
+ for (auto *func : LocalFuncs)
1479
+ TypeChecker::typeCheckDecl (func);
1480
+
1481
+ return body;
1482
+ }
1459
1483
};
1460
1484
1461
1485
}
@@ -1552,7 +1576,7 @@ bool ConstraintSystem::applySolutionToBody(Solution &solution,
1552
1576
auto closureType = cs.getType (closure)->castTo <FunctionType>();
1553
1577
ClosureConstraintApplication application (
1554
1578
solution, closure, closureType->getResult (), rewriteTarget);
1555
- auto body = application.visit (closure-> getBody () );
1579
+ auto body = application.apply ( );
1556
1580
1557
1581
if (!body || application.hadError )
1558
1582
return true ;
0 commit comments