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.
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.
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 `visit::walk_*` to apply the default traversal algorithm, or prevent
14 //! deeper traversal by doing nothing.
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.
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.
27 use syntax
::ast
::{Ident, NodeId, CRATE_NODE_ID, Name, Attribute}
;
28 use syntax
::codemap
::Span
;
31 #[derive(Copy, Clone, PartialEq, Eq)]
33 /// fn foo() or extern "Abi" fn foo()
34 ItemFn(Name
, &'a Generics
, Unsafety
, Constness
, Abi
, Visibility
),
37 Method(Name
, &'a MethodSig
, Option
<Visibility
>),
43 /// Each method of the Visitor trait is a hook to be potentially
44 /// overridden. Each method's default implementation recursively visits
45 /// the substructure of the input via the corresponding `walk` method;
46 /// e.g. the `visit_mod` method by default calls `visit::walk_mod`.
48 /// If you want to ensure that your code handles every variant
49 /// explicitly, you need to override each method. (And you also need
50 /// to monitor future changes to `Visitor` in case a new method with a
51 /// new default implementation gets introduced.)
52 pub trait Visitor
<'v
> : Sized
{
53 fn visit_name(&mut self, _span
: Span
, _name
: Name
) {
56 fn visit_ident(&mut self, span
: Span
, ident
: Ident
) {
57 walk_ident(self, span
, ident
);
59 fn visit_mod(&mut self, m
: &'v Mod
, _s
: Span
, _n
: NodeId
) {
62 fn visit_foreign_item(&mut self, i
: &'v ForeignItem
) {
63 walk_foreign_item(self, i
)
65 fn visit_item(&mut self, i
: &'v Item
) {
68 fn visit_local(&mut self, l
: &'v Local
) {
71 fn visit_block(&mut self, b
: &'v Block
) {
74 fn visit_stmt(&mut self, s
: &'v Stmt
) {
77 fn visit_arm(&mut self, a
: &'v Arm
) {
80 fn visit_pat(&mut self, p
: &'v Pat
) {
83 fn visit_decl(&mut self, d
: &'v Decl
) {
86 fn visit_expr(&mut self, ex
: &'v Expr
) {
89 fn visit_expr_post(&mut self, _ex
: &'v Expr
) {
91 fn visit_ty(&mut self, t
: &'v Ty
) {
94 fn visit_generics(&mut self, g
: &'v Generics
) {
95 walk_generics(self, g
)
97 fn visit_fn(&mut self, fk
: FnKind
<'v
>, fd
: &'v FnDecl
, b
: &'v Block
, s
: Span
, _
: NodeId
) {
98 walk_fn(self, fk
, fd
, b
, s
)
100 fn visit_trait_item(&mut self, ti
: &'v TraitItem
) {
101 walk_trait_item(self, ti
)
103 fn visit_impl_item(&mut self, ii
: &'v ImplItem
) {
104 walk_impl_item(self, ii
)
106 fn visit_trait_ref(&mut self, t
: &'v TraitRef
) {
107 walk_trait_ref(self, t
)
109 fn visit_ty_param_bound(&mut self, bounds
: &'v TyParamBound
) {
110 walk_ty_param_bound(self, bounds
)
112 fn visit_poly_trait_ref(&mut self, t
: &'v PolyTraitRef
, m
: &'v TraitBoundModifier
) {
113 walk_poly_trait_ref(self, t
, m
)
115 fn visit_variant_data(&mut self, s
: &'v VariantData
, _
: Name
,
116 _
: &'v Generics
, _
: NodeId
, _
: Span
) {
117 walk_struct_def(self, s
)
119 fn visit_struct_field(&mut self, s
: &'v StructField
) {
120 walk_struct_field(self, s
)
122 fn visit_enum_def(&mut self, enum_definition
: &'v EnumDef
,
123 generics
: &'v Generics
, item_id
: NodeId
, _
: Span
) {
124 walk_enum_def(self, enum_definition
, generics
, item_id
)
126 fn visit_variant(&mut self, v
: &'v Variant
, g
: &'v Generics
, item_id
: NodeId
) {
127 walk_variant(self, v
, g
, item_id
)
129 fn visit_lifetime(&mut self, lifetime
: &'v Lifetime
) {
130 walk_lifetime(self, lifetime
)
132 fn visit_lifetime_def(&mut self, lifetime
: &'v LifetimeDef
) {
133 walk_lifetime_def(self, lifetime
)
135 fn visit_explicit_self(&mut self, es
: &'v ExplicitSelf
) {
136 walk_explicit_self(self, es
)
138 fn visit_path(&mut self, path
: &'v Path
, _id
: NodeId
) {
139 walk_path(self, path
)
141 fn visit_path_list_item(&mut self, prefix
: &'v Path
, item
: &'v PathListItem
) {
142 walk_path_list_item(self, prefix
, item
)
144 fn visit_path_segment(&mut self, path_span
: Span
, path_segment
: &'v PathSegment
) {
145 walk_path_segment(self, path_span
, path_segment
)
147 fn visit_path_parameters(&mut self, path_span
: Span
, path_parameters
: &'v PathParameters
) {
148 walk_path_parameters(self, path_span
, path_parameters
)
150 fn visit_assoc_type_binding(&mut self, type_binding
: &'v TypeBinding
) {
151 walk_assoc_type_binding(self, type_binding
)
153 fn visit_attribute(&mut self, _attr
: &'v Attribute
) {
155 fn visit_macro_def(&mut self, macro_def
: &'v MacroDef
) {
156 walk_macro_def(self, macro_def
)
160 pub fn walk_opt_name
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, span
: Span
, opt_name
: Option
<Name
>) {
161 for name
in opt_name
{
162 visitor
.visit_name(span
, name
);
166 pub fn walk_opt_ident
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, span
: Span
, opt_ident
: Option
<Ident
>) {
167 for ident
in opt_ident
{
168 visitor
.visit_ident(span
, ident
);
172 pub fn walk_ident
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, span
: Span
, ident
: Ident
) {
173 visitor
.visit_name(span
, ident
.name
);
176 pub fn walk_crate
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, krate
: &'v Crate
) {
177 visitor
.visit_mod(&krate
.module
, krate
.span
, CRATE_NODE_ID
);
178 walk_list
!(visitor
, visit_attribute
, &krate
.attrs
);
179 walk_list
!(visitor
, visit_macro_def
, &krate
.exported_macros
);
182 pub fn walk_macro_def
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, macro_def
: &'v MacroDef
) {
183 visitor
.visit_name(macro_def
.span
, macro_def
.name
);
184 walk_opt_name(visitor
, macro_def
.span
, macro_def
.imported_from
);
185 walk_list
!(visitor
, visit_attribute
, ¯o_def
.attrs
);
188 pub fn walk_mod
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, module
: &'v Mod
) {
189 walk_list
!(visitor
, visit_item
, &module
.items
);
192 pub fn walk_local
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, local
: &'v Local
) {
193 visitor
.visit_pat(&local
.pat
);
194 walk_list
!(visitor
, visit_ty
, &local
.ty
);
195 walk_list
!(visitor
, visit_expr
, &local
.init
);
198 pub fn walk_lifetime
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, lifetime
: &'v Lifetime
) {
199 visitor
.visit_name(lifetime
.span
, lifetime
.name
);
202 pub fn walk_lifetime_def
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, lifetime_def
: &'v LifetimeDef
) {
203 visitor
.visit_lifetime(&lifetime_def
.lifetime
);
204 walk_list
!(visitor
, visit_lifetime
, &lifetime_def
.bounds
);
207 pub fn walk_explicit_self
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, explicit_self
: &'v ExplicitSelf
) {
208 match explicit_self
.node
{
211 visitor
.visit_name(explicit_self
.span
, name
)
213 SelfRegion(ref opt_lifetime
, _
, name
) => {
214 visitor
.visit_name(explicit_self
.span
, name
);
215 walk_list
!(visitor
, visit_lifetime
, opt_lifetime
);
217 SelfExplicit(ref typ
, name
) => {
218 visitor
.visit_name(explicit_self
.span
, name
);
219 visitor
.visit_ty(typ
)
224 pub fn walk_poly_trait_ref
<'v
, V
>(visitor
: &mut V
,
225 trait_ref
: &'v PolyTraitRef
,
226 _modifier
: &'v TraitBoundModifier
)
231 &trait_ref
.bound_lifetimes
);
232 visitor
.visit_trait_ref(&trait_ref
.trait_ref
);
235 pub fn walk_trait_ref
<'v
, V
>(visitor
: &mut V
, trait_ref
: &'v TraitRef
)
238 visitor
.visit_path(&trait_ref
.path
, trait_ref
.ref_id
)
241 pub fn walk_item
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, item
: &'v Item
) {
242 visitor
.visit_name(item
.span
, item
.name
);
244 ItemExternCrate(opt_name
) => {
245 walk_opt_name(visitor
, item
.span
, opt_name
)
249 ViewPathSimple(name
, ref path
) => {
250 visitor
.visit_name(vp
.span
, name
);
251 visitor
.visit_path(path
, item
.id
);
253 ViewPathGlob(ref path
) => {
254 visitor
.visit_path(path
, item
.id
);
256 ViewPathList(ref prefix
, ref list
) => {
257 if !list
.is_empty() {
259 visitor
.visit_path_list_item(prefix
, item
)
262 visitor
.visit_path(prefix
, item
.id
);
267 ItemStatic(ref typ
, _
, ref expr
) |
268 ItemConst(ref typ
, ref expr
) => {
269 visitor
.visit_ty(typ
);
270 visitor
.visit_expr(expr
);
272 ItemFn(ref declaration
, unsafety
, constness
, abi
, ref generics
, ref body
) => {
273 visitor
.visit_fn(FnKind
::ItemFn(item
.name
,
284 ItemMod(ref module
) => {
285 visitor
.visit_mod(module
, item
.span
, item
.id
)
287 ItemForeignMod(ref foreign_module
) => {
288 walk_list
!(visitor
, visit_foreign_item
, &foreign_module
.items
);
290 ItemTy(ref typ
, ref type_parameters
) => {
291 visitor
.visit_ty(typ
);
292 visitor
.visit_generics(type_parameters
)
294 ItemEnum(ref enum_definition
, ref type_parameters
) => {
295 visitor
.visit_generics(type_parameters
);
296 visitor
.visit_enum_def(enum_definition
, type_parameters
, item
.id
, item
.span
)
298 ItemDefaultImpl(_
, ref trait_ref
) => {
299 visitor
.visit_trait_ref(trait_ref
)
303 ref opt_trait_reference
,
306 visitor
.visit_generics(type_parameters
);
307 walk_list
!(visitor
, visit_trait_ref
, opt_trait_reference
);
308 visitor
.visit_ty(typ
);
309 walk_list
!(visitor
, visit_impl_item
, impl_items
);
311 ItemStruct(ref struct_definition
, ref generics
) => {
312 visitor
.visit_generics(generics
);
313 visitor
.visit_variant_data(struct_definition
, item
.name
,
314 generics
, item
.id
, item
.span
);
316 ItemTrait(_
, ref generics
, ref bounds
, ref methods
) => {
317 visitor
.visit_generics(generics
);
318 walk_list
!(visitor
, visit_ty_param_bound
, bounds
);
319 walk_list
!(visitor
, visit_trait_item
, methods
);
322 walk_list
!(visitor
, visit_attribute
, &item
.attrs
);
325 pub fn walk_enum_def
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
326 enum_definition
: &'v EnumDef
,
327 generics
: &'v Generics
,
329 walk_list
!(visitor
, visit_variant
, &enum_definition
.variants
, generics
, item_id
);
332 pub fn walk_variant
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
333 variant
: &'v Variant
,
334 generics
: &'v Generics
,
336 visitor
.visit_name(variant
.span
, variant
.node
.name
);
337 visitor
.visit_variant_data(&variant
.node
.data
, variant
.node
.name
,
338 generics
, item_id
, variant
.span
);
339 walk_list
!(visitor
, visit_expr
, &variant
.node
.disr_expr
);
340 walk_list
!(visitor
, visit_attribute
, &variant
.node
.attrs
);
343 pub fn walk_ty
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, typ
: &'v Ty
) {
345 TyVec(ref ty
) | TyParen(ref ty
) => {
348 TyPtr(ref mutable_type
) => {
349 visitor
.visit_ty(&mutable_type
.ty
)
351 TyRptr(ref opt_lifetime
, ref mutable_type
) => {
352 walk_list
!(visitor
, visit_lifetime
, opt_lifetime
);
353 visitor
.visit_ty(&mutable_type
.ty
)
355 TyTup(ref tuple_element_types
) => {
356 walk_list
!(visitor
, visit_ty
, tuple_element_types
);
358 TyBareFn(ref function_declaration
) => {
359 walk_fn_decl(visitor
, &function_declaration
.decl
);
362 &function_declaration
.lifetimes
);
364 TyPath(ref maybe_qself
, ref path
) => {
365 if let Some(ref qself
) = *maybe_qself
{
366 visitor
.visit_ty(&qself
.ty
);
368 visitor
.visit_path(path
, typ
.id
);
370 TyObjectSum(ref ty
, ref bounds
) => {
371 visitor
.visit_ty(ty
);
372 walk_list
!(visitor
, visit_ty_param_bound
, bounds
);
374 TyFixedLengthVec(ref ty
, ref expression
) => {
375 visitor
.visit_ty(ty
);
376 visitor
.visit_expr(expression
)
378 TyPolyTraitRef(ref bounds
) => {
379 walk_list
!(visitor
, visit_ty_param_bound
, bounds
);
381 TyTypeof(ref expression
) => {
382 visitor
.visit_expr(expression
)
388 pub fn walk_path
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, path
: &'v Path
) {
389 for segment
in &path
.segments
{
390 visitor
.visit_path_segment(path
.span
, segment
);
394 pub fn walk_path_list_item
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
396 item
: &'v PathListItem
) {
397 for segment
in &prefix
.segments
{
398 visitor
.visit_path_segment(prefix
.span
, segment
);
401 walk_opt_name(visitor
, item
.span
, item
.node
.name());
402 walk_opt_name(visitor
, item
.span
, item
.node
.rename());
405 pub fn walk_path_segment
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
407 segment
: &'v PathSegment
) {
408 visitor
.visit_ident(path_span
, segment
.identifier
);
409 visitor
.visit_path_parameters(path_span
, &segment
.parameters
);
412 pub fn walk_path_parameters
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
414 path_parameters
: &'v PathParameters
) {
415 match *path_parameters
{
416 AngleBracketedParameters(ref data
) => {
417 walk_list
!(visitor
, visit_ty
, &data
.types
);
418 walk_list
!(visitor
, visit_lifetime
, &data
.lifetimes
);
419 walk_list
!(visitor
, visit_assoc_type_binding
, &data
.bindings
);
421 ParenthesizedParameters(ref data
) => {
422 walk_list
!(visitor
, visit_ty
, &data
.inputs
);
423 walk_list
!(visitor
, visit_ty
, &data
.output
);
428 pub fn walk_assoc_type_binding
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
429 type_binding
: &'v TypeBinding
) {
430 visitor
.visit_name(type_binding
.span
, type_binding
.name
);
431 visitor
.visit_ty(&type_binding
.ty
);
434 pub fn walk_pat
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, pattern
: &'v Pat
) {
436 PatEnum(ref path
, ref opt_children
) => {
437 visitor
.visit_path(path
, pattern
.id
);
438 if let Some(ref children
) = *opt_children
{
439 walk_list
!(visitor
, visit_pat
, children
);
442 PatQPath(ref qself
, ref path
) => {
443 visitor
.visit_ty(&qself
.ty
);
444 visitor
.visit_path(path
, pattern
.id
)
446 PatStruct(ref path
, ref fields
, _
) => {
447 visitor
.visit_path(path
, pattern
.id
);
448 for field
in fields
{
449 visitor
.visit_name(field
.span
, field
.node
.name
);
450 visitor
.visit_pat(&field
.node
.pat
)
453 PatTup(ref tuple_elements
) => {
454 walk_list
!(visitor
, visit_pat
, tuple_elements
);
456 PatBox(ref subpattern
) |
457 PatRegion(ref subpattern
, _
) => {
458 visitor
.visit_pat(subpattern
)
460 PatIdent(_
, ref pth1
, ref optional_subpattern
) => {
461 visitor
.visit_ident(pth1
.span
, pth1
.node
);
462 walk_list
!(visitor
, visit_pat
, optional_subpattern
);
464 PatLit(ref expression
) => visitor
.visit_expr(expression
),
465 PatRange(ref lower_bound
, ref upper_bound
) => {
466 visitor
.visit_expr(lower_bound
);
467 visitor
.visit_expr(upper_bound
)
470 PatVec(ref prepatterns
, ref slice_pattern
, ref postpatterns
) => {
471 walk_list
!(visitor
, visit_pat
, prepatterns
);
472 walk_list
!(visitor
, visit_pat
, slice_pattern
);
473 walk_list
!(visitor
, visit_pat
, postpatterns
);
478 pub fn walk_foreign_item
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, foreign_item
: &'v ForeignItem
) {
479 visitor
.visit_name(foreign_item
.span
, foreign_item
.name
);
481 match foreign_item
.node
{
482 ForeignItemFn(ref function_declaration
, ref generics
) => {
483 walk_fn_decl(visitor
, function_declaration
);
484 visitor
.visit_generics(generics
)
486 ForeignItemStatic(ref typ
, _
) => visitor
.visit_ty(typ
),
489 walk_list
!(visitor
, visit_attribute
, &foreign_item
.attrs
);
492 pub fn walk_ty_param_bound
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, bound
: &'v TyParamBound
) {
494 TraitTyParamBound(ref typ
, ref modifier
) => {
495 visitor
.visit_poly_trait_ref(typ
, modifier
);
497 RegionTyParamBound(ref lifetime
) => {
498 visitor
.visit_lifetime(lifetime
);
503 pub fn walk_generics
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, generics
: &'v Generics
) {
504 for param
in &generics
.ty_params
{
505 visitor
.visit_name(param
.span
, param
.name
);
506 walk_list
!(visitor
, visit_ty_param_bound
, ¶m
.bounds
);
507 walk_list
!(visitor
, visit_ty
, ¶m
.default);
509 walk_list
!(visitor
, visit_lifetime_def
, &generics
.lifetimes
);
510 for predicate
in &generics
.where_clause
.predicates
{
512 &WherePredicate
::BoundPredicate(WhereBoundPredicate
{ref bounded_ty
,
516 visitor
.visit_ty(bounded_ty
);
517 walk_list
!(visitor
, visit_ty_param_bound
, bounds
);
518 walk_list
!(visitor
, visit_lifetime_def
, bound_lifetimes
);
520 &WherePredicate
::RegionPredicate(WhereRegionPredicate
{ref lifetime
,
523 visitor
.visit_lifetime(lifetime
);
524 walk_list
!(visitor
, visit_lifetime
, bounds
);
526 &WherePredicate
::EqPredicate(WhereEqPredicate
{id
,
530 visitor
.visit_path(path
, id
);
531 visitor
.visit_ty(ty
);
537 pub fn walk_fn_ret_ty
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, ret_ty
: &'v FunctionRetTy
) {
538 if let Return(ref output_ty
) = *ret_ty
{
539 visitor
.visit_ty(output_ty
)
543 pub fn walk_fn_decl
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, function_declaration
: &'v FnDecl
) {
544 for argument
in &function_declaration
.inputs
{
545 visitor
.visit_pat(&argument
.pat
);
546 visitor
.visit_ty(&argument
.ty
)
548 walk_fn_ret_ty(visitor
, &function_declaration
.output
)
551 pub fn walk_fn_decl_nopat
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, function_declaration
: &'v FnDecl
) {
552 for argument
in &function_declaration
.inputs
{
553 visitor
.visit_ty(&argument
.ty
)
555 walk_fn_ret_ty(visitor
, &function_declaration
.output
)
558 pub fn walk_fn_kind
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, function_kind
: FnKind
<'v
>) {
559 match function_kind
{
560 FnKind
::ItemFn(_
, generics
, _
, _
, _
, _
) => {
561 visitor
.visit_generics(generics
);
563 FnKind
::Method(_
, sig
, _
) => {
564 visitor
.visit_generics(&sig
.generics
);
565 visitor
.visit_explicit_self(&sig
.explicit_self
);
567 FnKind
::Closure
=> {}
571 pub fn walk_fn
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
572 function_kind
: FnKind
<'v
>,
573 function_declaration
: &'v FnDecl
,
574 function_body
: &'v Block
,
576 walk_fn_decl(visitor
, function_declaration
);
577 walk_fn_kind(visitor
, function_kind
);
578 visitor
.visit_block(function_body
)
581 pub fn walk_trait_item
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, trait_item
: &'v TraitItem
) {
582 visitor
.visit_name(trait_item
.span
, trait_item
.name
);
583 walk_list
!(visitor
, visit_attribute
, &trait_item
.attrs
);
584 match trait_item
.node
{
585 ConstTraitItem(ref ty
, ref default) => {
586 visitor
.visit_ty(ty
);
587 walk_list
!(visitor
, visit_expr
, default);
589 MethodTraitItem(ref sig
, None
) => {
590 visitor
.visit_explicit_self(&sig
.explicit_self
);
591 visitor
.visit_generics(&sig
.generics
);
592 walk_fn_decl(visitor
, &sig
.decl
);
594 MethodTraitItem(ref sig
, Some(ref body
)) => {
595 visitor
.visit_fn(FnKind
::Method(trait_item
.name
, sig
, None
),
601 TypeTraitItem(ref bounds
, ref default) => {
602 walk_list
!(visitor
, visit_ty_param_bound
, bounds
);
603 walk_list
!(visitor
, visit_ty
, default);
608 pub fn walk_impl_item
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, impl_item
: &'v ImplItem
) {
609 visitor
.visit_name(impl_item
.span
, impl_item
.name
);
610 walk_list
!(visitor
, visit_attribute
, &impl_item
.attrs
);
611 match impl_item
.node
{
612 ConstImplItem(ref ty
, ref expr
) => {
613 visitor
.visit_ty(ty
);
614 visitor
.visit_expr(expr
);
616 MethodImplItem(ref sig
, ref body
) => {
617 visitor
.visit_fn(FnKind
::Method(impl_item
.name
, sig
, Some(impl_item
.vis
)),
623 TypeImplItem(ref ty
) => {
624 visitor
.visit_ty(ty
);
629 pub fn walk_struct_def
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, struct_definition
: &'v VariantData
) {
630 walk_list
!(visitor
, visit_struct_field
, struct_definition
.fields());
633 pub fn walk_struct_field
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, struct_field
: &'v StructField
) {
634 walk_opt_name(visitor
, struct_field
.span
, struct_field
.node
.name());
635 visitor
.visit_ty(&struct_field
.node
.ty
);
636 walk_list
!(visitor
, visit_attribute
, &struct_field
.node
.attrs
);
639 pub fn walk_block
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, block
: &'v Block
) {
640 walk_list
!(visitor
, visit_stmt
, &block
.stmts
);
641 walk_list
!(visitor
, visit_expr
, &block
.expr
);
644 pub fn walk_stmt
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, statement
: &'v Stmt
) {
645 match statement
.node
{
646 StmtDecl(ref declaration
, _
) => visitor
.visit_decl(declaration
),
647 StmtExpr(ref expression
, _
) | StmtSemi(ref expression
, _
) => {
648 visitor
.visit_expr(expression
)
653 pub fn walk_decl
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, declaration
: &'v Decl
) {
654 match declaration
.node
{
655 DeclLocal(ref local
) => visitor
.visit_local(local
),
656 DeclItem(ref item
) => visitor
.visit_item(item
),
660 pub fn walk_expr
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, expression
: &'v Expr
) {
661 match expression
.node
{
662 ExprBox(ref subexpression
) => {
663 visitor
.visit_expr(subexpression
)
665 ExprVec(ref subexpressions
) => {
666 walk_list
!(visitor
, visit_expr
, subexpressions
);
668 ExprRepeat(ref element
, ref count
) => {
669 visitor
.visit_expr(element
);
670 visitor
.visit_expr(count
)
672 ExprStruct(ref path
, ref fields
, ref optional_base
) => {
673 visitor
.visit_path(path
, expression
.id
);
674 for field
in fields
{
675 visitor
.visit_name(field
.name
.span
, field
.name
.node
);
676 visitor
.visit_expr(&field
.expr
)
678 walk_list
!(visitor
, visit_expr
, optional_base
);
680 ExprTup(ref subexpressions
) => {
681 walk_list
!(visitor
, visit_expr
, subexpressions
);
683 ExprCall(ref callee_expression
, ref arguments
) => {
684 walk_list
!(visitor
, visit_expr
, arguments
);
685 visitor
.visit_expr(callee_expression
)
687 ExprMethodCall(ref name
, ref types
, ref arguments
) => {
688 visitor
.visit_name(name
.span
, name
.node
);
689 walk_list
!(visitor
, visit_expr
, arguments
);
690 walk_list
!(visitor
, visit_ty
, types
);
692 ExprBinary(_
, ref left_expression
, ref right_expression
) => {
693 visitor
.visit_expr(left_expression
);
694 visitor
.visit_expr(right_expression
)
696 ExprAddrOf(_
, ref subexpression
) | ExprUnary(_
, ref subexpression
) => {
697 visitor
.visit_expr(subexpression
)
700 ExprCast(ref subexpression
, ref typ
) => {
701 visitor
.visit_expr(subexpression
);
702 visitor
.visit_ty(typ
)
704 ExprIf(ref head_expression
, ref if_block
, ref optional_else
) => {
705 visitor
.visit_expr(head_expression
);
706 visitor
.visit_block(if_block
);
707 walk_list
!(visitor
, visit_expr
, optional_else
);
709 ExprWhile(ref subexpression
, ref block
, opt_ident
) => {
710 visitor
.visit_expr(subexpression
);
711 visitor
.visit_block(block
);
712 walk_opt_ident(visitor
, expression
.span
, opt_ident
)
714 ExprLoop(ref block
, opt_ident
) => {
715 visitor
.visit_block(block
);
716 walk_opt_ident(visitor
, expression
.span
, opt_ident
)
718 ExprMatch(ref subexpression
, ref arms
, _
) => {
719 visitor
.visit_expr(subexpression
);
720 walk_list
!(visitor
, visit_arm
, arms
);
722 ExprClosure(_
, ref function_declaration
, ref body
) => {
723 visitor
.visit_fn(FnKind
::Closure
,
724 function_declaration
,
729 ExprBlock(ref block
) => visitor
.visit_block(block
),
730 ExprAssign(ref left_hand_expression
, ref right_hand_expression
) => {
731 visitor
.visit_expr(right_hand_expression
);
732 visitor
.visit_expr(left_hand_expression
)
734 ExprAssignOp(_
, ref left_expression
, ref right_expression
) => {
735 visitor
.visit_expr(right_expression
);
736 visitor
.visit_expr(left_expression
)
738 ExprField(ref subexpression
, ref name
) => {
739 visitor
.visit_expr(subexpression
);
740 visitor
.visit_name(name
.span
, name
.node
);
742 ExprTupField(ref subexpression
, _
) => {
743 visitor
.visit_expr(subexpression
);
745 ExprIndex(ref main_expression
, ref index_expression
) => {
746 visitor
.visit_expr(main_expression
);
747 visitor
.visit_expr(index_expression
)
749 ExprRange(ref start
, ref end
) => {
750 walk_list
!(visitor
, visit_expr
, start
);
751 walk_list
!(visitor
, visit_expr
, end
);
753 ExprPath(ref maybe_qself
, ref path
) => {
754 if let Some(ref qself
) = *maybe_qself
{
755 visitor
.visit_ty(&qself
.ty
);
757 visitor
.visit_path(path
, expression
.id
)
759 ExprBreak(ref opt_sp_ident
) | ExprAgain(ref opt_sp_ident
) => {
760 for sp_ident
in opt_sp_ident
{
761 visitor
.visit_ident(sp_ident
.span
, sp_ident
.node
);
764 ExprRet(ref optional_expression
) => {
765 walk_list
!(visitor
, visit_expr
, optional_expression
);
767 ExprInlineAsm(ref ia
) => {
768 for &(_
, ref input
) in &ia
.inputs
{
769 visitor
.visit_expr(&input
)
771 for &(_
, ref output
, _
) in &ia
.outputs
{
772 visitor
.visit_expr(&output
)
777 visitor
.visit_expr_post(expression
)
780 pub fn walk_arm
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, arm
: &'v Arm
) {
781 walk_list
!(visitor
, visit_pat
, &arm
.pats
);
782 walk_list
!(visitor
, visit_expr
, &arm
.guard
);
783 visitor
.visit_expr(&arm
.body
);
784 walk_list
!(visitor
, visit_attribute
, &arm
.attrs
);