]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/visit.rs
remove extern_in_paths.
[rust.git] / src / libsyntax / visit.rs
1 //! AST walker. Each overridden visit method has full control over what
2 //! happens with its node, it can do its own traversal of the node's children,
3 //! call `visit::walk_*` to apply the default traversal algorithm, or prevent
4 //! deeper traversal by doing nothing.
5 //!
6 //! Note: it is an important invariant that the default visitor walks the body
7 //! of a function in "execution order" (more concretely, reverse post-order
8 //! with respect to the CFG implied by the AST), meaning that if AST node A may
9 //! execute before AST node B, then A is visited first.  The borrow checker in
10 //! particular relies on this property.
11 //!
12 //! Note: walking an AST before macro expansion is probably a bad idea. For
13 //! instance, a walker looking for item names in a module will miss all of
14 //! those that are created by the expansion of a macro.
15
16 use ast::*;
17 use syntax_pos::Span;
18 use parse::token::Token;
19 use tokenstream::{TokenTree, TokenStream};
20
21 #[derive(Copy, Clone)]
22 pub enum FnKind<'a> {
23     /// fn foo() or extern "Abi" fn foo()
24     ItemFn(Ident, FnHeader, &'a Visibility, &'a Block),
25
26     /// fn foo(&self)
27     Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block),
28
29     /// |x, y| body
30     Closure(&'a Expr),
31 }
32
33 /// Each method of the Visitor trait is a hook to be potentially
34 /// overridden.  Each method's default implementation recursively visits
35 /// the substructure of the input via the corresponding `walk` method;
36 /// e.g., the `visit_mod` method by default calls `visit::walk_mod`.
37 ///
38 /// If you want to ensure that your code handles every variant
39 /// explicitly, you need to override each method.  (And you also need
40 /// to monitor future changes to `Visitor` in case a new method with a
41 /// new default implementation gets introduced.)
42 pub trait Visitor<'ast>: Sized {
43     fn visit_name(&mut self, _span: Span, _name: Name) {
44         // Nothing to do.
45     }
46     fn visit_ident(&mut self, ident: Ident) {
47         walk_ident(self, ident);
48     }
49     fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _attrs: &[Attribute], _n: NodeId) {
50         walk_mod(self, m);
51     }
52     fn visit_foreign_item(&mut self, i: &'ast ForeignItem) { walk_foreign_item(self, i) }
53     fn visit_global_asm(&mut self, ga: &'ast GlobalAsm) { walk_global_asm(self, ga) }
54     fn visit_item(&mut self, i: &'ast Item) { walk_item(self, i) }
55     fn visit_local(&mut self, l: &'ast Local) { walk_local(self, l) }
56     fn visit_block(&mut self, b: &'ast Block) { walk_block(self, b) }
57     fn visit_stmt(&mut self, s: &'ast Stmt) { walk_stmt(self, s) }
58     fn visit_arm(&mut self, a: &'ast Arm) { walk_arm(self, a) }
59     fn visit_pat(&mut self, p: &'ast Pat) { walk_pat(self, p) }
60     fn visit_anon_const(&mut self, c: &'ast AnonConst) { walk_anon_const(self, c) }
61     fn visit_expr(&mut self, ex: &'ast Expr) { walk_expr(self, ex) }
62     fn visit_expr_post(&mut self, _ex: &'ast Expr) { }
63     fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) }
64     fn visit_generic_param(&mut self, param: &'ast GenericParam) {
65         walk_generic_param(self, param)
66     }
67     fn visit_generics(&mut self, g: &'ast Generics) { walk_generics(self, g) }
68     fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
69         walk_where_predicate(self, p)
70     }
71     fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl, s: Span, _: NodeId) {
72         walk_fn(self, fk, fd, s)
73     }
74     fn visit_trait_item(&mut self, ti: &'ast TraitItem) { walk_trait_item(self, ti) }
75     fn visit_impl_item(&mut self, ii: &'ast ImplItem) { walk_impl_item(self, ii) }
76     fn visit_trait_ref(&mut self, t: &'ast TraitRef) { walk_trait_ref(self, t) }
77     fn visit_param_bound(&mut self, bounds: &'ast GenericBound) {
78         walk_param_bound(self, bounds)
79     }
80     fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) {
81         walk_poly_trait_ref(self, t, m)
82     }
83     fn visit_variant_data(&mut self, s: &'ast VariantData, _: Ident,
84                           _: &'ast Generics, _: NodeId, _: Span) {
85         walk_struct_def(self, s)
86     }
87     fn visit_struct_field(&mut self, s: &'ast StructField) { walk_struct_field(self, s) }
88     fn visit_enum_def(&mut self, enum_definition: &'ast EnumDef,
89                       generics: &'ast Generics, item_id: NodeId, _: Span) {
90         walk_enum_def(self, enum_definition, generics, item_id)
91     }
92     fn visit_variant(&mut self, v: &'ast Variant, g: &'ast Generics, item_id: NodeId) {
93         walk_variant(self, v, g, item_id)
94     }
95     fn visit_label(&mut self, label: &'ast Label) {
96         walk_label(self, label)
97     }
98     fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
99         walk_lifetime(self, lifetime)
100     }
101     fn visit_mac(&mut self, _mac: &'ast Mac) {
102         panic!("visit_mac disabled by default");
103         // N.B., see note about macros above.
104         // if you really want a visitor that
105         // works on macros, use this
106         // definition in your trait impl:
107         // visit::walk_mac(self, _mac)
108     }
109     fn visit_mac_def(&mut self, _mac: &'ast MacroDef, _id: NodeId) {
110         // Nothing to do
111     }
112     fn visit_path(&mut self, path: &'ast Path, _id: NodeId) {
113         walk_path(self, path)
114     }
115     fn visit_use_tree(&mut self, use_tree: &'ast UseTree, id: NodeId, _nested: bool) {
116         walk_use_tree(self, use_tree, id)
117     }
118     fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) {
119         walk_path_segment(self, path_span, path_segment)
120     }
121     fn visit_generic_args(&mut self, path_span: Span, generic_args: &'ast GenericArgs) {
122         walk_generic_args(self, path_span, generic_args)
123     }
124     fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) {
125         match generic_arg {
126             GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
127             GenericArg::Type(ty) => self.visit_ty(ty),
128         }
129     }
130     fn visit_assoc_type_binding(&mut self, type_binding: &'ast TypeBinding) {
131         walk_assoc_type_binding(self, type_binding)
132     }
133     fn visit_attribute(&mut self, attr: &'ast Attribute) {
134         walk_attribute(self, attr)
135     }
136     fn visit_tt(&mut self, tt: TokenTree) {
137         walk_tt(self, tt)
138     }
139     fn visit_tts(&mut self, tts: TokenStream) {
140         walk_tts(self, tts)
141     }
142     fn visit_token(&mut self, _t: Token) {}
143     // FIXME: add `visit_interpolated` and `walk_interpolated`
144     fn visit_vis(&mut self, vis: &'ast Visibility) {
145         walk_vis(self, vis)
146     }
147     fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FunctionRetTy) {
148         walk_fn_ret_ty(self, ret_ty)
149     }
150 }
151
152 #[macro_export]
153 macro_rules! walk_list {
154     ($visitor: expr, $method: ident, $list: expr) => {
155         for elem in $list {
156             $visitor.$method(elem)
157         }
158     };
159     ($visitor: expr, $method: ident, $list: expr, $($extra_args: expr),*) => {
160         for elem in $list {
161             $visitor.$method(elem, $($extra_args,)*)
162         }
163     }
164 }
165
166 pub fn walk_ident<'a, V: Visitor<'a>>(visitor: &mut V, ident: Ident) {
167     visitor.visit_name(ident.span, ident.name);
168 }
169
170 pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) {
171     visitor.visit_mod(&krate.module, krate.span, &krate.attrs, CRATE_NODE_ID);
172     walk_list!(visitor, visit_attribute, &krate.attrs);
173 }
174
175 pub fn walk_mod<'a, V: Visitor<'a>>(visitor: &mut V, module: &'a Mod) {
176     walk_list!(visitor, visit_item, &module.items);
177 }
178
179 pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) {
180     for attr in local.attrs.iter() {
181         visitor.visit_attribute(attr);
182     }
183     visitor.visit_pat(&local.pat);
184     walk_list!(visitor, visit_ty, &local.ty);
185     walk_list!(visitor, visit_expr, &local.init);
186 }
187
188 pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, label: &'a Label) {
189     visitor.visit_ident(label.ident);
190 }
191
192 pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) {
193     visitor.visit_ident(lifetime.ident);
194 }
195
196 pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V,
197                                   trait_ref: &'a PolyTraitRef,
198                                   _: &TraitBoundModifier)
199     where V: Visitor<'a>,
200 {
201     walk_list!(visitor, visit_generic_param, &trait_ref.bound_generic_params);
202     visitor.visit_trait_ref(&trait_ref.trait_ref);
203 }
204
205 pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitRef) {
206     visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
207 }
208
209 pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
210     visitor.visit_vis(&item.vis);
211     visitor.visit_ident(item.ident);
212     match item.node {
213         ItemKind::ExternCrate(orig_name) => {
214             if let Some(orig_name) = orig_name {
215                 visitor.visit_name(item.span, orig_name);
216             }
217         }
218         ItemKind::Use(ref use_tree) => {
219             visitor.visit_use_tree(use_tree, item.id, false)
220         }
221         ItemKind::Static(ref typ, _, ref expr) |
222         ItemKind::Const(ref typ, ref expr) => {
223             visitor.visit_ty(typ);
224             visitor.visit_expr(expr);
225         }
226         ItemKind::Fn(ref declaration, header, ref generics, ref body) => {
227             visitor.visit_generics(generics);
228             visitor.visit_fn(FnKind::ItemFn(item.ident, header,
229                                             &item.vis, body),
230                              declaration,
231                              item.span,
232                              item.id)
233         }
234         ItemKind::Mod(ref module) => {
235             visitor.visit_mod(module, item.span, &item.attrs, item.id)
236         }
237         ItemKind::ForeignMod(ref foreign_module) => {
238             walk_list!(visitor, visit_foreign_item, &foreign_module.items);
239         }
240         ItemKind::GlobalAsm(ref ga) => visitor.visit_global_asm(ga),
241         ItemKind::Ty(ref typ, ref type_parameters) => {
242             visitor.visit_ty(typ);
243             visitor.visit_generics(type_parameters)
244         }
245         ItemKind::Existential(ref bounds, ref type_parameters) => {
246             walk_list!(visitor, visit_param_bound, bounds);
247             visitor.visit_generics(type_parameters)
248         }
249         ItemKind::Enum(ref enum_definition, ref type_parameters) => {
250             visitor.visit_generics(type_parameters);
251             visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
252         }
253         ItemKind::Impl(_, _, _,
254                  ref type_parameters,
255                  ref opt_trait_reference,
256                  ref typ,
257                  ref impl_items) => {
258             visitor.visit_generics(type_parameters);
259             walk_list!(visitor, visit_trait_ref, opt_trait_reference);
260             visitor.visit_ty(typ);
261             walk_list!(visitor, visit_impl_item, impl_items);
262         }
263         ItemKind::Struct(ref struct_definition, ref generics) |
264         ItemKind::Union(ref struct_definition, ref generics) => {
265             visitor.visit_generics(generics);
266             visitor.visit_variant_data(struct_definition, item.ident,
267                                      generics, item.id, item.span);
268         }
269         ItemKind::Trait(.., ref generics, ref bounds, ref methods) => {
270             visitor.visit_generics(generics);
271             walk_list!(visitor, visit_param_bound, bounds);
272             walk_list!(visitor, visit_trait_item, methods);
273         }
274         ItemKind::TraitAlias(ref generics, ref bounds) => {
275             visitor.visit_generics(generics);
276             walk_list!(visitor, visit_param_bound, bounds);
277         }
278         ItemKind::Mac(ref mac) => visitor.visit_mac(mac),
279         ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id),
280     }
281     walk_list!(visitor, visit_attribute, &item.attrs);
282 }
283
284 pub fn walk_enum_def<'a, V: Visitor<'a>>(visitor: &mut V,
285                                  enum_definition: &'a EnumDef,
286                                  generics: &'a Generics,
287                                  item_id: NodeId) {
288     walk_list!(visitor, visit_variant, &enum_definition.variants, generics, item_id);
289 }
290
291 pub fn walk_variant<'a, V>(visitor: &mut V,
292                            variant: &'a Variant,
293                            generics: &'a Generics,
294                            item_id: NodeId)
295     where V: Visitor<'a>,
296 {
297     visitor.visit_ident(variant.node.ident);
298     visitor.visit_variant_data(&variant.node.data, variant.node.ident,
299                              generics, item_id, variant.span);
300     walk_list!(visitor, visit_anon_const, &variant.node.disr_expr);
301     walk_list!(visitor, visit_attribute, &variant.node.attrs);
302 }
303
304 pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
305     match typ.node {
306         TyKind::Slice(ref ty) | TyKind::Paren(ref ty) => {
307             visitor.visit_ty(ty)
308         }
309         TyKind::Ptr(ref mutable_type) => {
310             visitor.visit_ty(&mutable_type.ty)
311         }
312         TyKind::Rptr(ref opt_lifetime, ref mutable_type) => {
313             walk_list!(visitor, visit_lifetime, opt_lifetime);
314             visitor.visit_ty(&mutable_type.ty)
315         }
316         TyKind::Never => {},
317         TyKind::Tup(ref tuple_element_types) => {
318             walk_list!(visitor, visit_ty, tuple_element_types);
319         }
320         TyKind::BareFn(ref function_declaration) => {
321             walk_list!(visitor, visit_generic_param, &function_declaration.generic_params);
322             walk_fn_decl(visitor, &function_declaration.decl);
323         }
324         TyKind::Path(ref maybe_qself, ref path) => {
325             if let Some(ref qself) = *maybe_qself {
326                 visitor.visit_ty(&qself.ty);
327             }
328             visitor.visit_path(path, typ.id);
329         }
330         TyKind::Array(ref ty, ref length) => {
331             visitor.visit_ty(ty);
332             visitor.visit_anon_const(length)
333         }
334         TyKind::TraitObject(ref bounds, ..) |
335         TyKind::ImplTrait(_, ref bounds) => {
336             walk_list!(visitor, visit_param_bound, bounds);
337         }
338         TyKind::Typeof(ref expression) => {
339             visitor.visit_anon_const(expression)
340         }
341         TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
342         TyKind::Mac(ref mac) => {
343             visitor.visit_mac(mac)
344         }
345     }
346 }
347
348 pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) {
349     for segment in &path.segments {
350         visitor.visit_path_segment(path.span, segment);
351     }
352 }
353
354 pub fn walk_use_tree<'a, V: Visitor<'a>>(
355     visitor: &mut V, use_tree: &'a UseTree, id: NodeId,
356 ) {
357     visitor.visit_path(&use_tree.prefix, id);
358     match use_tree.kind {
359         UseTreeKind::Simple(rename, ..) => {
360             // the extra IDs are handled during HIR lowering
361             if let Some(rename) = rename {
362                 visitor.visit_ident(rename);
363             }
364         }
365         UseTreeKind::Glob => {},
366         UseTreeKind::Nested(ref use_trees) => {
367             for &(ref nested_tree, nested_id) in use_trees {
368                 visitor.visit_use_tree(nested_tree, nested_id, true);
369             }
370         }
371     }
372 }
373
374 pub fn walk_path_segment<'a, V: Visitor<'a>>(visitor: &mut V,
375                                              path_span: Span,
376                                              segment: &'a PathSegment) {
377     visitor.visit_ident(segment.ident);
378     if let Some(ref args) = segment.args {
379         visitor.visit_generic_args(path_span, args);
380     }
381 }
382
383 pub fn walk_generic_args<'a, V>(visitor: &mut V,
384                                 _path_span: Span,
385                                 generic_args: &'a GenericArgs)
386     where V: Visitor<'a>,
387 {
388     match *generic_args {
389         GenericArgs::AngleBracketed(ref data) => {
390             walk_list!(visitor, visit_generic_arg, &data.args);
391             walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
392         }
393         GenericArgs::Parenthesized(ref data) => {
394             walk_list!(visitor, visit_ty, &data.inputs);
395             walk_list!(visitor, visit_ty, &data.output);
396         }
397     }
398 }
399
400 pub fn walk_assoc_type_binding<'a, V: Visitor<'a>>(visitor: &mut V,
401                                                    type_binding: &'a TypeBinding) {
402     visitor.visit_ident(type_binding.ident);
403     visitor.visit_ty(&type_binding.ty);
404 }
405
406 pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
407     match pattern.node {
408         PatKind::TupleStruct(ref path, ref children, _) => {
409             visitor.visit_path(path, pattern.id);
410             walk_list!(visitor, visit_pat, children);
411         }
412         PatKind::Path(ref opt_qself, ref path) => {
413             if let Some(ref qself) = *opt_qself {
414                 visitor.visit_ty(&qself.ty);
415             }
416             visitor.visit_path(path, pattern.id)
417         }
418         PatKind::Struct(ref path, ref fields, _) => {
419             visitor.visit_path(path, pattern.id);
420             for field in fields {
421                 walk_list!(visitor, visit_attribute, field.node.attrs.iter());
422                 visitor.visit_ident(field.node.ident);
423                 visitor.visit_pat(&field.node.pat)
424             }
425         }
426         PatKind::Tuple(ref tuple_elements, _) => {
427             walk_list!(visitor, visit_pat, tuple_elements);
428         }
429         PatKind::Box(ref subpattern) |
430         PatKind::Ref(ref subpattern, _) |
431         PatKind::Paren(ref subpattern) => {
432             visitor.visit_pat(subpattern)
433         }
434         PatKind::Ident(_, ident, ref optional_subpattern) => {
435             visitor.visit_ident(ident);
436             walk_list!(visitor, visit_pat, optional_subpattern);
437         }
438         PatKind::Lit(ref expression) => visitor.visit_expr(expression),
439         PatKind::Range(ref lower_bound, ref upper_bound, _) => {
440             visitor.visit_expr(lower_bound);
441             visitor.visit_expr(upper_bound);
442         }
443         PatKind::Wild => (),
444         PatKind::Slice(ref prepatterns, ref slice_pattern, ref postpatterns) => {
445             walk_list!(visitor, visit_pat, prepatterns);
446             walk_list!(visitor, visit_pat, slice_pattern);
447             walk_list!(visitor, visit_pat, postpatterns);
448         }
449         PatKind::Mac(ref mac) => visitor.visit_mac(mac),
450     }
451 }
452
453 pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, foreign_item: &'a ForeignItem) {
454     visitor.visit_vis(&foreign_item.vis);
455     visitor.visit_ident(foreign_item.ident);
456
457     match foreign_item.node {
458         ForeignItemKind::Fn(ref function_declaration, ref generics) => {
459             walk_fn_decl(visitor, function_declaration);
460             visitor.visit_generics(generics)
461         }
462         ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ),
463         ForeignItemKind::Ty => (),
464         ForeignItemKind::Macro(ref mac) => visitor.visit_mac(mac),
465     }
466
467     walk_list!(visitor, visit_attribute, &foreign_item.attrs);
468 }
469
470 pub fn walk_global_asm<'a, V: Visitor<'a>>(_: &mut V, _: &'a GlobalAsm) {
471     // Empty!
472 }
473
474 pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) {
475     match *bound {
476         GenericBound::Trait(ref typ, ref modifier) => visitor.visit_poly_trait_ref(typ, modifier),
477         GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
478     }
479 }
480
481 pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) {
482     visitor.visit_ident(param.ident);
483     walk_list!(visitor, visit_attribute, param.attrs.iter());
484     walk_list!(visitor, visit_param_bound, &param.bounds);
485     match param.kind {
486         GenericParamKind::Lifetime => {}
487         GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default),
488     }
489 }
490
491 pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) {
492     walk_list!(visitor, visit_generic_param, &generics.params);
493     walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates);
494 }
495
496 pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a WherePredicate) {
497     match *predicate {
498         WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty,
499                                                            ref bounds,
500                                                            ref bound_generic_params,
501                                                            ..}) => {
502             visitor.visit_ty(bounded_ty);
503             walk_list!(visitor, visit_param_bound, bounds);
504             walk_list!(visitor, visit_generic_param, bound_generic_params);
505         }
506         WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
507                                                              ref bounds,
508                                                              ..}) => {
509             visitor.visit_lifetime(lifetime);
510             walk_list!(visitor, visit_param_bound, bounds);
511         }
512         WherePredicate::EqPredicate(WhereEqPredicate{ref lhs_ty,
513                                                      ref rhs_ty,
514                                                      ..}) => {
515             visitor.visit_ty(lhs_ty);
516             visitor.visit_ty(rhs_ty);
517         }
518     }
519 }
520
521 pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FunctionRetTy) {
522     if let FunctionRetTy::Ty(ref output_ty) = *ret_ty {
523         visitor.visit_ty(output_ty)
524     }
525 }
526
527 pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) {
528     for argument in &function_declaration.inputs {
529         visitor.visit_pat(&argument.pat);
530         visitor.visit_ty(&argument.ty)
531     }
532     visitor.visit_fn_ret_ty(&function_declaration.output)
533 }
534
535 pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl, _span: Span)
536     where V: Visitor<'a>,
537 {
538     match kind {
539         FnKind::ItemFn(_, _, _, body) => {
540             walk_fn_decl(visitor, declaration);
541             visitor.visit_block(body);
542         }
543         FnKind::Method(_, _, _, body) => {
544             walk_fn_decl(visitor, declaration);
545             visitor.visit_block(body);
546         }
547         FnKind::Closure(body) => {
548             walk_fn_decl(visitor, declaration);
549             visitor.visit_expr(body);
550         }
551     }
552 }
553
554 pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a TraitItem) {
555     visitor.visit_ident(trait_item.ident);
556     walk_list!(visitor, visit_attribute, &trait_item.attrs);
557     visitor.visit_generics(&trait_item.generics);
558     match trait_item.node {
559         TraitItemKind::Const(ref ty, ref default) => {
560             visitor.visit_ty(ty);
561             walk_list!(visitor, visit_expr, default);
562         }
563         TraitItemKind::Method(ref sig, None) => {
564             walk_fn_decl(visitor, &sig.decl);
565         }
566         TraitItemKind::Method(ref sig, Some(ref body)) => {
567             visitor.visit_fn(FnKind::Method(trait_item.ident, sig, None, body),
568                              &sig.decl, trait_item.span, trait_item.id);
569         }
570         TraitItemKind::Type(ref bounds, ref default) => {
571             walk_list!(visitor, visit_param_bound, bounds);
572             walk_list!(visitor, visit_ty, default);
573         }
574         TraitItemKind::Macro(ref mac) => {
575             visitor.visit_mac(mac);
576         }
577     }
578 }
579
580 pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplItem) {
581     visitor.visit_vis(&impl_item.vis);
582     visitor.visit_ident(impl_item.ident);
583     walk_list!(visitor, visit_attribute, &impl_item.attrs);
584     visitor.visit_generics(&impl_item.generics);
585     match impl_item.node {
586         ImplItemKind::Const(ref ty, ref expr) => {
587             visitor.visit_ty(ty);
588             visitor.visit_expr(expr);
589         }
590         ImplItemKind::Method(ref sig, ref body) => {
591             visitor.visit_fn(FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), body),
592                              &sig.decl, impl_item.span, impl_item.id);
593         }
594         ImplItemKind::Type(ref ty) => {
595             visitor.visit_ty(ty);
596         }
597         ImplItemKind::Existential(ref bounds) => {
598             walk_list!(visitor, visit_param_bound, bounds);
599         }
600         ImplItemKind::Macro(ref mac) => {
601             visitor.visit_mac(mac);
602         }
603     }
604 }
605
606 pub fn walk_struct_def<'a, V: Visitor<'a>>(visitor: &mut V, struct_definition: &'a VariantData) {
607     walk_list!(visitor, visit_struct_field, struct_definition.fields());
608 }
609
610 pub fn walk_struct_field<'a, V: Visitor<'a>>(visitor: &mut V, struct_field: &'a StructField) {
611     visitor.visit_vis(&struct_field.vis);
612     if let Some(ident) = struct_field.ident {
613         visitor.visit_ident(ident);
614     }
615     visitor.visit_ty(&struct_field.ty);
616     walk_list!(visitor, visit_attribute, &struct_field.attrs);
617 }
618
619 pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) {
620     walk_list!(visitor, visit_stmt, &block.stmts);
621 }
622
623 pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) {
624     match statement.node {
625         StmtKind::Local(ref local) => visitor.visit_local(local),
626         StmtKind::Item(ref item) => visitor.visit_item(item),
627         StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => {
628             visitor.visit_expr(expression)
629         }
630         StmtKind::Mac(ref mac) => {
631             let (ref mac, _, ref attrs) = **mac;
632             visitor.visit_mac(mac);
633             for attr in attrs.iter() {
634                 visitor.visit_attribute(attr);
635             }
636         }
637     }
638 }
639
640 pub fn walk_mac<'a, V: Visitor<'a>>(_: &mut V, _: &Mac) {
641     // Empty!
642 }
643
644 pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) {
645     visitor.visit_expr(&constant.value);
646 }
647
648 pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
649     for attr in expression.attrs.iter() {
650         visitor.visit_attribute(attr);
651     }
652     match expression.node {
653         ExprKind::Box(ref subexpression) => {
654             visitor.visit_expr(subexpression)
655         }
656         ExprKind::ObsoleteInPlace(ref place, ref subexpression) => {
657             visitor.visit_expr(place);
658             visitor.visit_expr(subexpression)
659         }
660         ExprKind::Array(ref subexpressions) => {
661             walk_list!(visitor, visit_expr, subexpressions);
662         }
663         ExprKind::Repeat(ref element, ref count) => {
664             visitor.visit_expr(element);
665             visitor.visit_anon_const(count)
666         }
667         ExprKind::Struct(ref path, ref fields, ref optional_base) => {
668             visitor.visit_path(path, expression.id);
669             for field in fields {
670                 walk_list!(visitor, visit_attribute, field.attrs.iter());
671                 visitor.visit_ident(field.ident);
672                 visitor.visit_expr(&field.expr)
673             }
674             walk_list!(visitor, visit_expr, optional_base);
675         }
676         ExprKind::Tup(ref subexpressions) => {
677             walk_list!(visitor, visit_expr, subexpressions);
678         }
679         ExprKind::Call(ref callee_expression, ref arguments) => {
680             visitor.visit_expr(callee_expression);
681             walk_list!(visitor, visit_expr, arguments);
682         }
683         ExprKind::MethodCall(ref segment, ref arguments) => {
684             visitor.visit_path_segment(expression.span, segment);
685             walk_list!(visitor, visit_expr, arguments);
686         }
687         ExprKind::Binary(_, ref left_expression, ref right_expression) => {
688             visitor.visit_expr(left_expression);
689             visitor.visit_expr(right_expression)
690         }
691         ExprKind::AddrOf(_, ref subexpression) | ExprKind::Unary(_, ref subexpression) => {
692             visitor.visit_expr(subexpression)
693         }
694         ExprKind::Lit(_) => {}
695         ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => {
696             visitor.visit_expr(subexpression);
697             visitor.visit_ty(typ)
698         }
699         ExprKind::If(ref head_expression, ref if_block, ref optional_else) => {
700             visitor.visit_expr(head_expression);
701             visitor.visit_block(if_block);
702             walk_list!(visitor, visit_expr, optional_else);
703         }
704         ExprKind::While(ref subexpression, ref block, ref opt_label) => {
705             walk_list!(visitor, visit_label, opt_label);
706             visitor.visit_expr(subexpression);
707             visitor.visit_block(block);
708         }
709         ExprKind::IfLet(ref pats, ref subexpression, ref if_block, ref optional_else) => {
710             walk_list!(visitor, visit_pat, pats);
711             visitor.visit_expr(subexpression);
712             visitor.visit_block(if_block);
713             walk_list!(visitor, visit_expr, optional_else);
714         }
715         ExprKind::WhileLet(ref pats, ref subexpression, ref block, ref opt_label) => {
716             walk_list!(visitor, visit_label, opt_label);
717             walk_list!(visitor, visit_pat, pats);
718             visitor.visit_expr(subexpression);
719             visitor.visit_block(block);
720         }
721         ExprKind::ForLoop(ref pattern, ref subexpression, ref block, ref opt_label) => {
722             walk_list!(visitor, visit_label, opt_label);
723             visitor.visit_pat(pattern);
724             visitor.visit_expr(subexpression);
725             visitor.visit_block(block);
726         }
727         ExprKind::Loop(ref block, ref opt_label) => {
728             walk_list!(visitor, visit_label, opt_label);
729             visitor.visit_block(block);
730         }
731         ExprKind::Match(ref subexpression, ref arms) => {
732             visitor.visit_expr(subexpression);
733             walk_list!(visitor, visit_arm, arms);
734         }
735         ExprKind::Closure(_, _, _, ref function_declaration, ref body, _decl_span) => {
736             visitor.visit_fn(FnKind::Closure(body),
737                              function_declaration,
738                              expression.span,
739                              expression.id)
740         }
741         ExprKind::Block(ref block, ref opt_label) => {
742             walk_list!(visitor, visit_label, opt_label);
743             visitor.visit_block(block);
744         }
745         ExprKind::Async(_, _, ref body) => {
746             visitor.visit_block(body);
747         }
748         ExprKind::Assign(ref left_hand_expression, ref right_hand_expression) => {
749             visitor.visit_expr(left_hand_expression);
750             visitor.visit_expr(right_hand_expression);
751         }
752         ExprKind::AssignOp(_, ref left_expression, ref right_expression) => {
753             visitor.visit_expr(left_expression);
754             visitor.visit_expr(right_expression);
755         }
756         ExprKind::Field(ref subexpression, ident) => {
757             visitor.visit_expr(subexpression);
758             visitor.visit_ident(ident);
759         }
760         ExprKind::Index(ref main_expression, ref index_expression) => {
761             visitor.visit_expr(main_expression);
762             visitor.visit_expr(index_expression)
763         }
764         ExprKind::Range(ref start, ref end, _) => {
765             walk_list!(visitor, visit_expr, start);
766             walk_list!(visitor, visit_expr, end);
767         }
768         ExprKind::Path(ref maybe_qself, ref path) => {
769             if let Some(ref qself) = *maybe_qself {
770                 visitor.visit_ty(&qself.ty);
771             }
772             visitor.visit_path(path, expression.id)
773         }
774         ExprKind::Break(ref opt_label, ref opt_expr) => {
775             walk_list!(visitor, visit_label, opt_label);
776             walk_list!(visitor, visit_expr, opt_expr);
777         }
778         ExprKind::Continue(ref opt_label) => {
779             walk_list!(visitor, visit_label, opt_label);
780         }
781         ExprKind::Ret(ref optional_expression) => {
782             walk_list!(visitor, visit_expr, optional_expression);
783         }
784         ExprKind::Mac(ref mac) => visitor.visit_mac(mac),
785         ExprKind::Paren(ref subexpression) => {
786             visitor.visit_expr(subexpression)
787         }
788         ExprKind::InlineAsm(ref ia) => {
789             for &(_, ref input) in &ia.inputs {
790                 visitor.visit_expr(input)
791             }
792             for output in &ia.outputs {
793                 visitor.visit_expr(&output.expr)
794             }
795         }
796         ExprKind::Yield(ref optional_expression) => {
797             walk_list!(visitor, visit_expr, optional_expression);
798         }
799         ExprKind::Try(ref subexpression) => {
800             visitor.visit_expr(subexpression)
801         }
802         ExprKind::TryBlock(ref body) => {
803             visitor.visit_block(body)
804         }
805         ExprKind::Err => {}
806     }
807
808     visitor.visit_expr_post(expression)
809 }
810
811 pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) {
812     walk_list!(visitor, visit_pat, &arm.pats);
813     if let Some(ref g) = &arm.guard {
814         match g {
815             Guard::If(ref e) => visitor.visit_expr(e),
816         }
817     }
818     visitor.visit_expr(&arm.body);
819     walk_list!(visitor, visit_attribute, &arm.attrs);
820 }
821
822 pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) {
823     if let VisibilityKind::Restricted { ref path, id } = vis.node {
824         visitor.visit_path(path, id);
825     }
826 }
827
828 pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) {
829     visitor.visit_tts(attr.tokens.clone());
830 }
831
832 pub fn walk_tt<'a, V: Visitor<'a>>(visitor: &mut V, tt: TokenTree) {
833     match tt {
834         TokenTree::Token(_, tok) => visitor.visit_token(tok),
835         TokenTree::Delimited(_, _, tts) => visitor.visit_tts(tts.stream()),
836     }
837 }
838
839 pub fn walk_tts<'a, V: Visitor<'a>>(visitor: &mut V, tts: TokenStream) {
840     for tt in tts.trees() {
841         visitor.visit_tt(tt);
842     }
843 }