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