@@ -61,61 +61,57 @@ using namespace swift;
61
61
#define DEBUG_TYPE " TypeCheckStmt"
62
62
63
63
namespace {
64
- // / After forming autoclosures, we must re-parent any closure expressions
65
- // / nested inside the autoclosure, because the autoclosure introduces a new
66
- // / DeclContext.
67
- class ContextualizeClosuresAndMacros : public ASTWalker {
64
+ // / After forming autoclosures and lazy initializer getters, we must update
65
+ // / the DeclContexts for any AST nodes that store the DeclContext they're
66
+ // / within. This includes e.g closures and decls, as well as some other
67
+ // / expressions, statements, and patterns.
68
+ class ContextualizationWalker : public ASTWalker {
68
69
DeclContext *ParentDC;
70
+ bool ForLazyInit;
71
+
72
+ ContextualizationWalker (DeclContext *parent, bool lazyInit)
73
+ : ParentDC(parent), ForLazyInit(lazyInit) {}
74
+
69
75
public:
70
- ContextualizeClosuresAndMacros (DeclContext *parent) : ParentDC(parent) {}
76
+ static void contextualize (ASTNode node, DeclContext *DC) {
77
+ node.walk (ContextualizationWalker (DC, /* forLazyInit*/ false ));
78
+ }
79
+
80
+ static void contextualizeLazyInit (Expr *E, DeclContext *DC) {
81
+ E->walk (ContextualizationWalker (DC, /* forLazyInit*/ true ));
82
+ }
71
83
72
84
MacroWalking getMacroWalkingBehavior () const override {
73
85
return MacroWalking::ArgumentsAndExpansion;
74
86
}
75
87
88
+ LazyInitializerWalking getLazyInitializerWalkingBehavior () override {
89
+ // Don't walk lazy initializers, we walk the getter body specially when
90
+ // synthesizing.
91
+ return LazyInitializerWalking::None;
92
+ }
93
+
76
94
PreWalkResult<Expr *> walkToExprPre (Expr *E) override {
77
- if (auto CE = dyn_cast<AutoClosureExpr >(E)) {
95
+ if (auto * CE = dyn_cast<AbstractClosureExpr >(E)) {
78
96
CE->setParent (ParentDC);
79
-
80
- // Recurse into the autoclosure body with the new ParentDC.
81
- auto oldParentDC = ParentDC;
82
- ParentDC = CE;
83
- CE->getBody ()->walk (*this );
84
- ParentDC = oldParentDC;
85
-
86
- TypeChecker::computeCaptures (CE);
87
- return Action::SkipNode (E);
88
- }
89
-
90
- if (auto CapE = dyn_cast<CaptureListExpr>(E)) {
91
- // Capture lists need to be reparented to enclosing autoclosures
92
- // and/or initializers of property wrapper backing properties
93
- // (because they subsume initializers associated with wrapped
94
- // properties).
95
- if (isa<AutoClosureExpr>(ParentDC) ||
96
- isPropertyWrapperBackingPropertyInitContext (ParentDC)) {
97
- for (auto &Cap : CapE->getCaptureList ()) {
98
- Cap.PBD ->setDeclContext (ParentDC);
99
- Cap.getVar ()->setDeclContext (ParentDC);
100
- }
97
+ // If we're contextualizing a lazy init, we don't need to walk into any
98
+ // child DeclContexts, they'll already be correctly parented. We don't
99
+ // need to compute captures either, that'll have been done already.
100
+ if (!ForLazyInit) {
101
+ contextualize (CE->getBody (), CE);
102
+ TypeChecker::computeCaptures (CE);
101
103
}
102
- }
103
-
104
- if (auto CE = dyn_cast<ClosureExpr>(E)) {
105
- CE->setParent (ParentDC);
106
- CE->getBody ()->walk (ContextualizeClosuresAndMacros (CE));
107
-
108
- TypeChecker::computeCaptures (CE);
109
104
return Action::SkipNode (E);
110
105
}
111
106
112
107
// Caller-side default arguments need their @autoclosures checked.
113
- if (auto *DAE = dyn_cast<DefaultArgumentExpr>(E))
108
+ if (auto *DAE = dyn_cast<DefaultArgumentExpr>(E)) {
114
109
if (DAE->isCallerSide () &&
115
110
(DAE->getParamDecl ()->isAutoClosure () ||
116
111
(DAE->getParamDecl ()->getDefaultArgumentKind () ==
117
112
DefaultArgumentKind::ExpressionMacro)))
118
113
DAE->getCallerSideDefaultExpr ()->walk (*this );
114
+ }
119
115
120
116
// Macro expansion expressions require a DeclContext as well.
121
117
if (auto macroExpansion = dyn_cast<MacroExpansionExpr>(E)) {
@@ -125,26 +121,59 @@ namespace {
125
121
return Action::Continue (E);
126
122
}
127
123
128
- // / We don't want to recurse into most local declarations.
129
- PreWalkAction walkToDeclPre (Decl *D) override {
130
- // But we do want to walk into the initializers of local
131
- // variables.
132
- return Action::VisitNodeIf (isa<PatternBindingDecl>(D));
124
+ PreWalkResult<Pattern *> walkToPatternPre (Pattern *P) override {
125
+ // A couple of patterns store DeclContexts.
126
+ if (auto *EP = dyn_cast<ExprPattern>(P))
127
+ EP->setDeclContext (ParentDC);
128
+ if (auto *EP = dyn_cast<EnumElementPattern>(P))
129
+ EP->setDeclContext (ParentDC);
130
+
131
+ return Action::Continue (P);
133
132
}
134
133
135
- private:
136
- static bool isPropertyWrapperBackingPropertyInitContext (DeclContext *DC) {
137
- auto *init = dyn_cast<PatternBindingInitializer>(DC);
138
- if (!init)
139
- return false ;
134
+ PreWalkResult<Stmt *> walkToStmtPre (Stmt *S) override {
135
+ // The ASTWalker doesn't walk the case body variables, contextualize them
136
+ // ourselves.
137
+ if (auto *CS = dyn_cast<CaseStmt>(S)) {
138
+ for (auto *CaseVar : CS->getCaseBodyVariablesOrEmptyArray ())
139
+ CaseVar->setDeclContext (ParentDC);
140
+ }
141
+ // A few statements store DeclContexts, update them.
142
+ if (auto *BS = dyn_cast<BreakStmt>(S))
143
+ BS->setDeclContext (ParentDC);
144
+ if (auto *CS = dyn_cast<ContinueStmt>(S))
145
+ CS->setDeclContext (ParentDC);
146
+ if (auto *FS = dyn_cast<FallthroughStmt>(S))
147
+ FS->setDeclContext (ParentDC);
148
+
149
+ return Action::Continue (S);
150
+ }
140
151
141
- if (auto *PB = init->getBinding ()) {
142
- auto *var = PB->getSingleVar ();
143
- return var && var->getOriginalWrappedProperty (
144
- PropertyWrapperSynthesizedPropertyKind::Backing);
152
+ PreWalkAction walkToDeclPre (Decl *D) override {
153
+ // We may encounter some decls parented outside of a local context, e.g
154
+ // VarDecls in TopLevelCodeDecls are parented to the file. In such cases,
155
+ // assume the DeclContext they already have is correct, autoclosures
156
+ // and lazy var inits cannot be defined in such contexts anyway.
157
+ if (!D->getDeclContext ()->isLocalContext ())
158
+ return Action::SkipNode ();
159
+
160
+ D->setDeclContext (ParentDC);
161
+
162
+ // Auxiliary decls need to have their contexts adjusted too.
163
+ if (auto *VD = dyn_cast<VarDecl>(D)) {
164
+ VD->visitAuxiliaryDecls ([&](VarDecl *D) {
165
+ D->setDeclContext (ParentDC);
166
+ });
145
167
}
146
168
147
- return false ;
169
+ // We don't currently support peer macro declarations in local contexts,
170
+ // however we don't reject them either; so just to be safe, adjust their
171
+ // context too.
172
+ D->visitAuxiliaryDecls ([&](Decl *D) {
173
+ D->setDeclContext (ParentDC);
174
+ });
175
+
176
+ return Action::VisitNodeIf (isa<PatternBindingDecl>(D));
148
177
}
149
178
};
150
179
@@ -197,20 +226,21 @@ namespace {
197
226
} // end anonymous namespace
198
227
199
228
void TypeChecker::contextualizeInitializer (Initializer *DC, Expr *E) {
200
- ContextualizeClosuresAndMacros CC (DC);
201
- E->walk (CC);
229
+ ContextualizationWalker::contextualize (E, DC);
202
230
}
203
231
204
232
void TypeChecker::contextualizeCallSideDefaultArgument (DeclContext *DC,
205
233
Expr *E) {
206
- ContextualizeClosuresAndMacros CC (DC);
207
- E->walk (CC);
234
+ ContextualizationWalker::contextualize (E, DC);
208
235
}
209
236
210
237
void TypeChecker::contextualizeTopLevelCode (TopLevelCodeDecl *TLCD) {
211
- ContextualizeClosuresAndMacros CC (TLCD);
212
238
if (auto *body = TLCD->getBody ())
213
- body->walk (CC);
239
+ ContextualizationWalker::contextualize (body, TLCD);
240
+ }
241
+
242
+ void TypeChecker::contextualizeLazyInit (Expr *E, DeclContext *DC) {
243
+ ContextualizationWalker::contextualizeLazyInit (E, DC);
214
244
}
215
245
216
246
namespace {
@@ -1033,7 +1063,7 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
1033
1063
// / Type-check an entire function body.
1034
1064
bool typeCheckBody (BraceStmt *&S) {
1035
1065
bool HadError = typeCheckStmt (S);
1036
- S-> walk ( ContextualizeClosuresAndMacros (DC) );
1066
+ ContextualizationWalker::contextualize (S, DC );
1037
1067
return HadError;
1038
1068
}
1039
1069
@@ -2915,7 +2945,7 @@ TypeCheckFunctionBodyRequest::evaluate(Evaluator &eval,
2915
2945
body = *optBody;
2916
2946
alreadyTypeChecked = true ;
2917
2947
2918
- body-> walk ( ContextualizeClosuresAndMacros ( AFD) );
2948
+ ContextualizationWalker::contextualize (body, AFD);
2919
2949
}
2920
2950
}
2921
2951
}
0 commit comments