blob: 8c8645d04d3cc4d5b1421877db76ed031b7f53b9 [file] [log] [blame]
David Tolnay55337722016-09-11 12:58:56 -07001// Adapted from libsyntax.
2
3//! AST walker. Each overridden visit method has full control over what
4//! happens with its node, it can do its own traversal of the node's children,
5//! call `visit::walk_*` to apply the default traversal algorithm, or prevent
6//! deeper traversal by doing nothing.
7//!
8//! Note: it is an important invariant that the default visitor walks the body
9//! of a function in "execution order" (more concretely, reverse post-order
10//! with respect to the CFG implied by the AST), meaning that if AST node A may
11//! execute before AST node B, then A is visited first. The borrow checker in
12//! particular relies on this property.
13//!
14//! Note: walking an AST before macro expansion is probably a bad idea. For
15//! instance, a walker looking for item names in a module will miss all of
16//! those that are created by the expansion of a macro.
17
18use super::*;
19
20/// Each method of the Visitor trait is a hook to be potentially
21/// overridden. Each method's default implementation recursively visits
22/// the substructure of the input via the corresponding `walk` method;
23/// e.g. the `visit_mod` method by default calls `visit::walk_mod`.
24///
25/// If you want to ensure that your code handles every variant
26/// explicitly, you need to override each method. (And you also need
27/// to monitor future changes to `Visitor` in case a new method with a
28/// new default implementation gets introduced.)
29pub trait Visitor: Sized {
30 fn visit_ident(&mut self, _ident: &Ident) {}
David Tolnay0e837402016-12-22 17:25:55 -050031 fn visit_derive_input(&mut self, derive_input: &DeriveInput) {
32 walk_derive_input(self, derive_input)
David Tolnay55337722016-09-11 12:58:56 -070033 }
34 fn visit_ty(&mut self, ty: &Ty) {
35 walk_ty(self, ty)
36 }
37 fn visit_generics(&mut self, generics: &Generics) {
38 walk_generics(self, generics)
39 }
40 fn visit_ty_param_bound(&mut self, bound: &TyParamBound) {
41 walk_ty_param_bound(self, bound)
42 }
43 fn visit_poly_trait_ref(&mut self, trait_ref: &PolyTraitRef, modifier: &TraitBoundModifier) {
44 walk_poly_trait_ref(self, trait_ref, modifier)
45 }
46 fn visit_variant_data(&mut self, data: &VariantData, _ident: &Ident, _generics: &Generics) {
47 walk_variant_data(self, data)
48 }
49 fn visit_field(&mut self, field: &Field) {
50 walk_field(self, field)
51 }
52 fn visit_variant(&mut self, variant: &Variant, generics: &Generics) {
53 walk_variant(self, variant, generics)
54 }
55 fn visit_lifetime(&mut self, _lifetime: &Lifetime) {}
56 fn visit_lifetime_def(&mut self, lifetime: &LifetimeDef) {
57 walk_lifetime_def(self, lifetime)
58 }
59 fn visit_path(&mut self, path: &Path) {
60 walk_path(self, path)
61 }
62 fn visit_path_segment(&mut self, path_segment: &PathSegment) {
63 walk_path_segment(self, path_segment)
64 }
65 fn visit_path_parameters(&mut self, path_parameters: &PathParameters) {
66 walk_path_parameters(self, path_parameters)
67 }
68 fn visit_assoc_type_binding(&mut self, type_binding: &TypeBinding) {
69 walk_assoc_type_binding(self, type_binding)
70 }
71 fn visit_attribute(&mut self, _attr: &Attribute) {}
72 fn visit_fn_ret_ty(&mut self, ret_ty: &FunctionRetTy) {
73 walk_fn_ret_ty(self, ret_ty)
74 }
David Tolnay68eb4c32016-10-07 23:30:32 -070075 fn visit_const_expr(&mut self, expr: &ConstExpr) {
76 walk_const_expr(self, expr)
David Tolnay429168f2016-10-05 23:41:04 -070077 }
David Tolnay68eb4c32016-10-07 23:30:32 -070078 fn visit_lit(&mut self, _lit: &Lit) {}
Michael Layzellb52df322017-01-22 17:36:55 -050079
Michael Layzellb52df322017-01-22 17:36:55 -050080 fn visit_mac(&mut self, mac: &Mac) {
81 walk_mac(self, mac);
82 }
83
84 #[cfg(feature = "full")]
85 fn visit_crate(&mut self, _crate: &Crate) {
86 walk_crate(self, _crate);
87 }
88 #[cfg(feature = "full")]
89 fn visit_item(&mut self, item: &Item) {
90 walk_item(self, item);
91 }
92 #[cfg(feature = "full")]
93 fn visit_expr(&mut self, expr: &Expr) {
94 walk_expr(self, expr);
95 }
96 #[cfg(feature = "full")]
97 fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
98 walk_foreign_item(self, foreign_item);
99 }
100 #[cfg(feature = "full")]
101 fn visit_pat(&mut self, pat: &Pat) {
102 walk_pat(self, pat);
103 }
104 #[cfg(feature = "full")]
105 fn visit_fn_decl(&mut self, fn_decl: &FnDecl) {
106 walk_fn_decl(self, fn_decl);
107 }
108 #[cfg(feature = "full")]
109 fn visit_trait_item(&mut self, trait_item: &TraitItem) {
110 walk_trait_item(self, trait_item);
111 }
112 #[cfg(feature = "full")]
113 fn visit_impl_item(&mut self, impl_item: &ImplItem) {
114 walk_impl_item(self, impl_item);
115 }
116 #[cfg(feature = "full")]
117 fn visit_method_sig(&mut self, method_sig: &MethodSig) {
118 walk_method_sig(self, method_sig);
119 }
120 #[cfg(feature = "full")]
121 fn visit_stmt(&mut self, stmt: &Stmt) {
122 walk_stmt(self, stmt);
123 }
124 #[cfg(feature = "full")]
125 fn visit_local(&mut self, local: &Local) {
126 walk_local(self, local);
127 }
128 #[cfg(feature = "full")]
129 fn visit_view_path(&mut self, view_path: &ViewPath) {
130 walk_view_path(self, view_path);
131 }
David Tolnay55337722016-09-11 12:58:56 -0700132}
133
David Tolnay55337722016-09-11 12:58:56 -0700134macro_rules! walk_list {
David Tolnaybdae3642017-01-23 00:39:55 -0800135 ($visitor:expr, $method:ident, $list:expr $(, $extra_args:expr)*) => {
David Tolnay55337722016-09-11 12:58:56 -0700136 for elem in $list {
David Tolnaybdae3642017-01-23 00:39:55 -0800137 $visitor.$method(elem $(, $extra_args)*)
David Tolnay55337722016-09-11 12:58:56 -0700138 }
139 };
David Tolnay55337722016-09-11 12:58:56 -0700140}
141
142pub fn walk_opt_ident<V: Visitor>(visitor: &mut V, opt_ident: &Option<Ident>) {
143 if let Some(ref ident) = *opt_ident {
144 visitor.visit_ident(ident);
145 }
146}
147
148pub fn walk_lifetime_def<V: Visitor>(visitor: &mut V, lifetime_def: &LifetimeDef) {
149 visitor.visit_lifetime(&lifetime_def.lifetime);
150 walk_list!(visitor, visit_lifetime, &lifetime_def.bounds);
151}
152
153pub fn walk_poly_trait_ref<V>(visitor: &mut V, trait_ref: &PolyTraitRef, _: &TraitBoundModifier)
David Tolnaydaaf7742016-10-03 11:11:43 -0700154 where V: Visitor
David Tolnay55337722016-09-11 12:58:56 -0700155{
156 walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes);
157 visitor.visit_path(&trait_ref.trait_ref);
158}
159
David Tolnay0e837402016-12-22 17:25:55 -0500160pub fn walk_derive_input<V: Visitor>(visitor: &mut V, derive_input: &DeriveInput) {
161 visitor.visit_ident(&derive_input.ident);
162 visitor.visit_generics(&derive_input.generics);
163 match derive_input.body {
David Tolnay55337722016-09-11 12:58:56 -0700164 Body::Enum(ref variants) => {
David Tolnay0e837402016-12-22 17:25:55 -0500165 walk_list!(visitor, visit_variant, variants, &derive_input.generics);
David Tolnay55337722016-09-11 12:58:56 -0700166 }
167 Body::Struct(ref variant_data) => {
David Tolnay0e837402016-12-22 17:25:55 -0500168 visitor.visit_variant_data(variant_data, &derive_input.ident, &derive_input.generics);
David Tolnay55337722016-09-11 12:58:56 -0700169 }
170 }
David Tolnay0e837402016-12-22 17:25:55 -0500171 walk_list!(visitor, visit_attribute, &derive_input.attrs);
David Tolnay55337722016-09-11 12:58:56 -0700172}
173
174pub fn walk_variant<V>(visitor: &mut V, variant: &Variant, generics: &Generics)
David Tolnaydaaf7742016-10-03 11:11:43 -0700175 where V: Visitor
David Tolnay55337722016-09-11 12:58:56 -0700176{
177 visitor.visit_ident(&variant.ident);
178 visitor.visit_variant_data(&variant.data, &variant.ident, generics);
179 walk_list!(visitor, visit_attribute, &variant.attrs);
180}
181
182pub fn walk_ty<V: Visitor>(visitor: &mut V, ty: &Ty) {
183 match *ty {
David Tolnay429168f2016-10-05 23:41:04 -0700184 Ty::Slice(ref inner) |
David Tolnaydaaf7742016-10-03 11:11:43 -0700185 Ty::Paren(ref inner) => visitor.visit_ty(inner),
186 Ty::Ptr(ref mutable_type) => visitor.visit_ty(&mutable_type.ty),
David Tolnay55337722016-09-11 12:58:56 -0700187 Ty::Rptr(ref opt_lifetime, ref mutable_type) => {
188 walk_list!(visitor, visit_lifetime, opt_lifetime);
189 visitor.visit_ty(&mutable_type.ty)
190 }
David Tolnay58f6f672016-10-19 08:44:25 -0700191 Ty::Never | Ty::Infer => {}
David Tolnay55337722016-09-11 12:58:56 -0700192 Ty::Tup(ref tuple_element_types) => {
193 walk_list!(visitor, visit_ty, tuple_element_types);
194 }
David Tolnay1391b522016-10-03 21:05:45 -0700195 Ty::BareFn(ref bare_fn) => {
196 walk_list!(visitor, visit_lifetime_def, &bare_fn.lifetimes);
197 for argument in &bare_fn.inputs {
198 walk_opt_ident(visitor, &argument.name);
199 visitor.visit_ty(&argument.ty)
200 }
201 visitor.visit_fn_ret_ty(&bare_fn.output)
David Tolnay55337722016-09-11 12:58:56 -0700202 }
203 Ty::Path(ref maybe_qself, ref path) => {
204 if let Some(ref qself) = *maybe_qself {
205 visitor.visit_ty(&qself.ty);
206 }
207 visitor.visit_path(path);
208 }
David Tolnay429168f2016-10-05 23:41:04 -0700209 Ty::Array(ref inner, ref len) => {
David Tolnay55337722016-09-11 12:58:56 -0700210 visitor.visit_ty(inner);
David Tolnay68eb4c32016-10-07 23:30:32 -0700211 visitor.visit_const_expr(len);
David Tolnay55337722016-09-11 12:58:56 -0700212 }
David Tolnayfa23f572017-01-23 00:19:11 -0800213 Ty::TraitObject(ref bounds) |
David Tolnay55337722016-09-11 12:58:56 -0700214 Ty::ImplTrait(ref bounds) => {
215 walk_list!(visitor, visit_ty_param_bound, bounds);
216 }
Michael Layzellb52df322017-01-22 17:36:55 -0500217 Ty::Mac(ref mac) => {
David Tolnay3f36a0a2017-01-23 17:59:46 -0800218 visitor.visit_mac(mac);
Michael Layzellb52df322017-01-22 17:36:55 -0500219 }
David Tolnay55337722016-09-11 12:58:56 -0700220 }
221}
222
223pub fn walk_path<V: Visitor>(visitor: &mut V, path: &Path) {
224 for segment in &path.segments {
225 visitor.visit_path_segment(segment);
226 }
227}
228
229pub fn walk_path_segment<V: Visitor>(visitor: &mut V, segment: &PathSegment) {
230 visitor.visit_ident(&segment.ident);
231 visitor.visit_path_parameters(&segment.parameters);
232}
233
234pub fn walk_path_parameters<V>(visitor: &mut V, path_parameters: &PathParameters)
David Tolnaydaaf7742016-10-03 11:11:43 -0700235 where V: Visitor
David Tolnay55337722016-09-11 12:58:56 -0700236{
237 match *path_parameters {
238 PathParameters::AngleBracketed(ref data) => {
239 walk_list!(visitor, visit_ty, &data.types);
240 walk_list!(visitor, visit_lifetime, &data.lifetimes);
241 walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
242 }
243 PathParameters::Parenthesized(ref data) => {
244 walk_list!(visitor, visit_ty, &data.inputs);
245 walk_list!(visitor, visit_ty, &data.output);
246 }
247 }
248}
249
250pub fn walk_assoc_type_binding<V: Visitor>(visitor: &mut V, type_binding: &TypeBinding) {
251 visitor.visit_ident(&type_binding.ident);
252 visitor.visit_ty(&type_binding.ty);
253}
254
255pub fn walk_ty_param_bound<V: Visitor>(visitor: &mut V, bound: &TyParamBound) {
256 match *bound {
257 TyParamBound::Trait(ref ty, ref modifier) => {
258 visitor.visit_poly_trait_ref(ty, modifier);
259 }
260 TyParamBound::Region(ref lifetime) => {
261 visitor.visit_lifetime(lifetime);
262 }
263 }
264}
265
266pub fn walk_generics<V: Visitor>(visitor: &mut V, generics: &Generics) {
267 for param in &generics.ty_params {
268 visitor.visit_ident(&param.ident);
269 walk_list!(visitor, visit_ty_param_bound, &param.bounds);
270 walk_list!(visitor, visit_ty, &param.default);
271 }
272 walk_list!(visitor, visit_lifetime_def, &generics.lifetimes);
273 for predicate in &generics.where_clause.predicates {
274 match *predicate {
David Tolnaydaaf7742016-10-03 11:11:43 -0700275 WherePredicate::BoundPredicate(WhereBoundPredicate { ref bounded_ty,
276 ref bounds,
277 ref bound_lifetimes,
278 .. }) => {
David Tolnay55337722016-09-11 12:58:56 -0700279 visitor.visit_ty(bounded_ty);
280 walk_list!(visitor, visit_ty_param_bound, bounds);
281 walk_list!(visitor, visit_lifetime_def, bound_lifetimes);
282 }
David Tolnaydaaf7742016-10-03 11:11:43 -0700283 WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime,
284 ref bounds,
285 .. }) => {
David Tolnay55337722016-09-11 12:58:56 -0700286 visitor.visit_lifetime(lifetime);
287 walk_list!(visitor, visit_lifetime, bounds);
288 }
David Tolnay05120ef2017-03-12 18:29:26 -0700289 WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => {
David Tolnayfa23f572017-01-23 00:19:11 -0800290 visitor.visit_ty(lhs_ty);
291 visitor.visit_ty(rhs_ty);
292 }
David Tolnay55337722016-09-11 12:58:56 -0700293 }
294 }
295}
296
297pub fn walk_fn_ret_ty<V: Visitor>(visitor: &mut V, ret_ty: &FunctionRetTy) {
298 if let FunctionRetTy::Ty(ref output_ty) = *ret_ty {
299 visitor.visit_ty(output_ty)
300 }
301}
302
David Tolnay55337722016-09-11 12:58:56 -0700303pub fn walk_variant_data<V: Visitor>(visitor: &mut V, data: &VariantData) {
304 walk_list!(visitor, visit_field, data.fields());
305}
306
307pub fn walk_field<V: Visitor>(visitor: &mut V, field: &Field) {
308 walk_opt_ident(visitor, &field.ident);
309 visitor.visit_ty(&field.ty);
310 walk_list!(visitor, visit_attribute, &field.attrs);
311}
David Tolnay429168f2016-10-05 23:41:04 -0700312
David Tolnay68eb4c32016-10-07 23:30:32 -0700313pub fn walk_const_expr<V: Visitor>(visitor: &mut V, len: &ConstExpr) {
David Tolnay429168f2016-10-05 23:41:04 -0700314 match *len {
David Tolnay68eb4c32016-10-07 23:30:32 -0700315 ConstExpr::Call(ref function, ref args) => {
David Tolnay58f6f672016-10-19 08:44:25 -0700316 visitor.visit_const_expr(function);
David Tolnay68eb4c32016-10-07 23:30:32 -0700317 walk_list!(visitor, visit_const_expr, args);
318 }
319 ConstExpr::Binary(_op, ref left, ref right) => {
320 visitor.visit_const_expr(left);
321 visitor.visit_const_expr(right);
322 }
323 ConstExpr::Unary(_op, ref v) => {
324 visitor.visit_const_expr(v);
325 }
326 ConstExpr::Lit(ref lit) => {
327 visitor.visit_lit(lit);
328 }
329 ConstExpr::Cast(ref expr, ref ty) => {
330 visitor.visit_const_expr(expr);
331 visitor.visit_ty(ty);
332 }
333 ConstExpr::Path(ref path) => {
David Tolnay429168f2016-10-05 23:41:04 -0700334 visitor.visit_path(path);
335 }
David Tolnay67588752016-10-30 12:23:10 -0700336 ConstExpr::Index(ref expr, ref index) => {
337 visitor.visit_const_expr(expr);
338 visitor.visit_const_expr(index);
339 }
David Tolnaye7b0d322016-10-30 10:27:23 -0700340 ConstExpr::Paren(ref expr) => {
341 visitor.visit_const_expr(expr);
342 }
Michael Layzellb52df322017-01-22 17:36:55 -0500343 ConstExpr::Other(ref other) => {
344 #[cfg(feature = "full")]
345 fn walk_other<V: Visitor>(visitor: &mut V, other: &Expr) {
346 visitor.visit_expr(other);
347 }
348 #[cfg(not(feature = "full"))]
349 fn walk_other<V: Visitor>(_: &mut V, _: &super::constant::Other) {}
350 walk_other(visitor, other);
351 }
352 }
353}
354
Michael Layzellb52df322017-01-22 17:36:55 -0500355pub fn walk_mac<V: Visitor>(visitor: &mut V, mac: &Mac) {
356 visitor.visit_path(&mac.path);
357}
358
359#[cfg(feature = "full")]
360pub fn walk_crate<V: Visitor>(visitor: &mut V, _crate: &Crate) {
361 walk_list!(visitor, visit_attribute, &_crate.attrs);
362 walk_list!(visitor, visit_item, &_crate.items);
363}
364
365#[cfg(feature = "full")]
366pub fn walk_item<V: Visitor>(visitor: &mut V, item: &Item) {
367 visitor.visit_ident(&item.ident);
368 walk_list!(visitor, visit_attribute, &item.attrs);
369 match item.node {
370 ItemKind::ExternCrate(ref ident) => {
371 walk_opt_ident(visitor, ident);
372 }
373 ItemKind::Use(ref view_path) => {
374 visitor.visit_view_path(view_path);
375 }
David Tolnay02a8d472017-02-19 12:59:44 -0800376 ItemKind::Static(ref ty, _, ref expr) |
Michael Layzellb52df322017-01-22 17:36:55 -0500377 ItemKind::Const(ref ty, ref expr) => {
378 visitor.visit_ty(ty);
379 visitor.visit_expr(expr);
380 }
381 ItemKind::Fn(ref decl, _, _, _, ref generics, ref body) => {
382 visitor.visit_fn_decl(decl);
383 visitor.visit_generics(generics);
384 walk_list!(visitor, visit_stmt, &body.stmts);
385 }
386 ItemKind::Mod(ref maybe_items) => {
387 if let Some(ref items) = *maybe_items {
388 walk_list!(visitor, visit_item, items);
389 }
390 }
391 ItemKind::ForeignMod(ref foreign_mod) => {
392 walk_list!(visitor, visit_foreign_item, &foreign_mod.items);
393 }
394 ItemKind::Ty(ref ty, ref generics) => {
395 visitor.visit_ty(ty);
396 visitor.visit_generics(generics);
397 }
398 ItemKind::Enum(ref variant, ref generics) => {
399 walk_list!(visitor, visit_variant, variant, generics);
400 }
David Tolnay02a8d472017-02-19 12:59:44 -0800401 ItemKind::Struct(ref variant_data, ref generics) |
Michael Layzellb52df322017-01-22 17:36:55 -0500402 ItemKind::Union(ref variant_data, ref generics) => {
403 visitor.visit_variant_data(variant_data, &item.ident, generics);
404 }
405 ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => {
406 visitor.visit_generics(generics);
407 walk_list!(visitor, visit_ty_param_bound, bounds);
408 walk_list!(visitor, visit_trait_item, trait_items);
409 }
410 ItemKind::DefaultImpl(_, ref path) => {
411 visitor.visit_path(path);
412 }
413 ItemKind::Impl(_, _, ref generics, ref maybe_path, ref ty, ref impl_items) => {
414 visitor.visit_generics(generics);
415 if let Some(ref path) = *maybe_path {
416 visitor.visit_path(path);
417 }
418 visitor.visit_ty(ty);
419 walk_list!(visitor, visit_impl_item, impl_items);
420 }
David Tolnay05120ef2017-03-12 18:29:26 -0700421 ItemKind::Mac(ref mac) => visitor.visit_mac(mac),
Michael Layzellb52df322017-01-22 17:36:55 -0500422 }
423}
424
425#[cfg(feature = "full")]
David Tolnay02a8d472017-02-19 12:59:44 -0800426#[cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))]
Michael Layzellb52df322017-01-22 17:36:55 -0500427pub fn walk_expr<V: Visitor>(visitor: &mut V, expr: &Expr) {
428 walk_list!(visitor, visit_attribute, &expr.attrs);
429 match expr.node {
Michael Layzellb52df322017-01-22 17:36:55 -0500430 ExprKind::InPlace(ref place, ref value) => {
431 visitor.visit_expr(place);
432 visitor.visit_expr(value);
433 }
Michael Layzellb52df322017-01-22 17:36:55 -0500434 ExprKind::Call(ref callee, ref args) => {
435 visitor.visit_expr(callee);
436 walk_list!(visitor, visit_expr, args);
437 }
438 ExprKind::MethodCall(ref name, ref ty_args, ref args) => {
439 visitor.visit_ident(name);
440 walk_list!(visitor, visit_ty, ty_args);
441 walk_list!(visitor, visit_expr, args);
442 }
David Tolnay02a8d472017-02-19 12:59:44 -0800443 ExprKind::Array(ref exprs) |
Michael Layzellb52df322017-01-22 17:36:55 -0500444 ExprKind::Tup(ref exprs) => {
445 walk_list!(visitor, visit_expr, exprs);
446 }
Michael Layzellb52df322017-01-22 17:36:55 -0500447 ExprKind::Unary(_, ref operand) => {
448 visitor.visit_expr(operand);
449 }
450 ExprKind::Lit(ref lit) => {
451 visitor.visit_lit(lit);
452 }
David Tolnay02a8d472017-02-19 12:59:44 -0800453 ExprKind::Cast(ref expr, ref ty) |
Michael Layzellb52df322017-01-22 17:36:55 -0500454 ExprKind::Type(ref expr, ref ty) => {
455 visitor.visit_expr(expr);
456 visitor.visit_ty(ty);
457 }
458 ExprKind::If(ref cond, ref cons, ref maybe_alt) => {
459 visitor.visit_expr(cond);
460 walk_list!(visitor, visit_stmt, &cons.stmts);
461 if let Some(ref alt) = *maybe_alt {
462 visitor.visit_expr(alt);
463 }
464 }
465 ExprKind::IfLet(ref pat, ref cond, ref cons, ref maybe_alt) => {
466 visitor.visit_pat(pat);
467 visitor.visit_expr(cond);
468 walk_list!(visitor, visit_stmt, &cons.stmts);
469 if let Some(ref alt) = *maybe_alt {
470 visitor.visit_expr(alt);
471 }
472 }
473 ExprKind::While(ref cond, ref body, ref label) => {
474 visitor.visit_expr(cond);
475 walk_list!(visitor, visit_stmt, &body.stmts);
476 walk_opt_ident(visitor, label);
477 }
478 ExprKind::WhileLet(ref pat, ref cond, ref body, ref label) => {
479 visitor.visit_pat(pat);
480 visitor.visit_expr(cond);
481 walk_list!(visitor, visit_stmt, &body.stmts);
482 walk_opt_ident(visitor, label);
483 }
484 ExprKind::ForLoop(ref pat, ref expr, ref body, ref label) => {
485 visitor.visit_pat(pat);
486 visitor.visit_expr(expr);
487 walk_list!(visitor, visit_stmt, &body.stmts);
488 walk_opt_ident(visitor, label);
489 }
490 ExprKind::Loop(ref body, ref label) => {
491 walk_list!(visitor, visit_stmt, &body.stmts);
492 walk_opt_ident(visitor, label);
493 }
494 ExprKind::Match(ref expr, ref arms) => {
495 visitor.visit_expr(expr);
David Tolnay05120ef2017-03-12 18:29:26 -0700496 for &Arm { ref attrs, ref pats, ref guard, ref body } in arms {
Michael Layzellb52df322017-01-22 17:36:55 -0500497 walk_list!(visitor, visit_attribute, attrs);
498 walk_list!(visitor, visit_pat, pats);
499 if let Some(ref guard) = *guard {
500 visitor.visit_expr(guard);
501 }
502 visitor.visit_expr(body);
503 }
504 }
505 ExprKind::Closure(_, ref decl, ref expr) => {
506 visitor.visit_fn_decl(decl);
507 visitor.visit_expr(expr);
508 }
509 ExprKind::Block(_, ref block) => {
510 walk_list!(visitor, visit_stmt, &block.stmts);
511 }
David Tolnay02a8d472017-02-19 12:59:44 -0800512 ExprKind::Binary(_, ref lhs, ref rhs) |
513 ExprKind::Assign(ref lhs, ref rhs) |
Michael Layzellb52df322017-01-22 17:36:55 -0500514 ExprKind::AssignOp(_, ref lhs, ref rhs) => {
515 visitor.visit_expr(lhs);
516 visitor.visit_expr(rhs);
517 }
518 ExprKind::Field(ref obj, ref field) => {
519 visitor.visit_expr(obj);
520 visitor.visit_ident(field);
521 }
522 ExprKind::TupField(ref obj, _) => {
523 visitor.visit_expr(obj);
524 }
525 ExprKind::Index(ref obj, ref idx) => {
526 visitor.visit_expr(obj);
527 visitor.visit_expr(idx);
528 }
529 ExprKind::Range(ref maybe_start, ref maybe_end, _) => {
530 if let Some(ref start) = *maybe_start {
531 visitor.visit_expr(start);
532 }
533 if let Some(ref end) = *maybe_end {
534 visitor.visit_expr(end);
535 }
536 }
537 ExprKind::Path(ref maybe_qself, ref path) => {
538 if let Some(ref qself) = *maybe_qself {
539 visitor.visit_ty(&qself.ty);
540 }
541 visitor.visit_path(path);
542 }
Michael Layzellb52df322017-01-22 17:36:55 -0500543 ExprKind::Break(ref maybe_label, ref maybe_expr) => {
544 walk_opt_ident(visitor, maybe_label);
545 if let Some(ref expr) = *maybe_expr {
546 visitor.visit_expr(expr);
547 }
548 }
549 ExprKind::Continue(ref maybe_label) => {
550 walk_opt_ident(visitor, maybe_label);
551 }
552 ExprKind::Ret(ref maybe_expr) => {
553 if let Some(ref expr) = *maybe_expr {
554 visitor.visit_expr(expr);
555 }
556 }
557 ExprKind::Mac(ref mac) => {
558 visitor.visit_mac(mac);
559 }
560 ExprKind::Struct(ref path, ref fields, ref maybe_base) => {
561 visitor.visit_path(path);
David Tolnay05120ef2017-03-12 18:29:26 -0700562 for &FieldValue { ref ident, ref expr, .. } in fields {
Michael Layzellb52df322017-01-22 17:36:55 -0500563 visitor.visit_ident(ident);
564 visitor.visit_expr(expr);
565 }
566 if let Some(ref base) = *maybe_base {
567 visitor.visit_expr(base);
568 }
569 }
570 ExprKind::Repeat(ref value, ref times) => {
571 visitor.visit_expr(value);
572 visitor.visit_expr(times);
573 }
David Tolnay02a8d472017-02-19 12:59:44 -0800574 ExprKind::Box(ref expr) |
575 ExprKind::AddrOf(_, ref expr) |
576 ExprKind::Paren(ref expr) |
Michael Layzellb52df322017-01-22 17:36:55 -0500577 ExprKind::Try(ref expr) => {
578 visitor.visit_expr(expr);
579 }
580 }
581}
582
583#[cfg(feature = "full")]
584pub fn walk_foreign_item<V: Visitor>(visitor: &mut V, foreign_item: &ForeignItem) {
585 visitor.visit_ident(&foreign_item.ident);
586 walk_list!(visitor, visit_attribute, &foreign_item.attrs);
587 match foreign_item.node {
588 ForeignItemKind::Fn(ref decl, ref generics) => {
589 visitor.visit_fn_decl(decl);
590 visitor.visit_generics(generics);
591 }
592 ForeignItemKind::Static(ref ty, _) => {
593 visitor.visit_ty(ty);
594 }
595 }
596}
597
598#[cfg(feature = "full")]
599pub fn walk_pat<V: Visitor>(visitor: &mut V, pat: &Pat) {
600 match *pat {
601 Pat::Wild => {}
602 Pat::Ident(_, ref ident, ref maybe_pat) => {
603 visitor.visit_ident(ident);
604 if let Some(ref pat) = *maybe_pat {
605 visitor.visit_pat(pat);
606 }
607 }
608 Pat::Struct(ref path, ref field_pats, _) => {
609 visitor.visit_path(path);
David Tolnay05120ef2017-03-12 18:29:26 -0700610 for &FieldPat { ref ident, ref pat, .. } in field_pats {
Michael Layzellb52df322017-01-22 17:36:55 -0500611 visitor.visit_ident(ident);
612 visitor.visit_pat(pat);
613 }
614 }
615 Pat::TupleStruct(ref path, ref pats, _) => {
616 visitor.visit_path(path);
617 walk_list!(visitor, visit_pat, pats);
618 }
619 Pat::Path(ref maybe_qself, ref path) => {
620 if let Some(ref qself) = *maybe_qself {
621 visitor.visit_ty(&qself.ty);
622 }
623 visitor.visit_path(path);
624 }
625 Pat::Tuple(ref pats, _) => {
626 walk_list!(visitor, visit_pat, pats);
627 }
628 Pat::Box(ref pat) |
629 Pat::Ref(ref pat, _) => {
630 visitor.visit_pat(pat);
631 }
632 Pat::Lit(ref expr) => {
633 visitor.visit_expr(expr);
634 }
635 Pat::Range(ref start, ref end) => {
636 visitor.visit_expr(start);
637 visitor.visit_expr(end);
638 }
639 Pat::Slice(ref start, ref maybe_mid, ref end) => {
640 walk_list!(visitor, visit_pat, start);
641 if let Some(ref mid) = *maybe_mid {
642 visitor.visit_pat(mid);
643 }
644 walk_list!(visitor, visit_pat, end);
645 }
646 Pat::Mac(ref mac) => {
647 visitor.visit_mac(mac);
648 }
649 }
650}
651
652#[cfg(feature = "full")]
653pub fn walk_fn_decl<V: Visitor>(visitor: &mut V, fn_decl: &FnDecl) {
654 for input in &fn_decl.inputs {
655 match *input {
David Tolnay05120ef2017-03-12 18:29:26 -0700656 FnArg::SelfRef(_, _) |
657 FnArg::SelfValue(_) => {}
Michael Layzellb52df322017-01-22 17:36:55 -0500658 FnArg::Captured(ref pat, ref ty) => {
659 visitor.visit_pat(pat);
660 visitor.visit_ty(ty);
661 }
662 FnArg::Ignored(ref ty) => {
663 visitor.visit_ty(ty);
664 }
665 }
666 }
667 visitor.visit_fn_ret_ty(&fn_decl.output);
668}
669
670#[cfg(feature = "full")]
671pub fn walk_trait_item<V: Visitor>(visitor: &mut V, trait_item: &TraitItem) {
672 visitor.visit_ident(&trait_item.ident);
673 walk_list!(visitor, visit_attribute, &trait_item.attrs);
674 match trait_item.node {
675 TraitItemKind::Const(ref ty, ref maybe_expr) => {
676 visitor.visit_ty(ty);
677 if let Some(ref expr) = *maybe_expr {
678 visitor.visit_expr(expr);
679 }
680 }
681 TraitItemKind::Method(ref method_sig, ref maybe_block) => {
682 visitor.visit_method_sig(method_sig);
683 if let Some(ref block) = *maybe_block {
684 walk_list!(visitor, visit_stmt, &block.stmts);
685 }
686 }
687 TraitItemKind::Type(ref bounds, ref maybe_ty) => {
688 walk_list!(visitor, visit_ty_param_bound, bounds);
689 if let Some(ref ty) = *maybe_ty {
690 visitor.visit_ty(ty);
691 }
692 }
693 TraitItemKind::Macro(ref mac) => {
694 visitor.visit_mac(mac);
695 }
696 }
697}
698
699#[cfg(feature = "full")]
700pub fn walk_impl_item<V: Visitor>(visitor: &mut V, impl_item: &ImplItem) {
701 visitor.visit_ident(&impl_item.ident);
702 walk_list!(visitor, visit_attribute, &impl_item.attrs);
703 match impl_item.node {
704 ImplItemKind::Const(ref ty, ref expr) => {
705 visitor.visit_ty(ty);
706 visitor.visit_expr(expr);
707 }
708 ImplItemKind::Method(ref method_sig, ref block) => {
709 visitor.visit_method_sig(method_sig);
710 walk_list!(visitor, visit_stmt, &block.stmts);
711 }
712 ImplItemKind::Type(ref ty) => {
713 visitor.visit_ty(ty);
714 }
715 ImplItemKind::Macro(ref mac) => {
716 visitor.visit_mac(mac);
717 }
718 }
719}
720
721#[cfg(feature = "full")]
722pub fn walk_method_sig<V: Visitor>(visitor: &mut V, method_sig: &MethodSig) {
723 visitor.visit_fn_decl(&method_sig.decl);
724 visitor.visit_generics(&method_sig.generics);
725}
726
727#[cfg(feature = "full")]
728pub fn walk_stmt<V: Visitor>(visitor: &mut V, stmt: &Stmt) {
729 match *stmt {
730 Stmt::Local(ref local) => {
731 visitor.visit_local(local);
732 }
733 Stmt::Item(ref item) => {
734 visitor.visit_item(item);
735 }
736 Stmt::Expr(ref expr) |
737 Stmt::Semi(ref expr) => {
738 visitor.visit_expr(expr);
739 }
740 Stmt::Mac(ref details) => {
741 let (ref mac, _, ref attrs) = **details;
742 visitor.visit_mac(mac);
743 walk_list!(visitor, visit_attribute, attrs);
744 }
745 }
746}
747
748#[cfg(feature = "full")]
749pub fn walk_local<V: Visitor>(visitor: &mut V, local: &Local) {
750 visitor.visit_pat(&local.pat);
751 if let Some(ref ty) = local.ty {
752 visitor.visit_ty(ty);
753 }
754 if let Some(ref init) = local.init {
755 visitor.visit_expr(init);
756 }
757 walk_list!(visitor, visit_attribute, &local.attrs);
758}
759
760#[cfg(feature = "full")]
761pub fn walk_view_path<V: Visitor>(visitor: &mut V, view_path: &ViewPath) {
762 match *view_path {
763 ViewPath::Simple(ref path, ref maybe_ident) => {
764 visitor.visit_path(path);
765 walk_opt_ident(visitor, maybe_ident);
766 }
767 ViewPath::Glob(ref path) => {
768 visitor.visit_path(path);
769 }
770 ViewPath::List(ref path, ref items) => {
771 visitor.visit_path(path);
David Tolnay05120ef2017-03-12 18:29:26 -0700772 for &PathListItem { ref name, ref rename } in items {
Michael Layzellb52df322017-01-22 17:36:55 -0500773 visitor.visit_ident(name);
774 walk_opt_ident(visitor, rename);
775 }
776 }
David Tolnay429168f2016-10-05 23:41:04 -0700777 }
778}