1 //! HIR walker for walking the contents of nodes.
3 //! **For an overview of the visitor strategy, see the docs on the
4 //! `super::itemlikevisit::ItemLikeVisitor` trait.**
6 //! If you have decided to use this visitor, here are some general
7 //! notes on how to do so:
9 //! Each overridden visit method has full control over what
10 //! happens with its node, it can do its own traversal of the node's children,
11 //! call `intravisit::walk_*` to apply the default traversal algorithm, or prevent
12 //! deeper traversal by doing nothing.
14 //! When visiting the HIR, the contents of nested items are NOT visited
15 //! by default. This is different from the AST visitor, which does a deep walk.
16 //! Hence this module is called `intravisit`; see the method `visit_nested_item`
19 //! Note: it is an important invariant that the default visitor walks
20 //! the body of a function in "execution order" - more concretely, if
21 //! we consider the reverse post-order (RPO) of the CFG implied by the HIR,
22 //! then a pre-order traversal of the HIR is consistent with the CFG RPO
23 //! on the *initial CFG point* of each HIR node, while a post-order traversal
24 //! of the HIR is consistent with the CFG RPO on each *final CFG point* of
27 //! One thing that follows is that if HIR node A always starts/ends executing
28 //! before HIR node B, then A appears in traversal pre/postorder before B,
29 //! respectively. (This follows from RPO respecting CFG domination).
31 //! This order consistency is required in a few places in rustc, for
32 //! example generator inference, and possibly also HIR borrowck.
34 use super::itemlikevisit
::DeepVisitor
;
37 use crate::hir
::map
::Map
;
39 use syntax
::ast
::{Ident, Name, Attribute}
;
42 #[derive(Copy, Clone)]
44 /// `#[xxx] pub async/const/extern "Abi" fn foo()`
45 ItemFn(Ident
, &'a Generics
, FnHeader
, &'a Visibility
, &'a
[Attribute
]),
48 Method(Ident
, &'a FnSig
, Option
<&'a Visibility
>, &'a
[Attribute
]),
51 Closure(&'a
[Attribute
]),
55 pub fn attrs(&self) -> &'a
[Attribute
] {
57 FnKind
::ItemFn(.., attrs
) => attrs
,
58 FnKind
::Method(.., attrs
) => attrs
,
59 FnKind
::Closure(attrs
) => attrs
,
63 pub fn header(&self) -> Option
<&FnHeader
> {
65 FnKind
::ItemFn(_
, _
, ref header
, _
, _
) => Some(header
),
66 FnKind
::Method(_
, ref sig
, _
, _
) => Some(&sig
.header
),
67 FnKind
::Closure(_
) => None
,
72 /// Specifies what nested things a visitor wants to visit. The most
73 /// common choice is `OnlyBodies`, which will cause the visitor to
74 /// visit fn bodies for fns that it encounters, but skip over nested
77 /// See the comments on `ItemLikeVisitor` for more details on the overall
79 pub enum NestedVisitorMap
<'this
, 'tcx
> {
80 /// Do not visit any nested things. When you add a new
81 /// "non-nested" thing, you will want to audit such uses to see if
82 /// they remain valid.
84 /// Use this if you are only walking some particular kind of tree
85 /// (i.e., a type, or fn signature) and you don't want to thread a
89 /// Do not visit nested item-like things, but visit nested things
90 /// that are inside of an item-like.
92 /// **This is the most common choice.** A very common pattern is
93 /// to use `visit_all_item_likes()` as an outer loop,
94 /// and to have the visitor that visits the contents of each item
95 /// using this setting.
96 OnlyBodies(&'this Map
<'tcx
>),
98 /// Visits all nested things, including item-likes.
100 /// **This is an unusual choice.** It is used when you want to
101 /// process everything within their lexical context. Typically you
102 /// kick off the visit by doing `walk_krate()`.
103 All(&'this Map
<'tcx
>),
106 impl<'this
, 'tcx
> NestedVisitorMap
<'this
, 'tcx
> {
107 /// Returns the map to use for an "intra item-like" thing (if any).
108 /// E.g., function body.
109 pub fn intra(self) -> Option
<&'this Map
<'tcx
>> {
111 NestedVisitorMap
::None
=> None
,
112 NestedVisitorMap
::OnlyBodies(map
) => Some(map
),
113 NestedVisitorMap
::All(map
) => Some(map
),
117 /// Returns the map to use for an "item-like" thing (if any).
118 /// E.g., item, impl-item.
119 pub fn inter(self) -> Option
<&'this Map
<'tcx
>> {
121 NestedVisitorMap
::None
=> None
,
122 NestedVisitorMap
::OnlyBodies(_
) => None
,
123 NestedVisitorMap
::All(map
) => Some(map
),
128 /// Each method of the Visitor trait is a hook to be potentially
129 /// overridden. Each method's default implementation recursively visits
130 /// the substructure of the input via the corresponding `walk` method;
131 /// e.g., the `visit_mod` method by default calls `intravisit::walk_mod`.
133 /// Note that this visitor does NOT visit nested items by default
134 /// (this is why the module is called `intravisit`, to distinguish it
135 /// from the AST's `visit` module, which acts differently). If you
136 /// simply want to visit all items in the crate in some order, you
137 /// should call `Crate::visit_all_items`. Otherwise, see the comment
138 /// on `visit_nested_item` for details on how to visit nested items.
140 /// If you want to ensure that your code handles every variant
141 /// explicitly, you need to override each method. (And you also need
142 /// to monitor future changes to `Visitor` in case a new method with a
143 /// new default implementation gets introduced.)
144 pub trait Visitor
<'v
>: Sized
{
145 ///////////////////////////////////////////////////////////////////////////
148 /// The default versions of the `visit_nested_XXX` routines invoke
149 /// this method to get a map to use. By selecting an enum variant,
150 /// you control which kinds of nested HIR are visited; see
151 /// `NestedVisitorMap` for details. By "nested HIR", we are
152 /// referring to bits of HIR that are not directly embedded within
153 /// one another but rather indirectly, through a table in the
154 /// crate. This is done to control dependencies during incremental
155 /// compilation: the non-inline bits of HIR can be tracked and
156 /// hashed separately.
158 /// **If for some reason you want the nested behavior, but don't
159 /// have a `Map` at your disposal:** then you should override the
160 /// `visit_nested_XXX` methods, and override this method to
161 /// `panic!()`. This way, if a new `visit_nested_XXX` variant is
162 /// added in the future, we will see the panic in your code and
163 /// fix it appropriately.
164 fn nested_visit_map
<'this
>(&'this
mut self) -> NestedVisitorMap
<'this
, 'v
>;
166 /// Invoked when a nested item is encountered. By default does
167 /// nothing unless you override `nested_visit_map` to return other than
168 /// `None`, in which case it will walk the item. **You probably
169 /// don't want to override this method** -- instead, override
170 /// `nested_visit_map` or use the "shallow" or "deep" visit
171 /// patterns described on `itemlikevisit::ItemLikeVisitor`. The only
172 /// reason to override this method is if you want a nested pattern
173 /// but cannot supply a `Map`; see `nested_visit_map` for advice.
174 #[allow(unused_variables)]
175 fn visit_nested_item(&mut self, id
: ItemId
) {
176 let opt_item
= self.nested_visit_map().inter().map(|map
| map
.expect_item(id
.id
));
177 if let Some(item
) = opt_item
{
178 self.visit_item(item
);
182 /// Like `visit_nested_item()`, but for trait items. See
183 /// `visit_nested_item()` for advice on when to override this
185 #[allow(unused_variables)]
186 fn visit_nested_trait_item(&mut self, id
: TraitItemId
) {
187 let opt_item
= self.nested_visit_map().inter().map(|map
| map
.trait_item(id
));
188 if let Some(item
) = opt_item
{
189 self.visit_trait_item(item
);
193 /// Like `visit_nested_item()`, but for impl items. See
194 /// `visit_nested_item()` for advice on when to override this
196 #[allow(unused_variables)]
197 fn visit_nested_impl_item(&mut self, id
: ImplItemId
) {
198 let opt_item
= self.nested_visit_map().inter().map(|map
| map
.impl_item(id
));
199 if let Some(item
) = opt_item
{
200 self.visit_impl_item(item
);
204 /// Invoked to visit the body of a function, method or closure. Like
205 /// visit_nested_item, does nothing by default unless you override
206 /// `nested_visit_map` to return other than `None`, in which case it will walk
208 fn visit_nested_body(&mut self, id
: BodyId
) {
209 let opt_body
= self.nested_visit_map().intra().map(|map
| map
.body(id
));
210 if let Some(body
) = opt_body
{
211 self.visit_body(body
);
215 fn visit_param(&mut self, param
: &'v Param
) {
216 walk_param(self, param
)
219 /// Visits the top-level item and (optionally) nested items / impl items. See
220 /// `visit_nested_item` for details.
221 fn visit_item(&mut self, i
: &'v Item
) {
225 fn visit_body(&mut self, b
: &'v Body
) {
229 /// When invoking `visit_all_item_likes()`, you need to supply an
230 /// item-like visitor. This method converts a "intra-visit"
231 /// visitor into an item-like visitor that walks the entire tree.
232 /// If you use this, you probably don't want to process the
233 /// contents of nested item-like things, since the outer loop will
234 /// visit them as well.
235 fn as_deep_visitor
<'s
>(&'s
mut self) -> DeepVisitor
<'s
, Self> {
236 DeepVisitor
::new(self)
239 ///////////////////////////////////////////////////////////////////////////
241 fn visit_id(&mut self, _hir_id
: HirId
) {
244 fn visit_name(&mut self, _span
: Span
, _name
: Name
) {
247 fn visit_ident(&mut self, ident
: Ident
) {
248 walk_ident(self, ident
)
250 fn visit_mod(&mut self, m
: &'v Mod
, _s
: Span
, n
: HirId
) {
253 fn visit_foreign_item(&mut self, i
: &'v ForeignItem
) {
254 walk_foreign_item(self, i
)
256 fn visit_local(&mut self, l
: &'v Local
) {
259 fn visit_block(&mut self, b
: &'v Block
) {
262 fn visit_stmt(&mut self, s
: &'v Stmt
) {
265 fn visit_arm(&mut self, a
: &'v Arm
) {
268 fn visit_pat(&mut self, p
: &'v Pat
) {
271 fn visit_anon_const(&mut self, c
: &'v AnonConst
) {
272 walk_anon_const(self, c
)
274 fn visit_expr(&mut self, ex
: &'v Expr
) {
277 fn visit_ty(&mut self, t
: &'v Ty
) {
280 fn visit_generic_param(&mut self, p
: &'v GenericParam
) {
281 walk_generic_param(self, p
)
283 fn visit_generics(&mut self, g
: &'v Generics
) {
284 walk_generics(self, g
)
286 fn visit_where_predicate(&mut self, predicate
: &'v WherePredicate
) {
287 walk_where_predicate(self, predicate
)
289 fn visit_fn_decl(&mut self, fd
: &'v FnDecl
) {
290 walk_fn_decl(self, fd
)
292 fn visit_fn(&mut self, fk
: FnKind
<'v
>, fd
: &'v FnDecl
, b
: BodyId
, s
: Span
, id
: HirId
) {
293 walk_fn(self, fk
, fd
, b
, s
, id
)
295 fn visit_use(&mut self, path
: &'v Path
, hir_id
: HirId
) {
296 walk_use(self, path
, hir_id
)
298 fn visit_trait_item(&mut self, ti
: &'v TraitItem
) {
299 walk_trait_item(self, ti
)
301 fn visit_trait_item_ref(&mut self, ii
: &'v TraitItemRef
) {
302 walk_trait_item_ref(self, ii
)
304 fn visit_impl_item(&mut self, ii
: &'v ImplItem
) {
305 walk_impl_item(self, ii
)
307 fn visit_impl_item_ref(&mut self, ii
: &'v ImplItemRef
) {
308 walk_impl_item_ref(self, ii
)
310 fn visit_trait_ref(&mut self, t
: &'v TraitRef
) {
311 walk_trait_ref(self, t
)
313 fn visit_param_bound(&mut self, bounds
: &'v GenericBound
) {
314 walk_param_bound(self, bounds
)
316 fn visit_poly_trait_ref(&mut self, t
: &'v PolyTraitRef
, m
: TraitBoundModifier
) {
317 walk_poly_trait_ref(self, t
, m
)
319 fn visit_variant_data(&mut self,
325 walk_struct_def(self, s
)
327 fn visit_struct_field(&mut self, s
: &'v StructField
) {
328 walk_struct_field(self, s
)
330 fn visit_enum_def(&mut self,
331 enum_definition
: &'v EnumDef
,
332 generics
: &'v Generics
,
335 walk_enum_def(self, enum_definition
, generics
, item_id
)
337 fn visit_variant(&mut self, v
: &'v Variant
, g
: &'v Generics
, item_id
: HirId
) {
338 walk_variant(self, v
, g
, item_id
)
340 fn visit_label(&mut self, label
: &'v Label
) {
341 walk_label(self, label
)
343 fn visit_generic_arg(&mut self, generic_arg
: &'v GenericArg
) {
345 GenericArg
::Lifetime(lt
) => self.visit_lifetime(lt
),
346 GenericArg
::Type(ty
) => self.visit_ty(ty
),
347 GenericArg
::Const(ct
) => self.visit_anon_const(&ct
.value
),
350 fn visit_lifetime(&mut self, lifetime
: &'v Lifetime
) {
351 walk_lifetime(self, lifetime
)
353 fn visit_qpath(&mut self, qpath
: &'v QPath
, id
: HirId
, span
: Span
) {
354 walk_qpath(self, qpath
, id
, span
)
356 fn visit_path(&mut self, path
: &'v Path
, _id
: HirId
) {
357 walk_path(self, path
)
359 fn visit_path_segment(&mut self, path_span
: Span
, path_segment
: &'v PathSegment
) {
360 walk_path_segment(self, path_span
, path_segment
)
362 fn visit_generic_args(&mut self, path_span
: Span
, generic_args
: &'v GenericArgs
) {
363 walk_generic_args(self, path_span
, generic_args
)
365 fn visit_assoc_type_binding(&mut self, type_binding
: &'v TypeBinding
) {
366 walk_assoc_type_binding(self, type_binding
)
368 fn visit_attribute(&mut self, _attr
: &'v Attribute
) {
370 fn visit_macro_def(&mut self, macro_def
: &'v MacroDef
) {
371 walk_macro_def(self, macro_def
)
373 fn visit_vis(&mut self, vis
: &'v Visibility
) {
376 fn visit_associated_item_kind(&mut self, kind
: &'v AssocItemKind
) {
377 walk_associated_item_kind(self, kind
);
379 fn visit_defaultness(&mut self, defaultness
: &'v Defaultness
) {
380 walk_defaultness(self, defaultness
);
384 /// Walks the contents of a crate. See also `Crate::visit_all_items`.
385 pub fn walk_crate
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, krate
: &'v Crate
) {
386 visitor
.visit_mod(&krate
.module
, krate
.span
, CRATE_HIR_ID
);
387 walk_list
!(visitor
, visit_attribute
, &krate
.attrs
);
388 walk_list
!(visitor
, visit_macro_def
, &krate
.exported_macros
);
391 pub fn walk_macro_def
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, macro_def
: &'v MacroDef
) {
392 visitor
.visit_id(macro_def
.hir_id
);
393 visitor
.visit_name(macro_def
.span
, macro_def
.name
);
394 walk_list
!(visitor
, visit_attribute
, ¯o_def
.attrs
);
397 pub fn walk_mod
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, module
: &'v Mod
, mod_hir_id
: HirId
) {
398 visitor
.visit_id(mod_hir_id
);
399 for &item_id
in &module
.item_ids
{
400 visitor
.visit_nested_item(item_id
);
404 pub fn walk_body
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, body
: &'v Body
) {
405 walk_list
!(visitor
, visit_param
, &body
.params
);
406 visitor
.visit_expr(&body
.value
);
409 pub fn walk_local
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, local
: &'v Local
) {
410 // Intentionally visiting the expr first - the initialization expr
411 // dominates the local's definition.
412 walk_list
!(visitor
, visit_expr
, &local
.init
);
413 walk_list
!(visitor
, visit_attribute
, local
.attrs
.iter());
414 visitor
.visit_id(local
.hir_id
);
415 visitor
.visit_pat(&local
.pat
);
416 walk_list
!(visitor
, visit_ty
, &local
.ty
);
419 pub fn walk_ident
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, ident
: Ident
) {
420 visitor
.visit_name(ident
.span
, ident
.name
);
423 pub fn walk_label
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, label
: &'v Label
) {
424 visitor
.visit_ident(label
.ident
);
427 pub fn walk_lifetime
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, lifetime
: &'v Lifetime
) {
428 visitor
.visit_id(lifetime
.hir_id
);
429 match lifetime
.name
{
430 LifetimeName
::Param(ParamName
::Plain(ident
)) => {
431 visitor
.visit_ident(ident
);
433 LifetimeName
::Param(ParamName
::Fresh(_
)) |
434 LifetimeName
::Param(ParamName
::Error
) |
435 LifetimeName
::Static
|
436 LifetimeName
::Error
|
437 LifetimeName
::Implicit
|
438 LifetimeName
::ImplicitObjectLifetimeDefault
|
439 LifetimeName
::Underscore
=> {}
443 pub fn walk_poly_trait_ref
<'v
, V
>(visitor
: &mut V
,
444 trait_ref
: &'v PolyTraitRef
,
445 _modifier
: TraitBoundModifier
)
448 walk_list
!(visitor
, visit_generic_param
, &trait_ref
.bound_generic_params
);
449 visitor
.visit_trait_ref(&trait_ref
.trait_ref
);
452 pub fn walk_trait_ref
<'v
, V
>(visitor
: &mut V
, trait_ref
: &'v TraitRef
)
455 visitor
.visit_id(trait_ref
.hir_ref_id
);
456 visitor
.visit_path(&trait_ref
.path
, trait_ref
.hir_ref_id
)
459 pub fn walk_param
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, param
: &'v Param
) {
460 visitor
.visit_id(param
.hir_id
);
461 visitor
.visit_pat(¶m
.pat
);
462 walk_list
!(visitor
, visit_attribute
, ¶m
.attrs
);
465 pub fn walk_item
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, item
: &'v Item
) {
466 visitor
.visit_vis(&item
.vis
);
467 visitor
.visit_ident(item
.ident
);
469 ItemKind
::ExternCrate(orig_name
) => {
470 visitor
.visit_id(item
.hir_id
);
471 if let Some(orig_name
) = orig_name
{
472 visitor
.visit_name(item
.span
, orig_name
);
475 ItemKind
::Use(ref path
, _
) => {
476 visitor
.visit_use(path
, item
.hir_id
);
478 ItemKind
::Static(ref typ
, _
, body
) |
479 ItemKind
::Const(ref typ
, body
) => {
480 visitor
.visit_id(item
.hir_id
);
481 visitor
.visit_ty(typ
);
482 visitor
.visit_nested_body(body
);
484 ItemKind
::Fn(ref sig
, ref generics
, body_id
) => {
485 visitor
.visit_fn(FnKind
::ItemFn(item
.ident
,
495 ItemKind
::Mod(ref module
) => {
496 // `visit_mod()` takes care of visiting the `Item`'s `HirId`.
497 visitor
.visit_mod(module
, item
.span
, item
.hir_id
)
499 ItemKind
::ForeignMod(ref foreign_module
) => {
500 visitor
.visit_id(item
.hir_id
);
501 walk_list
!(visitor
, visit_foreign_item
, &foreign_module
.items
);
503 ItemKind
::GlobalAsm(_
) => {
504 visitor
.visit_id(item
.hir_id
);
506 ItemKind
::TyAlias(ref ty
, ref generics
) => {
507 visitor
.visit_id(item
.hir_id
);
508 visitor
.visit_ty(ty
);
509 visitor
.visit_generics(generics
)
511 ItemKind
::OpaqueTy(OpaqueTy
{
516 visitor
.visit_id(item
.hir_id
);
517 walk_generics(visitor
, generics
);
518 walk_list
!(visitor
, visit_param_bound
, bounds
);
520 ItemKind
::Enum(ref enum_definition
, ref generics
) => {
521 visitor
.visit_generics(generics
);
522 // `visit_enum_def()` takes care of visiting the `Item`'s `HirId`.
523 visitor
.visit_enum_def(enum_definition
, generics
, item
.hir_id
, item
.span
)
528 ref opt_trait_reference
,
532 visitor
.visit_id(item
.hir_id
);
533 visitor
.visit_generics(generics
);
534 walk_list
!(visitor
, visit_trait_ref
, opt_trait_reference
);
535 visitor
.visit_ty(typ
);
536 walk_list
!(visitor
, visit_impl_item_ref
, impl_item_refs
);
538 ItemKind
::Struct(ref struct_definition
, ref generics
) |
539 ItemKind
::Union(ref struct_definition
, ref generics
) => {
540 visitor
.visit_generics(generics
);
541 visitor
.visit_id(item
.hir_id
);
542 visitor
.visit_variant_data(struct_definition
, item
.ident
.name
, generics
, item
.hir_id
,
545 ItemKind
::Trait(.., ref generics
, ref bounds
, ref trait_item_refs
) => {
546 visitor
.visit_id(item
.hir_id
);
547 visitor
.visit_generics(generics
);
548 walk_list
!(visitor
, visit_param_bound
, bounds
);
549 walk_list
!(visitor
, visit_trait_item_ref
, trait_item_refs
);
551 ItemKind
::TraitAlias(ref generics
, ref bounds
) => {
552 visitor
.visit_id(item
.hir_id
);
553 visitor
.visit_generics(generics
);
554 walk_list
!(visitor
, visit_param_bound
, bounds
);
557 walk_list
!(visitor
, visit_attribute
, &item
.attrs
);
560 pub fn walk_use
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
563 visitor
.visit_id(hir_id
);
564 visitor
.visit_path(path
, hir_id
);
567 pub fn walk_enum_def
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
568 enum_definition
: &'v EnumDef
,
569 generics
: &'v Generics
,
571 visitor
.visit_id(item_id
);
574 &enum_definition
.variants
,
579 pub fn walk_variant
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
580 variant
: &'v Variant
,
581 generics
: &'v Generics
,
582 parent_item_id
: HirId
) {
583 visitor
.visit_ident(variant
.ident
);
584 visitor
.visit_id(variant
.id
);
585 visitor
.visit_variant_data(&variant
.data
,
590 walk_list
!(visitor
, visit_anon_const
, &variant
.disr_expr
);
591 walk_list
!(visitor
, visit_attribute
, &variant
.attrs
);
594 pub fn walk_ty
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, typ
: &'v Ty
) {
595 visitor
.visit_id(typ
.hir_id
);
598 TyKind
::Slice(ref ty
) => {
601 TyKind
::Ptr(ref mutable_type
) => {
602 visitor
.visit_ty(&mutable_type
.ty
)
604 TyKind
::Rptr(ref lifetime
, ref mutable_type
) => {
605 visitor
.visit_lifetime(lifetime
);
606 visitor
.visit_ty(&mutable_type
.ty
)
609 TyKind
::Tup(ref tuple_element_types
) => {
610 walk_list
!(visitor
, visit_ty
, tuple_element_types
);
612 TyKind
::BareFn(ref function_declaration
) => {
613 walk_list
!(visitor
, visit_generic_param
, &function_declaration
.generic_params
);
614 visitor
.visit_fn_decl(&function_declaration
.decl
);
616 TyKind
::Path(ref qpath
) => {
617 visitor
.visit_qpath(qpath
, typ
.hir_id
, typ
.span
);
619 TyKind
::Def(item_id
, ref lifetimes
) => {
620 visitor
.visit_nested_item(item_id
);
621 walk_list
!(visitor
, visit_generic_arg
, lifetimes
);
623 TyKind
::Array(ref ty
, ref length
) => {
624 visitor
.visit_ty(ty
);
625 visitor
.visit_anon_const(length
)
627 TyKind
::TraitObject(ref bounds
, ref lifetime
) => {
628 for bound
in bounds
{
629 visitor
.visit_poly_trait_ref(bound
, TraitBoundModifier
::None
);
631 visitor
.visit_lifetime(lifetime
);
633 TyKind
::Typeof(ref expression
) => {
634 visitor
.visit_anon_const(expression
)
636 TyKind
::Infer
| TyKind
::Err
=> {}
640 pub fn walk_qpath
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, qpath
: &'v QPath
, id
: HirId
, span
: Span
) {
642 QPath
::Resolved(ref maybe_qself
, ref path
) => {
643 if let Some(ref qself
) = *maybe_qself
{
644 visitor
.visit_ty(qself
);
646 visitor
.visit_path(path
, id
)
648 QPath
::TypeRelative(ref qself
, ref segment
) => {
649 visitor
.visit_ty(qself
);
650 visitor
.visit_path_segment(span
, segment
);
655 pub fn walk_path
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, path
: &'v Path
) {
656 for segment
in &path
.segments
{
657 visitor
.visit_path_segment(path
.span
, segment
);
661 pub fn walk_path_segment
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
663 segment
: &'v PathSegment
) {
664 visitor
.visit_ident(segment
.ident
);
665 if let Some(id
) = segment
.hir_id
{
666 visitor
.visit_id(id
);
668 if let Some(ref args
) = segment
.args
{
669 visitor
.visit_generic_args(path_span
, args
);
673 pub fn walk_generic_args
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
675 generic_args
: &'v GenericArgs
) {
676 walk_list
!(visitor
, visit_generic_arg
, &generic_args
.args
);
677 walk_list
!(visitor
, visit_assoc_type_binding
, &generic_args
.bindings
);
680 pub fn walk_assoc_type_binding
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
681 type_binding
: &'v TypeBinding
) {
682 visitor
.visit_id(type_binding
.hir_id
);
683 visitor
.visit_ident(type_binding
.ident
);
684 match type_binding
.kind
{
685 TypeBindingKind
::Equality { ref ty }
=> {
686 visitor
.visit_ty(ty
);
688 TypeBindingKind
::Constraint { ref bounds }
=> {
689 walk_list
!(visitor
, visit_param_bound
, bounds
);
694 pub fn walk_pat
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, pattern
: &'v Pat
) {
695 visitor
.visit_id(pattern
.hir_id
);
697 PatKind
::TupleStruct(ref qpath
, ref children
, _
) => {
698 visitor
.visit_qpath(qpath
, pattern
.hir_id
, pattern
.span
);
699 walk_list
!(visitor
, visit_pat
, children
);
701 PatKind
::Path(ref qpath
) => {
702 visitor
.visit_qpath(qpath
, pattern
.hir_id
, pattern
.span
);
704 PatKind
::Struct(ref qpath
, ref fields
, _
) => {
705 visitor
.visit_qpath(qpath
, pattern
.hir_id
, pattern
.span
);
706 for field
in fields
{
707 visitor
.visit_id(field
.hir_id
);
708 visitor
.visit_ident(field
.ident
);
709 visitor
.visit_pat(&field
.pat
)
712 PatKind
::Or(ref pats
) => walk_list
!(visitor
, visit_pat
, pats
),
713 PatKind
::Tuple(ref tuple_elements
, _
) => {
714 walk_list
!(visitor
, visit_pat
, tuple_elements
);
716 PatKind
::Box(ref subpattern
) |
717 PatKind
::Ref(ref subpattern
, _
) => {
718 visitor
.visit_pat(subpattern
)
720 PatKind
::Binding(_
, _hir_id
, ident
, ref optional_subpattern
) => {
721 visitor
.visit_ident(ident
);
722 walk_list
!(visitor
, visit_pat
, optional_subpattern
);
724 PatKind
::Lit(ref expression
) => visitor
.visit_expr(expression
),
725 PatKind
::Range(ref lower_bound
, ref upper_bound
, _
) => {
726 visitor
.visit_expr(lower_bound
);
727 visitor
.visit_expr(upper_bound
)
730 PatKind
::Slice(ref prepatterns
, ref slice_pattern
, ref postpatterns
) => {
731 walk_list
!(visitor
, visit_pat
, prepatterns
);
732 walk_list
!(visitor
, visit_pat
, slice_pattern
);
733 walk_list
!(visitor
, visit_pat
, postpatterns
);
738 pub fn walk_foreign_item
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, foreign_item
: &'v ForeignItem
) {
739 visitor
.visit_id(foreign_item
.hir_id
);
740 visitor
.visit_vis(&foreign_item
.vis
);
741 visitor
.visit_ident(foreign_item
.ident
);
743 match foreign_item
.kind
{
744 ForeignItemKind
::Fn(ref function_declaration
, ref param_names
, ref generics
) => {
745 visitor
.visit_generics(generics
);
746 visitor
.visit_fn_decl(function_declaration
);
747 for ¶m_name
in param_names
{
748 visitor
.visit_ident(param_name
);
751 ForeignItemKind
::Static(ref typ
, _
) => visitor
.visit_ty(typ
),
752 ForeignItemKind
::Type
=> (),
755 walk_list
!(visitor
, visit_attribute
, &foreign_item
.attrs
);
758 pub fn walk_param_bound
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, bound
: &'v GenericBound
) {
760 GenericBound
::Trait(ref typ
, modifier
) => {
761 visitor
.visit_poly_trait_ref(typ
, modifier
);
763 GenericBound
::Outlives(ref lifetime
) => visitor
.visit_lifetime(lifetime
),
767 pub fn walk_generic_param
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, param
: &'v GenericParam
) {
768 visitor
.visit_id(param
.hir_id
);
769 walk_list
!(visitor
, visit_attribute
, ¶m
.attrs
);
771 ParamName
::Plain(ident
) => visitor
.visit_ident(ident
),
772 ParamName
::Error
| ParamName
::Fresh(_
) => {}
775 GenericParamKind
::Lifetime { .. }
=> {}
776 GenericParamKind
::Type { ref default, .. }
=> walk_list
!(visitor
, visit_ty
, default),
777 GenericParamKind
::Const { ref ty }
=> visitor
.visit_ty(ty
),
779 walk_list
!(visitor
, visit_param_bound
, ¶m
.bounds
);
782 pub fn walk_generics
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, generics
: &'v Generics
) {
783 walk_list
!(visitor
, visit_generic_param
, &generics
.params
);
784 walk_list
!(visitor
, visit_where_predicate
, &generics
.where_clause
.predicates
);
787 pub fn walk_where_predicate
<'v
, V
: Visitor
<'v
>>(
789 predicate
: &'v WherePredicate
)
792 &WherePredicate
::BoundPredicate(WhereBoundPredicate
{ref bounded_ty
,
794 ref bound_generic_params
,
796 visitor
.visit_ty(bounded_ty
);
797 walk_list
!(visitor
, visit_param_bound
, bounds
);
798 walk_list
!(visitor
, visit_generic_param
, bound_generic_params
);
800 &WherePredicate
::RegionPredicate(WhereRegionPredicate
{ref lifetime
,
803 visitor
.visit_lifetime(lifetime
);
804 walk_list
!(visitor
, visit_param_bound
, bounds
);
806 &WherePredicate
::EqPredicate(WhereEqPredicate
{hir_id
,
810 visitor
.visit_id(hir_id
);
811 visitor
.visit_ty(lhs_ty
);
812 visitor
.visit_ty(rhs_ty
);
817 pub fn walk_fn_ret_ty
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, ret_ty
: &'v FunctionRetTy
) {
818 if let Return(ref output_ty
) = *ret_ty
{
819 visitor
.visit_ty(output_ty
)
823 pub fn walk_fn_decl
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, function_declaration
: &'v FnDecl
) {
824 for ty
in &function_declaration
.inputs
{
827 walk_fn_ret_ty(visitor
, &function_declaration
.output
)
830 pub fn walk_fn_kind
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, function_kind
: FnKind
<'v
>) {
831 match function_kind
{
832 FnKind
::ItemFn(_
, generics
, ..) => {
833 visitor
.visit_generics(generics
);
836 FnKind
::Closure(_
) => {}
840 pub fn walk_fn
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
,
841 function_kind
: FnKind
<'v
>,
842 function_declaration
: &'v FnDecl
,
846 visitor
.visit_id(id
);
847 visitor
.visit_fn_decl(function_declaration
);
848 walk_fn_kind(visitor
, function_kind
);
849 visitor
.visit_nested_body(body_id
)
852 pub fn walk_trait_item
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, trait_item
: &'v TraitItem
) {
853 visitor
.visit_ident(trait_item
.ident
);
854 walk_list
!(visitor
, visit_attribute
, &trait_item
.attrs
);
855 visitor
.visit_generics(&trait_item
.generics
);
856 match trait_item
.kind
{
857 TraitItemKind
::Const(ref ty
, default) => {
858 visitor
.visit_id(trait_item
.hir_id
);
859 visitor
.visit_ty(ty
);
860 walk_list
!(visitor
, visit_nested_body
, default);
862 TraitItemKind
::Method(ref sig
, TraitMethod
::Required(ref param_names
)) => {
863 visitor
.visit_id(trait_item
.hir_id
);
864 visitor
.visit_fn_decl(&sig
.decl
);
865 for ¶m_name
in param_names
{
866 visitor
.visit_ident(param_name
);
869 TraitItemKind
::Method(ref sig
, TraitMethod
::Provided(body_id
)) => {
870 visitor
.visit_fn(FnKind
::Method(trait_item
.ident
,
879 TraitItemKind
::Type(ref bounds
, ref default) => {
880 visitor
.visit_id(trait_item
.hir_id
);
881 walk_list
!(visitor
, visit_param_bound
, bounds
);
882 walk_list
!(visitor
, visit_ty
, default);
887 pub fn walk_trait_item_ref
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, trait_item_ref
: &'v TraitItemRef
) {
888 // N.B., deliberately force a compilation error if/when new fields are added.
889 let TraitItemRef { id, ident, ref kind, span: _, ref defaultness }
= *trait_item_ref
;
890 visitor
.visit_nested_trait_item(id
);
891 visitor
.visit_ident(ident
);
892 visitor
.visit_associated_item_kind(kind
);
893 visitor
.visit_defaultness(defaultness
);
896 pub fn walk_impl_item
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, impl_item
: &'v ImplItem
) {
897 // N.B., deliberately force a compilation error if/when new fields are added.
909 visitor
.visit_ident(ident
);
910 visitor
.visit_vis(vis
);
911 visitor
.visit_defaultness(defaultness
);
912 walk_list
!(visitor
, visit_attribute
, attrs
);
913 visitor
.visit_generics(generics
);
915 ImplItemKind
::Const(ref ty
, body
) => {
916 visitor
.visit_id(impl_item
.hir_id
);
917 visitor
.visit_ty(ty
);
918 visitor
.visit_nested_body(body
);
920 ImplItemKind
::Method(ref sig
, body_id
) => {
921 visitor
.visit_fn(FnKind
::Method(impl_item
.ident
,
923 Some(&impl_item
.vis
),
930 ImplItemKind
::TyAlias(ref ty
) => {
931 visitor
.visit_id(impl_item
.hir_id
);
932 visitor
.visit_ty(ty
);
934 ImplItemKind
::OpaqueTy(ref bounds
) => {
935 visitor
.visit_id(impl_item
.hir_id
);
936 walk_list
!(visitor
, visit_param_bound
, bounds
);
941 pub fn walk_impl_item_ref
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, impl_item_ref
: &'v ImplItemRef
) {
942 // N.B., deliberately force a compilation error if/when new fields are added.
943 let ImplItemRef { id, ident, ref kind, span: _, ref vis, ref defaultness }
= *impl_item_ref
;
944 visitor
.visit_nested_impl_item(id
);
945 visitor
.visit_ident(ident
);
946 visitor
.visit_associated_item_kind(kind
);
947 visitor
.visit_vis(vis
);
948 visitor
.visit_defaultness(defaultness
);
951 pub fn walk_struct_def
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, struct_definition
: &'v VariantData
) {
952 if let Some(ctor_hir_id
) = struct_definition
.ctor_hir_id() {
953 visitor
.visit_id(ctor_hir_id
);
955 walk_list
!(visitor
, visit_struct_field
, struct_definition
.fields());
958 pub fn walk_struct_field
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, struct_field
: &'v StructField
) {
959 visitor
.visit_id(struct_field
.hir_id
);
960 visitor
.visit_vis(&struct_field
.vis
);
961 visitor
.visit_ident(struct_field
.ident
);
962 visitor
.visit_ty(&struct_field
.ty
);
963 walk_list
!(visitor
, visit_attribute
, &struct_field
.attrs
);
966 pub fn walk_block
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, block
: &'v Block
) {
967 visitor
.visit_id(block
.hir_id
);
968 walk_list
!(visitor
, visit_stmt
, &block
.stmts
);
969 walk_list
!(visitor
, visit_expr
, &block
.expr
);
972 pub fn walk_stmt
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, statement
: &'v Stmt
) {
973 visitor
.visit_id(statement
.hir_id
);
974 match statement
.kind
{
975 StmtKind
::Local(ref local
) => visitor
.visit_local(local
),
976 StmtKind
::Item(item
) => visitor
.visit_nested_item(item
),
977 StmtKind
::Expr(ref expression
) |
978 StmtKind
::Semi(ref expression
) => {
979 visitor
.visit_expr(expression
)
984 pub fn walk_anon_const
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, constant
: &'v AnonConst
) {
985 visitor
.visit_id(constant
.hir_id
);
986 visitor
.visit_nested_body(constant
.body
);
989 pub fn walk_expr
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, expression
: &'v Expr
) {
990 visitor
.visit_id(expression
.hir_id
);
991 walk_list
!(visitor
, visit_attribute
, expression
.attrs
.iter());
992 match expression
.kind
{
993 ExprKind
::Box(ref subexpression
) => {
994 visitor
.visit_expr(subexpression
)
996 ExprKind
::Array(ref subexpressions
) => {
997 walk_list
!(visitor
, visit_expr
, subexpressions
);
999 ExprKind
::Repeat(ref element
, ref count
) => {
1000 visitor
.visit_expr(element
);
1001 visitor
.visit_anon_const(count
)
1003 ExprKind
::Struct(ref qpath
, ref fields
, ref optional_base
) => {
1004 visitor
.visit_qpath(qpath
, expression
.hir_id
, expression
.span
);
1005 for field
in fields
{
1006 visitor
.visit_id(field
.hir_id
);
1007 visitor
.visit_ident(field
.ident
);
1008 visitor
.visit_expr(&field
.expr
)
1010 walk_list
!(visitor
, visit_expr
, optional_base
);
1012 ExprKind
::Tup(ref subexpressions
) => {
1013 walk_list
!(visitor
, visit_expr
, subexpressions
);
1015 ExprKind
::Call(ref callee_expression
, ref arguments
) => {
1016 visitor
.visit_expr(callee_expression
);
1017 walk_list
!(visitor
, visit_expr
, arguments
);
1019 ExprKind
::MethodCall(ref segment
, _
, ref arguments
) => {
1020 visitor
.visit_path_segment(expression
.span
, segment
);
1021 walk_list
!(visitor
, visit_expr
, arguments
);
1023 ExprKind
::Binary(_
, ref left_expression
, ref right_expression
) => {
1024 visitor
.visit_expr(left_expression
);
1025 visitor
.visit_expr(right_expression
)
1027 ExprKind
::AddrOf(_
, _
, ref subexpression
) | ExprKind
::Unary(_
, ref subexpression
) => {
1028 visitor
.visit_expr(subexpression
)
1030 ExprKind
::Cast(ref subexpression
, ref typ
) | ExprKind
::Type(ref subexpression
, ref typ
) => {
1031 visitor
.visit_expr(subexpression
);
1032 visitor
.visit_ty(typ
)
1034 ExprKind
::DropTemps(ref subexpression
) => {
1035 visitor
.visit_expr(subexpression
);
1037 ExprKind
::Loop(ref block
, ref opt_label
, _
) => {
1038 walk_list
!(visitor
, visit_label
, opt_label
);
1039 visitor
.visit_block(block
);
1041 ExprKind
::Match(ref subexpression
, ref arms
, _
) => {
1042 visitor
.visit_expr(subexpression
);
1043 walk_list
!(visitor
, visit_arm
, arms
);
1045 ExprKind
::Closure(_
, ref function_declaration
, body
, _fn_decl_span
, _gen
) => {
1046 visitor
.visit_fn(FnKind
::Closure(&expression
.attrs
),
1047 function_declaration
,
1052 ExprKind
::Block(ref block
, ref opt_label
) => {
1053 walk_list
!(visitor
, visit_label
, opt_label
);
1054 visitor
.visit_block(block
);
1056 ExprKind
::Assign(ref left_hand_expression
, ref right_hand_expression
) => {
1057 visitor
.visit_expr(right_hand_expression
);
1058 visitor
.visit_expr(left_hand_expression
)
1060 ExprKind
::AssignOp(_
, ref left_expression
, ref right_expression
) => {
1061 visitor
.visit_expr(right_expression
);
1062 visitor
.visit_expr(left_expression
);
1064 ExprKind
::Field(ref subexpression
, ident
) => {
1065 visitor
.visit_expr(subexpression
);
1066 visitor
.visit_ident(ident
);
1068 ExprKind
::Index(ref main_expression
, ref index_expression
) => {
1069 visitor
.visit_expr(main_expression
);
1070 visitor
.visit_expr(index_expression
)
1072 ExprKind
::Path(ref qpath
) => {
1073 visitor
.visit_qpath(qpath
, expression
.hir_id
, expression
.span
);
1075 ExprKind
::Break(ref destination
, ref opt_expr
) => {
1076 if let Some(ref label
) = destination
.label
{
1077 visitor
.visit_label(label
);
1079 walk_list
!(visitor
, visit_expr
, opt_expr
);
1081 ExprKind
::Continue(ref destination
) => {
1082 if let Some(ref label
) = destination
.label
{
1083 visitor
.visit_label(label
);
1086 ExprKind
::Ret(ref optional_expression
) => {
1087 walk_list
!(visitor
, visit_expr
, optional_expression
);
1089 ExprKind
::InlineAsm(ref asm
) => {
1090 walk_list
!(visitor
, visit_expr
, &asm
.outputs_exprs
);
1091 walk_list
!(visitor
, visit_expr
, &asm
.inputs_exprs
);
1093 ExprKind
::Yield(ref subexpression
, _
) => {
1094 visitor
.visit_expr(subexpression
);
1096 ExprKind
::Lit(_
) | ExprKind
::Err
=> {}
1100 pub fn walk_arm
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, arm
: &'v Arm
) {
1101 visitor
.visit_id(arm
.hir_id
);
1102 visitor
.visit_pat(&arm
.pat
);
1103 if let Some(ref g
) = arm
.guard
{
1105 Guard
::If(ref e
) => visitor
.visit_expr(e
),
1108 visitor
.visit_expr(&arm
.body
);
1109 walk_list
!(visitor
, visit_attribute
, &arm
.attrs
);
1112 pub fn walk_vis
<'v
, V
: Visitor
<'v
>>(visitor
: &mut V
, vis
: &'v Visibility
) {
1113 if let VisibilityKind
::Restricted { ref path, hir_id }
= vis
.node
{
1114 visitor
.visit_id(hir_id
);
1115 visitor
.visit_path(path
, hir_id
)
1119 pub fn walk_associated_item_kind
<'v
, V
: Visitor
<'v
>>(_
: &mut V
, _
: &'v AssocItemKind
) {
1120 // No visitable content here: this fn exists so you can call it if
1121 // the right thing to do, should content be added in the future,
1122 // would be to walk it.
1125 pub fn walk_defaultness
<'v
, V
: Visitor
<'v
>>(_
: &mut V
, _
: &'v Defaultness
) {
1126 // No visitable content here: this fn exists so you can call it if
1127 // the right thing to do, should content be added in the future,
1128 // would be to walk it.