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