blob: 82a8486fc6304bfa837b4859c558809f3b67bc95 [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 Tolnayc4fbf402016-09-24 09:31:47 -070031 fn visit_macro_input(&mut self, macro_input: &MacroInput) {
32 walk_macro_input(self, macro_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
80 #[cfg(feature = "type-macros")]
81 fn visit_mac(&mut self, mac: &Mac) {
82 walk_mac(self, mac);
83 }
84
85 #[cfg(feature = "full")]
86 fn visit_crate(&mut self, _crate: &Crate) {
87 walk_crate(self, _crate);
88 }
89 #[cfg(feature = "full")]
90 fn visit_item(&mut self, item: &Item) {
91 walk_item(self, item);
92 }
93 #[cfg(feature = "full")]
94 fn visit_expr(&mut self, expr: &Expr) {
95 walk_expr(self, expr);
96 }
97 #[cfg(feature = "full")]
98 fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
99 walk_foreign_item(self, foreign_item);
100 }
101 #[cfg(feature = "full")]
102 fn visit_pat(&mut self, pat: &Pat) {
103 walk_pat(self, pat);
104 }
105 #[cfg(feature = "full")]
106 fn visit_fn_decl(&mut self, fn_decl: &FnDecl) {
107 walk_fn_decl(self, fn_decl);
108 }
109 #[cfg(feature = "full")]
110 fn visit_trait_item(&mut self, trait_item: &TraitItem) {
111 walk_trait_item(self, trait_item);
112 }
113 #[cfg(feature = "full")]
114 fn visit_impl_item(&mut self, impl_item: &ImplItem) {
115 walk_impl_item(self, impl_item);
116 }
117 #[cfg(feature = "full")]
118 fn visit_method_sig(&mut self, method_sig: &MethodSig) {
119 walk_method_sig(self, method_sig);
120 }
121 #[cfg(feature = "full")]
122 fn visit_stmt(&mut self, stmt: &Stmt) {
123 walk_stmt(self, stmt);
124 }
125 #[cfg(feature = "full")]
126 fn visit_local(&mut self, local: &Local) {
127 walk_local(self, local);
128 }
129 #[cfg(feature = "full")]
130 fn visit_view_path(&mut self, view_path: &ViewPath) {
131 walk_view_path(self, view_path);
132 }
David Tolnay55337722016-09-11 12:58:56 -0700133}
134
David Tolnay55337722016-09-11 12:58:56 -0700135macro_rules! walk_list {
136 ($visitor: expr, $method: ident, $list: expr) => {
137 for elem in $list {
138 $visitor.$method(elem)
139 }
140 };
141 ($visitor: expr, $method: ident, $list: expr, $($extra_args: expr),*) => {
142 for elem in $list {
143 $visitor.$method(elem, $($extra_args,)*)
144 }
145 }
146}
147
148pub fn walk_opt_ident<V: Visitor>(visitor: &mut V, opt_ident: &Option<Ident>) {
149 if let Some(ref ident) = *opt_ident {
150 visitor.visit_ident(ident);
151 }
152}
153
154pub fn walk_lifetime_def<V: Visitor>(visitor: &mut V, lifetime_def: &LifetimeDef) {
155 visitor.visit_lifetime(&lifetime_def.lifetime);
156 walk_list!(visitor, visit_lifetime, &lifetime_def.bounds);
157}
158
159pub fn walk_poly_trait_ref<V>(visitor: &mut V, trait_ref: &PolyTraitRef, _: &TraitBoundModifier)
David Tolnaydaaf7742016-10-03 11:11:43 -0700160 where V: Visitor
David Tolnay55337722016-09-11 12:58:56 -0700161{
162 walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes);
163 visitor.visit_path(&trait_ref.trait_ref);
164}
165
David Tolnayc4fbf402016-09-24 09:31:47 -0700166pub fn walk_macro_input<V: Visitor>(visitor: &mut V, macro_input: &MacroInput) {
167 visitor.visit_ident(&macro_input.ident);
168 visitor.visit_generics(&macro_input.generics);
169 match macro_input.body {
David Tolnay55337722016-09-11 12:58:56 -0700170 Body::Enum(ref variants) => {
David Tolnayc4fbf402016-09-24 09:31:47 -0700171 walk_list!(visitor, visit_variant, variants, &macro_input.generics);
David Tolnay55337722016-09-11 12:58:56 -0700172 }
173 Body::Struct(ref variant_data) => {
David Tolnaydaaf7742016-10-03 11:11:43 -0700174 visitor.visit_variant_data(variant_data, &macro_input.ident, &macro_input.generics);
David Tolnay55337722016-09-11 12:58:56 -0700175 }
176 }
David Tolnayc4fbf402016-09-24 09:31:47 -0700177 walk_list!(visitor, visit_attribute, &macro_input.attrs);
David Tolnay55337722016-09-11 12:58:56 -0700178}
179
180pub fn walk_variant<V>(visitor: &mut V, variant: &Variant, generics: &Generics)
David Tolnaydaaf7742016-10-03 11:11:43 -0700181 where V: Visitor
David Tolnay55337722016-09-11 12:58:56 -0700182{
183 visitor.visit_ident(&variant.ident);
184 visitor.visit_variant_data(&variant.data, &variant.ident, generics);
185 walk_list!(visitor, visit_attribute, &variant.attrs);
186}
187
188pub fn walk_ty<V: Visitor>(visitor: &mut V, ty: &Ty) {
189 match *ty {
David Tolnay429168f2016-10-05 23:41:04 -0700190 Ty::Slice(ref inner) |
David Tolnaydaaf7742016-10-03 11:11:43 -0700191 Ty::Paren(ref inner) => visitor.visit_ty(inner),
192 Ty::Ptr(ref mutable_type) => visitor.visit_ty(&mutable_type.ty),
David Tolnay55337722016-09-11 12:58:56 -0700193 Ty::Rptr(ref opt_lifetime, ref mutable_type) => {
194 walk_list!(visitor, visit_lifetime, opt_lifetime);
195 visitor.visit_ty(&mutable_type.ty)
196 }
David Tolnay58f6f672016-10-19 08:44:25 -0700197 Ty::Never | Ty::Infer => {}
David Tolnay55337722016-09-11 12:58:56 -0700198 Ty::Tup(ref tuple_element_types) => {
199 walk_list!(visitor, visit_ty, tuple_element_types);
200 }
David Tolnay1391b522016-10-03 21:05:45 -0700201 Ty::BareFn(ref bare_fn) => {
202 walk_list!(visitor, visit_lifetime_def, &bare_fn.lifetimes);
203 for argument in &bare_fn.inputs {
204 walk_opt_ident(visitor, &argument.name);
205 visitor.visit_ty(&argument.ty)
206 }
207 visitor.visit_fn_ret_ty(&bare_fn.output)
David Tolnay55337722016-09-11 12:58:56 -0700208 }
209 Ty::Path(ref maybe_qself, ref path) => {
210 if let Some(ref qself) = *maybe_qself {
211 visitor.visit_ty(&qself.ty);
212 }
213 visitor.visit_path(path);
214 }
David Tolnay429168f2016-10-05 23:41:04 -0700215 Ty::Array(ref inner, ref len) => {
David Tolnay55337722016-09-11 12:58:56 -0700216 visitor.visit_ty(inner);
David Tolnay68eb4c32016-10-07 23:30:32 -0700217 visitor.visit_const_expr(len);
David Tolnay55337722016-09-11 12:58:56 -0700218 }
David Tolnayfa23f572017-01-23 00:19:11 -0800219 Ty::TraitObject(ref bounds) |
David Tolnay55337722016-09-11 12:58:56 -0700220 Ty::ImplTrait(ref bounds) => {
221 walk_list!(visitor, visit_ty_param_bound, bounds);
222 }
Michael Layzellb52df322017-01-22 17:36:55 -0500223 Ty::Mac(ref mac) => {
224 #[cfg(feature = "type-macros")]
225 fn walk_tymac<V: Visitor>(visitor: &mut V, mac: &Mac) {
226 visitor.visit_mac(mac);
227 }
228 #[cfg(not(feature = "type-macros"))]
229 fn walk_tymac<V: Visitor>(_: &mut V, _: &super::ty::Mac) {}
230 walk_tymac(visitor, mac);
231 }
David Tolnay55337722016-09-11 12:58:56 -0700232 }
233}
234
235pub fn walk_path<V: Visitor>(visitor: &mut V, path: &Path) {
236 for segment in &path.segments {
237 visitor.visit_path_segment(segment);
238 }
239}
240
241pub fn walk_path_segment<V: Visitor>(visitor: &mut V, segment: &PathSegment) {
242 visitor.visit_ident(&segment.ident);
243 visitor.visit_path_parameters(&segment.parameters);
244}
245
246pub fn walk_path_parameters<V>(visitor: &mut V, path_parameters: &PathParameters)
David Tolnaydaaf7742016-10-03 11:11:43 -0700247 where V: Visitor
David Tolnay55337722016-09-11 12:58:56 -0700248{
249 match *path_parameters {
250 PathParameters::AngleBracketed(ref data) => {
251 walk_list!(visitor, visit_ty, &data.types);
252 walk_list!(visitor, visit_lifetime, &data.lifetimes);
253 walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
254 }
255 PathParameters::Parenthesized(ref data) => {
256 walk_list!(visitor, visit_ty, &data.inputs);
257 walk_list!(visitor, visit_ty, &data.output);
258 }
259 }
260}
261
262pub fn walk_assoc_type_binding<V: Visitor>(visitor: &mut V, type_binding: &TypeBinding) {
263 visitor.visit_ident(&type_binding.ident);
264 visitor.visit_ty(&type_binding.ty);
265}
266
267pub fn walk_ty_param_bound<V: Visitor>(visitor: &mut V, bound: &TyParamBound) {
268 match *bound {
269 TyParamBound::Trait(ref ty, ref modifier) => {
270 visitor.visit_poly_trait_ref(ty, modifier);
271 }
272 TyParamBound::Region(ref lifetime) => {
273 visitor.visit_lifetime(lifetime);
274 }
275 }
276}
277
278pub fn walk_generics<V: Visitor>(visitor: &mut V, generics: &Generics) {
279 for param in &generics.ty_params {
280 visitor.visit_ident(&param.ident);
281 walk_list!(visitor, visit_ty_param_bound, &param.bounds);
282 walk_list!(visitor, visit_ty, &param.default);
283 }
284 walk_list!(visitor, visit_lifetime_def, &generics.lifetimes);
285 for predicate in &generics.where_clause.predicates {
286 match *predicate {
David Tolnaydaaf7742016-10-03 11:11:43 -0700287 WherePredicate::BoundPredicate(WhereBoundPredicate { ref bounded_ty,
288 ref bounds,
289 ref bound_lifetimes,
290 .. }) => {
David Tolnay55337722016-09-11 12:58:56 -0700291 visitor.visit_ty(bounded_ty);
292 walk_list!(visitor, visit_ty_param_bound, bounds);
293 walk_list!(visitor, visit_lifetime_def, bound_lifetimes);
294 }
David Tolnaydaaf7742016-10-03 11:11:43 -0700295 WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime,
296 ref bounds,
297 .. }) => {
David Tolnay55337722016-09-11 12:58:56 -0700298 visitor.visit_lifetime(lifetime);
299 walk_list!(visitor, visit_lifetime, bounds);
300 }
David Tolnayfa23f572017-01-23 00:19:11 -0800301 WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty,
302 ref rhs_ty,
303 .. }) => {
304 visitor.visit_ty(lhs_ty);
305 visitor.visit_ty(rhs_ty);
306 }
David Tolnay55337722016-09-11 12:58:56 -0700307 }
308 }
309}
310
311pub fn walk_fn_ret_ty<V: Visitor>(visitor: &mut V, ret_ty: &FunctionRetTy) {
312 if let FunctionRetTy::Ty(ref output_ty) = *ret_ty {
313 visitor.visit_ty(output_ty)
314 }
315}
316
David Tolnay55337722016-09-11 12:58:56 -0700317pub fn walk_variant_data<V: Visitor>(visitor: &mut V, data: &VariantData) {
318 walk_list!(visitor, visit_field, data.fields());
319}
320
321pub fn walk_field<V: Visitor>(visitor: &mut V, field: &Field) {
322 walk_opt_ident(visitor, &field.ident);
323 visitor.visit_ty(&field.ty);
324 walk_list!(visitor, visit_attribute, &field.attrs);
325}
David Tolnay429168f2016-10-05 23:41:04 -0700326
David Tolnay68eb4c32016-10-07 23:30:32 -0700327pub fn walk_const_expr<V: Visitor>(visitor: &mut V, len: &ConstExpr) {
David Tolnay429168f2016-10-05 23:41:04 -0700328 match *len {
David Tolnay68eb4c32016-10-07 23:30:32 -0700329 ConstExpr::Call(ref function, ref args) => {
David Tolnay58f6f672016-10-19 08:44:25 -0700330 visitor.visit_const_expr(function);
David Tolnay68eb4c32016-10-07 23:30:32 -0700331 walk_list!(visitor, visit_const_expr, args);
332 }
333 ConstExpr::Binary(_op, ref left, ref right) => {
334 visitor.visit_const_expr(left);
335 visitor.visit_const_expr(right);
336 }
337 ConstExpr::Unary(_op, ref v) => {
338 visitor.visit_const_expr(v);
339 }
340 ConstExpr::Lit(ref lit) => {
341 visitor.visit_lit(lit);
342 }
343 ConstExpr::Cast(ref expr, ref ty) => {
344 visitor.visit_const_expr(expr);
345 visitor.visit_ty(ty);
346 }
347 ConstExpr::Path(ref path) => {
David Tolnay429168f2016-10-05 23:41:04 -0700348 visitor.visit_path(path);
349 }
David Tolnay67588752016-10-30 12:23:10 -0700350 ConstExpr::Index(ref expr, ref index) => {
351 visitor.visit_const_expr(expr);
352 visitor.visit_const_expr(index);
353 }
David Tolnaye7b0d322016-10-30 10:27:23 -0700354 ConstExpr::Paren(ref expr) => {
355 visitor.visit_const_expr(expr);
356 }
Michael Layzellb52df322017-01-22 17:36:55 -0500357 ConstExpr::Other(ref other) => {
358 #[cfg(feature = "full")]
359 fn walk_other<V: Visitor>(visitor: &mut V, other: &Expr) {
360 visitor.visit_expr(other);
361 }
362 #[cfg(not(feature = "full"))]
363 fn walk_other<V: Visitor>(_: &mut V, _: &super::constant::Other) {}
364 walk_other(visitor, other);
365 }
366 }
367}
368
369#[cfg(feature = "type-macros")]
370pub fn walk_mac<V: Visitor>(visitor: &mut V, mac: &Mac) {
371 visitor.visit_path(&mac.path);
372}
373
374#[cfg(feature = "full")]
375pub fn walk_crate<V: Visitor>(visitor: &mut V, _crate: &Crate) {
376 walk_list!(visitor, visit_attribute, &_crate.attrs);
377 walk_list!(visitor, visit_item, &_crate.items);
378}
379
380#[cfg(feature = "full")]
381pub fn walk_item<V: Visitor>(visitor: &mut V, item: &Item) {
382 visitor.visit_ident(&item.ident);
383 walk_list!(visitor, visit_attribute, &item.attrs);
384 match item.node {
385 ItemKind::ExternCrate(ref ident) => {
386 walk_opt_ident(visitor, ident);
387 }
388 ItemKind::Use(ref view_path) => {
389 visitor.visit_view_path(view_path);
390 }
391 ItemKind::Static(ref ty, _, ref expr) => {
392 visitor.visit_ty(ty);
393 visitor.visit_expr(expr);
394 }
395 ItemKind::Const(ref ty, ref expr) => {
396 visitor.visit_ty(ty);
397 visitor.visit_expr(expr);
398 }
399 ItemKind::Fn(ref decl, _, _, _, ref generics, ref body) => {
400 visitor.visit_fn_decl(decl);
401 visitor.visit_generics(generics);
402 walk_list!(visitor, visit_stmt, &body.stmts);
403 }
404 ItemKind::Mod(ref maybe_items) => {
405 if let Some(ref items) = *maybe_items {
406 walk_list!(visitor, visit_item, items);
407 }
408 }
409 ItemKind::ForeignMod(ref foreign_mod) => {
410 walk_list!(visitor, visit_foreign_item, &foreign_mod.items);
411 }
412 ItemKind::Ty(ref ty, ref generics) => {
413 visitor.visit_ty(ty);
414 visitor.visit_generics(generics);
415 }
416 ItemKind::Enum(ref variant, ref generics) => {
417 walk_list!(visitor, visit_variant, variant, generics);
418 }
419 ItemKind::Struct(ref variant_data, ref generics) => {
420 visitor.visit_variant_data(variant_data, &item.ident, generics);
421 }
422 ItemKind::Union(ref variant_data, ref generics) => {
423 visitor.visit_variant_data(variant_data, &item.ident, generics);
424 }
425 ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => {
426 visitor.visit_generics(generics);
427 walk_list!(visitor, visit_ty_param_bound, bounds);
428 walk_list!(visitor, visit_trait_item, trait_items);
429 }
430 ItemKind::DefaultImpl(_, ref path) => {
431 visitor.visit_path(path);
432 }
433 ItemKind::Impl(_, _, ref generics, ref maybe_path, ref ty, ref impl_items) => {
434 visitor.visit_generics(generics);
435 if let Some(ref path) = *maybe_path {
436 visitor.visit_path(path);
437 }
438 visitor.visit_ty(ty);
439 walk_list!(visitor, visit_impl_item, impl_items);
440 }
441 ItemKind::Mac(ref mac) => {
442 visitor.visit_mac(mac)
443 }
444 }
445}
446
447#[cfg(feature = "full")]
448pub fn walk_expr<V: Visitor>(visitor: &mut V, expr: &Expr) {
449 walk_list!(visitor, visit_attribute, &expr.attrs);
450 match expr.node {
451 ExprKind::Box(ref expr) => {
452 visitor.visit_expr(expr);
453 }
454 ExprKind::InPlace(ref place, ref value) => {
455 visitor.visit_expr(place);
456 visitor.visit_expr(value);
457 }
David Tolnayfa23f572017-01-23 00:19:11 -0800458 ExprKind::Array(ref exprs) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500459 walk_list!(visitor, visit_expr, exprs);
460 }
461 ExprKind::Call(ref callee, ref args) => {
462 visitor.visit_expr(callee);
463 walk_list!(visitor, visit_expr, args);
464 }
465 ExprKind::MethodCall(ref name, ref ty_args, ref args) => {
466 visitor.visit_ident(name);
467 walk_list!(visitor, visit_ty, ty_args);
468 walk_list!(visitor, visit_expr, args);
469 }
470 ExprKind::Tup(ref exprs) => {
471 walk_list!(visitor, visit_expr, exprs);
472 }
473 ExprKind::Binary(_, ref lhs, ref rhs) => {
474 visitor.visit_expr(lhs);
475 visitor.visit_expr(rhs);
476 }
477 ExprKind::Unary(_, ref operand) => {
478 visitor.visit_expr(operand);
479 }
480 ExprKind::Lit(ref lit) => {
481 visitor.visit_lit(lit);
482 }
483 ExprKind::Cast(ref expr, ref ty) => {
484 visitor.visit_expr(expr);
485 visitor.visit_ty(ty);
486 }
487 ExprKind::Type(ref expr, ref ty) => {
488 visitor.visit_expr(expr);
489 visitor.visit_ty(ty);
490 }
491 ExprKind::If(ref cond, ref cons, ref maybe_alt) => {
492 visitor.visit_expr(cond);
493 walk_list!(visitor, visit_stmt, &cons.stmts);
494 if let Some(ref alt) = *maybe_alt {
495 visitor.visit_expr(alt);
496 }
497 }
498 ExprKind::IfLet(ref pat, ref cond, ref cons, ref maybe_alt) => {
499 visitor.visit_pat(pat);
500 visitor.visit_expr(cond);
501 walk_list!(visitor, visit_stmt, &cons.stmts);
502 if let Some(ref alt) = *maybe_alt {
503 visitor.visit_expr(alt);
504 }
505 }
506 ExprKind::While(ref cond, ref body, ref label) => {
507 visitor.visit_expr(cond);
508 walk_list!(visitor, visit_stmt, &body.stmts);
509 walk_opt_ident(visitor, label);
510 }
511 ExprKind::WhileLet(ref pat, ref cond, ref body, ref label) => {
512 visitor.visit_pat(pat);
513 visitor.visit_expr(cond);
514 walk_list!(visitor, visit_stmt, &body.stmts);
515 walk_opt_ident(visitor, label);
516 }
517 ExprKind::ForLoop(ref pat, ref expr, ref body, ref label) => {
518 visitor.visit_pat(pat);
519 visitor.visit_expr(expr);
520 walk_list!(visitor, visit_stmt, &body.stmts);
521 walk_opt_ident(visitor, label);
522 }
523 ExprKind::Loop(ref body, ref label) => {
524 walk_list!(visitor, visit_stmt, &body.stmts);
525 walk_opt_ident(visitor, label);
526 }
527 ExprKind::Match(ref expr, ref arms) => {
528 visitor.visit_expr(expr);
529 for &Arm{ref attrs, ref pats, ref guard, ref body} in arms {
530 walk_list!(visitor, visit_attribute, attrs);
531 walk_list!(visitor, visit_pat, pats);
532 if let Some(ref guard) = *guard {
533 visitor.visit_expr(guard);
534 }
535 visitor.visit_expr(body);
536 }
537 }
538 ExprKind::Closure(_, ref decl, ref expr) => {
539 visitor.visit_fn_decl(decl);
540 visitor.visit_expr(expr);
541 }
542 ExprKind::Block(_, ref block) => {
543 walk_list!(visitor, visit_stmt, &block.stmts);
544 }
545 ExprKind::Assign(ref lhs, ref rhs) => {
546 visitor.visit_expr(lhs);
547 visitor.visit_expr(rhs);
548 }
549 ExprKind::AssignOp(_, ref lhs, ref rhs) => {
550 visitor.visit_expr(lhs);
551 visitor.visit_expr(rhs);
552 }
553 ExprKind::Field(ref obj, ref field) => {
554 visitor.visit_expr(obj);
555 visitor.visit_ident(field);
556 }
557 ExprKind::TupField(ref obj, _) => {
558 visitor.visit_expr(obj);
559 }
560 ExprKind::Index(ref obj, ref idx) => {
561 visitor.visit_expr(obj);
562 visitor.visit_expr(idx);
563 }
564 ExprKind::Range(ref maybe_start, ref maybe_end, _) => {
565 if let Some(ref start) = *maybe_start {
566 visitor.visit_expr(start);
567 }
568 if let Some(ref end) = *maybe_end {
569 visitor.visit_expr(end);
570 }
571 }
572 ExprKind::Path(ref maybe_qself, ref path) => {
573 if let Some(ref qself) = *maybe_qself {
574 visitor.visit_ty(&qself.ty);
575 }
576 visitor.visit_path(path);
577 }
578 ExprKind::AddrOf(_, ref expr) => {
579 visitor.visit_expr(expr);
580 }
581 ExprKind::Break(ref maybe_label, ref maybe_expr) => {
582 walk_opt_ident(visitor, maybe_label);
583 if let Some(ref expr) = *maybe_expr {
584 visitor.visit_expr(expr);
585 }
586 }
587 ExprKind::Continue(ref maybe_label) => {
588 walk_opt_ident(visitor, maybe_label);
589 }
590 ExprKind::Ret(ref maybe_expr) => {
591 if let Some(ref expr) = *maybe_expr {
592 visitor.visit_expr(expr);
593 }
594 }
595 ExprKind::Mac(ref mac) => {
596 visitor.visit_mac(mac);
597 }
598 ExprKind::Struct(ref path, ref fields, ref maybe_base) => {
599 visitor.visit_path(path);
600 for &FieldValue{ref ident, ref expr, ..} in fields {
601 visitor.visit_ident(ident);
602 visitor.visit_expr(expr);
603 }
604 if let Some(ref base) = *maybe_base {
605 visitor.visit_expr(base);
606 }
607 }
608 ExprKind::Repeat(ref value, ref times) => {
609 visitor.visit_expr(value);
610 visitor.visit_expr(times);
611 }
612 ExprKind::Paren(ref expr) => {
613 visitor.visit_expr(expr);
614 }
615 ExprKind::Try(ref expr) => {
616 visitor.visit_expr(expr);
617 }
618 }
619}
620
621#[cfg(feature = "full")]
622pub fn walk_foreign_item<V: Visitor>(visitor: &mut V, foreign_item: &ForeignItem) {
623 visitor.visit_ident(&foreign_item.ident);
624 walk_list!(visitor, visit_attribute, &foreign_item.attrs);
625 match foreign_item.node {
626 ForeignItemKind::Fn(ref decl, ref generics) => {
627 visitor.visit_fn_decl(decl);
628 visitor.visit_generics(generics);
629 }
630 ForeignItemKind::Static(ref ty, _) => {
631 visitor.visit_ty(ty);
632 }
633 }
634}
635
636#[cfg(feature = "full")]
637pub fn walk_pat<V: Visitor>(visitor: &mut V, pat: &Pat) {
638 match *pat {
639 Pat::Wild => {}
640 Pat::Ident(_, ref ident, ref maybe_pat) => {
641 visitor.visit_ident(ident);
642 if let Some(ref pat) = *maybe_pat {
643 visitor.visit_pat(pat);
644 }
645 }
646 Pat::Struct(ref path, ref field_pats, _) => {
647 visitor.visit_path(path);
648 for &FieldPat{ref ident, ref pat, ..} in field_pats {
649 visitor.visit_ident(ident);
650 visitor.visit_pat(pat);
651 }
652 }
653 Pat::TupleStruct(ref path, ref pats, _) => {
654 visitor.visit_path(path);
655 walk_list!(visitor, visit_pat, pats);
656 }
657 Pat::Path(ref maybe_qself, ref path) => {
658 if let Some(ref qself) = *maybe_qself {
659 visitor.visit_ty(&qself.ty);
660 }
661 visitor.visit_path(path);
662 }
663 Pat::Tuple(ref pats, _) => {
664 walk_list!(visitor, visit_pat, pats);
665 }
666 Pat::Box(ref pat) |
667 Pat::Ref(ref pat, _) => {
668 visitor.visit_pat(pat);
669 }
670 Pat::Lit(ref expr) => {
671 visitor.visit_expr(expr);
672 }
673 Pat::Range(ref start, ref end) => {
674 visitor.visit_expr(start);
675 visitor.visit_expr(end);
676 }
677 Pat::Slice(ref start, ref maybe_mid, ref end) => {
678 walk_list!(visitor, visit_pat, start);
679 if let Some(ref mid) = *maybe_mid {
680 visitor.visit_pat(mid);
681 }
682 walk_list!(visitor, visit_pat, end);
683 }
684 Pat::Mac(ref mac) => {
685 visitor.visit_mac(mac);
686 }
687 }
688}
689
690#[cfg(feature = "full")]
691pub fn walk_fn_decl<V: Visitor>(visitor: &mut V, fn_decl: &FnDecl) {
692 for input in &fn_decl.inputs {
693 match *input {
694 FnArg::SelfRef(_, _) | FnArg::SelfValue(_) => {}
695 FnArg::Captured(ref pat, ref ty) => {
696 visitor.visit_pat(pat);
697 visitor.visit_ty(ty);
698 }
699 FnArg::Ignored(ref ty) => {
700 visitor.visit_ty(ty);
701 }
702 }
703 }
704 visitor.visit_fn_ret_ty(&fn_decl.output);
705}
706
707#[cfg(feature = "full")]
708pub fn walk_trait_item<V: Visitor>(visitor: &mut V, trait_item: &TraitItem) {
709 visitor.visit_ident(&trait_item.ident);
710 walk_list!(visitor, visit_attribute, &trait_item.attrs);
711 match trait_item.node {
712 TraitItemKind::Const(ref ty, ref maybe_expr) => {
713 visitor.visit_ty(ty);
714 if let Some(ref expr) = *maybe_expr {
715 visitor.visit_expr(expr);
716 }
717 }
718 TraitItemKind::Method(ref method_sig, ref maybe_block) => {
719 visitor.visit_method_sig(method_sig);
720 if let Some(ref block) = *maybe_block {
721 walk_list!(visitor, visit_stmt, &block.stmts);
722 }
723 }
724 TraitItemKind::Type(ref bounds, ref maybe_ty) => {
725 walk_list!(visitor, visit_ty_param_bound, bounds);
726 if let Some(ref ty) = *maybe_ty {
727 visitor.visit_ty(ty);
728 }
729 }
730 TraitItemKind::Macro(ref mac) => {
731 visitor.visit_mac(mac);
732 }
733 }
734}
735
736#[cfg(feature = "full")]
737pub fn walk_impl_item<V: Visitor>(visitor: &mut V, impl_item: &ImplItem) {
738 visitor.visit_ident(&impl_item.ident);
739 walk_list!(visitor, visit_attribute, &impl_item.attrs);
740 match impl_item.node {
741 ImplItemKind::Const(ref ty, ref expr) => {
742 visitor.visit_ty(ty);
743 visitor.visit_expr(expr);
744 }
745 ImplItemKind::Method(ref method_sig, ref block) => {
746 visitor.visit_method_sig(method_sig);
747 walk_list!(visitor, visit_stmt, &block.stmts);
748 }
749 ImplItemKind::Type(ref ty) => {
750 visitor.visit_ty(ty);
751 }
752 ImplItemKind::Macro(ref mac) => {
753 visitor.visit_mac(mac);
754 }
755 }
756}
757
758#[cfg(feature = "full")]
759pub fn walk_method_sig<V: Visitor>(visitor: &mut V, method_sig: &MethodSig) {
760 visitor.visit_fn_decl(&method_sig.decl);
761 visitor.visit_generics(&method_sig.generics);
762}
763
764#[cfg(feature = "full")]
765pub fn walk_stmt<V: Visitor>(visitor: &mut V, stmt: &Stmt) {
766 match *stmt {
767 Stmt::Local(ref local) => {
768 visitor.visit_local(local);
769 }
770 Stmt::Item(ref item) => {
771 visitor.visit_item(item);
772 }
773 Stmt::Expr(ref expr) |
774 Stmt::Semi(ref expr) => {
775 visitor.visit_expr(expr);
776 }
777 Stmt::Mac(ref details) => {
778 let (ref mac, _, ref attrs) = **details;
779 visitor.visit_mac(mac);
780 walk_list!(visitor, visit_attribute, attrs);
781 }
782 }
783}
784
785#[cfg(feature = "full")]
786pub fn walk_local<V: Visitor>(visitor: &mut V, local: &Local) {
787 visitor.visit_pat(&local.pat);
788 if let Some(ref ty) = local.ty {
789 visitor.visit_ty(ty);
790 }
791 if let Some(ref init) = local.init {
792 visitor.visit_expr(init);
793 }
794 walk_list!(visitor, visit_attribute, &local.attrs);
795}
796
797#[cfg(feature = "full")]
798pub fn walk_view_path<V: Visitor>(visitor: &mut V, view_path: &ViewPath) {
799 match *view_path {
800 ViewPath::Simple(ref path, ref maybe_ident) => {
801 visitor.visit_path(path);
802 walk_opt_ident(visitor, maybe_ident);
803 }
804 ViewPath::Glob(ref path) => {
805 visitor.visit_path(path);
806 }
807 ViewPath::List(ref path, ref items) => {
808 visitor.visit_path(path);
809 for &PathListItem{ref name, ref rename} in items {
810 visitor.visit_ident(name);
811 walk_opt_ident(visitor, rename);
812 }
813 }
David Tolnay429168f2016-10-05 23:41:04 -0700814 }
815}