]> git.proxmox.com Git - rustc.git/blob - src/librustc/hir/intravisit.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / librustc / hir / intravisit.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 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! HIR 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 `intravisit::walk_*` to apply the default traversal algorithm, or prevent
14 //! deeper traversal by doing nothing.
15 //!
16 //! When visiting the HIR, the contents of nested items are NOT visited
17 //! by default. This is different from the AST visitor, which does a deep walk.
18 //! Hence this module is called `intravisit`; see the method `visit_nested_item`
19 //! for more details.
20 //!
21 //! Note: it is an important invariant that the default visitor walks
22 //! the body of a function in "execution order" (more concretely,
23 //! reverse post-order with respect to the CFG implied by the AST),
24 //! meaning that if AST node A may execute before AST node B, then A
25 //! is visited first. The borrow checker in particular relies on this
26 //! property.
27
28 use syntax::abi::Abi;
29 use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute};
30 use syntax::attr::ThinAttributesExt;
31 use syntax::codemap::Span;
32 use hir::*;
33
34 use std::cmp;
35 use std::u32;
36
37 #[derive(Copy, Clone, PartialEq, Eq)]
38 pub enum FnKind<'a> {
39 /// fn foo() or extern "Abi" fn foo()
40 ItemFn(Name, &'a Generics, Unsafety, Constness, Abi, &'a Visibility, &'a [Attribute]),
41
42 /// fn foo(&self)
43 Method(Name, &'a MethodSig, Option<&'a Visibility>, &'a [Attribute]),
44
45 /// |x, y| {}
46 Closure(&'a [Attribute]),
47 }
48
49 impl<'a> FnKind<'a> {
50 pub fn attrs(&self) -> &'a [Attribute] {
51 match *self {
52 FnKind::ItemFn(_, _, _, _, _, _, attrs) => attrs,
53 FnKind::Method(_, _, _, attrs) => attrs,
54 FnKind::Closure(attrs) => attrs,
55 }
56 }
57 }
58
59 /// Each method of the Visitor trait is a hook to be potentially
60 /// overridden. Each method's default implementation recursively visits
61 /// the substructure of the input via the corresponding `walk` method;
62 /// e.g. the `visit_mod` method by default calls `intravisit::walk_mod`.
63 ///
64 /// Note that this visitor does NOT visit nested items by default
65 /// (this is why the module is called `intravisit`, to distinguish it
66 /// from the AST's `visit` module, which acts differently). If you
67 /// simply want to visit all items in the crate in some order, you
68 /// should call `Crate::visit_all_items`. Otherwise, see the comment
69 /// on `visit_nested_item` for details on how to visit nested items.
70 ///
71 /// If you want to ensure that your code handles every variant
72 /// explicitly, you need to override each method. (And you also need
73 /// to monitor future changes to `Visitor` in case a new method with a
74 /// new default implementation gets introduced.)
75 pub trait Visitor<'v> : Sized {
76 ///////////////////////////////////////////////////////////////////////////
77 // Nested items.
78
79 /// Invoked when a nested item is encountered. By default, does
80 /// nothing. If you want a deep walk, you need to override to
81 /// fetch the item contents. But most of the time, it is easier
82 /// (and better) to invoke `Crate::visit_all_items`, which visits
83 /// all items in the crate in some order (but doesn't respect
84 /// nesting).
85 #[allow(unused_variables)]
86 fn visit_nested_item(&mut self, id: ItemId) {
87 }
88
89 /// Visit the top-level item and (optionally) nested items. See
90 /// `visit_nested_item` for details.
91 fn visit_item(&mut self, i: &'v Item) {
92 walk_item(self, i)
93 }
94
95 ///////////////////////////////////////////////////////////////////////////
96
97 fn visit_name(&mut self, _span: Span, _name: Name) {
98 // Nothing to do.
99 }
100 fn visit_ident(&mut self, span: Span, ident: Ident) {
101 walk_ident(self, span, ident);
102 }
103 fn visit_mod(&mut self, m: &'v Mod, _s: Span, _n: NodeId) {
104 walk_mod(self, m)
105 }
106 fn visit_foreign_item(&mut self, i: &'v ForeignItem) {
107 walk_foreign_item(self, i)
108 }
109 fn visit_local(&mut self, l: &'v Local) {
110 walk_local(self, l)
111 }
112 fn visit_block(&mut self, b: &'v Block) {
113 walk_block(self, b)
114 }
115 fn visit_stmt(&mut self, s: &'v Stmt) {
116 walk_stmt(self, s)
117 }
118 fn visit_arm(&mut self, a: &'v Arm) {
119 walk_arm(self, a)
120 }
121 fn visit_pat(&mut self, p: &'v Pat) {
122 walk_pat(self, p)
123 }
124 fn visit_decl(&mut self, d: &'v Decl) {
125 walk_decl(self, d)
126 }
127 fn visit_expr(&mut self, ex: &'v Expr) {
128 walk_expr(self, ex)
129 }
130 fn visit_expr_post(&mut self, _ex: &'v Expr) {
131 }
132 fn visit_ty(&mut self, t: &'v Ty) {
133 walk_ty(self, t)
134 }
135 fn visit_generics(&mut self, g: &'v Generics) {
136 walk_generics(self, g)
137 }
138 fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, _: NodeId) {
139 walk_fn(self, fk, fd, b, s)
140 }
141 fn visit_trait_item(&mut self, ti: &'v TraitItem) {
142 walk_trait_item(self, ti)
143 }
144 fn visit_impl_item(&mut self, ii: &'v ImplItem) {
145 walk_impl_item(self, ii)
146 }
147 fn visit_trait_ref(&mut self, t: &'v TraitRef) {
148 walk_trait_ref(self, t)
149 }
150 fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
151 walk_ty_param_bound(self, bounds)
152 }
153 fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) {
154 walk_poly_trait_ref(self, t, m)
155 }
156 fn visit_variant_data(&mut self,
157 s: &'v VariantData,
158 _: Name,
159 _: &'v Generics,
160 _: NodeId,
161 _: Span) {
162 walk_struct_def(self, s)
163 }
164 fn visit_struct_field(&mut self, s: &'v StructField) {
165 walk_struct_field(self, s)
166 }
167 fn visit_enum_def(&mut self,
168 enum_definition: &'v EnumDef,
169 generics: &'v Generics,
170 item_id: NodeId,
171 _: Span) {
172 walk_enum_def(self, enum_definition, generics, item_id)
173 }
174 fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics, item_id: NodeId) {
175 walk_variant(self, v, g, item_id)
176 }
177 fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
178 walk_lifetime(self, lifetime)
179 }
180 fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) {
181 walk_lifetime_def(self, lifetime)
182 }
183 fn visit_explicit_self(&mut self, es: &'v ExplicitSelf) {
184 walk_explicit_self(self, es)
185 }
186 fn visit_path(&mut self, path: &'v Path, _id: NodeId) {
187 walk_path(self, path)
188 }
189 fn visit_path_list_item(&mut self, prefix: &'v Path, item: &'v PathListItem) {
190 walk_path_list_item(self, prefix, item)
191 }
192 fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
193 walk_path_segment(self, path_span, path_segment)
194 }
195 fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) {
196 walk_path_parameters(self, path_span, path_parameters)
197 }
198 fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding) {
199 walk_assoc_type_binding(self, type_binding)
200 }
201 fn visit_attribute(&mut self, _attr: &'v Attribute) {
202 }
203 fn visit_macro_def(&mut self, macro_def: &'v MacroDef) {
204 walk_macro_def(self, macro_def)
205 }
206 }
207
208 pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option<Name>) {
209 for name in opt_name {
210 visitor.visit_name(span, name);
211 }
212 }
213
214 pub fn walk_opt_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_ident: Option<Ident>) {
215 for ident in opt_ident {
216 visitor.visit_ident(span, ident);
217 }
218 }
219
220 pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, ident: Ident) {
221 visitor.visit_name(span, ident.name);
222 }
223
224 /// Walks the contents of a crate. See also `Crate::visit_all_items`.
225 pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
226 visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
227 walk_list!(visitor, visit_attribute, &krate.attrs);
228 walk_list!(visitor, visit_macro_def, &krate.exported_macros);
229 }
230
231 pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) {
232 visitor.visit_name(macro_def.span, macro_def.name);
233 walk_opt_name(visitor, macro_def.span, macro_def.imported_from);
234 walk_list!(visitor, visit_attribute, &macro_def.attrs);
235 }
236
237 pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) {
238 for &item_id in &module.item_ids {
239 visitor.visit_nested_item(item_id);
240 }
241 }
242
243 pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
244 visitor.visit_pat(&local.pat);
245 walk_list!(visitor, visit_ty, &local.ty);
246 walk_list!(visitor, visit_expr, &local.init);
247 }
248
249 pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
250 visitor.visit_name(lifetime.span, lifetime.name);
251 }
252
253 pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v LifetimeDef) {
254 visitor.visit_lifetime(&lifetime_def.lifetime);
255 walk_list!(visitor, visit_lifetime, &lifetime_def.bounds);
256 }
257
258 pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V, explicit_self: &'v ExplicitSelf) {
259 match explicit_self.node {
260 SelfStatic => {}
261 SelfValue(name) => {
262 visitor.visit_name(explicit_self.span, name)
263 }
264 SelfRegion(ref opt_lifetime, _, name) => {
265 visitor.visit_name(explicit_self.span, name);
266 walk_list!(visitor, visit_lifetime, opt_lifetime);
267 }
268 SelfExplicit(ref typ, name) => {
269 visitor.visit_name(explicit_self.span, name);
270 visitor.visit_ty(typ)
271 }
272 }
273 }
274
275 pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
276 trait_ref: &'v PolyTraitRef,
277 _modifier: &'v TraitBoundModifier)
278 where V: Visitor<'v>
279 {
280 walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes);
281 visitor.visit_trait_ref(&trait_ref.trait_ref);
282 }
283
284 pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef)
285 where V: Visitor<'v>
286 {
287 visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
288 }
289
290 pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
291 visitor.visit_name(item.span, item.name);
292 match item.node {
293 ItemExternCrate(opt_name) => {
294 walk_opt_name(visitor, item.span, opt_name)
295 }
296 ItemUse(ref vp) => {
297 match vp.node {
298 ViewPathSimple(name, ref path) => {
299 visitor.visit_name(vp.span, name);
300 visitor.visit_path(path, item.id);
301 }
302 ViewPathGlob(ref path) => {
303 visitor.visit_path(path, item.id);
304 }
305 ViewPathList(ref prefix, ref list) => {
306 if !list.is_empty() {
307 for item in list {
308 visitor.visit_path_list_item(prefix, item)
309 }
310 } else {
311 visitor.visit_path(prefix, item.id);
312 }
313 }
314 }
315 }
316 ItemStatic(ref typ, _, ref expr) |
317 ItemConst(ref typ, ref expr) => {
318 visitor.visit_ty(typ);
319 visitor.visit_expr(expr);
320 }
321 ItemFn(ref declaration, unsafety, constness, abi, ref generics, ref body) => {
322 visitor.visit_fn(FnKind::ItemFn(item.name,
323 generics,
324 unsafety,
325 constness,
326 abi,
327 &item.vis,
328 &item.attrs),
329 declaration,
330 body,
331 item.span,
332 item.id)
333 }
334 ItemMod(ref module) => {
335 visitor.visit_mod(module, item.span, item.id)
336 }
337 ItemForeignMod(ref foreign_module) => {
338 walk_list!(visitor, visit_foreign_item, &foreign_module.items);
339 }
340 ItemTy(ref typ, ref type_parameters) => {
341 visitor.visit_ty(typ);
342 visitor.visit_generics(type_parameters)
343 }
344 ItemEnum(ref enum_definition, ref type_parameters) => {
345 visitor.visit_generics(type_parameters);
346 visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
347 }
348 ItemDefaultImpl(_, ref trait_ref) => {
349 visitor.visit_trait_ref(trait_ref)
350 }
351 ItemImpl(_, _, ref type_parameters, ref opt_trait_reference, ref typ, ref impl_items) => {
352 visitor.visit_generics(type_parameters);
353 walk_list!(visitor, visit_trait_ref, opt_trait_reference);
354 visitor.visit_ty(typ);
355 walk_list!(visitor, visit_impl_item, impl_items);
356 }
357 ItemStruct(ref struct_definition, ref generics) => {
358 visitor.visit_generics(generics);
359 visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span);
360 }
361 ItemTrait(_, ref generics, ref bounds, ref methods) => {
362 visitor.visit_generics(generics);
363 walk_list!(visitor, visit_ty_param_bound, bounds);
364 walk_list!(visitor, visit_trait_item, methods);
365 }
366 }
367 walk_list!(visitor, visit_attribute, &item.attrs);
368 }
369
370 pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V,
371 enum_definition: &'v EnumDef,
372 generics: &'v Generics,
373 item_id: NodeId) {
374 walk_list!(visitor,
375 visit_variant,
376 &enum_definition.variants,
377 generics,
378 item_id);
379 }
380
381 pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
382 variant: &'v Variant,
383 generics: &'v Generics,
384 item_id: NodeId) {
385 visitor.visit_name(variant.span, variant.node.name);
386 visitor.visit_variant_data(&variant.node.data,
387 variant.node.name,
388 generics,
389 item_id,
390 variant.span);
391 walk_list!(visitor, visit_expr, &variant.node.disr_expr);
392 walk_list!(visitor, visit_attribute, &variant.node.attrs);
393 }
394
395 pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
396 match typ.node {
397 TyVec(ref ty) => {
398 visitor.visit_ty(ty)
399 }
400 TyPtr(ref mutable_type) => {
401 visitor.visit_ty(&mutable_type.ty)
402 }
403 TyRptr(ref opt_lifetime, ref mutable_type) => {
404 walk_list!(visitor, visit_lifetime, opt_lifetime);
405 visitor.visit_ty(&mutable_type.ty)
406 }
407 TyTup(ref tuple_element_types) => {
408 walk_list!(visitor, visit_ty, tuple_element_types);
409 }
410 TyBareFn(ref function_declaration) => {
411 walk_fn_decl(visitor, &function_declaration.decl);
412 walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes);
413 }
414 TyPath(ref maybe_qself, ref path) => {
415 if let Some(ref qself) = *maybe_qself {
416 visitor.visit_ty(&qself.ty);
417 }
418 visitor.visit_path(path, typ.id);
419 }
420 TyObjectSum(ref ty, ref bounds) => {
421 visitor.visit_ty(ty);
422 walk_list!(visitor, visit_ty_param_bound, bounds);
423 }
424 TyFixedLengthVec(ref ty, ref expression) => {
425 visitor.visit_ty(ty);
426 visitor.visit_expr(expression)
427 }
428 TyPolyTraitRef(ref bounds) => {
429 walk_list!(visitor, visit_ty_param_bound, bounds);
430 }
431 TyTypeof(ref expression) => {
432 visitor.visit_expr(expression)
433 }
434 TyInfer => {}
435 }
436 }
437
438 pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
439 for segment in &path.segments {
440 visitor.visit_path_segment(path.span, segment);
441 }
442 }
443
444 pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V,
445 prefix: &'v Path,
446 item: &'v PathListItem) {
447 for segment in &prefix.segments {
448 visitor.visit_path_segment(prefix.span, segment);
449 }
450
451 walk_opt_name(visitor, item.span, item.node.name());
452 walk_opt_name(visitor, item.span, item.node.rename());
453 }
454
455 pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
456 path_span: Span,
457 segment: &'v PathSegment) {
458 visitor.visit_ident(path_span, segment.identifier);
459 visitor.visit_path_parameters(path_span, &segment.parameters);
460 }
461
462 pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
463 _path_span: Span,
464 path_parameters: &'v PathParameters) {
465 match *path_parameters {
466 AngleBracketedParameters(ref data) => {
467 walk_list!(visitor, visit_ty, &data.types);
468 walk_list!(visitor, visit_lifetime, &data.lifetimes);
469 walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
470 }
471 ParenthesizedParameters(ref data) => {
472 walk_list!(visitor, visit_ty, &data.inputs);
473 walk_list!(visitor, visit_ty, &data.output);
474 }
475 }
476 }
477
478 pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
479 type_binding: &'v TypeBinding) {
480 visitor.visit_name(type_binding.span, type_binding.name);
481 visitor.visit_ty(&type_binding.ty);
482 }
483
484 pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
485 match pattern.node {
486 PatKind::TupleStruct(ref path, ref opt_children) => {
487 visitor.visit_path(path, pattern.id);
488 if let Some(ref children) = *opt_children {
489 walk_list!(visitor, visit_pat, children);
490 }
491 }
492 PatKind::Path(ref path) => {
493 visitor.visit_path(path, pattern.id);
494 }
495 PatKind::QPath(ref qself, ref path) => {
496 visitor.visit_ty(&qself.ty);
497 visitor.visit_path(path, pattern.id)
498 }
499 PatKind::Struct(ref path, ref fields, _) => {
500 visitor.visit_path(path, pattern.id);
501 for field in fields {
502 visitor.visit_name(field.span, field.node.name);
503 visitor.visit_pat(&field.node.pat)
504 }
505 }
506 PatKind::Tup(ref tuple_elements) => {
507 walk_list!(visitor, visit_pat, tuple_elements);
508 }
509 PatKind::Box(ref subpattern) |
510 PatKind::Ref(ref subpattern, _) => {
511 visitor.visit_pat(subpattern)
512 }
513 PatKind::Ident(_, ref pth1, ref optional_subpattern) => {
514 visitor.visit_ident(pth1.span, pth1.node);
515 walk_list!(visitor, visit_pat, optional_subpattern);
516 }
517 PatKind::Lit(ref expression) => visitor.visit_expr(expression),
518 PatKind::Range(ref lower_bound, ref upper_bound) => {
519 visitor.visit_expr(lower_bound);
520 visitor.visit_expr(upper_bound)
521 }
522 PatKind::Wild => (),
523 PatKind::Vec(ref prepatterns, ref slice_pattern, ref postpatterns) => {
524 walk_list!(visitor, visit_pat, prepatterns);
525 walk_list!(visitor, visit_pat, slice_pattern);
526 walk_list!(visitor, visit_pat, postpatterns);
527 }
528 }
529 }
530
531 pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem) {
532 visitor.visit_name(foreign_item.span, foreign_item.name);
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 walk_list!(visitor, visit_attribute, &foreign_item.attrs);
543 }
544
545 pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyParamBound) {
546 match *bound {
547 TraitTyParamBound(ref typ, ref modifier) => {
548 visitor.visit_poly_trait_ref(typ, modifier);
549 }
550 RegionTyParamBound(ref lifetime) => {
551 visitor.visit_lifetime(lifetime);
552 }
553 }
554 }
555
556 pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
557 for param in &generics.ty_params {
558 visitor.visit_name(param.span, param.name);
559 walk_list!(visitor, visit_ty_param_bound, &param.bounds);
560 walk_list!(visitor, visit_ty, &param.default);
561 }
562 walk_list!(visitor, visit_lifetime_def, &generics.lifetimes);
563 for predicate in &generics.where_clause.predicates {
564 match predicate {
565 &WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty,
566 ref bounds,
567 ref bound_lifetimes,
568 ..}) => {
569 visitor.visit_ty(bounded_ty);
570 walk_list!(visitor, visit_ty_param_bound, bounds);
571 walk_list!(visitor, visit_lifetime_def, bound_lifetimes);
572 }
573 &WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
574 ref bounds,
575 ..}) => {
576 visitor.visit_lifetime(lifetime);
577 walk_list!(visitor, visit_lifetime, bounds);
578 }
579 &WherePredicate::EqPredicate(WhereEqPredicate{id,
580 ref path,
581 ref ty,
582 ..}) => {
583 visitor.visit_path(path, id);
584 visitor.visit_ty(ty);
585 }
586 }
587 }
588 }
589
590 pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionRetTy) {
591 if let Return(ref output_ty) = *ret_ty {
592 visitor.visit_ty(output_ty)
593 }
594 }
595
596 pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
597 for argument in &function_declaration.inputs {
598 visitor.visit_pat(&argument.pat);
599 visitor.visit_ty(&argument.ty)
600 }
601 walk_fn_ret_ty(visitor, &function_declaration.output)
602 }
603
604 pub fn walk_fn_decl_nopat<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
605 for argument in &function_declaration.inputs {
606 visitor.visit_ty(&argument.ty)
607 }
608 walk_fn_ret_ty(visitor, &function_declaration.output)
609 }
610
611 pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) {
612 match function_kind {
613 FnKind::ItemFn(_, generics, _, _, _, _, _) => {
614 visitor.visit_generics(generics);
615 }
616 FnKind::Method(_, sig, _, _) => {
617 visitor.visit_generics(&sig.generics);
618 visitor.visit_explicit_self(&sig.explicit_self);
619 }
620 FnKind::Closure(_) => {}
621 }
622 }
623
624 pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
625 function_kind: FnKind<'v>,
626 function_declaration: &'v FnDecl,
627 function_body: &'v Block,
628 _span: Span) {
629 walk_fn_decl(visitor, function_declaration);
630 walk_fn_kind(visitor, function_kind);
631 visitor.visit_block(function_body)
632 }
633
634 pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) {
635 visitor.visit_name(trait_item.span, trait_item.name);
636 walk_list!(visitor, visit_attribute, &trait_item.attrs);
637 match trait_item.node {
638 ConstTraitItem(ref ty, ref default) => {
639 visitor.visit_ty(ty);
640 walk_list!(visitor, visit_expr, default);
641 }
642 MethodTraitItem(ref sig, None) => {
643 visitor.visit_explicit_self(&sig.explicit_self);
644 visitor.visit_generics(&sig.generics);
645 walk_fn_decl(visitor, &sig.decl);
646 }
647 MethodTraitItem(ref sig, Some(ref body)) => {
648 visitor.visit_fn(FnKind::Method(trait_item.name,
649 sig,
650 None,
651 &trait_item.attrs),
652 &sig.decl,
653 body,
654 trait_item.span,
655 trait_item.id);
656 }
657 TypeTraitItem(ref bounds, ref default) => {
658 walk_list!(visitor, visit_ty_param_bound, bounds);
659 walk_list!(visitor, visit_ty, 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_name(impl_item.span, impl_item.name);
666 walk_list!(visitor, visit_attribute, &impl_item.attrs);
667 match impl_item.node {
668 ImplItemKind::Const(ref ty, ref expr) => {
669 visitor.visit_ty(ty);
670 visitor.visit_expr(expr);
671 }
672 ImplItemKind::Method(ref sig, ref body) => {
673 visitor.visit_fn(FnKind::Method(impl_item.name,
674 sig,
675 Some(&impl_item.vis),
676 &impl_item.attrs),
677 &sig.decl,
678 body,
679 impl_item.span,
680 impl_item.id);
681 }
682 ImplItemKind::Type(ref ty) => {
683 visitor.visit_ty(ty);
684 }
685 }
686 }
687
688 pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) {
689 walk_list!(visitor, visit_struct_field, struct_definition.fields());
690 }
691
692 pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) {
693 visitor.visit_name(struct_field.span, struct_field.name);
694 visitor.visit_ty(&struct_field.ty);
695 walk_list!(visitor, visit_attribute, &struct_field.attrs);
696 }
697
698 pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) {
699 walk_list!(visitor, visit_stmt, &block.stmts);
700 walk_list!(visitor, visit_expr, &block.expr);
701 }
702
703 pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
704 match statement.node {
705 StmtDecl(ref declaration, _) => visitor.visit_decl(declaration),
706 StmtExpr(ref expression, _) | StmtSemi(ref expression, _) => {
707 visitor.visit_expr(expression)
708 }
709 }
710 }
711
712 pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) {
713 match declaration.node {
714 DeclLocal(ref local) => visitor.visit_local(local),
715 DeclItem(item) => visitor.visit_nested_item(item),
716 }
717 }
718
719 pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
720 match expression.node {
721 ExprBox(ref subexpression) => {
722 visitor.visit_expr(subexpression)
723 }
724 ExprVec(ref subexpressions) => {
725 walk_list!(visitor, visit_expr, subexpressions);
726 }
727 ExprRepeat(ref element, ref count) => {
728 visitor.visit_expr(element);
729 visitor.visit_expr(count)
730 }
731 ExprStruct(ref path, ref fields, ref optional_base) => {
732 visitor.visit_path(path, expression.id);
733 for field in fields {
734 visitor.visit_name(field.name.span, field.name.node);
735 visitor.visit_expr(&field.expr)
736 }
737 walk_list!(visitor, visit_expr, optional_base);
738 }
739 ExprTup(ref subexpressions) => {
740 walk_list!(visitor, visit_expr, subexpressions);
741 }
742 ExprCall(ref callee_expression, ref arguments) => {
743 walk_list!(visitor, visit_expr, arguments);
744 visitor.visit_expr(callee_expression)
745 }
746 ExprMethodCall(ref name, ref types, ref arguments) => {
747 visitor.visit_name(name.span, name.node);
748 walk_list!(visitor, visit_expr, arguments);
749 walk_list!(visitor, visit_ty, types);
750 }
751 ExprBinary(_, ref left_expression, ref right_expression) => {
752 visitor.visit_expr(left_expression);
753 visitor.visit_expr(right_expression)
754 }
755 ExprAddrOf(_, ref subexpression) | ExprUnary(_, ref subexpression) => {
756 visitor.visit_expr(subexpression)
757 }
758 ExprLit(_) => {}
759 ExprCast(ref subexpression, ref typ) | ExprType(ref subexpression, ref typ) => {
760 visitor.visit_expr(subexpression);
761 visitor.visit_ty(typ)
762 }
763 ExprIf(ref head_expression, ref if_block, ref optional_else) => {
764 visitor.visit_expr(head_expression);
765 visitor.visit_block(if_block);
766 walk_list!(visitor, visit_expr, optional_else);
767 }
768 ExprWhile(ref subexpression, ref block, opt_ident) => {
769 visitor.visit_expr(subexpression);
770 visitor.visit_block(block);
771 walk_opt_ident(visitor, expression.span, opt_ident)
772 }
773 ExprLoop(ref block, opt_ident) => {
774 visitor.visit_block(block);
775 walk_opt_ident(visitor, expression.span, opt_ident)
776 }
777 ExprMatch(ref subexpression, ref arms, _) => {
778 visitor.visit_expr(subexpression);
779 walk_list!(visitor, visit_arm, arms);
780 }
781 ExprClosure(_, ref function_declaration, ref body) => {
782 visitor.visit_fn(FnKind::Closure(expression.attrs.as_attr_slice()),
783 function_declaration,
784 body,
785 expression.span,
786 expression.id)
787 }
788 ExprBlock(ref block) => visitor.visit_block(block),
789 ExprAssign(ref left_hand_expression, ref right_hand_expression) => {
790 visitor.visit_expr(right_hand_expression);
791 visitor.visit_expr(left_hand_expression)
792 }
793 ExprAssignOp(_, ref left_expression, ref right_expression) => {
794 visitor.visit_expr(right_expression);
795 visitor.visit_expr(left_expression)
796 }
797 ExprField(ref subexpression, ref name) => {
798 visitor.visit_expr(subexpression);
799 visitor.visit_name(name.span, name.node);
800 }
801 ExprTupField(ref subexpression, _) => {
802 visitor.visit_expr(subexpression);
803 }
804 ExprIndex(ref main_expression, ref index_expression) => {
805 visitor.visit_expr(main_expression);
806 visitor.visit_expr(index_expression)
807 }
808 ExprPath(ref maybe_qself, ref path) => {
809 if let Some(ref qself) = *maybe_qself {
810 visitor.visit_ty(&qself.ty);
811 }
812 visitor.visit_path(path, expression.id)
813 }
814 ExprBreak(ref opt_sp_ident) | ExprAgain(ref opt_sp_ident) => {
815 for sp_ident in opt_sp_ident {
816 visitor.visit_ident(sp_ident.span, sp_ident.node);
817 }
818 }
819 ExprRet(ref optional_expression) => {
820 walk_list!(visitor, visit_expr, optional_expression);
821 }
822 ExprInlineAsm(_, ref outputs, ref inputs) => {
823 for output in outputs {
824 visitor.visit_expr(output)
825 }
826 for input in inputs {
827 visitor.visit_expr(input)
828 }
829 }
830 }
831
832 visitor.visit_expr_post(expression)
833 }
834
835 pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
836 walk_list!(visitor, visit_pat, &arm.pats);
837 walk_list!(visitor, visit_expr, &arm.guard);
838 visitor.visit_expr(&arm.body);
839 walk_list!(visitor, visit_attribute, &arm.attrs);
840 }
841
842 #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
843 pub struct IdRange {
844 pub min: NodeId,
845 pub max: NodeId,
846 }
847
848 impl IdRange {
849 pub fn max() -> IdRange {
850 IdRange {
851 min: u32::MAX,
852 max: u32::MIN,
853 }
854 }
855
856 pub fn empty(&self) -> bool {
857 self.min >= self.max
858 }
859
860 pub fn add(&mut self, id: NodeId) {
861 self.min = cmp::min(self.min, id);
862 self.max = cmp::max(self.max, id + 1);
863 }
864 }
865
866 pub trait IdVisitingOperation {
867 fn visit_id(&mut self, node_id: NodeId);
868 }
869
870 pub struct IdRangeComputingVisitor {
871 pub result: IdRange,
872 }
873
874 impl IdRangeComputingVisitor {
875 pub fn new() -> IdRangeComputingVisitor {
876 IdRangeComputingVisitor { result: IdRange::max() }
877 }
878
879 pub fn result(&self) -> IdRange {
880 self.result
881 }
882 }
883
884 impl IdVisitingOperation for IdRangeComputingVisitor {
885 fn visit_id(&mut self, id: NodeId) {
886 self.result.add(id);
887 }
888 }
889
890 pub struct IdVisitor<'a, O: 'a> {
891 operation: &'a mut O,
892
893 // In general, the id visitor visits the contents of an item, but
894 // not including nested trait/impl items, nor other nested items.
895 // The base visitor itself always skips nested items, but not
896 // trait/impl items. This means in particular that if you start by
897 // visiting a trait or an impl, you should not visit the
898 // trait/impl items respectively. This is handled by setting
899 // `skip_members` to true when `visit_item` is on the stack. This
900 // way, if the user begins by calling `visit_trait_item`, we will
901 // visit the trait item, but if they begin with `visit_item`, we
902 // won't visit the (nested) trait items.
903 skip_members: bool,
904 }
905
906 impl<'a, O: IdVisitingOperation> IdVisitor<'a, O> {
907 pub fn new(operation: &'a mut O) -> IdVisitor<'a, O> {
908 IdVisitor { operation: operation, skip_members: false }
909 }
910
911 fn visit_generics_helper(&mut self, generics: &Generics) {
912 for type_parameter in generics.ty_params.iter() {
913 self.operation.visit_id(type_parameter.id)
914 }
915 for lifetime in &generics.lifetimes {
916 self.operation.visit_id(lifetime.lifetime.id)
917 }
918 }
919 }
920
921 impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
922 fn visit_mod(&mut self, module: &Mod, _: Span, node_id: NodeId) {
923 self.operation.visit_id(node_id);
924 walk_mod(self, module)
925 }
926
927 fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
928 self.operation.visit_id(foreign_item.id);
929 walk_foreign_item(self, foreign_item)
930 }
931
932 fn visit_item(&mut self, item: &Item) {
933 assert!(!self.skip_members);
934 self.skip_members = true;
935
936 self.operation.visit_id(item.id);
937 match item.node {
938 ItemUse(ref view_path) => {
939 match view_path.node {
940 ViewPathSimple(_, _) |
941 ViewPathGlob(_) => {}
942 ViewPathList(_, ref paths) => {
943 for path in paths {
944 self.operation.visit_id(path.node.id())
945 }
946 }
947 }
948 }
949 _ => {}
950 }
951 walk_item(self, item);
952
953 self.skip_members = false;
954 }
955
956 fn visit_local(&mut self, local: &Local) {
957 self.operation.visit_id(local.id);
958 walk_local(self, local)
959 }
960
961 fn visit_block(&mut self, block: &Block) {
962 self.operation.visit_id(block.id);
963 walk_block(self, block)
964 }
965
966 fn visit_stmt(&mut self, statement: &Stmt) {
967 self.operation.visit_id(statement.node.id());
968 walk_stmt(self, statement)
969 }
970
971 fn visit_pat(&mut self, pattern: &Pat) {
972 self.operation.visit_id(pattern.id);
973 walk_pat(self, pattern)
974 }
975
976 fn visit_expr(&mut self, expression: &Expr) {
977 self.operation.visit_id(expression.id);
978 walk_expr(self, expression)
979 }
980
981 fn visit_ty(&mut self, typ: &Ty) {
982 self.operation.visit_id(typ.id);
983 walk_ty(self, typ)
984 }
985
986 fn visit_generics(&mut self, generics: &Generics) {
987 self.visit_generics_helper(generics);
988 walk_generics(self, generics)
989 }
990
991 fn visit_fn(&mut self,
992 function_kind: FnKind<'v>,
993 function_declaration: &'v FnDecl,
994 block: &'v Block,
995 span: Span,
996 node_id: NodeId) {
997 self.operation.visit_id(node_id);
998
999 match function_kind {
1000 FnKind::ItemFn(_, generics, _, _, _, _, _) => {
1001 self.visit_generics_helper(generics)
1002 }
1003 FnKind::Method(_, sig, _, _) => {
1004 self.visit_generics_helper(&sig.generics)
1005 }
1006 FnKind::Closure(_) => {}
1007 }
1008
1009 for argument in &function_declaration.inputs {
1010 self.operation.visit_id(argument.id)
1011 }
1012
1013 walk_fn(self, function_kind, function_declaration, block, span);
1014 }
1015
1016 fn visit_struct_field(&mut self, struct_field: &StructField) {
1017 self.operation.visit_id(struct_field.id);
1018 walk_struct_field(self, struct_field)
1019 }
1020
1021 fn visit_variant_data(&mut self,
1022 struct_def: &VariantData,
1023 _: Name,
1024 _: &Generics,
1025 _: NodeId,
1026 _: Span) {
1027 self.operation.visit_id(struct_def.id());
1028 walk_struct_def(self, struct_def);
1029 }
1030
1031 fn visit_trait_item(&mut self, ti: &TraitItem) {
1032 if !self.skip_members {
1033 self.operation.visit_id(ti.id);
1034 walk_trait_item(self, ti);
1035 }
1036 }
1037
1038 fn visit_impl_item(&mut self, ii: &ImplItem) {
1039 if !self.skip_members {
1040 self.operation.visit_id(ii.id);
1041 walk_impl_item(self, ii);
1042 }
1043 }
1044
1045 fn visit_lifetime(&mut self, lifetime: &Lifetime) {
1046 self.operation.visit_id(lifetime.id);
1047 }
1048
1049 fn visit_lifetime_def(&mut self, def: &LifetimeDef) {
1050 self.visit_lifetime(&def.lifetime);
1051 }
1052
1053 fn visit_trait_ref(&mut self, trait_ref: &TraitRef) {
1054 self.operation.visit_id(trait_ref.ref_id);
1055 walk_trait_ref(self, trait_ref);
1056 }
1057 }
1058
1059 /// Computes the id range for a single fn body, ignoring nested items.
1060 pub fn compute_id_range_for_fn_body(fk: FnKind,
1061 decl: &FnDecl,
1062 body: &Block,
1063 sp: Span,
1064 id: NodeId)
1065 -> IdRange {
1066 let mut visitor = IdRangeComputingVisitor { result: IdRange::max() };
1067 let mut id_visitor = IdVisitor::new(&mut visitor);
1068 id_visitor.visit_fn(fk, decl, body, sp, id);
1069 id_visitor.operation.result
1070 }