]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/visit.rs
Auto merge of #24865 - bluss:range-size, r=alexcrichton
[rust.git] / src / libsyntax / visit.rs
1 // Copyright 2012-2014 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 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! AST walker. Each overridden visit method has full control over what
12 //! happens with its node, it can do its own traversal of the node's children,
13 //! call `visit::walk_*` to apply the default traversal algorithm, or prevent
14 //! deeper traversal by doing nothing.
15 //!
16 //! Note: it is an important invariant that the default visitor walks the body
17 //! of a function in "execution order" (more concretely, reverse post-order
18 //! with respect to the CFG implied by the AST), meaning that if AST node A may
19 //! execute before AST node B, then A is visited first.  The borrow checker in
20 //! particular relies on this property.
21 //!
22 //! Note: walking an AST before macro expansion is probably a bad idea. For
23 //! instance, a walker looking for item names in a module will miss all of
24 //! those that are created by the expansion of a macro.
25
26 pub use self::FnKind::*;
27
28 use abi::Abi;
29 use ast::*;
30 use ast;
31 use codemap::Span;
32 use ptr::P;
33 use owned_slice::OwnedSlice;
34
35 #[derive(Copy, Clone)]
36 pub enum FnKind<'a> {
37     /// fn foo() or extern "Abi" fn foo()
38     FkItemFn(Ident, &'a Generics, Unsafety, Abi, Visibility),
39
40     /// fn foo(&self)
41     FkMethod(Ident, &'a MethodSig, Option<Visibility>),
42
43     /// |x, y| ...
44     /// proc(x, y) ...
45     FkFnBlock,
46 }
47
48 /// Each method of the Visitor trait is a hook to be potentially
49 /// overridden.  Each method's default implementation recursively visits
50 /// the substructure of the input via the corresponding `walk` method;
51 /// e.g. the `visit_mod` method by default calls `visit::walk_mod`.
52 ///
53 /// If you want to ensure that your code handles every variant
54 /// explicitly, you need to override each method.  (And you also need
55 /// to monitor future changes to `Visitor` in case a new method with a
56 /// new default implementation gets introduced.)
57 pub trait Visitor<'v> : Sized {
58     fn visit_name(&mut self, _span: Span, _name: Name) {
59         // Nothing to do.
60     }
61     fn visit_ident(&mut self, span: Span, ident: Ident) {
62         self.visit_name(span, ident.name);
63     }
64     fn visit_mod(&mut self, m: &'v Mod, _s: Span, _n: NodeId) { walk_mod(self, m) }
65     fn visit_foreign_item(&mut self, i: &'v ForeignItem) { walk_foreign_item(self, i) }
66     fn visit_item(&mut self, i: &'v Item) { walk_item(self, i) }
67     fn visit_local(&mut self, l: &'v Local) { walk_local(self, l) }
68     fn visit_block(&mut self, b: &'v Block) { walk_block(self, b) }
69     fn visit_stmt(&mut self, s: &'v Stmt) { walk_stmt(self, s) }
70     fn visit_arm(&mut self, a: &'v Arm) { walk_arm(self, a) }
71     fn visit_pat(&mut self, p: &'v Pat) { walk_pat(self, p) }
72     fn visit_decl(&mut self, d: &'v Decl) { walk_decl(self, d) }
73     fn visit_expr(&mut self, ex: &'v Expr) { walk_expr(self, ex) }
74     fn visit_expr_post(&mut self, _ex: &'v Expr) { }
75     fn visit_ty(&mut self, t: &'v Ty) { walk_ty(self, t) }
76     fn visit_generics(&mut self, g: &'v Generics) { walk_generics(self, g) }
77     fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, _: NodeId) {
78         walk_fn(self, fk, fd, b, s)
79     }
80     fn visit_trait_item(&mut self, ti: &'v TraitItem) { walk_trait_item(self, ti) }
81     fn visit_impl_item(&mut self, ii: &'v ImplItem) { walk_impl_item(self, ii) }
82     fn visit_trait_ref(&mut self, t: &'v TraitRef) { walk_trait_ref(self, t) }
83     fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
84         walk_ty_param_bound(self, bounds)
85     }
86     fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) {
87         walk_poly_trait_ref(self, t, m)
88     }
89     fn visit_struct_def(&mut self, s: &'v StructDef, _: Ident, _: &'v Generics, _: NodeId) {
90         walk_struct_def(self, s)
91     }
92     fn visit_struct_field(&mut self, s: &'v StructField) { walk_struct_field(self, s) }
93     fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics) { walk_variant(self, v, g) }
94
95     /// Visits an optional reference to a lifetime. The `span` is the span of some surrounding
96     /// reference should opt_lifetime be None.
97     fn visit_opt_lifetime_ref(&mut self,
98                               _span: Span,
99                               opt_lifetime: &'v Option<Lifetime>) {
100         match *opt_lifetime {
101             Some(ref l) => self.visit_lifetime_ref(l),
102             None => ()
103         }
104     }
105     fn visit_lifetime_bound(&mut self, lifetime: &'v Lifetime) {
106         walk_lifetime_bound(self, lifetime)
107     }
108     fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) {
109         walk_lifetime_ref(self, lifetime)
110     }
111     fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) {
112         walk_lifetime_def(self, lifetime)
113     }
114     fn visit_explicit_self(&mut self, es: &'v ExplicitSelf) {
115         walk_explicit_self(self, es)
116     }
117     fn visit_mac(&mut self, _mac: &'v Mac) {
118         panic!("visit_mac disabled by default");
119         // NB: see note about macros above.
120         // if you really want a visitor that
121         // works on macros, use this
122         // definition in your trait impl:
123         // visit::walk_mac(self, _mac)
124     }
125     fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) {
126         walk_path(self, path)
127     }
128     fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
129         walk_path_segment(self, path_span, path_segment)
130     }
131     fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) {
132         walk_path_parameters(self, path_span, path_parameters)
133     }
134     fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding) {
135         walk_assoc_type_binding(self, type_binding)
136     }
137     fn visit_attribute(&mut self, _attr: &'v Attribute) {}
138 }
139
140 pub fn walk_inlined_item<'v,V>(visitor: &mut V, item: &'v InlinedItem)
141                          where V: Visitor<'v> {
142     match *item {
143         IIItem(ref i) => visitor.visit_item(&**i),
144         IIForeign(ref i) => visitor.visit_foreign_item(&**i),
145         IITraitItem(_, ref ti) => visitor.visit_trait_item(ti),
146         IIImplItem(_, ref ii) => visitor.visit_impl_item(ii),
147     }
148 }
149
150
151 pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
152     visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
153     for attr in &krate.attrs {
154         visitor.visit_attribute(attr);
155     }
156 }
157
158 pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) {
159     for item in &module.items {
160         visitor.visit_item(&**item)
161     }
162 }
163
164 pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
165     visitor.visit_pat(&*local.pat);
166     walk_ty_opt(visitor, &local.ty);
167     walk_expr_opt(visitor, &local.init);
168 }
169
170 pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V,
171                                               lifetime_def: &'v LifetimeDef) {
172     visitor.visit_name(lifetime_def.lifetime.span, lifetime_def.lifetime.name);
173     for bound in &lifetime_def.bounds {
174         visitor.visit_lifetime_bound(bound);
175     }
176 }
177
178 pub fn walk_lifetime_bound<'v, V: Visitor<'v>>(visitor: &mut V,
179                                                lifetime_ref: &'v Lifetime) {
180     visitor.visit_lifetime_ref(lifetime_ref)
181 }
182
183 pub fn walk_lifetime_ref<'v, V: Visitor<'v>>(visitor: &mut V,
184                                              lifetime_ref: &'v Lifetime) {
185     visitor.visit_name(lifetime_ref.span, lifetime_ref.name)
186 }
187
188 pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V,
189                                               explicit_self: &'v ExplicitSelf) {
190     match explicit_self.node {
191         SelfStatic | SelfValue(_) => {},
192         SelfRegion(ref lifetime, _, _) => {
193             visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime)
194         }
195         SelfExplicit(ref typ, _) => visitor.visit_ty(&**typ),
196     }
197 }
198
199 pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
200                                   trait_ref: &'v PolyTraitRef,
201                                   _modifier: &'v TraitBoundModifier)
202     where V: Visitor<'v>
203 {
204     walk_lifetime_decls_helper(visitor, &trait_ref.bound_lifetimes);
205     visitor.visit_trait_ref(&trait_ref.trait_ref);
206 }
207
208 pub fn walk_trait_ref<'v,V>(visitor: &mut V,
209                                    trait_ref: &'v TraitRef)
210     where V: Visitor<'v>
211 {
212     visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
213 }
214
215 pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
216     visitor.visit_ident(item.span, item.ident);
217     match item.node {
218         ItemExternCrate(..) => {}
219         ItemUse(ref vp) => {
220             match vp.node {
221                 ViewPathSimple(ident, ref path) => {
222                     visitor.visit_ident(vp.span, ident);
223                     visitor.visit_path(path, item.id);
224                 }
225                 ViewPathGlob(ref path) => {
226                     visitor.visit_path(path, item.id);
227                 }
228                 ViewPathList(ref prefix, ref list) => {
229                     for id in list {
230                         match id.node {
231                             PathListIdent { name, .. } => {
232                                 visitor.visit_ident(id.span, name);
233                             }
234                             PathListMod { .. } => ()
235                         }
236                     }
237
238                     // Note that the `prefix` here is not a complete
239                     // path, so we don't use `visit_path`.
240                     walk_path(visitor, prefix);
241                 }
242             }
243         }
244         ItemStatic(ref typ, _, ref expr) |
245         ItemConst(ref typ, ref expr) => {
246             visitor.visit_ty(&**typ);
247             visitor.visit_expr(&**expr);
248         }
249         ItemFn(ref declaration, fn_style, abi, ref generics, ref body) => {
250             visitor.visit_fn(FkItemFn(item.ident, generics, fn_style, abi, item.vis),
251                              &**declaration,
252                              &**body,
253                              item.span,
254                              item.id)
255         }
256         ItemMod(ref module) => {
257             visitor.visit_mod(module, item.span, item.id)
258         }
259         ItemForeignMod(ref foreign_module) => {
260             for foreign_item in &foreign_module.items {
261                 visitor.visit_foreign_item(&**foreign_item)
262             }
263         }
264         ItemTy(ref typ, ref type_parameters) => {
265             visitor.visit_ty(&**typ);
266             visitor.visit_generics(type_parameters)
267         }
268         ItemEnum(ref enum_definition, ref type_parameters) => {
269             visitor.visit_generics(type_parameters);
270             walk_enum_def(visitor, enum_definition, type_parameters)
271         }
272         ItemDefaultImpl(_, ref trait_ref) => {
273             visitor.visit_trait_ref(trait_ref)
274         }
275         ItemImpl(_, _,
276                  ref type_parameters,
277                  ref trait_reference,
278                  ref typ,
279                  ref impl_items) => {
280             visitor.visit_generics(type_parameters);
281             match *trait_reference {
282                 Some(ref trait_reference) => visitor.visit_trait_ref(trait_reference),
283                 None => ()
284             }
285             visitor.visit_ty(&**typ);
286             for impl_item in impl_items {
287                 visitor.visit_impl_item(impl_item);
288             }
289         }
290         ItemStruct(ref struct_definition, ref generics) => {
291             visitor.visit_generics(generics);
292             visitor.visit_struct_def(&**struct_definition,
293                                      item.ident,
294                                      generics,
295                                      item.id)
296         }
297         ItemTrait(_, ref generics, ref bounds, ref methods) => {
298             visitor.visit_generics(generics);
299             walk_ty_param_bounds_helper(visitor, bounds);
300             for method in methods {
301                 visitor.visit_trait_item(method)
302             }
303         }
304         ItemMac(ref mac) => visitor.visit_mac(mac),
305     }
306     for attr in &item.attrs {
307         visitor.visit_attribute(attr);
308     }
309 }
310
311 pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V,
312                                          enum_definition: &'v EnumDef,
313                                          generics: &'v Generics) {
314     for variant in &enum_definition.variants {
315         visitor.visit_variant(&**variant, generics);
316     }
317 }
318
319 pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
320                                         variant: &'v Variant,
321                                         generics: &'v Generics) {
322     visitor.visit_ident(variant.span, variant.node.name);
323
324     match variant.node.kind {
325         TupleVariantKind(ref variant_arguments) => {
326             for variant_argument in variant_arguments {
327                 visitor.visit_ty(&*variant_argument.ty)
328             }
329         }
330         StructVariantKind(ref struct_definition) => {
331             visitor.visit_struct_def(&**struct_definition,
332                                      variant.node.name,
333                                      generics,
334                                      variant.node.id)
335         }
336     }
337     match variant.node.disr_expr {
338         Some(ref expr) => visitor.visit_expr(&**expr),
339         None => ()
340     }
341     for attr in &variant.node.attrs {
342         visitor.visit_attribute(attr);
343     }
344 }
345
346 pub fn skip_ty<'v, V: Visitor<'v>>(_: &mut V, _: &'v Ty) {
347     // Empty!
348 }
349
350 pub fn walk_ty_opt<'v, V: Visitor<'v>>(visitor: &mut V, optional_type: &'v Option<P<Ty>>) {
351     match *optional_type {
352         Some(ref ty) => visitor.visit_ty(&**ty),
353         None => ()
354     }
355 }
356
357 pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
358     match typ.node {
359         TyVec(ref ty) | TyParen(ref ty) => {
360             visitor.visit_ty(&**ty)
361         }
362         TyPtr(ref mutable_type) => {
363             visitor.visit_ty(&*mutable_type.ty)
364         }
365         TyRptr(ref lifetime, ref mutable_type) => {
366             visitor.visit_opt_lifetime_ref(typ.span, lifetime);
367             visitor.visit_ty(&*mutable_type.ty)
368         }
369         TyTup(ref tuple_element_types) => {
370             for tuple_element_type in tuple_element_types {
371                 visitor.visit_ty(&**tuple_element_type)
372             }
373         }
374         TyBareFn(ref function_declaration) => {
375             for argument in &function_declaration.decl.inputs {
376                 visitor.visit_ty(&*argument.ty)
377             }
378             walk_fn_ret_ty(visitor, &function_declaration.decl.output);
379             walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
380         }
381         TyPath(ref maybe_qself, ref path) => {
382             if let Some(ref qself) = *maybe_qself {
383                 visitor.visit_ty(&qself.ty);
384             }
385             visitor.visit_path(path, typ.id);
386         }
387         TyObjectSum(ref ty, ref bounds) => {
388             visitor.visit_ty(&**ty);
389             walk_ty_param_bounds_helper(visitor, bounds);
390         }
391         TyFixedLengthVec(ref ty, ref expression) => {
392             visitor.visit_ty(&**ty);
393             visitor.visit_expr(&**expression)
394         }
395         TyPolyTraitRef(ref bounds) => {
396             walk_ty_param_bounds_helper(visitor, bounds)
397         }
398         TyTypeof(ref expression) => {
399             visitor.visit_expr(&**expression)
400         }
401         TyInfer => {}
402     }
403 }
404
405 pub fn walk_lifetime_decls_helper<'v, V: Visitor<'v>>(visitor: &mut V,
406                                                       lifetimes: &'v Vec<LifetimeDef>) {
407     for l in lifetimes {
408         visitor.visit_lifetime_def(l);
409     }
410 }
411
412 pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
413     for segment in &path.segments {
414         visitor.visit_path_segment(path.span, segment);
415     }
416 }
417
418 pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
419                                              path_span: Span,
420                                              segment: &'v PathSegment) {
421     visitor.visit_ident(path_span, segment.identifier);
422     visitor.visit_path_parameters(path_span, &segment.parameters);
423 }
424
425 pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
426                                                 _path_span: Span,
427                                                 path_parameters: &'v PathParameters) {
428     match *path_parameters {
429         ast::AngleBracketedParameters(ref data) => {
430             for typ in &*data.types {
431                 visitor.visit_ty(&**typ);
432             }
433             for lifetime in &data.lifetimes {
434                 visitor.visit_lifetime_ref(lifetime);
435             }
436             for binding in &*data.bindings {
437                 visitor.visit_assoc_type_binding(&**binding);
438             }
439         }
440         ast::ParenthesizedParameters(ref data) => {
441             for typ in &data.inputs {
442                 visitor.visit_ty(&**typ);
443             }
444             if let Some(ref typ) = data.output {
445                 visitor.visit_ty(&**typ);
446             }
447         }
448     }
449 }
450
451 pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
452                                                    type_binding: &'v TypeBinding) {
453     visitor.visit_ident(type_binding.span, type_binding.ident);
454     visitor.visit_ty(&*type_binding.ty);
455 }
456
457 pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
458     match pattern.node {
459         PatEnum(ref path, ref children) => {
460             visitor.visit_path(path, pattern.id);
461             if let Some(ref children) = *children {
462                 for child in children {
463                     visitor.visit_pat(&*child)
464                 }
465             }
466         }
467         PatQPath(ref qself, ref path) => {
468             visitor.visit_ty(&qself.ty);
469             visitor.visit_path(path, pattern.id)
470         }
471         PatStruct(ref path, ref fields, _) => {
472             visitor.visit_path(path, pattern.id);
473             for field in fields {
474                 visitor.visit_pat(&*field.node.pat)
475             }
476         }
477         PatTup(ref tuple_elements) => {
478             for tuple_element in tuple_elements {
479                 visitor.visit_pat(&**tuple_element)
480             }
481         }
482         PatBox(ref subpattern) |
483         PatRegion(ref subpattern, _) => {
484             visitor.visit_pat(&**subpattern)
485         }
486         PatIdent(_, ref pth1, ref optional_subpattern) => {
487             visitor.visit_ident(pth1.span, pth1.node);
488             match *optional_subpattern {
489                 None => {}
490                 Some(ref subpattern) => visitor.visit_pat(&**subpattern),
491             }
492         }
493         PatLit(ref expression) => visitor.visit_expr(&**expression),
494         PatRange(ref lower_bound, ref upper_bound) => {
495             visitor.visit_expr(&**lower_bound);
496             visitor.visit_expr(&**upper_bound)
497         }
498         PatWild(_) => (),
499         PatVec(ref prepattern, ref slice_pattern, ref postpatterns) => {
500             for prepattern in prepattern {
501                 visitor.visit_pat(&**prepattern)
502             }
503             if let Some(ref slice_pattern) = *slice_pattern {
504                 visitor.visit_pat(&**slice_pattern)
505             }
506             for postpattern in postpatterns {
507                 visitor.visit_pat(&**postpattern)
508             }
509         }
510         PatMac(ref mac) => visitor.visit_mac(mac),
511     }
512 }
513
514 pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V,
515                                              foreign_item: &'v ForeignItem) {
516     visitor.visit_ident(foreign_item.span, foreign_item.ident);
517
518     match foreign_item.node {
519         ForeignItemFn(ref function_declaration, ref generics) => {
520             walk_fn_decl(visitor, &**function_declaration);
521             visitor.visit_generics(generics)
522         }
523         ForeignItemStatic(ref typ, _) => visitor.visit_ty(&**typ),
524     }
525
526     for attr in &foreign_item.attrs {
527         visitor.visit_attribute(attr);
528     }
529 }
530
531 pub fn walk_ty_param_bounds_helper<'v, V: Visitor<'v>>(visitor: &mut V,
532                                                        bounds: &'v OwnedSlice<TyParamBound>) {
533     for bound in &**bounds {
534         visitor.visit_ty_param_bound(bound)
535     }
536 }
537
538 pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V,
539                                                bound: &'v TyParamBound) {
540     match *bound {
541         TraitTyParamBound(ref typ, ref modifier) => {
542             visitor.visit_poly_trait_ref(typ, modifier);
543         }
544         RegionTyParamBound(ref lifetime) => {
545             visitor.visit_lifetime_bound(lifetime);
546         }
547     }
548 }
549
550 pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
551     for param in &*generics.ty_params {
552         visitor.visit_ident(param.span, param.ident);
553         walk_ty_param_bounds_helper(visitor, &param.bounds);
554         walk_ty_opt(visitor, &param.default);
555     }
556     walk_lifetime_decls_helper(visitor, &generics.lifetimes);
557     for predicate in &generics.where_clause.predicates {
558         match predicate {
559             &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bounded_ty,
560                                                                           ref bounds,
561                                                                           ..}) => {
562                 visitor.visit_ty(&**bounded_ty);
563                 walk_ty_param_bounds_helper(visitor, bounds);
564             }
565             &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
566                                                                             ref bounds,
567                                                                             ..}) => {
568                 visitor.visit_lifetime_ref(lifetime);
569
570                 for bound in bounds {
571                     visitor.visit_lifetime_ref(bound);
572                 }
573             }
574             &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,
575                                                                     ref path,
576                                                                     ref ty,
577                                                                     ..}) => {
578                 visitor.visit_path(path, id);
579                 visitor.visit_ty(&**ty);
580             }
581         }
582     }
583 }
584
585 pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionRetTy) {
586     if let Return(ref output_ty) = *ret_ty {
587         visitor.visit_ty(&**output_ty)
588     }
589 }
590
591 pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
592     for argument in &function_declaration.inputs {
593         visitor.visit_pat(&*argument.pat);
594         visitor.visit_ty(&*argument.ty)
595     }
596     walk_fn_ret_ty(visitor, &function_declaration.output)
597 }
598
599 pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
600                                    function_kind: FnKind<'v>,
601                                    function_declaration: &'v FnDecl,
602                                    function_body: &'v Block,
603                                    _span: Span) {
604     walk_fn_decl(visitor, function_declaration);
605
606     match function_kind {
607         FkItemFn(_, generics, _, _, _) => {
608             visitor.visit_generics(generics);
609         }
610         FkMethod(_, sig, _) => {
611             visitor.visit_generics(&sig.generics);
612             visitor.visit_explicit_self(&sig.explicit_self);
613         }
614         FkFnBlock(..) => {}
615     }
616
617     visitor.visit_block(function_body)
618 }
619
620 pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) {
621     visitor.visit_ident(trait_item.span, trait_item.ident);
622     for attr in &trait_item.attrs {
623         visitor.visit_attribute(attr);
624     }
625     match trait_item.node {
626         ConstTraitItem(ref ty, ref default) => {
627             visitor.visit_ty(ty);
628             if let Some(ref expr) = *default {
629                 visitor.visit_expr(expr);
630             }
631         }
632         MethodTraitItem(ref sig, None) => {
633             visitor.visit_explicit_self(&sig.explicit_self);
634             visitor.visit_generics(&sig.generics);
635             walk_fn_decl(visitor, &sig.decl);
636         }
637         MethodTraitItem(ref sig, Some(ref body)) => {
638             visitor.visit_fn(FkMethod(trait_item.ident, sig, None), &sig.decl,
639                              body, trait_item.span, trait_item.id);
640         }
641         TypeTraitItem(ref bounds, ref default) => {
642             walk_ty_param_bounds_helper(visitor, bounds);
643             walk_ty_opt(visitor, default);
644         }
645     }
646 }
647
648 pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
649     visitor.visit_ident(impl_item.span, impl_item.ident);
650     for attr in &impl_item.attrs {
651         visitor.visit_attribute(attr);
652     }
653     match impl_item.node {
654         ConstImplItem(ref ty, ref expr) => {
655             visitor.visit_ty(ty);
656             visitor.visit_expr(expr);
657         }
658         MethodImplItem(ref sig, ref body) => {
659             visitor.visit_fn(FkMethod(impl_item.ident, sig, Some(impl_item.vis)), &sig.decl,
660                              body, impl_item.span, impl_item.id);
661         }
662         TypeImplItem(ref ty) => {
663             visitor.visit_ty(ty);
664         }
665         MacImplItem(ref mac) => {
666             visitor.visit_mac(mac);
667         }
668     }
669 }
670
671 pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V,
672                                            struct_definition: &'v StructDef) {
673     for field in &struct_definition.fields {
674         visitor.visit_struct_field(field)
675     }
676 }
677
678 pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V,
679                                              struct_field: &'v StructField) {
680     if let NamedField(name, _) = struct_field.node.kind {
681         visitor.visit_ident(struct_field.span, name);
682     }
683
684     visitor.visit_ty(&*struct_field.node.ty);
685
686     for attr in &struct_field.node.attrs {
687         visitor.visit_attribute(attr);
688     }
689 }
690
691 pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) {
692     for statement in &block.stmts {
693         visitor.visit_stmt(&**statement)
694     }
695     walk_expr_opt(visitor, &block.expr)
696 }
697
698 pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
699     match statement.node {
700         StmtDecl(ref declaration, _) => visitor.visit_decl(&**declaration),
701         StmtExpr(ref expression, _) | StmtSemi(ref expression, _) => {
702             visitor.visit_expr(&**expression)
703         }
704         StmtMac(ref mac, _) => visitor.visit_mac(&**mac),
705     }
706 }
707
708 pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) {
709     match declaration.node {
710         DeclLocal(ref local) => visitor.visit_local(&**local),
711         DeclItem(ref item) => visitor.visit_item(&**item),
712     }
713 }
714
715 pub fn walk_expr_opt<'v, V: Visitor<'v>>(visitor: &mut V,
716                                          optional_expression: &'v Option<P<Expr>>) {
717     match *optional_expression {
718         None => {}
719         Some(ref expression) => visitor.visit_expr(&**expression),
720     }
721 }
722
723 pub fn walk_exprs<'v, V: Visitor<'v>>(visitor: &mut V, expressions: &'v [P<Expr>]) {
724     for expression in expressions {
725         visitor.visit_expr(&**expression)
726     }
727 }
728
729 pub fn walk_mac<'v, V: Visitor<'v>>(_: &mut V, _: &'v Mac) {
730     // Empty!
731 }
732
733 pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
734     match expression.node {
735         ExprBox(ref place, ref subexpression) => {
736             place.as_ref().map(|e|visitor.visit_expr(&**e));
737             visitor.visit_expr(&**subexpression)
738         }
739         ExprVec(ref subexpressions) => {
740             walk_exprs(visitor, subexpressions)
741         }
742         ExprRepeat(ref element, ref count) => {
743             visitor.visit_expr(&**element);
744             visitor.visit_expr(&**count)
745         }
746         ExprStruct(ref path, ref fields, ref optional_base) => {
747             visitor.visit_path(path, expression.id);
748             for field in fields {
749                 visitor.visit_expr(&*field.expr)
750             }
751             walk_expr_opt(visitor, optional_base)
752         }
753         ExprTup(ref subexpressions) => {
754             for subexpression in subexpressions {
755                 visitor.visit_expr(&**subexpression)
756             }
757         }
758         ExprCall(ref callee_expression, ref arguments) => {
759             for argument in arguments {
760                 visitor.visit_expr(&**argument)
761             }
762             visitor.visit_expr(&**callee_expression)
763         }
764         ExprMethodCall(_, ref types, ref arguments) => {
765             walk_exprs(visitor, arguments);
766             for typ in types {
767                 visitor.visit_ty(&**typ)
768             }
769         }
770         ExprBinary(_, ref left_expression, ref right_expression) => {
771             visitor.visit_expr(&**left_expression);
772             visitor.visit_expr(&**right_expression)
773         }
774         ExprAddrOf(_, ref subexpression) | ExprUnary(_, ref subexpression) => {
775             visitor.visit_expr(&**subexpression)
776         }
777         ExprLit(_) => {}
778         ExprCast(ref subexpression, ref typ) => {
779             visitor.visit_expr(&**subexpression);
780             visitor.visit_ty(&**typ)
781         }
782         ExprIf(ref head_expression, ref if_block, ref optional_else) => {
783             visitor.visit_expr(&**head_expression);
784             visitor.visit_block(&**if_block);
785             walk_expr_opt(visitor, optional_else)
786         }
787         ExprWhile(ref subexpression, ref block, _) => {
788             visitor.visit_expr(&**subexpression);
789             visitor.visit_block(&**block)
790         }
791         ExprIfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => {
792             visitor.visit_pat(&**pattern);
793             visitor.visit_expr(&**subexpression);
794             visitor.visit_block(&**if_block);
795             walk_expr_opt(visitor, optional_else);
796         }
797         ExprWhileLet(ref pattern, ref subexpression, ref block, _) => {
798             visitor.visit_pat(&**pattern);
799             visitor.visit_expr(&**subexpression);
800             visitor.visit_block(&**block);
801         }
802         ExprForLoop(ref pattern, ref subexpression, ref block, _) => {
803             visitor.visit_pat(&**pattern);
804             visitor.visit_expr(&**subexpression);
805             visitor.visit_block(&**block)
806         }
807         ExprLoop(ref block, _) => visitor.visit_block(&**block),
808         ExprMatch(ref subexpression, ref arms, _) => {
809             visitor.visit_expr(&**subexpression);
810             for arm in arms {
811                 visitor.visit_arm(arm)
812             }
813         }
814         ExprClosure(_, ref function_declaration, ref body) => {
815             visitor.visit_fn(FkFnBlock,
816                              &**function_declaration,
817                              &**body,
818                              expression.span,
819                              expression.id)
820         }
821         ExprBlock(ref block) => visitor.visit_block(&**block),
822         ExprAssign(ref left_hand_expression, ref right_hand_expression) => {
823             visitor.visit_expr(&**right_hand_expression);
824             visitor.visit_expr(&**left_hand_expression)
825         }
826         ExprAssignOp(_, ref left_expression, ref right_expression) => {
827             visitor.visit_expr(&**right_expression);
828             visitor.visit_expr(&**left_expression)
829         }
830         ExprField(ref subexpression, _) => {
831             visitor.visit_expr(&**subexpression);
832         }
833         ExprTupField(ref subexpression, _) => {
834             visitor.visit_expr(&**subexpression);
835         }
836         ExprIndex(ref main_expression, ref index_expression) => {
837             visitor.visit_expr(&**main_expression);
838             visitor.visit_expr(&**index_expression)
839         }
840         ExprRange(ref start, ref end) => {
841             walk_expr_opt(visitor, start);
842             walk_expr_opt(visitor, end)
843         }
844         ExprPath(ref maybe_qself, ref path) => {
845             if let Some(ref qself) = *maybe_qself {
846                 visitor.visit_ty(&qself.ty);
847             }
848             visitor.visit_path(path, expression.id)
849         }
850         ExprBreak(_) | ExprAgain(_) => {}
851         ExprRet(ref optional_expression) => {
852             walk_expr_opt(visitor, optional_expression)
853         }
854         ExprMac(ref mac) => visitor.visit_mac(mac),
855         ExprParen(ref subexpression) => {
856             visitor.visit_expr(&**subexpression)
857         }
858         ExprInlineAsm(ref ia) => {
859             for input in &ia.inputs {
860                 let (_, ref input) = *input;
861                 visitor.visit_expr(&**input)
862             }
863             for output in &ia.outputs {
864                 let (_, ref output, _) = *output;
865                 visitor.visit_expr(&**output)
866             }
867         }
868     }
869
870     visitor.visit_expr_post(expression)
871 }
872
873 pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
874     for pattern in &arm.pats {
875         visitor.visit_pat(&**pattern)
876     }
877     walk_expr_opt(visitor, &arm.guard);
878     visitor.visit_expr(&*arm.body);
879     for attr in &arm.attrs {
880         visitor.visit_attribute(attr);
881     }
882 }