rustc_hir/
intravisit.rs

1//! HIR walker for walking the contents of nodes.
2//!
3//! Here are the three available patterns for the visitor strategy,
4//! in roughly the order of desirability:
5//!
6//! 1. **Shallow visit**: Get a simple callback for every item (or item-like thing) in the HIR.
7//!    - Example: find all items with a `#[foo]` attribute on them.
8//!    - How: Use the `hir_crate_items` or `hir_module_items` query to traverse over item-like ids
9//!       (ItemId, TraitItemId, etc.) and use tcx.def_kind and `tcx.hir().item*(id)` to filter and
10//!       access actual item-like thing, respectively.
11//!    - Pro: Efficient; just walks the lists of item ids and gives users control whether to access
12//!       the hir_owners themselves or not.
13//!    - Con: Don't get information about nesting
14//!    - Con: Don't have methods for specific bits of HIR, like "on
15//!      every expr, do this".
16//! 2. **Deep visit**: Want to scan for specific kinds of HIR nodes within
17//!    an item, but don't care about how item-like things are nested
18//!    within one another.
19//!    - Example: Examine each expression to look for its type and do some check or other.
20//!    - How: Implement `intravisit::Visitor` and override the `NestedFilter` type to
21//!      `nested_filter::OnlyBodies` (and implement `nested_visit_map`), and use
22//!      `tcx.hir().visit_all_item_likes_in_crate(&mut visitor)`. Within your
23//!      `intravisit::Visitor` impl, implement methods like `visit_expr()` (don't forget to invoke
24//!      `intravisit::walk_expr()` to keep walking the subparts).
25//!    - Pro: Visitor methods for any kind of HIR node, not just item-like things.
26//!    - Pro: Integrates well into dependency tracking.
27//!    - Con: Don't get information about nesting between items
28//! 3. **Nested visit**: Want to visit the whole HIR and you care about the nesting between
29//!    item-like things.
30//!    - Example: Lifetime resolution, which wants to bring lifetimes declared on the
31//!      impl into scope while visiting the impl-items, and then back out again.
32//!    - How: Implement `intravisit::Visitor` and override the `NestedFilter` type to
33//!      `nested_filter::All` (and implement `nested_visit_map`). Walk your crate with
34//!      `tcx.hir().walk_toplevel_module(visitor)` invoked on `tcx.hir().krate()`.
35//!    - Pro: Visitor methods for any kind of HIR node, not just item-like things.
36//!    - Pro: Preserves nesting information
37//!    - Con: Does not integrate well into dependency tracking.
38//!
39//! If you have decided to use this visitor, here are some general
40//! notes on how to do so:
41//!
42//! Each overridden visit method has full control over what
43//! happens with its node, it can do its own traversal of the node's children,
44//! call `intravisit::walk_*` to apply the default traversal algorithm, or prevent
45//! deeper traversal by doing nothing.
46//!
47//! When visiting the HIR, the contents of nested items are NOT visited
48//! by default. This is different from the AST visitor, which does a deep walk.
49//! Hence this module is called `intravisit`; see the method `visit_nested_item`
50//! for more details.
51//!
52//! Note: it is an important invariant that the default visitor walks
53//! the body of a function in "execution order" - more concretely, if
54//! we consider the reverse post-order (RPO) of the CFG implied by the HIR,
55//! then a pre-order traversal of the HIR is consistent with the CFG RPO
56//! on the *initial CFG point* of each HIR node, while a post-order traversal
57//! of the HIR is consistent with the CFG RPO on each *final CFG point* of
58//! each CFG node.
59//!
60//! One thing that follows is that if HIR node A always starts/ends executing
61//! before HIR node B, then A appears in traversal pre/postorder before B,
62//! respectively. (This follows from RPO respecting CFG domination).
63//!
64//! This order consistency is required in a few places in rustc, for
65//! example coroutine inference, and possibly also HIR borrowck.
66
67use rustc_ast::Label;
68use rustc_ast::visit::{VisitorResult, try_visit, visit_opt, walk_list};
69use rustc_span::def_id::LocalDefId;
70use rustc_span::{Ident, Span, Symbol};
71
72use crate::hir::*;
73
74pub trait IntoVisitor<'hir> {
75    type Visitor: Visitor<'hir>;
76    fn into_visitor(&self) -> Self::Visitor;
77}
78
79#[derive(Copy, Clone, Debug)]
80pub enum FnKind<'a> {
81    /// `#[xxx] pub async/const/extern "Abi" fn foo()`
82    ItemFn(Ident, &'a Generics<'a>, FnHeader),
83
84    /// `fn foo(&self)`
85    Method(Ident, &'a FnSig<'a>),
86
87    /// `|x, y| {}`
88    Closure,
89}
90
91impl<'a> FnKind<'a> {
92    pub fn header(&self) -> Option<&FnHeader> {
93        match *self {
94            FnKind::ItemFn(_, _, ref header) => Some(header),
95            FnKind::Method(_, ref sig) => Some(&sig.header),
96            FnKind::Closure => None,
97        }
98    }
99
100    pub fn constness(self) -> Constness {
101        self.header().map_or(Constness::NotConst, |header| header.constness)
102    }
103
104    pub fn asyncness(self) -> IsAsync {
105        self.header().map_or(IsAsync::NotAsync, |header| header.asyncness)
106    }
107}
108
109/// An abstract representation of the HIR `rustc_middle::hir::map::Map`.
110pub trait Map<'hir> {
111    /// Retrieves the `Node` corresponding to `id`.
112    fn hir_node(&self, hir_id: HirId) -> Node<'hir>;
113    fn hir_node_by_def_id(&self, def_id: LocalDefId) -> Node<'hir>;
114    fn body(&self, id: BodyId) -> &'hir Body<'hir>;
115    fn item(&self, id: ItemId) -> &'hir Item<'hir>;
116    fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>;
117    fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>;
118    fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir>;
119}
120
121// Used when no map is actually available, forcing manual implementation of nested visitors.
122impl<'hir> Map<'hir> for ! {
123    fn hir_node(&self, _: HirId) -> Node<'hir> {
124        *self;
125    }
126    fn hir_node_by_def_id(&self, _: LocalDefId) -> Node<'hir> {
127        *self;
128    }
129    fn body(&self, _: BodyId) -> &'hir Body<'hir> {
130        *self;
131    }
132    fn item(&self, _: ItemId) -> &'hir Item<'hir> {
133        *self;
134    }
135    fn trait_item(&self, _: TraitItemId) -> &'hir TraitItem<'hir> {
136        *self;
137    }
138    fn impl_item(&self, _: ImplItemId) -> &'hir ImplItem<'hir> {
139        *self;
140    }
141    fn foreign_item(&self, _: ForeignItemId) -> &'hir ForeignItem<'hir> {
142        *self;
143    }
144}
145
146pub mod nested_filter {
147    use super::Map;
148
149    /// Specifies what nested things a visitor wants to visit. By "nested
150    /// things", we are referring to bits of HIR that are not directly embedded
151    /// within one another but rather indirectly, through a table in the crate.
152    /// This is done to control dependencies during incremental compilation: the
153    /// non-inline bits of HIR can be tracked and hashed separately.
154    ///
155    /// The most common choice is `OnlyBodies`, which will cause the visitor to
156    /// visit fn bodies for fns that it encounters, and closure bodies, but
157    /// skip over nested item-like things.
158    ///
159    /// See the comments at [`rustc_hir::intravisit`] for more details on the overall
160    /// visit strategy.
161    pub trait NestedFilter<'hir> {
162        type Map: Map<'hir>;
163
164        /// Whether the visitor visits nested "item-like" things.
165        /// E.g., item, impl-item.
166        const INTER: bool;
167        /// Whether the visitor visits "intra item-like" things.
168        /// E.g., function body, closure, `AnonConst`
169        const INTRA: bool;
170    }
171
172    /// Do not visit any nested things. When you add a new
173    /// "non-nested" thing, you will want to audit such uses to see if
174    /// they remain valid.
175    ///
176    /// Use this if you are only walking some particular kind of tree
177    /// (i.e., a type, or fn signature) and you don't want to thread a
178    /// HIR map around.
179    pub struct None(());
180    impl NestedFilter<'_> for None {
181        type Map = !;
182        const INTER: bool = false;
183        const INTRA: bool = false;
184    }
185}
186
187use nested_filter::NestedFilter;
188
189/// Each method of the Visitor trait is a hook to be potentially
190/// overridden. Each method's default implementation recursively visits
191/// the substructure of the input via the corresponding `walk` method;
192/// e.g., the `visit_mod` method by default calls `intravisit::walk_mod`.
193///
194/// Note that this visitor does NOT visit nested items by default
195/// (this is why the module is called `intravisit`, to distinguish it
196/// from the AST's `visit` module, which acts differently). If you
197/// simply want to visit all items in the crate in some order, you
198/// should call `tcx.hir().visit_all_item_likes_in_crate`. Otherwise, see the comment
199/// on `visit_nested_item` for details on how to visit nested items.
200///
201/// If you want to ensure that your code handles every variant
202/// explicitly, you need to override each method. (And you also need
203/// to monitor future changes to `Visitor` in case a new method with a
204/// new default implementation gets introduced.)
205pub trait Visitor<'v>: Sized {
206    // this type should not be overridden, it exists for convenient usage as `Self::Map`
207    type Map: Map<'v> = <Self::NestedFilter as NestedFilter<'v>>::Map;
208
209    ///////////////////////////////////////////////////////////////////////////
210    // Nested items.
211
212    /// Override this type to control which nested HIR are visited; see
213    /// [`NestedFilter`] for details. If you override this type, you
214    /// must also override [`nested_visit_map`](Self::nested_visit_map).
215    ///
216    /// **If for some reason you want the nested behavior, but don't
217    /// have a `Map` at your disposal:** then override the
218    /// `visit_nested_XXX` methods. If a new `visit_nested_XXX` variant is
219    /// added in the future, it will cause a panic which can be detected
220    /// and fixed appropriately.
221    type NestedFilter: NestedFilter<'v> = nested_filter::None;
222
223    /// The result type of the `visit_*` methods. Can be either `()`,
224    /// or `ControlFlow<T>`.
225    type Result: VisitorResult = ();
226
227    /// If `type NestedFilter` is set to visit nested items, this method
228    /// must also be overridden to provide a map to retrieve nested items.
229    fn nested_visit_map(&mut self) -> Self::Map {
230        panic!(
231            "nested_visit_map must be implemented or consider using \
232            `type NestedFilter = nested_filter::None` (the default)"
233        );
234    }
235
236    /// Invoked when a nested item is encountered. By default, when
237    /// `Self::NestedFilter` is `nested_filter::None`, this method does
238    /// nothing. **You probably don't want to override this method** --
239    /// instead, override [`Self::NestedFilter`] or use the "shallow" or
240    /// "deep" visit patterns described at
241    /// [`rustc_hir::intravisit`]. The only reason to override
242    /// this method is if you want a nested pattern but cannot supply a
243    /// [`Map`]; see `nested_visit_map` for advice.
244    fn visit_nested_item(&mut self, id: ItemId) -> Self::Result {
245        if Self::NestedFilter::INTER {
246            let item = self.nested_visit_map().item(id);
247            try_visit!(self.visit_item(item));
248        }
249        Self::Result::output()
250    }
251
252    /// Like `visit_nested_item()`, but for trait items. See
253    /// `visit_nested_item()` for advice on when to override this
254    /// method.
255    fn visit_nested_trait_item(&mut self, id: TraitItemId) -> Self::Result {
256        if Self::NestedFilter::INTER {
257            let item = self.nested_visit_map().trait_item(id);
258            try_visit!(self.visit_trait_item(item));
259        }
260        Self::Result::output()
261    }
262
263    /// Like `visit_nested_item()`, but for impl items. See
264    /// `visit_nested_item()` for advice on when to override this
265    /// method.
266    fn visit_nested_impl_item(&mut self, id: ImplItemId) -> Self::Result {
267        if Self::NestedFilter::INTER {
268            let item = self.nested_visit_map().impl_item(id);
269            try_visit!(self.visit_impl_item(item));
270        }
271        Self::Result::output()
272    }
273
274    /// Like `visit_nested_item()`, but for foreign items. See
275    /// `visit_nested_item()` for advice on when to override this
276    /// method.
277    fn visit_nested_foreign_item(&mut self, id: ForeignItemId) -> Self::Result {
278        if Self::NestedFilter::INTER {
279            let item = self.nested_visit_map().foreign_item(id);
280            try_visit!(self.visit_foreign_item(item));
281        }
282        Self::Result::output()
283    }
284
285    /// Invoked to visit the body of a function, method or closure. Like
286    /// `visit_nested_item`, does nothing by default unless you override
287    /// `Self::NestedFilter`.
288    fn visit_nested_body(&mut self, id: BodyId) -> Self::Result {
289        if Self::NestedFilter::INTRA {
290            let body = self.nested_visit_map().body(id);
291            try_visit!(self.visit_body(body));
292        }
293        Self::Result::output()
294    }
295
296    fn visit_param(&mut self, param: &'v Param<'v>) -> Self::Result {
297        walk_param(self, param)
298    }
299
300    /// Visits the top-level item and (optionally) nested items / impl items. See
301    /// `visit_nested_item` for details.
302    fn visit_item(&mut self, i: &'v Item<'v>) -> Self::Result {
303        walk_item(self, i)
304    }
305
306    fn visit_body(&mut self, b: &Body<'v>) -> Self::Result {
307        walk_body(self, b)
308    }
309
310    ///////////////////////////////////////////////////////////////////////////
311
312    fn visit_id(&mut self, _hir_id: HirId) -> Self::Result {
313        Self::Result::output()
314    }
315    fn visit_name(&mut self, _name: Symbol) -> Self::Result {
316        Self::Result::output()
317    }
318    fn visit_ident(&mut self, ident: Ident) -> Self::Result {
319        walk_ident(self, ident)
320    }
321    fn visit_mod(&mut self, m: &'v Mod<'v>, _s: Span, n: HirId) -> Self::Result {
322        walk_mod(self, m, n)
323    }
324    fn visit_foreign_item(&mut self, i: &'v ForeignItem<'v>) -> Self::Result {
325        walk_foreign_item(self, i)
326    }
327    fn visit_local(&mut self, l: &'v LetStmt<'v>) -> Self::Result {
328        walk_local(self, l)
329    }
330    fn visit_block(&mut self, b: &'v Block<'v>) -> Self::Result {
331        walk_block(self, b)
332    }
333    fn visit_stmt(&mut self, s: &'v Stmt<'v>) -> Self::Result {
334        walk_stmt(self, s)
335    }
336    fn visit_arm(&mut self, a: &'v Arm<'v>) -> Self::Result {
337        walk_arm(self, a)
338    }
339    fn visit_pat(&mut self, p: &'v Pat<'v>) -> Self::Result {
340        walk_pat(self, p)
341    }
342    fn visit_pat_field(&mut self, f: &'v PatField<'v>) -> Self::Result {
343        walk_pat_field(self, f)
344    }
345    fn visit_pat_expr(&mut self, expr: &'v PatExpr<'v>) -> Self::Result {
346        walk_pat_expr(self, expr)
347    }
348    fn visit_lit(&mut self, _hir_id: HirId, _lit: &'v Lit, _negated: bool) -> Self::Result {
349        Self::Result::output()
350    }
351    fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
352        walk_anon_const(self, c)
353    }
354    fn visit_inline_const(&mut self, c: &'v ConstBlock) -> Self::Result {
355        walk_inline_const(self, c)
356    }
357
358    fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) -> Self::Result {
359        walk_generic_arg(self, generic_arg)
360    }
361
362    /// All types are treated as ambiguous types for the purposes of hir visiting in
363    /// order to ensure that visitors can handle infer vars without it being too error-prone.
364    ///
365    /// See the doc comments on [`Ty`] for an explanation of what it means for a type to be
366    /// ambiguous.
367    ///
368    /// The [`Visitor::visit_infer`] method should be overriden in order to handle infer vars.
369    fn visit_ty(&mut self, t: &'v Ty<'v, AmbigArg>) -> Self::Result {
370        walk_ty(self, t)
371    }
372
373    /// All consts are treated as ambiguous consts for the purposes of hir visiting in
374    /// order to ensure that visitors can handle infer vars without it being too error-prone.
375    ///
376    /// See the doc comments on [`ConstArg`] for an explanation of what it means for a const to be
377    /// ambiguous.
378    ///
379    /// The [`Visitor::visit_infer`] method should be overriden in order to handle infer vars.
380    fn visit_const_arg(&mut self, c: &'v ConstArg<'v, AmbigArg>) -> Self::Result {
381        walk_ambig_const_arg(self, c)
382    }
383
384    #[allow(unused_variables)]
385    fn visit_infer(&mut self, inf_id: HirId, inf_span: Span, kind: InferKind<'v>) -> Self::Result {
386        self.visit_id(inf_id)
387    }
388
389    fn visit_lifetime(&mut self, lifetime: &'v Lifetime) -> Self::Result {
390        walk_lifetime(self, lifetime)
391    }
392
393    fn visit_expr(&mut self, ex: &'v Expr<'v>) -> Self::Result {
394        walk_expr(self, ex)
395    }
396    fn visit_expr_field(&mut self, field: &'v ExprField<'v>) -> Self::Result {
397        walk_expr_field(self, field)
398    }
399    fn visit_pattern_type_pattern(&mut self, p: &'v TyPat<'v>) -> Self::Result {
400        walk_ty_pat(self, p)
401    }
402    fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) -> Self::Result {
403        walk_generic_param(self, p)
404    }
405    fn visit_const_param_default(&mut self, _param: HirId, ct: &'v ConstArg<'v>) -> Self::Result {
406        walk_const_param_default(self, ct)
407    }
408    fn visit_generics(&mut self, g: &'v Generics<'v>) -> Self::Result {
409        walk_generics(self, g)
410    }
411    fn visit_where_predicate(&mut self, predicate: &'v WherePredicate<'v>) -> Self::Result {
412        walk_where_predicate(self, predicate)
413    }
414    fn visit_fn_ret_ty(&mut self, ret_ty: &'v FnRetTy<'v>) -> Self::Result {
415        walk_fn_ret_ty(self, ret_ty)
416    }
417    fn visit_fn_decl(&mut self, fd: &'v FnDecl<'v>) -> Self::Result {
418        walk_fn_decl(self, fd)
419    }
420    fn visit_fn(
421        &mut self,
422        fk: FnKind<'v>,
423        fd: &'v FnDecl<'v>,
424        b: BodyId,
425        _: Span,
426        id: LocalDefId,
427    ) -> Self::Result {
428        walk_fn(self, fk, fd, b, id)
429    }
430    fn visit_use(&mut self, path: &'v UsePath<'v>, hir_id: HirId) -> Self::Result {
431        walk_use(self, path, hir_id)
432    }
433    fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) -> Self::Result {
434        walk_trait_item(self, ti)
435    }
436    fn visit_trait_item_ref(&mut self, ii: &'v TraitItemRef) -> Self::Result {
437        walk_trait_item_ref(self, ii)
438    }
439    fn visit_impl_item(&mut self, ii: &'v ImplItem<'v>) -> Self::Result {
440        walk_impl_item(self, ii)
441    }
442    fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef) -> Self::Result {
443        walk_foreign_item_ref(self, ii)
444    }
445    fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef) -> Self::Result {
446        walk_impl_item_ref(self, ii)
447    }
448    fn visit_trait_ref(&mut self, t: &'v TraitRef<'v>) -> Self::Result {
449        walk_trait_ref(self, t)
450    }
451    fn visit_param_bound(&mut self, bounds: &'v GenericBound<'v>) -> Self::Result {
452        walk_param_bound(self, bounds)
453    }
454    fn visit_precise_capturing_arg(&mut self, arg: &'v PreciseCapturingArg<'v>) -> Self::Result {
455        walk_precise_capturing_arg(self, arg)
456    }
457    fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef<'v>) -> Self::Result {
458        walk_poly_trait_ref(self, t)
459    }
460    fn visit_opaque_ty(&mut self, opaque: &'v OpaqueTy<'v>) -> Self::Result {
461        walk_opaque_ty(self, opaque)
462    }
463    fn visit_variant_data(&mut self, s: &'v VariantData<'v>) -> Self::Result {
464        walk_struct_def(self, s)
465    }
466    fn visit_field_def(&mut self, s: &'v FieldDef<'v>) -> Self::Result {
467        walk_field_def(self, s)
468    }
469    fn visit_enum_def(&mut self, enum_definition: &'v EnumDef<'v>, item_id: HirId) -> Self::Result {
470        walk_enum_def(self, enum_definition, item_id)
471    }
472    fn visit_variant(&mut self, v: &'v Variant<'v>) -> Self::Result {
473        walk_variant(self, v)
474    }
475    fn visit_label(&mut self, label: &'v Label) -> Self::Result {
476        walk_label(self, label)
477    }
478    // The span is that of the surrounding type/pattern/expr/whatever.
479    fn visit_qpath(&mut self, qpath: &'v QPath<'v>, id: HirId, _span: Span) -> Self::Result {
480        walk_qpath(self, qpath, id)
481    }
482    fn visit_path(&mut self, path: &Path<'v>, _id: HirId) -> Self::Result {
483        walk_path(self, path)
484    }
485    fn visit_path_segment(&mut self, path_segment: &'v PathSegment<'v>) -> Self::Result {
486        walk_path_segment(self, path_segment)
487    }
488    fn visit_generic_args(&mut self, generic_args: &'v GenericArgs<'v>) -> Self::Result {
489        walk_generic_args(self, generic_args)
490    }
491    fn visit_assoc_item_constraint(
492        &mut self,
493        constraint: &'v AssocItemConstraint<'v>,
494    ) -> Self::Result {
495        walk_assoc_item_constraint(self, constraint)
496    }
497    fn visit_attribute(&mut self, _attr: &'v Attribute) -> Self::Result {
498        Self::Result::output()
499    }
500    fn visit_associated_item_kind(&mut self, kind: &'v AssocItemKind) -> Self::Result {
501        walk_associated_item_kind(self, kind)
502    }
503    fn visit_defaultness(&mut self, defaultness: &'v Defaultness) -> Self::Result {
504        walk_defaultness(self, defaultness)
505    }
506    fn visit_inline_asm(&mut self, asm: &'v InlineAsm<'v>, id: HirId) -> Self::Result {
507        walk_inline_asm(self, asm, id)
508    }
509}
510
511pub trait VisitorExt<'v>: Visitor<'v> {
512    /// Extension trait method to visit types in unambiguous positions, this is not
513    /// directly on the [`Visitor`] trait as this method should never be overridden.
514    ///
515    /// Named `visit_ty_unambig` instead of `visit_unambig_ty` to aid in discovery
516    /// by IDes when `v.visit_ty` is written.
517    fn visit_ty_unambig(&mut self, t: &'v Ty<'v>) -> Self::Result {
518        walk_unambig_ty(self, t)
519    }
520    /// Extension trait method to visit consts in unambiguous positions, this is not
521    /// directly on the [`Visitor`] trait as this method should never be overridden.
522    ///
523    /// Named `visit_const_arg_unambig` instead of `visit_unambig_const_arg` to aid in
524    /// discovery by IDes when `v.visit_const_arg` is written.
525    fn visit_const_arg_unambig(&mut self, c: &'v ConstArg<'v>) -> Self::Result {
526        walk_const_arg(self, c)
527    }
528}
529impl<'v, V: Visitor<'v>> VisitorExt<'v> for V {}
530
531pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) -> V::Result {
532    try_visit!(visitor.visit_id(param.hir_id));
533    visitor.visit_pat(param.pat)
534}
535
536pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::Result {
537    try_visit!(visitor.visit_ident(item.ident));
538    match item.kind {
539        ItemKind::ExternCrate(orig_name) => {
540            try_visit!(visitor.visit_id(item.hir_id()));
541            visit_opt!(visitor, visit_name, orig_name);
542        }
543        ItemKind::Use(ref path, _) => {
544            try_visit!(visitor.visit_use(path, item.hir_id()));
545        }
546        ItemKind::Static(ref typ, _, body) => {
547            try_visit!(visitor.visit_id(item.hir_id()));
548            try_visit!(visitor.visit_ty_unambig(typ));
549            try_visit!(visitor.visit_nested_body(body));
550        }
551        ItemKind::Const(ref typ, ref generics, body) => {
552            try_visit!(visitor.visit_id(item.hir_id()));
553            try_visit!(visitor.visit_ty_unambig(typ));
554            try_visit!(visitor.visit_generics(generics));
555            try_visit!(visitor.visit_nested_body(body));
556        }
557        ItemKind::Fn { sig, generics, body: body_id, .. } => {
558            try_visit!(visitor.visit_id(item.hir_id()));
559            try_visit!(visitor.visit_fn(
560                FnKind::ItemFn(item.ident, generics, sig.header),
561                sig.decl,
562                body_id,
563                item.span,
564                item.owner_id.def_id,
565            ));
566        }
567        ItemKind::Macro(..) => {
568            try_visit!(visitor.visit_id(item.hir_id()));
569        }
570        ItemKind::Mod(ref module) => {
571            // `visit_mod()` takes care of visiting the `Item`'s `HirId`.
572            try_visit!(visitor.visit_mod(module, item.span, item.hir_id()));
573        }
574        ItemKind::ForeignMod { abi: _, items } => {
575            try_visit!(visitor.visit_id(item.hir_id()));
576            walk_list!(visitor, visit_foreign_item_ref, items);
577        }
578        ItemKind::GlobalAsm(asm) => {
579            try_visit!(visitor.visit_id(item.hir_id()));
580            try_visit!(visitor.visit_inline_asm(asm, item.hir_id()));
581        }
582        ItemKind::TyAlias(ref ty, ref generics) => {
583            try_visit!(visitor.visit_id(item.hir_id()));
584            try_visit!(visitor.visit_ty_unambig(ty));
585            try_visit!(visitor.visit_generics(generics));
586        }
587        ItemKind::Enum(ref enum_definition, ref generics) => {
588            try_visit!(visitor.visit_generics(generics));
589            // `visit_enum_def()` takes care of visiting the `Item`'s `HirId`.
590            try_visit!(visitor.visit_enum_def(enum_definition, item.hir_id()));
591        }
592        ItemKind::Impl(Impl {
593            constness: _,
594            safety: _,
595            defaultness: _,
596            polarity: _,
597            defaultness_span: _,
598            ref generics,
599            ref of_trait,
600            ref self_ty,
601            items,
602        }) => {
603            try_visit!(visitor.visit_id(item.hir_id()));
604            try_visit!(visitor.visit_generics(generics));
605            visit_opt!(visitor, visit_trait_ref, of_trait);
606            try_visit!(visitor.visit_ty_unambig(self_ty));
607            walk_list!(visitor, visit_impl_item_ref, *items);
608        }
609        ItemKind::Struct(ref struct_definition, ref generics)
610        | ItemKind::Union(ref struct_definition, ref generics) => {
611            try_visit!(visitor.visit_generics(generics));
612            try_visit!(visitor.visit_id(item.hir_id()));
613            try_visit!(visitor.visit_variant_data(struct_definition));
614        }
615        ItemKind::Trait(.., ref generics, bounds, trait_item_refs) => {
616            try_visit!(visitor.visit_id(item.hir_id()));
617            try_visit!(visitor.visit_generics(generics));
618            walk_list!(visitor, visit_param_bound, bounds);
619            walk_list!(visitor, visit_trait_item_ref, trait_item_refs);
620        }
621        ItemKind::TraitAlias(ref generics, bounds) => {
622            try_visit!(visitor.visit_id(item.hir_id()));
623            try_visit!(visitor.visit_generics(generics));
624            walk_list!(visitor, visit_param_bound, bounds);
625        }
626    }
627    V::Result::output()
628}
629
630pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &Body<'v>) -> V::Result {
631    walk_list!(visitor, visit_param, body.params);
632    visitor.visit_expr(body.value)
633}
634
635pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, ident: Ident) -> V::Result {
636    visitor.visit_name(ident.name)
637}
638
639pub fn walk_mod<'v, V: Visitor<'v>>(
640    visitor: &mut V,
641    module: &'v Mod<'v>,
642    mod_hir_id: HirId,
643) -> V::Result {
644    try_visit!(visitor.visit_id(mod_hir_id));
645    walk_list!(visitor, visit_nested_item, module.item_ids.iter().copied());
646    V::Result::output()
647}
648
649pub fn walk_foreign_item<'v, V: Visitor<'v>>(
650    visitor: &mut V,
651    foreign_item: &'v ForeignItem<'v>,
652) -> V::Result {
653    try_visit!(visitor.visit_id(foreign_item.hir_id()));
654    try_visit!(visitor.visit_ident(foreign_item.ident));
655
656    match foreign_item.kind {
657        ForeignItemKind::Fn(ref sig, param_names, ref generics) => {
658            try_visit!(visitor.visit_generics(generics));
659            try_visit!(visitor.visit_fn_decl(sig.decl));
660            walk_list!(visitor, visit_ident, param_names.iter().copied());
661        }
662        ForeignItemKind::Static(ref typ, _, _) => {
663            try_visit!(visitor.visit_ty_unambig(typ));
664        }
665        ForeignItemKind::Type => (),
666    }
667    V::Result::output()
668}
669
670pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v LetStmt<'v>) -> V::Result {
671    // Intentionally visiting the expr first - the initialization expr
672    // dominates the local's definition.
673    visit_opt!(visitor, visit_expr, local.init);
674    try_visit!(visitor.visit_id(local.hir_id));
675    try_visit!(visitor.visit_pat(local.pat));
676    visit_opt!(visitor, visit_block, local.els);
677    visit_opt!(visitor, visit_ty_unambig, local.ty);
678    V::Result::output()
679}
680
681pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) -> V::Result {
682    try_visit!(visitor.visit_id(block.hir_id));
683    walk_list!(visitor, visit_stmt, block.stmts);
684    visit_opt!(visitor, visit_expr, block.expr);
685    V::Result::output()
686}
687
688pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) -> V::Result {
689    try_visit!(visitor.visit_id(statement.hir_id));
690    match statement.kind {
691        StmtKind::Let(ref local) => visitor.visit_local(local),
692        StmtKind::Item(item) => visitor.visit_nested_item(item),
693        StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => {
694            visitor.visit_expr(expression)
695        }
696    }
697}
698
699pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) -> V::Result {
700    try_visit!(visitor.visit_id(arm.hir_id));
701    try_visit!(visitor.visit_pat(arm.pat));
702    visit_opt!(visitor, visit_expr, arm.guard);
703    visitor.visit_expr(arm.body)
704}
705
706pub fn walk_ty_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v TyPat<'v>) -> V::Result {
707    try_visit!(visitor.visit_id(pattern.hir_id));
708    match pattern.kind {
709        TyPatKind::Range(lower_bound, upper_bound, _) => {
710            visit_opt!(visitor, visit_const_arg_unambig, lower_bound);
711            visit_opt!(visitor, visit_const_arg_unambig, upper_bound);
712        }
713        TyPatKind::Err(_) => (),
714    }
715    V::Result::output()
716}
717
718pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V::Result {
719    try_visit!(visitor.visit_id(pattern.hir_id));
720    match pattern.kind {
721        PatKind::TupleStruct(ref qpath, children, _) => {
722            try_visit!(visitor.visit_qpath(qpath, pattern.hir_id, pattern.span));
723            walk_list!(visitor, visit_pat, children);
724        }
725        PatKind::Struct(ref qpath, fields, _) => {
726            try_visit!(visitor.visit_qpath(qpath, pattern.hir_id, pattern.span));
727            walk_list!(visitor, visit_pat_field, fields);
728        }
729        PatKind::Or(pats) => walk_list!(visitor, visit_pat, pats),
730        PatKind::Tuple(tuple_elements, _) => {
731            walk_list!(visitor, visit_pat, tuple_elements);
732        }
733        PatKind::Box(ref subpattern)
734        | PatKind::Deref(ref subpattern)
735        | PatKind::Ref(ref subpattern, _) => {
736            try_visit!(visitor.visit_pat(subpattern));
737        }
738        PatKind::Binding(_, _hir_id, ident, ref optional_subpattern) => {
739            try_visit!(visitor.visit_ident(ident));
740            visit_opt!(visitor, visit_pat, optional_subpattern);
741        }
742        PatKind::Expr(ref expression) => try_visit!(visitor.visit_pat_expr(expression)),
743        PatKind::Range(ref lower_bound, ref upper_bound, _) => {
744            visit_opt!(visitor, visit_pat_expr, lower_bound);
745            visit_opt!(visitor, visit_pat_expr, upper_bound);
746        }
747        PatKind::Never | PatKind::Wild | PatKind::Err(_) => (),
748        PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
749            walk_list!(visitor, visit_pat, prepatterns);
750            visit_opt!(visitor, visit_pat, slice_pattern);
751            walk_list!(visitor, visit_pat, postpatterns);
752        }
753        PatKind::Guard(subpat, condition) => {
754            try_visit!(visitor.visit_pat(subpat));
755            try_visit!(visitor.visit_expr(condition));
756        }
757    }
758    V::Result::output()
759}
760
761pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'v>) -> V::Result {
762    try_visit!(visitor.visit_id(field.hir_id));
763    try_visit!(visitor.visit_ident(field.ident));
764    visitor.visit_pat(field.pat)
765}
766
767pub fn walk_pat_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v PatExpr<'v>) -> V::Result {
768    try_visit!(visitor.visit_id(expr.hir_id));
769    match &expr.kind {
770        PatExprKind::Lit { lit, negated } => visitor.visit_lit(expr.hir_id, lit, *negated),
771        PatExprKind::ConstBlock(c) => visitor.visit_inline_const(c),
772        PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, expr.hir_id, expr.span),
773    }
774}
775
776pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) -> V::Result {
777    try_visit!(visitor.visit_id(constant.hir_id));
778    visitor.visit_nested_body(constant.body)
779}
780
781pub fn walk_inline_const<'v, V: Visitor<'v>>(
782    visitor: &mut V,
783    constant: &'v ConstBlock,
784) -> V::Result {
785    try_visit!(visitor.visit_id(constant.hir_id));
786    visitor.visit_nested_body(constant.body)
787}
788
789pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) -> V::Result {
790    try_visit!(visitor.visit_id(expression.hir_id));
791    match expression.kind {
792        ExprKind::Array(subexpressions) => {
793            walk_list!(visitor, visit_expr, subexpressions);
794        }
795        ExprKind::ConstBlock(ref const_block) => {
796            try_visit!(visitor.visit_inline_const(const_block))
797        }
798        ExprKind::Repeat(ref element, ref count) => {
799            try_visit!(visitor.visit_expr(element));
800            try_visit!(visitor.visit_const_arg_unambig(count));
801        }
802        ExprKind::Struct(ref qpath, fields, ref optional_base) => {
803            try_visit!(visitor.visit_qpath(qpath, expression.hir_id, expression.span));
804            walk_list!(visitor, visit_expr_field, fields);
805            match optional_base {
806                StructTailExpr::Base(base) => try_visit!(visitor.visit_expr(base)),
807                StructTailExpr::None | StructTailExpr::DefaultFields(_) => {}
808            }
809        }
810        ExprKind::Tup(subexpressions) => {
811            walk_list!(visitor, visit_expr, subexpressions);
812        }
813        ExprKind::Call(ref callee_expression, arguments) => {
814            try_visit!(visitor.visit_expr(callee_expression));
815            walk_list!(visitor, visit_expr, arguments);
816        }
817        ExprKind::MethodCall(ref segment, receiver, arguments, _) => {
818            try_visit!(visitor.visit_path_segment(segment));
819            try_visit!(visitor.visit_expr(receiver));
820            walk_list!(visitor, visit_expr, arguments);
821        }
822        ExprKind::Binary(_, ref left_expression, ref right_expression) => {
823            try_visit!(visitor.visit_expr(left_expression));
824            try_visit!(visitor.visit_expr(right_expression));
825        }
826        ExprKind::AddrOf(_, _, ref subexpression) | ExprKind::Unary(_, ref subexpression) => {
827            try_visit!(visitor.visit_expr(subexpression));
828        }
829        ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => {
830            try_visit!(visitor.visit_expr(subexpression));
831            try_visit!(visitor.visit_ty_unambig(typ));
832        }
833        ExprKind::DropTemps(ref subexpression) => {
834            try_visit!(visitor.visit_expr(subexpression));
835        }
836        ExprKind::Let(LetExpr { span: _, pat, ty, init, recovered: _ }) => {
837            // match the visit order in walk_local
838            try_visit!(visitor.visit_expr(init));
839            try_visit!(visitor.visit_pat(pat));
840            visit_opt!(visitor, visit_ty_unambig, ty);
841        }
842        ExprKind::If(ref cond, ref then, ref else_opt) => {
843            try_visit!(visitor.visit_expr(cond));
844            try_visit!(visitor.visit_expr(then));
845            visit_opt!(visitor, visit_expr, else_opt);
846        }
847        ExprKind::Loop(ref block, ref opt_label, _, _) => {
848            visit_opt!(visitor, visit_label, opt_label);
849            try_visit!(visitor.visit_block(block));
850        }
851        ExprKind::Match(ref subexpression, arms, _) => {
852            try_visit!(visitor.visit_expr(subexpression));
853            walk_list!(visitor, visit_arm, arms);
854        }
855        ExprKind::Closure(&Closure {
856            def_id,
857            binder: _,
858            bound_generic_params,
859            fn_decl,
860            body,
861            capture_clause: _,
862            fn_decl_span: _,
863            fn_arg_span: _,
864            kind: _,
865            constness: _,
866        }) => {
867            walk_list!(visitor, visit_generic_param, bound_generic_params);
868            try_visit!(visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, def_id));
869        }
870        ExprKind::Block(ref block, ref opt_label) => {
871            visit_opt!(visitor, visit_label, opt_label);
872            try_visit!(visitor.visit_block(block));
873        }
874        ExprKind::Assign(ref lhs, ref rhs, _) => {
875            try_visit!(visitor.visit_expr(rhs));
876            try_visit!(visitor.visit_expr(lhs));
877        }
878        ExprKind::AssignOp(_, ref left_expression, ref right_expression) => {
879            try_visit!(visitor.visit_expr(right_expression));
880            try_visit!(visitor.visit_expr(left_expression));
881        }
882        ExprKind::Field(ref subexpression, ident) => {
883            try_visit!(visitor.visit_expr(subexpression));
884            try_visit!(visitor.visit_ident(ident));
885        }
886        ExprKind::Index(ref main_expression, ref index_expression, _) => {
887            try_visit!(visitor.visit_expr(main_expression));
888            try_visit!(visitor.visit_expr(index_expression));
889        }
890        ExprKind::Path(ref qpath) => {
891            try_visit!(visitor.visit_qpath(qpath, expression.hir_id, expression.span));
892        }
893        ExprKind::Break(ref destination, ref opt_expr) => {
894            visit_opt!(visitor, visit_label, &destination.label);
895            visit_opt!(visitor, visit_expr, opt_expr);
896        }
897        ExprKind::Continue(ref destination) => {
898            visit_opt!(visitor, visit_label, &destination.label);
899        }
900        ExprKind::Ret(ref optional_expression) => {
901            visit_opt!(visitor, visit_expr, optional_expression);
902        }
903        ExprKind::Become(ref expr) => try_visit!(visitor.visit_expr(expr)),
904        ExprKind::InlineAsm(ref asm) => {
905            try_visit!(visitor.visit_inline_asm(asm, expression.hir_id));
906        }
907        ExprKind::OffsetOf(ref container, ref fields) => {
908            try_visit!(visitor.visit_ty_unambig(container));
909            walk_list!(visitor, visit_ident, fields.iter().copied());
910        }
911        ExprKind::Yield(ref subexpression, _) => {
912            try_visit!(visitor.visit_expr(subexpression));
913        }
914        ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
915            try_visit!(visitor.visit_expr(expr));
916            visit_opt!(visitor, visit_ty_unambig, ty);
917        }
918        ExprKind::Lit(lit) => try_visit!(visitor.visit_lit(expression.hir_id, lit, false)),
919        ExprKind::Err(_) => {}
920    }
921    V::Result::output()
922}
923
924pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField<'v>) -> V::Result {
925    try_visit!(visitor.visit_id(field.hir_id));
926    try_visit!(visitor.visit_ident(field.ident));
927    visitor.visit_expr(field.expr)
928}
929/// We track whether an infer var is from a [`Ty`], [`ConstArg`], or [`GenericArg`] so that
930/// HIR visitors overriding [`Visitor::visit_infer`] can determine what kind of infer is being visited
931pub enum InferKind<'hir> {
932    Ty(&'hir Ty<'hir>),
933    Const(&'hir ConstArg<'hir>),
934    Ambig(&'hir InferArg),
935}
936
937pub fn walk_generic_arg<'v, V: Visitor<'v>>(
938    visitor: &mut V,
939    generic_arg: &'v GenericArg<'v>,
940) -> V::Result {
941    match generic_arg {
942        GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt),
943        GenericArg::Type(ty) => visitor.visit_ty(ty),
944        GenericArg::Const(ct) => visitor.visit_const_arg(ct),
945        GenericArg::Infer(inf) => visitor.visit_infer(inf.hir_id, inf.span, InferKind::Ambig(inf)),
946    }
947}
948
949pub fn walk_unambig_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Result {
950    match typ.try_as_ambig_ty() {
951        Some(ambig_ty) => visitor.visit_ty(ambig_ty),
952        None => {
953            try_visit!(visitor.visit_id(typ.hir_id));
954            visitor.visit_infer(typ.hir_id, typ.span, InferKind::Ty(typ))
955        }
956    }
957}
958
959pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v, AmbigArg>) -> V::Result {
960    try_visit!(visitor.visit_id(typ.hir_id));
961
962    match typ.kind {
963        TyKind::Slice(ref ty) => try_visit!(visitor.visit_ty_unambig(ty)),
964        TyKind::Ptr(ref mutable_type) => try_visit!(visitor.visit_ty_unambig(mutable_type.ty)),
965        TyKind::Ref(ref lifetime, ref mutable_type) => {
966            try_visit!(visitor.visit_lifetime(lifetime));
967            try_visit!(visitor.visit_ty_unambig(mutable_type.ty));
968        }
969        TyKind::Never => {}
970        TyKind::Tup(tuple_element_types) => {
971            walk_list!(visitor, visit_ty_unambig, tuple_element_types);
972        }
973        TyKind::BareFn(ref function_declaration) => {
974            walk_list!(visitor, visit_generic_param, function_declaration.generic_params);
975            try_visit!(visitor.visit_fn_decl(function_declaration.decl));
976        }
977        TyKind::UnsafeBinder(ref unsafe_binder) => {
978            walk_list!(visitor, visit_generic_param, unsafe_binder.generic_params);
979            try_visit!(visitor.visit_ty_unambig(unsafe_binder.inner_ty));
980        }
981        TyKind::Path(ref qpath) => {
982            try_visit!(visitor.visit_qpath(qpath, typ.hir_id, typ.span));
983        }
984        TyKind::OpaqueDef(opaque) => {
985            try_visit!(visitor.visit_opaque_ty(opaque));
986        }
987        TyKind::TraitAscription(bounds) => {
988            walk_list!(visitor, visit_param_bound, bounds);
989        }
990        TyKind::Array(ref ty, ref length) => {
991            try_visit!(visitor.visit_ty_unambig(ty));
992            try_visit!(visitor.visit_const_arg_unambig(length));
993        }
994        TyKind::TraitObject(bounds, ref lifetime) => {
995            for bound in bounds {
996                try_visit!(visitor.visit_poly_trait_ref(bound));
997            }
998            try_visit!(visitor.visit_lifetime(lifetime));
999        }
1000        TyKind::Typeof(ref expression) => try_visit!(visitor.visit_anon_const(expression)),
1001        TyKind::InferDelegation(..) | TyKind::Err(_) => {}
1002        TyKind::Pat(ty, pat) => {
1003            try_visit!(visitor.visit_ty_unambig(ty));
1004            try_visit!(visitor.visit_pattern_type_pattern(pat));
1005        }
1006    }
1007    V::Result::output()
1008}
1009
1010pub fn walk_const_arg<'v, V: Visitor<'v>>(
1011    visitor: &mut V,
1012    const_arg: &'v ConstArg<'v>,
1013) -> V::Result {
1014    match const_arg.try_as_ambig_ct() {
1015        Some(ambig_ct) => visitor.visit_const_arg(ambig_ct),
1016        None => {
1017            try_visit!(visitor.visit_id(const_arg.hir_id));
1018            visitor.visit_infer(const_arg.hir_id, const_arg.span(), InferKind::Const(const_arg))
1019        }
1020    }
1021}
1022
1023pub fn walk_ambig_const_arg<'v, V: Visitor<'v>>(
1024    visitor: &mut V,
1025    const_arg: &'v ConstArg<'v, AmbigArg>,
1026) -> V::Result {
1027    try_visit!(visitor.visit_id(const_arg.hir_id));
1028    match &const_arg.kind {
1029        ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, const_arg.hir_id, qpath.span()),
1030        ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon),
1031    }
1032}
1033
1034pub fn walk_generic_param<'v, V: Visitor<'v>>(
1035    visitor: &mut V,
1036    param: &'v GenericParam<'v>,
1037) -> V::Result {
1038    try_visit!(visitor.visit_id(param.hir_id));
1039    match param.name {
1040        ParamName::Plain(ident) | ParamName::Error(ident) => try_visit!(visitor.visit_ident(ident)),
1041        ParamName::Fresh => {}
1042    }
1043    match param.kind {
1044        GenericParamKind::Lifetime { .. } => {}
1045        GenericParamKind::Type { ref default, .. } => {
1046            visit_opt!(visitor, visit_ty_unambig, default)
1047        }
1048        GenericParamKind::Const { ref ty, ref default, synthetic: _ } => {
1049            try_visit!(visitor.visit_ty_unambig(ty));
1050            if let Some(ref default) = default {
1051                try_visit!(visitor.visit_const_param_default(param.hir_id, default));
1052            }
1053        }
1054    }
1055    V::Result::output()
1056}
1057
1058pub fn walk_const_param_default<'v, V: Visitor<'v>>(
1059    visitor: &mut V,
1060    ct: &'v ConstArg<'v>,
1061) -> V::Result {
1062    visitor.visit_const_arg_unambig(ct)
1063}
1064
1065pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) -> V::Result {
1066    walk_list!(visitor, visit_generic_param, generics.params);
1067    walk_list!(visitor, visit_where_predicate, generics.predicates);
1068    V::Result::output()
1069}
1070
1071pub fn walk_where_predicate<'v, V: Visitor<'v>>(
1072    visitor: &mut V,
1073    predicate: &'v WherePredicate<'v>,
1074) -> V::Result {
1075    let &WherePredicate { hir_id, kind, span: _ } = predicate;
1076    try_visit!(visitor.visit_id(hir_id));
1077    match *kind {
1078        WherePredicateKind::BoundPredicate(WhereBoundPredicate {
1079            ref bounded_ty,
1080            bounds,
1081            bound_generic_params,
1082            origin: _,
1083        }) => {
1084            try_visit!(visitor.visit_ty_unambig(bounded_ty));
1085            walk_list!(visitor, visit_param_bound, bounds);
1086            walk_list!(visitor, visit_generic_param, bound_generic_params);
1087        }
1088        WherePredicateKind::RegionPredicate(WhereRegionPredicate {
1089            ref lifetime,
1090            bounds,
1091            in_where_clause: _,
1092        }) => {
1093            try_visit!(visitor.visit_lifetime(lifetime));
1094            walk_list!(visitor, visit_param_bound, bounds);
1095        }
1096        WherePredicateKind::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty }) => {
1097            try_visit!(visitor.visit_ty_unambig(lhs_ty));
1098            try_visit!(visitor.visit_ty_unambig(rhs_ty));
1099        }
1100    }
1101    V::Result::output()
1102}
1103
1104pub fn walk_fn_decl<'v, V: Visitor<'v>>(
1105    visitor: &mut V,
1106    function_declaration: &'v FnDecl<'v>,
1107) -> V::Result {
1108    walk_list!(visitor, visit_ty_unambig, function_declaration.inputs);
1109    visitor.visit_fn_ret_ty(&function_declaration.output)
1110}
1111
1112pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FnRetTy<'v>) -> V::Result {
1113    if let FnRetTy::Return(output_ty) = *ret_ty {
1114        try_visit!(visitor.visit_ty_unambig(output_ty));
1115    }
1116    V::Result::output()
1117}
1118
1119pub fn walk_fn<'v, V: Visitor<'v>>(
1120    visitor: &mut V,
1121    function_kind: FnKind<'v>,
1122    function_declaration: &'v FnDecl<'v>,
1123    body_id: BodyId,
1124    _: LocalDefId,
1125) -> V::Result {
1126    try_visit!(visitor.visit_fn_decl(function_declaration));
1127    try_visit!(walk_fn_kind(visitor, function_kind));
1128    visitor.visit_nested_body(body_id)
1129}
1130
1131pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) -> V::Result {
1132    match function_kind {
1133        FnKind::ItemFn(_, generics, ..) => {
1134            try_visit!(visitor.visit_generics(generics));
1135        }
1136        FnKind::Closure | FnKind::Method(..) => {}
1137    }
1138    V::Result::output()
1139}
1140
1141pub fn walk_use<'v, V: Visitor<'v>>(
1142    visitor: &mut V,
1143    path: &'v UsePath<'v>,
1144    hir_id: HirId,
1145) -> V::Result {
1146    try_visit!(visitor.visit_id(hir_id));
1147    let UsePath { segments, ref res, span } = *path;
1148    for &res in res {
1149        try_visit!(visitor.visit_path(&Path { segments, res, span }, hir_id));
1150    }
1151    V::Result::output()
1152}
1153
1154pub fn walk_trait_item<'v, V: Visitor<'v>>(
1155    visitor: &mut V,
1156    trait_item: &'v TraitItem<'v>,
1157) -> V::Result {
1158    // N.B., deliberately force a compilation error if/when new fields are added.
1159    let TraitItem { ident, generics, ref defaultness, ref kind, span, owner_id: _ } = *trait_item;
1160    let hir_id = trait_item.hir_id();
1161    try_visit!(visitor.visit_ident(ident));
1162    try_visit!(visitor.visit_generics(&generics));
1163    try_visit!(visitor.visit_defaultness(&defaultness));
1164    try_visit!(visitor.visit_id(hir_id));
1165    match *kind {
1166        TraitItemKind::Const(ref ty, default) => {
1167            try_visit!(visitor.visit_ty_unambig(ty));
1168            visit_opt!(visitor, visit_nested_body, default);
1169        }
1170        TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
1171            try_visit!(visitor.visit_fn_decl(sig.decl));
1172            walk_list!(visitor, visit_ident, param_names.iter().copied());
1173        }
1174        TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
1175            try_visit!(visitor.visit_fn(
1176                FnKind::Method(ident, sig),
1177                sig.decl,
1178                body_id,
1179                span,
1180                trait_item.owner_id.def_id,
1181            ));
1182        }
1183        TraitItemKind::Type(bounds, ref default) => {
1184            walk_list!(visitor, visit_param_bound, bounds);
1185            visit_opt!(visitor, visit_ty_unambig, default);
1186        }
1187    }
1188    V::Result::output()
1189}
1190
1191pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(
1192    visitor: &mut V,
1193    trait_item_ref: &'v TraitItemRef,
1194) -> V::Result {
1195    // N.B., deliberately force a compilation error if/when new fields are added.
1196    let TraitItemRef { id, ident, ref kind, span: _ } = *trait_item_ref;
1197    try_visit!(visitor.visit_nested_trait_item(id));
1198    try_visit!(visitor.visit_ident(ident));
1199    visitor.visit_associated_item_kind(kind)
1200}
1201
1202pub fn walk_impl_item<'v, V: Visitor<'v>>(
1203    visitor: &mut V,
1204    impl_item: &'v ImplItem<'v>,
1205) -> V::Result {
1206    // N.B., deliberately force a compilation error if/when new fields are added.
1207    let ImplItem {
1208        owner_id: _,
1209        ident,
1210        ref generics,
1211        ref kind,
1212        ref defaultness,
1213        span: _,
1214        vis_span: _,
1215    } = *impl_item;
1216
1217    try_visit!(visitor.visit_ident(ident));
1218    try_visit!(visitor.visit_generics(generics));
1219    try_visit!(visitor.visit_defaultness(defaultness));
1220    try_visit!(visitor.visit_id(impl_item.hir_id()));
1221    match *kind {
1222        ImplItemKind::Const(ref ty, body) => {
1223            try_visit!(visitor.visit_ty_unambig(ty));
1224            visitor.visit_nested_body(body)
1225        }
1226        ImplItemKind::Fn(ref sig, body_id) => visitor.visit_fn(
1227            FnKind::Method(impl_item.ident, sig),
1228            sig.decl,
1229            body_id,
1230            impl_item.span,
1231            impl_item.owner_id.def_id,
1232        ),
1233        ImplItemKind::Type(ref ty) => visitor.visit_ty_unambig(ty),
1234    }
1235}
1236
1237pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>(
1238    visitor: &mut V,
1239    foreign_item_ref: &'v ForeignItemRef,
1240) -> V::Result {
1241    // N.B., deliberately force a compilation error if/when new fields are added.
1242    let ForeignItemRef { id, ident, span: _ } = *foreign_item_ref;
1243    try_visit!(visitor.visit_nested_foreign_item(id));
1244    visitor.visit_ident(ident)
1245}
1246
1247pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(
1248    visitor: &mut V,
1249    impl_item_ref: &'v ImplItemRef,
1250) -> V::Result {
1251    // N.B., deliberately force a compilation error if/when new fields are added.
1252    let ImplItemRef { id, ident, ref kind, span: _, trait_item_def_id: _ } = *impl_item_ref;
1253    try_visit!(visitor.visit_nested_impl_item(id));
1254    try_visit!(visitor.visit_ident(ident));
1255    visitor.visit_associated_item_kind(kind)
1256}
1257
1258pub fn walk_trait_ref<'v, V: Visitor<'v>>(
1259    visitor: &mut V,
1260    trait_ref: &'v TraitRef<'v>,
1261) -> V::Result {
1262    try_visit!(visitor.visit_id(trait_ref.hir_ref_id));
1263    visitor.visit_path(trait_ref.path, trait_ref.hir_ref_id)
1264}
1265
1266pub fn walk_param_bound<'v, V: Visitor<'v>>(
1267    visitor: &mut V,
1268    bound: &'v GenericBound<'v>,
1269) -> V::Result {
1270    match *bound {
1271        GenericBound::Trait(ref typ) => visitor.visit_poly_trait_ref(typ),
1272        GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
1273        GenericBound::Use(args, _) => {
1274            walk_list!(visitor, visit_precise_capturing_arg, args);
1275            V::Result::output()
1276        }
1277    }
1278}
1279
1280pub fn walk_precise_capturing_arg<'v, V: Visitor<'v>>(
1281    visitor: &mut V,
1282    arg: &'v PreciseCapturingArg<'v>,
1283) -> V::Result {
1284    match *arg {
1285        PreciseCapturingArg::Lifetime(lt) => visitor.visit_lifetime(lt),
1286        PreciseCapturingArg::Param(param) => visitor.visit_id(param.hir_id),
1287    }
1288}
1289
1290pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(
1291    visitor: &mut V,
1292    trait_ref: &'v PolyTraitRef<'v>,
1293) -> V::Result {
1294    walk_list!(visitor, visit_generic_param, trait_ref.bound_generic_params);
1295    visitor.visit_trait_ref(&trait_ref.trait_ref)
1296}
1297
1298pub fn walk_opaque_ty<'v, V: Visitor<'v>>(visitor: &mut V, opaque: &'v OpaqueTy<'v>) -> V::Result {
1299    let &OpaqueTy { hir_id, def_id: _, bounds, origin: _, span: _ } = opaque;
1300    try_visit!(visitor.visit_id(hir_id));
1301    walk_list!(visitor, visit_param_bound, bounds);
1302    V::Result::output()
1303}
1304
1305pub fn walk_struct_def<'v, V: Visitor<'v>>(
1306    visitor: &mut V,
1307    struct_definition: &'v VariantData<'v>,
1308) -> V::Result {
1309    visit_opt!(visitor, visit_id, struct_definition.ctor_hir_id());
1310    walk_list!(visitor, visit_field_def, struct_definition.fields());
1311    V::Result::output()
1312}
1313
1314pub fn walk_field_def<'v, V: Visitor<'v>>(
1315    visitor: &mut V,
1316    FieldDef { hir_id, ident, ty, default, span: _, vis_span: _, def_id: _, safety: _ }: &'v FieldDef<'v>,
1317) -> V::Result {
1318    try_visit!(visitor.visit_id(*hir_id));
1319    try_visit!(visitor.visit_ident(*ident));
1320    visit_opt!(visitor, visit_anon_const, default);
1321    visitor.visit_ty_unambig(*ty)
1322}
1323
1324pub fn walk_enum_def<'v, V: Visitor<'v>>(
1325    visitor: &mut V,
1326    enum_definition: &'v EnumDef<'v>,
1327    item_id: HirId,
1328) -> V::Result {
1329    try_visit!(visitor.visit_id(item_id));
1330    walk_list!(visitor, visit_variant, enum_definition.variants);
1331    V::Result::output()
1332}
1333
1334pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, variant: &'v Variant<'v>) -> V::Result {
1335    try_visit!(visitor.visit_ident(variant.ident));
1336    try_visit!(visitor.visit_id(variant.hir_id));
1337    try_visit!(visitor.visit_variant_data(&variant.data));
1338    visit_opt!(visitor, visit_anon_const, &variant.disr_expr);
1339    V::Result::output()
1340}
1341
1342pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) -> V::Result {
1343    visitor.visit_ident(label.ident)
1344}
1345
1346pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) -> V::Result {
1347    visitor.visit_id(inf.hir_id)
1348}
1349
1350pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) -> V::Result {
1351    try_visit!(visitor.visit_id(lifetime.hir_id));
1352    visitor.visit_ident(lifetime.ident)
1353}
1354
1355pub fn walk_qpath<'v, V: Visitor<'v>>(
1356    visitor: &mut V,
1357    qpath: &'v QPath<'v>,
1358    id: HirId,
1359) -> V::Result {
1360    match *qpath {
1361        QPath::Resolved(ref maybe_qself, ref path) => {
1362            visit_opt!(visitor, visit_ty_unambig, maybe_qself);
1363            visitor.visit_path(path, id)
1364        }
1365        QPath::TypeRelative(ref qself, ref segment) => {
1366            try_visit!(visitor.visit_ty_unambig(qself));
1367            visitor.visit_path_segment(segment)
1368        }
1369        QPath::LangItem(..) => V::Result::output(),
1370    }
1371}
1372
1373pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &Path<'v>) -> V::Result {
1374    walk_list!(visitor, visit_path_segment, path.segments);
1375    V::Result::output()
1376}
1377
1378pub fn walk_path_segment<'v, V: Visitor<'v>>(
1379    visitor: &mut V,
1380    segment: &'v PathSegment<'v>,
1381) -> V::Result {
1382    try_visit!(visitor.visit_ident(segment.ident));
1383    try_visit!(visitor.visit_id(segment.hir_id));
1384    visit_opt!(visitor, visit_generic_args, segment.args);
1385    V::Result::output()
1386}
1387
1388pub fn walk_generic_args<'v, V: Visitor<'v>>(
1389    visitor: &mut V,
1390    generic_args: &'v GenericArgs<'v>,
1391) -> V::Result {
1392    walk_list!(visitor, visit_generic_arg, generic_args.args);
1393    walk_list!(visitor, visit_assoc_item_constraint, generic_args.constraints);
1394    V::Result::output()
1395}
1396
1397pub fn walk_assoc_item_constraint<'v, V: Visitor<'v>>(
1398    visitor: &mut V,
1399    constraint: &'v AssocItemConstraint<'v>,
1400) -> V::Result {
1401    try_visit!(visitor.visit_id(constraint.hir_id));
1402    try_visit!(visitor.visit_ident(constraint.ident));
1403    try_visit!(visitor.visit_generic_args(constraint.gen_args));
1404    match constraint.kind {
1405        AssocItemConstraintKind::Equality { ref term } => match term {
1406            Term::Ty(ref ty) => try_visit!(visitor.visit_ty_unambig(ty)),
1407            Term::Const(ref c) => try_visit!(visitor.visit_const_arg_unambig(c)),
1408        },
1409        AssocItemConstraintKind::Bound { bounds } => {
1410            walk_list!(visitor, visit_param_bound, bounds)
1411        }
1412    }
1413    V::Result::output()
1414}
1415
1416pub fn walk_associated_item_kind<'v, V: Visitor<'v>>(_: &mut V, _: &'v AssocItemKind) -> V::Result {
1417    // No visitable content here: this fn exists so you can call it if
1418    // the right thing to do, should content be added in the future,
1419    // would be to walk it.
1420    V::Result::output()
1421}
1422
1423pub fn walk_defaultness<'v, V: Visitor<'v>>(_: &mut V, _: &'v Defaultness) -> V::Result {
1424    // No visitable content here: this fn exists so you can call it if
1425    // the right thing to do, should content be added in the future,
1426    // would be to walk it.
1427    V::Result::output()
1428}
1429
1430pub fn walk_inline_asm<'v, V: Visitor<'v>>(
1431    visitor: &mut V,
1432    asm: &'v InlineAsm<'v>,
1433    id: HirId,
1434) -> V::Result {
1435    for (op, op_sp) in asm.operands {
1436        match op {
1437            InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => {
1438                try_visit!(visitor.visit_expr(expr));
1439            }
1440            InlineAsmOperand::Out { expr, .. } => {
1441                visit_opt!(visitor, visit_expr, expr);
1442            }
1443            InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
1444                try_visit!(visitor.visit_expr(in_expr));
1445                visit_opt!(visitor, visit_expr, out_expr);
1446            }
1447            InlineAsmOperand::Const { anon_const, .. }
1448            | InlineAsmOperand::SymFn { anon_const, .. } => {
1449                try_visit!(visitor.visit_anon_const(anon_const));
1450            }
1451            InlineAsmOperand::SymStatic { path, .. } => {
1452                try_visit!(visitor.visit_qpath(path, id, *op_sp));
1453            }
1454            InlineAsmOperand::Label { block } => try_visit!(visitor.visit_block(block)),
1455        }
1456    }
1457    V::Result::output()
1458}