Skip to content

Commit 2524044

Browse files
committed
[CS] Delay type-checking of local decls
Delay `typeCheckDecl` for local decls until the end of CSApply. This replaces the existing logic for delaying type-checking for local functions.
1 parent 152d0ed commit 2524044

File tree

3 files changed

+36
-40
lines changed

3 files changed

+36
-40
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2065,6 +2065,8 @@ class SyntacticElementTargetRewriter {
20652065
virtual Solution &getSolution() const = 0;
20662066
virtual DeclContext *&getCurrentDC() const = 0;
20672067

2068+
virtual void addLocalDeclToTypeCheck(Decl *D) = 0;
2069+
20682070
virtual std::optional<SyntacticElementTarget>
20692071
rewriteTarget(SyntacticElementTarget target) = 0;
20702072

lib/Sema/CSApply.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8823,15 +8823,26 @@ namespace {
88238823
class ExprWalker : public ASTWalker, public SyntacticElementTargetRewriter {
88248824
ExprRewriter &Rewriter;
88258825
SmallVector<ClosureExpr *, 4> ClosuresToTypeCheck;
8826+
SmallVector<Decl *, 4> LocalDeclsToTypeCheck;
88268827

88278828
public:
88288829
ExprWalker(ExprRewriter &Rewriter) : Rewriter(Rewriter) { }
88298830

8830-
~ExprWalker() { assert(ClosuresToTypeCheck.empty()); }
8831+
~ExprWalker() {
8832+
assert(ClosuresToTypeCheck.empty());
8833+
8834+
// Type-check any local decls encountered.
8835+
for (auto *D : LocalDeclsToTypeCheck)
8836+
TypeChecker::typeCheckDecl(D);
8837+
}
88318838

88328839
Solution &getSolution() const override { return Rewriter.solution; }
88338840
DeclContext *&getCurrentDC() const override { return Rewriter.dc; }
88348841

8842+
void addLocalDeclToTypeCheck(Decl *D) override {
8843+
LocalDeclsToTypeCheck.push_back(D);
8844+
}
8845+
88358846
bool shouldWalkIntoPropertyWrapperPlaceholderValue() override {
88368847
// Property wrapper placeholder underlying values are filled in
88378848
// with already-type-checked expressions. Don't walk into them.

lib/Sema/CSSyntacticElement.cpp

Lines changed: 22 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,9 +1671,6 @@ class SyntacticElementSolutionApplication
16711671
SyntacticElementContext context;
16721672
SyntacticElementTargetRewriter &rewriter;
16731673

1674-
/// All `func`s declared in the body of the closure.
1675-
SmallVector<FuncDecl *, 4> LocalFuncs;
1676-
16771674
public:
16781675
/// Whether an error was encountered while generating constraints.
16791676
bool hadError = false;
@@ -1729,44 +1726,37 @@ class SyntacticElementSolutionApplication
17291726
return rewritten;
17301727
}
17311728

1729+
bool visitPatternBindingDecl(PatternBindingDecl *PBD) {
1730+
// If this is a placeholder variable with an initializer, we just need to
1731+
// set the inferred type.
1732+
if (isPlaceholderVar(PBD) && PBD->getInit(0)) {
1733+
auto *pattern = PBD->getPattern(0);
1734+
pattern->setType(solution.getResolvedType(PBD->getSingleVar()));
1735+
return false;
1736+
}
1737+
1738+
SyntacticElementTarget target(PBD);
1739+
return !rewriter.rewriteTarget(target).has_value();
1740+
}
1741+
17321742
void visitDecl(Decl *decl) {
17331743
if (isa<IfConfigDecl>(decl))
17341744
return;
17351745

1736-
// Generate constraints for pattern binding declarations.
1737-
if (auto patternBinding = dyn_cast<PatternBindingDecl>(decl)) {
1738-
SyntacticElementTarget target(patternBinding);
1739-
1740-
// If this is a placeholder varaible with an initializer, let's set
1741-
// the inferred type, and ask `typeCheckDecl` to type-check initializer.
1742-
if (isPlaceholderVar(patternBinding) && patternBinding->getInit(0)) {
1743-
auto *pattern = patternBinding->getPattern(0);
1744-
pattern->setType(
1745-
solution.getResolvedType(patternBinding->getSingleVar()));
1746-
1747-
TypeChecker::typeCheckDecl(decl);
1748-
return;
1749-
}
1750-
1751-
if (!rewriter.rewriteTarget(target)) {
1746+
if (auto *PBD = dyn_cast<PatternBindingDecl>(decl)) {
1747+
if (visitPatternBindingDecl(PBD)) {
17521748
hadError = true;
17531749
return;
17541750
}
1755-
1756-
// Allow `typeCheckDecl` to be called after solution is applied
1757-
// to a pattern binding. That would materialize required
1751+
// Fall through to allow `typeCheckDecl` to be called after solution is
1752+
// applied to a pattern binding. That will materialize required
17581753
// information e.g. accessors and do access/availability checks.
17591754
}
17601755

1761-
// Local functions cannot be type-checked in-order because they can
1762-
// capture variables declared after them. Let's save them to be
1763-
// processed after the solution has been applied to the body.
1764-
if (auto *func = dyn_cast<FuncDecl>(decl)) {
1765-
LocalFuncs.push_back(func);
1766-
return;
1767-
}
1768-
1769-
TypeChecker::typeCheckDecl(decl);
1756+
// Delay the type-checking of local decls to ensure that parent closures
1757+
// have solutions applied, which is needed by MiscDiagnostics passes such as
1758+
// `diagnoseImplicitSelfUseInClosure`
1759+
rewriter.addLocalDeclToTypeCheck(decl);
17701760
}
17711761

17721762
ASTNode visitBreakStmt(BreakStmt *breakStmt) {
@@ -1792,7 +1782,7 @@ class SyntacticElementSolutionApplication
17921782
}
17931783

17941784
ASTNode visitDeferStmt(DeferStmt *deferStmt) {
1795-
TypeChecker::typeCheckDecl(deferStmt->getTempDecl());
1785+
rewriter.addLocalDeclToTypeCheck(deferStmt->getTempDecl());
17961786

17971787
Expr *theCall = deferStmt->getCallExpr();
17981788
TypeChecker::typeCheckExpression(theCall, context.getAsDeclContext());
@@ -2234,13 +2224,6 @@ class SyntacticElementSolutionApplication
22342224
/// Apply the solution to the context and return updated statement.
22352225
Stmt *apply() {
22362226
auto body = visit(context.getStmt());
2237-
2238-
// Since local functions can capture variables that are declared
2239-
// after them, let's type-check them after all of the pattern
2240-
// bindings have been resolved by applying solution to the body.
2241-
for (auto *func : LocalFuncs)
2242-
TypeChecker::typeCheckDecl(func);
2243-
22442227
return body ? body.get<Stmt *>() : nullptr;
22452228
}
22462229
};

0 commit comments

Comments
 (0)