Skip to content

Commit 7b012d8

Browse files
authored
Merge pull request #70600 from hamishknight/postal-service
[ASTWalker] Continue post-walking with `Action::SkipChildren`
2 parents 1707e76 + 15fa06d commit 7b012d8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+489
-504
lines changed

include/swift/AST/ASTWalker.h

Lines changed: 72 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -163,23 +163,24 @@ class ASTWalker {
163163

164164
// The 'Action' set of types, which do not take a payload.
165165
struct ContinueWalkAction {};
166-
struct SkipChildrenIfWalkAction { bool Cond; };
166+
struct SkipChildrenIfWalkAction { bool Cond; bool SkipPostWalk; };
167167
struct StopIfWalkAction { bool Cond; };
168168
struct StopWalkAction {};
169169

170170
// The 'Result' set of types, which do take a payload.
171171
template <typename T>
172172
struct ContinueWalkResult {
173+
ContinueWalkAction Action;
173174
T Value;
174175
};
175176
template <typename T>
176177
struct SkipChildrenIfWalkResult {
177-
bool Cond;
178+
SkipChildrenIfWalkAction Action;
178179
T Value;
179180
};
180181
template <typename T>
181182
struct StopIfWalkResult {
182-
bool Cond;
183+
StopIfWalkAction Action;
183184
T Value;
184185
};
185186
};
@@ -212,23 +213,39 @@ class ASTWalker {
212213
/// Continue the current walk, replacing the current node with \p node.
213214
template <typename T>
214215
static _Detail::ContinueWalkResult<T> Continue(T node) {
215-
return {std::move(node)};
216+
return {Continue(), std::move(node)};
216217
}
217218

218219
/// Continue the current walk, replacing the current node with \p node.
219-
/// However, skip visiting the children of \p node, and instead resume the
220-
/// walk of the parent node.
220+
/// However, skip visiting the children of \p node, and resume at its
221+
/// post-walk.
221222
template <typename T>
222223
static _Detail::SkipChildrenIfWalkResult<T> SkipChildren(T node) {
223224
return SkipChildrenIf(true, std::move(node));
224225
}
225226

227+
/// Similar to \c Action::SkipChildren, but also skips the call to the
228+
/// post-visitation method.
229+
template <typename T>
230+
static _Detail::SkipChildrenIfWalkResult<T>
231+
SkipNode(T node) {
232+
return SkipNodeIf(true, std::move(node));
233+
}
234+
226235
/// If \p cond is true, this is equivalent to \c Action::SkipChildren(node).
227236
/// Otherwise, it is equivalent to \c Action::Continue(node).
228237
template <typename T>
229238
static _Detail::SkipChildrenIfWalkResult<T>
230239
SkipChildrenIf(bool cond, T node) {
231-
return {cond, std::move(node)};
240+
return {SkipChildrenIf(cond), std::move(node)};
241+
}
242+
243+
/// If \p cond is true, this is equivalent to \c Action::SkipNode(node).
244+
/// Otherwise, it is equivalent to \c Action::Continue(node).
245+
template <typename T>
246+
static _Detail::SkipChildrenIfWalkResult<T>
247+
SkipNodeIf(bool cond, T node) {
248+
return {SkipNodeIf(cond), std::move(node)};
232249
}
233250

234251
/// If \p cond is true, this is equivalent to \c Action::Continue(node).
@@ -239,26 +256,47 @@ class ASTWalker {
239256
return SkipChildrenIf(!cond, std::move(node));
240257
}
241258

259+
/// If \p cond is true, this is equivalent to \c Action::Continue(node).
260+
/// Otherwise, it is equivalent to \c Action::SkipNode(node).
261+
template <typename T>
262+
static _Detail::SkipChildrenIfWalkResult<T>
263+
VisitNodeIf(bool cond, T node) {
264+
return SkipNodeIf(!cond, std::move(node));
265+
}
266+
242267
/// If \p cond is true, this is equivalent to \c Action::Stop().
243268
/// Otherwise, it is equivalent to \c Action::Continue(node).
244269
template <typename T>
245270
static _Detail::StopIfWalkResult<T> StopIf(bool cond, T node) {
246-
return {cond, std::move(node)};
271+
return {StopIf(cond), std::move(node)};
247272
}
248273

249274
/// Continue the current walk.
250275
static _Detail::ContinueWalkAction Continue() { return {}; }
251276

252277
/// Continue the current walk, but do not visit the children of the current
253-
/// node. Instead, resume at the parent's post-walk.
278+
/// node, resuming at its post-walk.
254279
static _Detail::SkipChildrenIfWalkAction SkipChildren() {
255280
return SkipChildrenIf(true);
256281
}
257282

283+
/// Similar to \c Action::SkipChildren, but also skips the call to the
284+
/// post-visitation method.
285+
static _Detail::SkipChildrenIfWalkAction SkipNode() {
286+
return SkipNodeIf(true);
287+
}
288+
258289
/// If \p cond is true, this is equivalent to \c Action::SkipChildren().
259290
/// Otherwise, it is equivalent to \c Action::Continue().
260291
static _Detail::SkipChildrenIfWalkAction SkipChildrenIf(bool cond) {
261-
return {cond};
292+
return {cond, /*SkipPostWalk*/ false};
293+
}
294+
295+
/// If \p cond is true, this is equivalent to \c Action::SkipNode().
296+
/// Otherwise, it is equivalent to \c Action::Continue().
297+
static _Detail::SkipChildrenIfWalkAction
298+
SkipNodeIf(bool cond) {
299+
return {cond, /*SkipPostWalk*/ true};
262300
}
263301

264302
/// If \p cond is true, this is equivalent to \c Action::Continue().
@@ -267,6 +305,13 @@ class ASTWalker {
267305
return SkipChildrenIf(!cond);
268306
}
269307

308+
/// If \p cond is true, this is equivalent to \c Action::Continue().
309+
/// Otherwise, it is equivalent to \c Action::SkipNode().
310+
static _Detail::SkipChildrenIfWalkAction
311+
VisitNodeIf(bool cond) {
312+
return SkipNodeIf(!cond);
313+
}
314+
270315
/// Terminate the walk, returning without visiting any other nodes.
271316
static _Detail::StopWalkAction Stop() { return {}; }
272317

@@ -280,16 +325,19 @@ class ASTWalker {
280325
/// A pre-visitation action for AST nodes that do not support being replaced
281326
/// while walking.
282327
struct PreWalkAction {
283-
enum Kind { Stop, SkipChildren, Continue };
328+
enum Kind { Stop, SkipChildren, SkipNode, Continue };
284329
Kind Action;
285330

286-
PreWalkAction(Kind action) : Action(action) {}
287-
288331
PreWalkAction(_Detail::ContinueWalkAction) : Action(Continue) {}
289332
PreWalkAction(_Detail::StopWalkAction) : Action(Stop) {}
290333

291-
PreWalkAction(_Detail::SkipChildrenIfWalkAction action)
292-
: Action(action.Cond ? SkipChildren : Continue) {}
334+
PreWalkAction(_Detail::SkipChildrenIfWalkAction action) {
335+
if (action.Cond) {
336+
Action = action.SkipPostWalk ? SkipNode : SkipChildren;
337+
} else {
338+
Action = Continue;
339+
}
340+
}
293341

294342
PreWalkAction(_Detail::StopIfWalkAction action)
295343
: Action(action.Cond ? Stop : Continue) {}
@@ -303,8 +351,6 @@ class ASTWalker {
303351
enum Kind { Stop, Continue };
304352
Kind Action;
305353

306-
PostWalkAction(Kind action) : Action(action) {}
307-
308354
PostWalkAction(_Detail::ContinueWalkAction) : Action(Continue) {}
309355
PostWalkAction(_Detail::StopWalkAction) : Action(Stop) {}
310356

@@ -340,21 +386,18 @@ class ASTWalker {
340386

341387
template <typename U>
342388
PreWalkResult(_Detail::ContinueWalkResult<U> Result)
343-
: Action(PreWalkAction::Continue), Value(std::move(Result.Value)) {}
389+
: Action(Result.Action), Value(std::move(Result.Value)) {}
344390

345391
template <typename U>
346392
PreWalkResult(_Detail::SkipChildrenIfWalkResult<U> Result)
347-
: Action(Result.Cond ? PreWalkAction::SkipChildren
348-
: PreWalkAction::Continue),
349-
Value(std::move(Result.Value)) {}
393+
: Action(Result.Action), Value(std::move(Result.Value)) {}
350394

351395
template <typename U>
352396
PreWalkResult(_Detail::StopIfWalkResult<U> Result)
353-
: Action(Result.Cond ? PreWalkAction::Stop : PreWalkAction::Continue),
354-
Value(std::move(Result.Value)) {}
397+
: Action(Result.Action), Value(std::move(Result.Value)) {}
355398

356-
PreWalkResult(_Detail::StopWalkAction)
357-
: Action(PreWalkAction::Stop), Value(llvm::None) {}
399+
PreWalkResult(_Detail::StopWalkAction Action)
400+
: Action(Action), Value(llvm::None) {}
358401
};
359402

360403
/// Do not construct directly, use \c Action::<action> instead.
@@ -385,15 +428,14 @@ class ASTWalker {
385428

386429
template <typename U>
387430
PostWalkResult(_Detail::ContinueWalkResult<U> Result)
388-
: Action(PostWalkAction::Continue), Value(std::move(Result.Value)) {}
431+
: Action(Result.Action), Value(std::move(Result.Value)) {}
389432

390433
template <typename U>
391434
PostWalkResult(_Detail::StopIfWalkResult<U> Result)
392-
: Action(Result.Cond ? PostWalkAction::Stop : PostWalkAction::Continue),
393-
Value(std::move(Result.Value)) {}
435+
: Action(Result.Action), Value(std::move(Result.Value)) {}
394436

395-
PostWalkResult(_Detail::StopWalkAction)
396-
: Action(PostWalkAction::Stop), Value(llvm::None) {}
437+
PostWalkResult(_Detail::StopWalkAction Action)
438+
: Action(Action), Value(llvm::None) {}
397439
};
398440

399441
/// This method is called when first visiting an expression

include/swift/AST/TypeWalker.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class TypeWalker {
2222
public:
2323
enum class Action {
2424
Continue,
25-
SkipChildren,
25+
SkipNode,
2626
Stop
2727
};
2828

include/swift/Sema/ConstraintSystem.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2685,12 +2685,12 @@ class ConstraintSystem {
26852685

26862686
/// Ignore statements.
26872687
PreWalkResult<Stmt *> walkToStmtPre(Stmt *stmt) override {
2688-
return Action::SkipChildren(stmt);
2688+
return Action::SkipNode(stmt);
26892689
}
26902690

26912691
/// Ignore declarations.
26922692
PreWalkAction walkToDeclPre(Decl *decl) override {
2693-
return Action::SkipChildren();
2693+
return Action::SkipNode();
26942694
}
26952695
};
26962696

@@ -6389,7 +6389,7 @@ class TypeVarRefCollector : public ASTWalker {
63896389
PreWalkAction walkToDeclPre(Decl *D) override {
63906390
// We only need to walk into PatternBindingDecls, other kinds of decls
63916391
// cannot reference outer vars.
6392-
return Action::VisitChildrenIf(isa<PatternBindingDecl>(D));
6392+
return Action::VisitNodeIf(isa<PatternBindingDecl>(D));
63936393
}
63946394

63956395
ArrayRef<TypeVariableType *> getTypeVars() const {

lib/APIDigester/ModuleAnalyzerNodes.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2445,10 +2445,10 @@ class ConstExtractor: public ASTWalker {
24452445
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
24462446
if (E->isSemanticallyConstExpr()) {
24472447
record(E, E);
2448-
return Action::SkipChildren(E);
2448+
return Action::SkipNode(E);
24492449
}
24502450
if (handleSimpleReference(E)) {
2451-
return Action::SkipChildren(E);
2451+
return Action::SkipNode(E);
24522452
}
24532453
return Action::Continue(E);
24542454
}

lib/AST/ASTScopeCreation.cpp

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -115,47 +115,45 @@ class ScopeCreator final : public ASTAllocated<ScopeCreator> {
115115
scopeCreator
116116
.constructExpandAndInsert<ClosureParametersScope>(
117117
parent, closure);
118-
return Action::SkipChildren(E);
118+
return Action::SkipNode(E);
119119
}
120120
if (auto *capture = dyn_cast<CaptureListExpr>(E)) {
121121
scopeCreator
122122
.constructExpandAndInsert<CaptureListScope>(
123123
parent, capture);
124-
return Action::SkipChildren(E);
124+
return Action::SkipNode(E);
125125
}
126126

127127
// If we have a single value statement expression, we need to add any
128128
// scopes in the underlying statement.
129129
if (auto *SVE = dyn_cast<SingleValueStmtExpr>(E)) {
130130
scopeCreator.addToScopeTree(SVE->getStmt(), parent);
131-
return Action::SkipChildren(E);
131+
return Action::SkipNode(E);
132132
}
133133

134134
// If we have a try/try!/try?, we need to add a scope for it
135135
if (auto anyTry = dyn_cast<AnyTryExpr>(E)) {
136136
scopeCreator.constructExpandAndInsert<TryScope>(parent, anyTry);
137-
return Action::SkipChildren(E);
137+
return Action::SkipNode(E);
138138
}
139139

140140
return Action::Continue(E);
141141
}
142142
PreWalkResult<Stmt *> walkToStmtPre(Stmt *S) override {
143-
if (isa<BraceStmt>(S)) { // closures hidden in here
144-
return Action::Continue(S);
145-
}
146-
return Action::SkipChildren(S);
143+
// Closures can occur in BraceStmts.
144+
return Action::VisitNodeIf(isa<BraceStmt>(S), S);
147145
}
148146
PreWalkResult<Pattern *> walkToPatternPre(Pattern *P) override {
149-
return Action::SkipChildren(P);
147+
return Action::SkipNode(P);
150148
}
151149
PreWalkAction walkToDeclPre(Decl *D) override {
152-
return Action::SkipChildren();
150+
return Action::SkipNode();
153151
}
154152
PreWalkAction walkToTypeReprPre(TypeRepr *T) override {
155-
return Action::SkipChildren();
153+
return Action::SkipNode();
156154
}
157155
PreWalkAction walkToParameterListPre(ParameterList *PL) override {
158-
return Action::SkipChildren();
156+
return Action::SkipNode();
159157
}
160158

161159
MacroWalking getMacroWalkingBehavior() const override {

lib/AST/ASTVerifier.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ ASTWalker::PreWalkResult<Expr *> dispatchVisitPreExprHelper(
125125
return ASTWalker::Action::Continue(node);
126126
}
127127
V.cleanup(node);
128-
return ASTWalker::Action::SkipChildren(node);
128+
return ASTWalker::Action::SkipNode(node);
129129
}
130130

131131
template <typename Verifier, typename Kind>
@@ -141,7 +141,7 @@ ASTWalker::PreWalkResult<Expr *> dispatchVisitPreExprHelper(
141141
return ASTWalker::Action::Continue(node);
142142
}
143143
V.cleanup(node);
144-
return ASTWalker::Action::SkipChildren(node);
144+
return ASTWalker::Action::SkipNode(node);
145145
}
146146

147147
template <typename Verifier, typename Kind>
@@ -157,7 +157,7 @@ ASTWalker::PreWalkResult<Expr *> dispatchVisitPreExprHelper(
157157
return ASTWalker::Action::Continue(node);
158158
}
159159
V.cleanup(node);
160-
return ASTWalker::Action::SkipChildren(node);
160+
return ASTWalker::Action::SkipNode(node);
161161
}
162162

163163
template <typename Verifier, typename Kind>
@@ -170,7 +170,7 @@ ASTWalker::PreWalkResult<Expr *> dispatchVisitPreExprHelper(
170170
return ASTWalker::Action::Continue(node);
171171
}
172172
V.cleanup(node);
173-
return ASTWalker::Action::SkipChildren(node);
173+
return ASTWalker::Action::SkipNode(node);
174174
}
175175

176176
namespace {
@@ -401,7 +401,7 @@ class Verifier : public ASTWalker {
401401
if (shouldVerify(node))
402402
return Action::Continue();
403403
cleanup(node);
404-
return Action::SkipChildren();
404+
return Action::SkipNode();
405405
}
406406

407407
/// Helper template for dispatching pre-visitation.
@@ -419,7 +419,7 @@ class Verifier : public ASTWalker {
419419
if (shouldVerify(node))
420420
return Action::Continue(node);
421421
cleanup(node);
422-
return Action::SkipChildren(node);
422+
return Action::SkipNode(node);
423423
}
424424

425425
/// Helper template for dispatching pre-visitation.
@@ -430,7 +430,7 @@ class Verifier : public ASTWalker {
430430
if (shouldVerify(node))
431431
return Action::Continue(node);
432432
cleanup(node);
433-
return Action::SkipChildren(node);
433+
return Action::SkipNode(node);
434434
}
435435

436436
/// Helper template for dispatching post-visitation.

0 commit comments

Comments
 (0)