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