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 `intravisit::walk_*` to apply the default traversal algorithm, or prevent
14 //! deeper traversal by doing nothing.
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`
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
29 use syntax
::ast
::{NodeId, CRATE_NODE_ID, Name, Attribute}
;
30 use syntax
::attr
::ThinAttributesExt
;
31 use syntax
::codemap
::Span
;
37 #[derive(Copy, Clone, PartialEq, Eq)]
39 /// fn foo() or extern "Abi" fn foo()
40 ItemFn(Name
, &'a Generics
, Unsafety
, Constness
, Abi
, &'a Visibility
, &'a
[Attribute
]),
43 Method(Name
, &'a MethodSig
, Option
<&'a Visibility
>, &'a
[Attribute
]),
46 Closure(&'a
[Attribute
]),
50 pub fn attrs(&self) -> &'a
[Attribute
] {
52 FnKind
::ItemFn(_
, _
, _
, _
, _
, _
, attrs
) => attrs
,
53 FnKind
::Method(_
, _
, _
, attrs
) => attrs
,
54 FnKind
::Closure(attrs
) => attrs
,
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`.
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.
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 ///////////////////////////////////////////////////////////////////////////
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
85 #[allow(unused_variables)]
86 fn visit_nested_item(&mut self, id
: ItemId
) {
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
) {
95 ///////////////////////////////////////////////////////////////////////////
97 fn visit_name(&mut self, _span
: Span
, _name
: Name
) {
100 fn visit_ident(&mut self, span
: Span
, ident
: Ident
) {
101 walk_ident(self, span
, ident
);
103 fn visit_mod(&mut self, m
: &'v Mod
, _s
: Span
, _n
: NodeId
) {
106 fn visit_foreign_item(&mut self, i
: &'v ForeignItem
) {
107 walk_foreign_item(self, i
)
109 fn visit_local(&mut self, l
: &'v Local
) {
112 fn visit_block(&mut self, b
: &'v Block
) {
115 fn visit_stmt(&mut self, s
: &'v Stmt
) {
118 fn visit_arm(&mut self, a
: &'v Arm
) {
121 fn visit_pat(&mut self, p
: &'v Pat
) {
124 fn visit_decl(&mut self, d
: &'v Decl
) {
127 fn visit_expr(&mut self, ex
: &'v Expr
) {
130 fn visit_expr_post(&mut self, _ex
: &'v Expr
) {
132 fn visit_ty(&mut self, t
: &'v Ty
) {
135 fn visit_generics(&mut self, g
: &'v Generics
) {
136 walk_generics(self, g
)
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
)
141 fn visit_trait_item(&mut self, ti
: &'v TraitItem
) {
142 walk_trait_item(self, ti
)
144 fn visit_impl_item(&mut self, ii
: &'v ImplItem
) {
145 walk_impl_item(self, ii
)
147 fn visit_trait_ref(&mut self, t
: &'v TraitRef
) {
148 walk_trait_ref(self, t
)
150 fn visit_ty_param_bound(&mut self, bounds
: &'v TyParamBound
) {
151 walk_ty_param_bound(self, bounds
)
153 fn visit_poly_trait_ref(&mut self, t
: &'v PolyTraitRef
, m
: &'v TraitBoundModifier
) {
154 walk_poly_trait_ref(self, t
, m
)
156 fn visit_variant_data(&mut self,
162 walk_struct_def(self, s
)
164 fn visit_struct_field(&mut self, s
: &'v StructField
) {
165 walk_struct_field(self, s
)
167 fn visit_enum_def(&mut self,
168 enum_definition
: &'v EnumDef
,
169 generics
: &'v Generics
,
172 walk_enum_def(self, enum_definition
, generics
, item_id
)
174 fn visit_variant(&mut self, v
: &'v Variant
, g
: &'v Generics
, item_id
: NodeId
) {
175 walk_variant(self, v
, g
, item_id
)
177 fn visit_lifetime(&mut self, lifetime
: &'v Lifetime
) {
178 walk_lifetime(self, lifetime
)
180 fn visit_lifetime_def(&mut self, lifetime
: &'v LifetimeDef
) {
181 walk_lifetime_def(self, lifetime
)
183 fn visit_explicit_self(&mut self, es
: &'v ExplicitSelf
) {
184 walk_explicit_self(self, es
)
186 fn visit_path(&mut self, path
: &'v Path
, _id
: NodeId
) {
187 walk_path(self, path
)
189 fn visit_path_list_item(&mut self, prefix
: &'v Path
, item
: &'v PathListItem
) {
190 walk_path_list_item(self, prefix
, item
)
192 fn visit_path_segment(&mut self, path_span
: Span
, path_segment
: &'v PathSegment
) {
193 walk_path_segment(self, path_span
, path_segment
)
195 fn visit_path_parameters(&mut self, path_span
: Span
, path_parameters
: &'v PathParameters
) {
196 walk_path_parameters(self, path_span
, path_parameters
)
198 fn visit_assoc_type_binding(&mut self, type_binding
: &'v TypeBinding
) {
199 walk_assoc_type_binding(self, type_binding
)
201 fn visit_attribute(&mut self, _attr
: &'v Attribute
) {
203 fn visit_macro_def(&mut self, macro_def
: &'v MacroDef
) {
204 walk_macro_def(self, macro_def
)
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
);
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
);
220 pub fn walk_ident
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, span
: Span
, ident
: Ident
) {
221 visitor
.visit_name(span
, ident
.name
);
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
);
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
, ¯o_def
.attrs
);
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
);
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
);
249 pub fn walk_lifetime
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, lifetime
: &'v Lifetime
) {
250 visitor
.visit_name(lifetime
.span
, lifetime
.name
);
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
);
258 pub fn walk_explicit_self
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, explicit_self
: &'v ExplicitSelf
) {
259 match explicit_self
.node
{
262 visitor
.visit_name(explicit_self
.span
, name
)
264 SelfRegion(ref opt_lifetime
, _
, name
) => {
265 visitor
.visit_name(explicit_self
.span
, name
);
266 walk_list
!(visitor
, visit_lifetime
, opt_lifetime
);
268 SelfExplicit(ref typ
, name
) => {
269 visitor
.visit_name(explicit_self
.span
, name
);
270 visitor
.visit_ty(typ
)
275 pub fn walk_poly_trait_ref
<'v
, V
>(visitor
: &mut V
,
276 trait_ref
: &'v PolyTraitRef
,
277 _modifier
: &'v TraitBoundModifier
)
280 walk_list
!(visitor
, visit_lifetime_def
, &trait_ref
.bound_lifetimes
);
281 visitor
.visit_trait_ref(&trait_ref
.trait_ref
);
284 pub fn walk_trait_ref
<'v
, V
>(visitor
: &mut V
, trait_ref
: &'v TraitRef
)
287 visitor
.visit_path(&trait_ref
.path
, trait_ref
.ref_id
)
290 pub fn walk_item
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, item
: &'v Item
) {
291 visitor
.visit_name(item
.span
, item
.name
);
293 ItemExternCrate(opt_name
) => {
294 walk_opt_name(visitor
, item
.span
, opt_name
)
298 ViewPathSimple(name
, ref path
) => {
299 visitor
.visit_name(vp
.span
, name
);
300 visitor
.visit_path(path
, item
.id
);
302 ViewPathGlob(ref path
) => {
303 visitor
.visit_path(path
, item
.id
);
305 ViewPathList(ref prefix
, ref list
) => {
306 if !list
.is_empty() {
308 visitor
.visit_path_list_item(prefix
, item
)
311 visitor
.visit_path(prefix
, item
.id
);
316 ItemStatic(ref typ
, _
, ref expr
) |
317 ItemConst(ref typ
, ref expr
) => {
318 visitor
.visit_ty(typ
);
319 visitor
.visit_expr(expr
);
321 ItemFn(ref declaration
, unsafety
, constness
, abi
, ref generics
, ref body
) => {
322 visitor
.visit_fn(FnKind
::ItemFn(item
.name
,
334 ItemMod(ref module
) => {
335 visitor
.visit_mod(module
, item
.span
, item
.id
)
337 ItemForeignMod(ref foreign_module
) => {
338 walk_list
!(visitor
, visit_foreign_item
, &foreign_module
.items
);
340 ItemTy(ref typ
, ref type_parameters
) => {
341 visitor
.visit_ty(typ
);
342 visitor
.visit_generics(type_parameters
)
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
)
348 ItemDefaultImpl(_
, ref trait_ref
) => {
349 visitor
.visit_trait_ref(trait_ref
)
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
);
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
);
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
);
367 walk_list
!(visitor
, visit_attribute
, &item
.attrs
);
370 pub fn walk_enum_def
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
371 enum_definition
: &'v EnumDef
,
372 generics
: &'v Generics
,
376 &enum_definition
.variants
,
381 pub fn walk_variant
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
382 variant
: &'v Variant
,
383 generics
: &'v Generics
,
385 visitor
.visit_name(variant
.span
, variant
.node
.name
);
386 visitor
.visit_variant_data(&variant
.node
.data
,
391 walk_list
!(visitor
, visit_expr
, &variant
.node
.disr_expr
);
392 walk_list
!(visitor
, visit_attribute
, &variant
.node
.attrs
);
395 pub fn walk_ty
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, typ
: &'v Ty
) {
400 TyPtr(ref mutable_type
) => {
401 visitor
.visit_ty(&mutable_type
.ty
)
403 TyRptr(ref opt_lifetime
, ref mutable_type
) => {
404 walk_list
!(visitor
, visit_lifetime
, opt_lifetime
);
405 visitor
.visit_ty(&mutable_type
.ty
)
407 TyTup(ref tuple_element_types
) => {
408 walk_list
!(visitor
, visit_ty
, tuple_element_types
);
410 TyBareFn(ref function_declaration
) => {
411 walk_fn_decl(visitor
, &function_declaration
.decl
);
412 walk_list
!(visitor
, visit_lifetime_def
, &function_declaration
.lifetimes
);
414 TyPath(ref maybe_qself
, ref path
) => {
415 if let Some(ref qself
) = *maybe_qself
{
416 visitor
.visit_ty(&qself
.ty
);
418 visitor
.visit_path(path
, typ
.id
);
420 TyObjectSum(ref ty
, ref bounds
) => {
421 visitor
.visit_ty(ty
);
422 walk_list
!(visitor
, visit_ty_param_bound
, bounds
);
424 TyFixedLengthVec(ref ty
, ref expression
) => {
425 visitor
.visit_ty(ty
);
426 visitor
.visit_expr(expression
)
428 TyPolyTraitRef(ref bounds
) => {
429 walk_list
!(visitor
, visit_ty_param_bound
, bounds
);
431 TyTypeof(ref expression
) => {
432 visitor
.visit_expr(expression
)
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
);
444 pub fn walk_path_list_item
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
446 item
: &'v PathListItem
) {
447 for segment
in &prefix
.segments
{
448 visitor
.visit_path_segment(prefix
.span
, segment
);
451 walk_opt_name(visitor
, item
.span
, item
.node
.name());
452 walk_opt_name(visitor
, item
.span
, item
.node
.rename());
455 pub fn walk_path_segment
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
457 segment
: &'v PathSegment
) {
458 visitor
.visit_ident(path_span
, segment
.identifier
);
459 visitor
.visit_path_parameters(path_span
, &segment
.parameters
);
462 pub fn walk_path_parameters
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
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
);
471 ParenthesizedParameters(ref data
) => {
472 walk_list
!(visitor
, visit_ty
, &data
.inputs
);
473 walk_list
!(visitor
, visit_ty
, &data
.output
);
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
);
484 pub fn walk_pat
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, pattern
: &'v Pat
) {
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
);
492 PatKind
::Path(ref path
) => {
493 visitor
.visit_path(path
, pattern
.id
);
495 PatKind
::QPath(ref qself
, ref path
) => {
496 visitor
.visit_ty(&qself
.ty
);
497 visitor
.visit_path(path
, pattern
.id
)
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
)
506 PatKind
::Tup(ref tuple_elements
) => {
507 walk_list
!(visitor
, visit_pat
, tuple_elements
);
509 PatKind
::Box(ref subpattern
) |
510 PatKind
::Ref(ref subpattern
, _
) => {
511 visitor
.visit_pat(subpattern
)
513 PatKind
::Ident(_
, ref pth1
, ref optional_subpattern
) => {
514 visitor
.visit_ident(pth1
.span
, pth1
.node
);
515 walk_list
!(visitor
, visit_pat
, optional_subpattern
);
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
)
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
);
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
);
534 match foreign_item
.node
{
535 ForeignItemFn(ref function_declaration
, ref generics
) => {
536 walk_fn_decl(visitor
, function_declaration
);
537 visitor
.visit_generics(generics
)
539 ForeignItemStatic(ref typ
, _
) => visitor
.visit_ty(typ
),
542 walk_list
!(visitor
, visit_attribute
, &foreign_item
.attrs
);
545 pub fn walk_ty_param_bound
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, bound
: &'v TyParamBound
) {
547 TraitTyParamBound(ref typ
, ref modifier
) => {
548 visitor
.visit_poly_trait_ref(typ
, modifier
);
550 RegionTyParamBound(ref lifetime
) => {
551 visitor
.visit_lifetime(lifetime
);
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
, ¶m
.bounds
);
560 walk_list
!(visitor
, visit_ty
, ¶m
.default);
562 walk_list
!(visitor
, visit_lifetime_def
, &generics
.lifetimes
);
563 for predicate
in &generics
.where_clause
.predicates
{
565 &WherePredicate
::BoundPredicate(WhereBoundPredicate
{ref bounded_ty
,
569 visitor
.visit_ty(bounded_ty
);
570 walk_list
!(visitor
, visit_ty_param_bound
, bounds
);
571 walk_list
!(visitor
, visit_lifetime_def
, bound_lifetimes
);
573 &WherePredicate
::RegionPredicate(WhereRegionPredicate
{ref lifetime
,
576 visitor
.visit_lifetime(lifetime
);
577 walk_list
!(visitor
, visit_lifetime
, bounds
);
579 &WherePredicate
::EqPredicate(WhereEqPredicate
{id
,
583 visitor
.visit_path(path
, id
);
584 visitor
.visit_ty(ty
);
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
)
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
)
601 walk_fn_ret_ty(visitor
, &function_declaration
.output
)
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
)
608 walk_fn_ret_ty(visitor
, &function_declaration
.output
)
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
);
616 FnKind
::Method(_
, sig
, _
, _
) => {
617 visitor
.visit_generics(&sig
.generics
);
618 visitor
.visit_explicit_self(&sig
.explicit_self
);
620 FnKind
::Closure(_
) => {}
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
,
629 walk_fn_decl(visitor
, function_declaration
);
630 walk_fn_kind(visitor
, function_kind
);
631 visitor
.visit_block(function_body
)
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);
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
);
647 MethodTraitItem(ref sig
, Some(ref body
)) => {
648 visitor
.visit_fn(FnKind
::Method(trait_item
.name
,
657 TypeTraitItem(ref bounds
, ref default) => {
658 walk_list
!(visitor
, visit_ty_param_bound
, bounds
);
659 walk_list
!(visitor
, visit_ty
, default);
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
);
672 ImplItemKind
::Method(ref sig
, ref body
) => {
673 visitor
.visit_fn(FnKind
::Method(impl_item
.name
,
675 Some(&impl_item
.vis
),
682 ImplItemKind
::Type(ref ty
) => {
683 visitor
.visit_ty(ty
);
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());
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
);
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
);
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
)
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
),
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
)
724 ExprVec(ref subexpressions
) => {
725 walk_list
!(visitor
, visit_expr
, subexpressions
);
727 ExprRepeat(ref element
, ref count
) => {
728 visitor
.visit_expr(element
);
729 visitor
.visit_expr(count
)
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
)
737 walk_list
!(visitor
, visit_expr
, optional_base
);
739 ExprTup(ref subexpressions
) => {
740 walk_list
!(visitor
, visit_expr
, subexpressions
);
742 ExprCall(ref callee_expression
, ref arguments
) => {
743 walk_list
!(visitor
, visit_expr
, arguments
);
744 visitor
.visit_expr(callee_expression
)
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
);
751 ExprBinary(_
, ref left_expression
, ref right_expression
) => {
752 visitor
.visit_expr(left_expression
);
753 visitor
.visit_expr(right_expression
)
755 ExprAddrOf(_
, ref subexpression
) | ExprUnary(_
, ref subexpression
) => {
756 visitor
.visit_expr(subexpression
)
759 ExprCast(ref subexpression
, ref typ
) | ExprType(ref subexpression
, ref typ
) => {
760 visitor
.visit_expr(subexpression
);
761 visitor
.visit_ty(typ
)
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
);
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
)
773 ExprLoop(ref block
, opt_ident
) => {
774 visitor
.visit_block(block
);
775 walk_opt_ident(visitor
, expression
.span
, opt_ident
)
777 ExprMatch(ref subexpression
, ref arms
, _
) => {
778 visitor
.visit_expr(subexpression
);
779 walk_list
!(visitor
, visit_arm
, arms
);
781 ExprClosure(_
, ref function_declaration
, ref body
) => {
782 visitor
.visit_fn(FnKind
::Closure(expression
.attrs
.as_attr_slice()),
783 function_declaration
,
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
)
793 ExprAssignOp(_
, ref left_expression
, ref right_expression
) => {
794 visitor
.visit_expr(right_expression
);
795 visitor
.visit_expr(left_expression
)
797 ExprField(ref subexpression
, ref name
) => {
798 visitor
.visit_expr(subexpression
);
799 visitor
.visit_name(name
.span
, name
.node
);
801 ExprTupField(ref subexpression
, _
) => {
802 visitor
.visit_expr(subexpression
);
804 ExprIndex(ref main_expression
, ref index_expression
) => {
805 visitor
.visit_expr(main_expression
);
806 visitor
.visit_expr(index_expression
)
808 ExprPath(ref maybe_qself
, ref path
) => {
809 if let Some(ref qself
) = *maybe_qself
{
810 visitor
.visit_ty(&qself
.ty
);
812 visitor
.visit_path(path
, expression
.id
)
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
);
819 ExprRet(ref optional_expression
) => {
820 walk_list
!(visitor
, visit_expr
, optional_expression
);
822 ExprInlineAsm(_
, ref outputs
, ref inputs
) => {
823 for output
in outputs
{
824 visitor
.visit_expr(output
)
826 for input
in inputs
{
827 visitor
.visit_expr(input
)
832 visitor
.visit_expr_post(expression
)
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
);
842 #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
849 pub fn max() -> IdRange
{
856 pub fn empty(&self) -> bool
{
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);
866 pub trait IdVisitingOperation
{
867 fn visit_id(&mut self, node_id
: NodeId
);
870 pub struct IdRangeComputingVisitor
{
874 impl IdRangeComputingVisitor
{
875 pub fn new() -> IdRangeComputingVisitor
{
876 IdRangeComputingVisitor { result: IdRange::max() }
879 pub fn result(&self) -> IdRange
{
884 impl IdVisitingOperation
for IdRangeComputingVisitor
{
885 fn visit_id(&mut self, id
: NodeId
) {
890 pub struct IdVisitor
<'a
, O
: 'a
> {
891 operation
: &'a
mut O
,
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.
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 }
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
)
915 for lifetime
in &generics
.lifetimes
{
916 self.operation
.visit_id(lifetime
.lifetime
.id
)
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
)
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
)
932 fn visit_item(&mut self, item
: &Item
) {
933 assert
!(!self.skip_members
);
934 self.skip_members
= true;
936 self.operation
.visit_id(item
.id
);
938 ItemUse(ref view_path
) => {
939 match view_path
.node
{
940 ViewPathSimple(_
, _
) |
941 ViewPathGlob(_
) => {}
942 ViewPathList(_
, ref paths
) => {
944 self.operation
.visit_id(path
.node
.id())
951 walk_item(self, item
);
953 self.skip_members
= false;
956 fn visit_local(&mut self, local
: &Local
) {
957 self.operation
.visit_id(local
.id
);
958 walk_local(self, local
)
961 fn visit_block(&mut self, block
: &Block
) {
962 self.operation
.visit_id(block
.id
);
963 walk_block(self, block
)
966 fn visit_stmt(&mut self, statement
: &Stmt
) {
967 self.operation
.visit_id(statement
.node
.id());
968 walk_stmt(self, statement
)
971 fn visit_pat(&mut self, pattern
: &Pat
) {
972 self.operation
.visit_id(pattern
.id
);
973 walk_pat(self, pattern
)
976 fn visit_expr(&mut self, expression
: &Expr
) {
977 self.operation
.visit_id(expression
.id
);
978 walk_expr(self, expression
)
981 fn visit_ty(&mut self, typ
: &Ty
) {
982 self.operation
.visit_id(typ
.id
);
986 fn visit_generics(&mut self, generics
: &Generics
) {
987 self.visit_generics_helper(generics
);
988 walk_generics(self, generics
)
991 fn visit_fn(&mut self,
992 function_kind
: FnKind
<'v
>,
993 function_declaration
: &'v FnDecl
,
997 self.operation
.visit_id(node_id
);
999 match function_kind
{
1000 FnKind
::ItemFn(_
, generics
, _
, _
, _
, _
, _
) => {
1001 self.visit_generics_helper(generics
)
1003 FnKind
::Method(_
, sig
, _
, _
) => {
1004 self.visit_generics_helper(&sig
.generics
)
1006 FnKind
::Closure(_
) => {}
1009 for argument
in &function_declaration
.inputs
{
1010 self.operation
.visit_id(argument
.id
)
1013 walk_fn(self, function_kind
, function_declaration
, block
, span
);
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
)
1021 fn visit_variant_data(&mut self,
1022 struct_def
: &VariantData
,
1027 self.operation
.visit_id(struct_def
.id());
1028 walk_struct_def(self, struct_def
);
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
);
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
);
1045 fn visit_lifetime(&mut self, lifetime
: &Lifetime
) {
1046 self.operation
.visit_id(lifetime
.id
);
1049 fn visit_lifetime_def(&mut self, def
: &LifetimeDef
) {
1050 self.visit_lifetime(&def
.lifetime
);
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
);
1059 /// Computes the id range for a single fn body, ignoring nested items.
1060 pub fn compute_id_range_for_fn_body(fk
: FnKind
,
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