rustc_ast/
visit.rs

1//! AST walker. Each overridden visit method has full control over what
2//! happens with its node, it can do its own traversal of the node's children,
3//! call `visit::walk_*` to apply the default traversal algorithm, or prevent
4//! deeper traversal by doing nothing.
5//!
6//! Note: it is an important invariant that the default visitor walks the body
7//! of a function in "execution order" (more concretely, reverse post-order
8//! with respect to the CFG implied by the AST), meaning that if AST node A may
9//! execute before AST node B, then A is visited first. The borrow checker in
10//! particular relies on this property.
11//!
12//! Note: walking an AST before macro expansion is probably a bad idea. For
13//! instance, a walker looking for item names in a module will miss all of
14//! those that are created by the expansion of a macro.
15
16pub use rustc_ast_ir::visit::VisitorResult;
17pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
18use rustc_span::{Ident, Span};
19use thin_vec::ThinVec;
20
21use crate::ast::*;
22use crate::ptr::P;
23
24#[derive(Copy, Clone, Debug, PartialEq)]
25pub enum AssocCtxt {
26    Trait,
27    Impl { of_trait: bool },
28}
29
30#[derive(Copy, Clone, Debug, PartialEq)]
31pub enum FnCtxt {
32    Free,
33    Foreign,
34    Assoc(AssocCtxt),
35}
36
37#[derive(Copy, Clone, Debug)]
38pub enum BoundKind {
39    /// Trait bounds in generics bounds and type/trait alias.
40    /// E.g., `<T: Bound>`, `type A: Bound`, or `where T: Bound`.
41    Bound,
42
43    /// Trait bounds in `impl` type.
44    /// E.g., `type Foo = impl Bound1 + Bound2 + Bound3`.
45    Impl,
46
47    /// Trait bounds in trait object type.
48    /// E.g., `dyn Bound1 + Bound2 + Bound3`.
49    TraitObject,
50
51    /// Super traits of a trait.
52    /// E.g., `trait A: B`
53    SuperTraits,
54}
55impl BoundKind {
56    pub fn descr(self) -> &'static str {
57        match self {
58            BoundKind::Bound => "bounds",
59            BoundKind::Impl => "`impl Trait`",
60            BoundKind::TraitObject => "`dyn` trait object bounds",
61            BoundKind::SuperTraits => "supertrait bounds",
62        }
63    }
64}
65
66#[derive(Copy, Clone, Debug)]
67pub enum FnKind<'a> {
68    /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
69    Fn(FnCtxt, &'a Ident, &'a Visibility, &'a Fn),
70
71    /// E.g., `|x, y| body`.
72    Closure(&'a ClosureBinder, &'a Option<CoroutineKind>, &'a FnDecl, &'a Expr),
73}
74
75impl<'a> FnKind<'a> {
76    pub fn header(&self) -> Option<&'a FnHeader> {
77        match *self {
78            FnKind::Fn(_, _, _, Fn { sig, .. }) => Some(&sig.header),
79            FnKind::Closure(..) => None,
80        }
81    }
82
83    pub fn ident(&self) -> Option<&Ident> {
84        match self {
85            FnKind::Fn(_, ident, ..) => Some(ident),
86            _ => None,
87        }
88    }
89
90    pub fn decl(&self) -> &'a FnDecl {
91        match self {
92            FnKind::Fn(_, _, _, Fn { sig, .. }) => &sig.decl,
93            FnKind::Closure(_, _, decl, _) => decl,
94        }
95    }
96
97    pub fn ctxt(&self) -> Option<FnCtxt> {
98        match self {
99            FnKind::Fn(ctxt, ..) => Some(*ctxt),
100            FnKind::Closure(..) => None,
101        }
102    }
103}
104
105#[derive(Copy, Clone, Debug)]
106pub enum LifetimeCtxt {
107    /// Appears in a reference type.
108    Ref,
109    /// Appears as a bound on a type or another lifetime.
110    Bound,
111    /// Appears as a generic argument.
112    GenericArg,
113}
114
115pub trait WalkItemKind {
116    type Ctxt;
117    fn walk<'a, V: Visitor<'a>>(
118        &'a self,
119        span: Span,
120        id: NodeId,
121        ident: &'a Ident,
122        visibility: &'a Visibility,
123        ctxt: Self::Ctxt,
124        visitor: &mut V,
125    ) -> V::Result;
126}
127
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_item` method by default calls `visit::walk_item`.
132///
133/// If you want to ensure that your code handles every variant
134/// explicitly, you need to override each method. (And you also need
135/// to monitor future changes to `Visitor` in case a new method with a
136/// new default implementation gets introduced.)
137pub trait Visitor<'ast>: Sized {
138    /// The result type of the `visit_*` methods. Can be either `()`,
139    /// or `ControlFlow<T>`.
140    type Result: VisitorResult = ();
141
142    fn visit_ident(&mut self, _ident: &'ast Ident) -> Self::Result {
143        Self::Result::output()
144    }
145    fn visit_foreign_item(&mut self, i: &'ast ForeignItem) -> Self::Result {
146        walk_item(self, i)
147    }
148    fn visit_item(&mut self, i: &'ast Item) -> Self::Result {
149        walk_item(self, i)
150    }
151    fn visit_local(&mut self, l: &'ast Local) -> Self::Result {
152        walk_local(self, l)
153    }
154    fn visit_block(&mut self, b: &'ast Block) -> Self::Result {
155        walk_block(self, b)
156    }
157    fn visit_stmt(&mut self, s: &'ast Stmt) -> Self::Result {
158        walk_stmt(self, s)
159    }
160    fn visit_param(&mut self, param: &'ast Param) -> Self::Result {
161        walk_param(self, param)
162    }
163    fn visit_arm(&mut self, a: &'ast Arm) -> Self::Result {
164        walk_arm(self, a)
165    }
166    fn visit_pat(&mut self, p: &'ast Pat) -> Self::Result {
167        walk_pat(self, p)
168    }
169    fn visit_anon_const(&mut self, c: &'ast AnonConst) -> Self::Result {
170        walk_anon_const(self, c)
171    }
172    fn visit_expr(&mut self, ex: &'ast Expr) -> Self::Result {
173        walk_expr(self, ex)
174    }
175    /// This method is a hack to workaround unstable of `stmt_expr_attributes`.
176    /// It can be removed once that feature is stabilized.
177    fn visit_method_receiver_expr(&mut self, ex: &'ast Expr) -> Self::Result {
178        self.visit_expr(ex)
179    }
180    fn visit_ty(&mut self, t: &'ast Ty) -> Self::Result {
181        walk_ty(self, t)
182    }
183    fn visit_ty_pat(&mut self, t: &'ast TyPat) -> Self::Result {
184        walk_ty_pat(self, t)
185    }
186    fn visit_generic_param(&mut self, param: &'ast GenericParam) -> Self::Result {
187        walk_generic_param(self, param)
188    }
189    fn visit_generics(&mut self, g: &'ast Generics) -> Self::Result {
190        walk_generics(self, g)
191    }
192    fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) -> Self::Result {
193        walk_closure_binder(self, b)
194    }
195    fn visit_contract(&mut self, c: &'ast FnContract) -> Self::Result {
196        walk_contract(self, c)
197    }
198    fn visit_where_predicate(&mut self, p: &'ast WherePredicate) -> Self::Result {
199        walk_where_predicate(self, p)
200    }
201    fn visit_where_predicate_kind(&mut self, k: &'ast WherePredicateKind) -> Self::Result {
202        walk_where_predicate_kind(self, k)
203    }
204    fn visit_fn(&mut self, fk: FnKind<'ast>, _: Span, _: NodeId) -> Self::Result {
205        walk_fn(self, fk)
206    }
207    fn visit_assoc_item(&mut self, i: &'ast AssocItem, ctxt: AssocCtxt) -> Self::Result {
208        walk_assoc_item(self, i, ctxt)
209    }
210    fn visit_trait_ref(&mut self, t: &'ast TraitRef) -> Self::Result {
211        walk_trait_ref(self, t)
212    }
213    fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) -> Self::Result {
214        walk_param_bound(self, bounds)
215    }
216    fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) -> Self::Result {
217        walk_precise_capturing_arg(self, arg)
218    }
219    fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) -> Self::Result {
220        walk_poly_trait_ref(self, t)
221    }
222    fn visit_variant_data(&mut self, s: &'ast VariantData) -> Self::Result {
223        walk_struct_def(self, s)
224    }
225    fn visit_field_def(&mut self, s: &'ast FieldDef) -> Self::Result {
226        walk_field_def(self, s)
227    }
228    fn visit_enum_def(&mut self, enum_definition: &'ast EnumDef) -> Self::Result {
229        walk_enum_def(self, enum_definition)
230    }
231    fn visit_variant(&mut self, v: &'ast Variant) -> Self::Result {
232        walk_variant(self, v)
233    }
234    fn visit_variant_discr(&mut self, discr: &'ast AnonConst) -> Self::Result {
235        self.visit_anon_const(discr)
236    }
237    fn visit_label(&mut self, label: &'ast Label) -> Self::Result {
238        walk_label(self, label)
239    }
240    fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) -> Self::Result {
241        walk_lifetime(self, lifetime)
242    }
243    fn visit_mac_call(&mut self, mac: &'ast MacCall) -> Self::Result {
244        walk_mac(self, mac)
245    }
246    fn visit_mac_def(&mut self, _mac: &'ast MacroDef, _id: NodeId) -> Self::Result {
247        Self::Result::output()
248    }
249    fn visit_path(&mut self, path: &'ast Path, _id: NodeId) -> Self::Result {
250        walk_path(self, path)
251    }
252    fn visit_use_tree(
253        &mut self,
254        use_tree: &'ast UseTree,
255        id: NodeId,
256        _nested: bool,
257    ) -> Self::Result {
258        walk_use_tree(self, use_tree, id)
259    }
260    fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) -> Self::Result {
261        walk_path_segment(self, path_segment)
262    }
263    fn visit_generic_args(&mut self, generic_args: &'ast GenericArgs) -> Self::Result {
264        walk_generic_args(self, generic_args)
265    }
266    fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) -> Self::Result {
267        walk_generic_arg(self, generic_arg)
268    }
269    fn visit_assoc_item_constraint(
270        &mut self,
271        constraint: &'ast AssocItemConstraint,
272    ) -> Self::Result {
273        walk_assoc_item_constraint(self, constraint)
274    }
275    fn visit_attribute(&mut self, attr: &'ast Attribute) -> Self::Result {
276        walk_attribute(self, attr)
277    }
278    fn visit_vis(&mut self, vis: &'ast Visibility) -> Self::Result {
279        walk_vis(self, vis)
280    }
281    fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FnRetTy) -> Self::Result {
282        walk_fn_ret_ty(self, ret_ty)
283    }
284    fn visit_fn_header(&mut self, header: &'ast FnHeader) -> Self::Result {
285        walk_fn_header(self, header)
286    }
287    fn visit_expr_field(&mut self, f: &'ast ExprField) -> Self::Result {
288        walk_expr_field(self, f)
289    }
290    fn visit_pat_field(&mut self, fp: &'ast PatField) -> Self::Result {
291        walk_pat_field(self, fp)
292    }
293    fn visit_crate(&mut self, krate: &'ast Crate) -> Self::Result {
294        walk_crate(self, krate)
295    }
296    fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) -> Self::Result {
297        walk_inline_asm(self, asm)
298    }
299    fn visit_format_args(&mut self, fmt: &'ast FormatArgs) -> Self::Result {
300        walk_format_args(self, fmt)
301    }
302    fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) -> Self::Result {
303        walk_inline_asm_sym(self, sym)
304    }
305    fn visit_capture_by(&mut self, _capture_by: &'ast CaptureBy) -> Self::Result {
306        Self::Result::output()
307    }
308    fn visit_coroutine_kind(&mut self, _coroutine_kind: &'ast CoroutineKind) -> Self::Result {
309        Self::Result::output()
310    }
311    fn visit_fn_decl(&mut self, fn_decl: &'ast FnDecl) -> Self::Result {
312        walk_fn_decl(self, fn_decl)
313    }
314    fn visit_qself(&mut self, qs: &'ast Option<P<QSelf>>) -> Self::Result {
315        walk_qself(self, qs)
316    }
317}
318
319pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result {
320    let Crate { attrs, items, spans: _, id: _, is_placeholder: _ } = krate;
321    walk_list!(visitor, visit_attribute, attrs);
322    walk_list!(visitor, visit_item, items);
323    V::Result::output()
324}
325
326pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) -> V::Result {
327    let Local { id: _, pat, ty, kind, span: _, colon_sp: _, attrs, tokens: _ } = local;
328    walk_list!(visitor, visit_attribute, attrs);
329    try_visit!(visitor.visit_pat(pat));
330    visit_opt!(visitor, visit_ty, ty);
331    if let Some((init, els)) = kind.init_else_opt() {
332        try_visit!(visitor.visit_expr(init));
333        visit_opt!(visitor, visit_block, els);
334    }
335    V::Result::output()
336}
337
338pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, Label { ident }: &'a Label) -> V::Result {
339    visitor.visit_ident(ident)
340}
341
342pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) -> V::Result {
343    let Lifetime { id: _, ident } = lifetime;
344    visitor.visit_ident(ident)
345}
346
347pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V, trait_ref: &'a PolyTraitRef) -> V::Result
348where
349    V: Visitor<'a>,
350{
351    let PolyTraitRef { bound_generic_params, modifiers: _, trait_ref, span: _ } = trait_ref;
352    walk_list!(visitor, visit_generic_param, bound_generic_params);
353    visitor.visit_trait_ref(trait_ref)
354}
355
356pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitRef) -> V::Result {
357    let TraitRef { path, ref_id } = trait_ref;
358    visitor.visit_path(path, *ref_id)
359}
360
361impl WalkItemKind for ItemKind {
362    type Ctxt = ();
363    fn walk<'a, V: Visitor<'a>>(
364        &'a self,
365        span: Span,
366        id: NodeId,
367        ident: &'a Ident,
368        vis: &'a Visibility,
369        _ctxt: Self::Ctxt,
370        visitor: &mut V,
371    ) -> V::Result {
372        match self {
373            ItemKind::ExternCrate(_rename) => {}
374            ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)),
375            ItemKind::Static(box StaticItem {
376                ty,
377                safety: _,
378                mutability: _,
379                expr,
380                define_opaque,
381            }) => {
382                try_visit!(visitor.visit_ty(ty));
383                visit_opt!(visitor, visit_expr, expr);
384                try_visit!(walk_define_opaques(visitor, define_opaque));
385            }
386            ItemKind::Const(box ConstItem {
387                defaultness: _,
388                generics,
389                ty,
390                expr,
391                define_opaque,
392            }) => {
393                try_visit!(visitor.visit_generics(generics));
394                try_visit!(visitor.visit_ty(ty));
395                visit_opt!(visitor, visit_expr, expr);
396                try_visit!(walk_define_opaques(visitor, define_opaque));
397            }
398            ItemKind::Fn(func) => {
399                let kind = FnKind::Fn(FnCtxt::Free, ident, vis, &*func);
400                try_visit!(visitor.visit_fn(kind, span, id));
401            }
402            ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
403                ModKind::Loaded(items, _inline, _inner_span, _) => {
404                    walk_list!(visitor, visit_item, items);
405                }
406                ModKind::Unloaded => {}
407            },
408            ItemKind::ForeignMod(ForeignMod { extern_span: _, safety: _, abi: _, items }) => {
409                walk_list!(visitor, visit_foreign_item, items);
410            }
411            ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)),
412            ItemKind::TyAlias(box TyAlias {
413                generics,
414                bounds,
415                ty,
416                defaultness: _,
417                where_clauses: _,
418            }) => {
419                try_visit!(visitor.visit_generics(generics));
420                walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
421                visit_opt!(visitor, visit_ty, ty);
422            }
423            ItemKind::Enum(enum_definition, generics) => {
424                try_visit!(visitor.visit_generics(generics));
425                try_visit!(visitor.visit_enum_def(enum_definition));
426            }
427            ItemKind::Impl(box Impl {
428                defaultness: _,
429                safety: _,
430                generics,
431                constness: _,
432                polarity: _,
433                of_trait,
434                self_ty,
435                items,
436            }) => {
437                try_visit!(visitor.visit_generics(generics));
438                visit_opt!(visitor, visit_trait_ref, of_trait);
439                try_visit!(visitor.visit_ty(self_ty));
440                walk_list!(
441                    visitor,
442                    visit_assoc_item,
443                    items,
444                    AssocCtxt::Impl { of_trait: of_trait.is_some() }
445                );
446            }
447            ItemKind::Struct(struct_definition, generics)
448            | ItemKind::Union(struct_definition, generics) => {
449                try_visit!(visitor.visit_generics(generics));
450                try_visit!(visitor.visit_variant_data(struct_definition));
451            }
452            ItemKind::Trait(box Trait { safety: _, is_auto: _, generics, bounds, items }) => {
453                try_visit!(visitor.visit_generics(generics));
454                walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits);
455                walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
456            }
457            ItemKind::TraitAlias(generics, bounds) => {
458                try_visit!(visitor.visit_generics(generics));
459                walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
460            }
461            ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
462            ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, id)),
463            ItemKind::Delegation(box Delegation {
464                id,
465                qself,
466                path,
467                rename,
468                body,
469                from_glob: _,
470            }) => {
471                try_visit!(visitor.visit_qself(qself));
472                try_visit!(visitor.visit_path(path, *id));
473                visit_opt!(visitor, visit_ident, rename);
474                visit_opt!(visitor, visit_block, body);
475            }
476            ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
477                try_visit!(visitor.visit_qself(qself));
478                try_visit!(visitor.visit_path(prefix, id));
479                if let Some(suffixes) = suffixes {
480                    for (ident, rename) in suffixes {
481                        visitor.visit_ident(ident);
482                        if let Some(rename) = rename {
483                            visitor.visit_ident(rename);
484                        }
485                    }
486                }
487                visit_opt!(visitor, visit_block, body);
488            }
489        }
490        V::Result::output()
491    }
492}
493
494pub fn walk_enum_def<'a, V: Visitor<'a>>(
495    visitor: &mut V,
496    EnumDef { variants }: &'a EnumDef,
497) -> V::Result {
498    walk_list!(visitor, visit_variant, variants);
499    V::Result::output()
500}
501
502pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant) -> V::Result
503where
504    V: Visitor<'a>,
505{
506    let Variant { attrs, id: _, span: _, vis, ident, data, disr_expr, is_placeholder: _ } = variant;
507    walk_list!(visitor, visit_attribute, attrs);
508    try_visit!(visitor.visit_vis(vis));
509    try_visit!(visitor.visit_ident(ident));
510    try_visit!(visitor.visit_variant_data(data));
511    visit_opt!(visitor, visit_variant_discr, disr_expr);
512    V::Result::output()
513}
514
515pub fn walk_expr_field<'a, V: Visitor<'a>>(visitor: &mut V, f: &'a ExprField) -> V::Result {
516    let ExprField { attrs, id: _, span: _, ident, expr, is_shorthand: _, is_placeholder: _ } = f;
517    walk_list!(visitor, visit_attribute, attrs);
518    try_visit!(visitor.visit_ident(ident));
519    try_visit!(visitor.visit_expr(expr));
520    V::Result::output()
521}
522
523pub fn walk_pat_field<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a PatField) -> V::Result {
524    let PatField { ident, pat, is_shorthand: _, attrs, id: _, span: _, is_placeholder: _ } = fp;
525    walk_list!(visitor, visit_attribute, attrs);
526    try_visit!(visitor.visit_ident(ident));
527    try_visit!(visitor.visit_pat(pat));
528    V::Result::output()
529}
530
531pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
532    let Ty { id, kind, span: _, tokens: _ } = typ;
533    match kind {
534        TyKind::Slice(ty) | TyKind::Paren(ty) => try_visit!(visitor.visit_ty(ty)),
535        TyKind::Ptr(MutTy { ty, mutbl: _ }) => try_visit!(visitor.visit_ty(ty)),
536        TyKind::Ref(opt_lifetime, MutTy { ty, mutbl: _ })
537        | TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl: _ }) => {
538            visit_opt!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref);
539            try_visit!(visitor.visit_ty(ty));
540        }
541        TyKind::Tup(tuple_element_types) => {
542            walk_list!(visitor, visit_ty, tuple_element_types);
543        }
544        TyKind::BareFn(function_declaration) => {
545            let BareFnTy { safety: _, ext: _, generic_params, decl, decl_span: _ } =
546                &**function_declaration;
547            walk_list!(visitor, visit_generic_param, generic_params);
548            try_visit!(visitor.visit_fn_decl(decl));
549        }
550        TyKind::UnsafeBinder(binder) => {
551            walk_list!(visitor, visit_generic_param, &binder.generic_params);
552            try_visit!(visitor.visit_ty(&binder.inner_ty));
553        }
554        TyKind::Path(maybe_qself, path) => {
555            try_visit!(visitor.visit_qself(maybe_qself));
556            try_visit!(visitor.visit_path(path, *id));
557        }
558        TyKind::Pat(ty, pat) => {
559            try_visit!(visitor.visit_ty(ty));
560            try_visit!(visitor.visit_ty_pat(pat));
561        }
562        TyKind::Array(ty, length) => {
563            try_visit!(visitor.visit_ty(ty));
564            try_visit!(visitor.visit_anon_const(length));
565        }
566        TyKind::TraitObject(bounds, _syntax) => {
567            walk_list!(visitor, visit_param_bound, bounds, BoundKind::TraitObject);
568        }
569        TyKind::ImplTrait(_id, bounds) => {
570            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl);
571        }
572        TyKind::Typeof(expression) => try_visit!(visitor.visit_anon_const(expression)),
573        TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy => {}
574        TyKind::Err(_guar) => {}
575        TyKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
576        TyKind::Never | TyKind::CVarArgs => {}
577    }
578    V::Result::output()
579}
580
581pub fn walk_ty_pat<'a, V: Visitor<'a>>(visitor: &mut V, tp: &'a TyPat) -> V::Result {
582    let TyPat { id: _, kind, span: _, tokens: _ } = tp;
583    match kind {
584        TyPatKind::Range(start, end, _include_end) => {
585            visit_opt!(visitor, visit_anon_const, start);
586            visit_opt!(visitor, visit_anon_const, end);
587        }
588        TyPatKind::Err(_) => {}
589    }
590    V::Result::output()
591}
592
593fn walk_qself<'a, V: Visitor<'a>>(visitor: &mut V, qself: &'a Option<P<QSelf>>) -> V::Result {
594    if let Some(qself) = qself {
595        let QSelf { ty, path_span: _, position: _ } = &**qself;
596        try_visit!(visitor.visit_ty(ty));
597    }
598    V::Result::output()
599}
600
601pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) -> V::Result {
602    let Path { span: _, segments, tokens: _ } = path;
603    walk_list!(visitor, visit_path_segment, segments);
604    V::Result::output()
605}
606
607pub fn walk_use_tree<'a, V: Visitor<'a>>(
608    visitor: &mut V,
609    use_tree: &'a UseTree,
610    id: NodeId,
611) -> V::Result {
612    let UseTree { prefix, kind, span: _ } = use_tree;
613    try_visit!(visitor.visit_path(prefix, id));
614    match kind {
615        UseTreeKind::Simple(rename) => {
616            // The extra IDs are handled during AST lowering.
617            visit_opt!(visitor, visit_ident, rename);
618        }
619        UseTreeKind::Glob => {}
620        UseTreeKind::Nested { items, span: _ } => {
621            for &(ref nested_tree, nested_id) in items {
622                try_visit!(visitor.visit_use_tree(nested_tree, nested_id, true));
623            }
624        }
625    }
626    V::Result::output()
627}
628
629pub fn walk_path_segment<'a, V: Visitor<'a>>(
630    visitor: &mut V,
631    segment: &'a PathSegment,
632) -> V::Result {
633    let PathSegment { ident, id: _, args } = segment;
634    try_visit!(visitor.visit_ident(ident));
635    visit_opt!(visitor, visit_generic_args, args);
636    V::Result::output()
637}
638
639pub fn walk_generic_args<'a, V>(visitor: &mut V, generic_args: &'a GenericArgs) -> V::Result
640where
641    V: Visitor<'a>,
642{
643    match generic_args {
644        GenericArgs::AngleBracketed(AngleBracketedArgs { span: _, args }) => {
645            for arg in args {
646                match arg {
647                    AngleBracketedArg::Arg(a) => try_visit!(visitor.visit_generic_arg(a)),
648                    AngleBracketedArg::Constraint(c) => {
649                        try_visit!(visitor.visit_assoc_item_constraint(c))
650                    }
651                }
652            }
653        }
654        GenericArgs::Parenthesized(data) => {
655            let ParenthesizedArgs { span: _, inputs, inputs_span: _, output } = data;
656            walk_list!(visitor, visit_ty, inputs);
657            try_visit!(visitor.visit_fn_ret_ty(output));
658        }
659        GenericArgs::ParenthesizedElided(_span) => {}
660    }
661    V::Result::output()
662}
663
664pub fn walk_generic_arg<'a, V>(visitor: &mut V, generic_arg: &'a GenericArg) -> V::Result
665where
666    V: Visitor<'a>,
667{
668    match generic_arg {
669        GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg),
670        GenericArg::Type(ty) => visitor.visit_ty(ty),
671        GenericArg::Const(ct) => visitor.visit_anon_const(ct),
672    }
673}
674
675pub fn walk_assoc_item_constraint<'a, V: Visitor<'a>>(
676    visitor: &mut V,
677    constraint: &'a AssocItemConstraint,
678) -> V::Result {
679    let AssocItemConstraint { id: _, ident, gen_args, kind, span: _ } = constraint;
680    try_visit!(visitor.visit_ident(ident));
681    visit_opt!(visitor, visit_generic_args, gen_args);
682    match kind {
683        AssocItemConstraintKind::Equality { term } => match term {
684            Term::Ty(ty) => try_visit!(visitor.visit_ty(ty)),
685            Term::Const(c) => try_visit!(visitor.visit_anon_const(c)),
686        },
687        AssocItemConstraintKind::Bound { bounds } => {
688            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
689        }
690    }
691    V::Result::output()
692}
693
694pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Result {
695    let Pat { id, kind, span: _, tokens: _ } = pattern;
696    match kind {
697        PatKind::TupleStruct(opt_qself, path, elems) => {
698            try_visit!(visitor.visit_qself(opt_qself));
699            try_visit!(visitor.visit_path(path, *id));
700            walk_list!(visitor, visit_pat, elems);
701        }
702        PatKind::Path(opt_qself, path) => {
703            try_visit!(visitor.visit_qself(opt_qself));
704            try_visit!(visitor.visit_path(path, *id))
705        }
706        PatKind::Struct(opt_qself, path, fields, _rest) => {
707            try_visit!(visitor.visit_qself(opt_qself));
708            try_visit!(visitor.visit_path(path, *id));
709            walk_list!(visitor, visit_pat_field, fields);
710        }
711        PatKind::Box(subpattern) | PatKind::Deref(subpattern) | PatKind::Paren(subpattern) => {
712            try_visit!(visitor.visit_pat(subpattern));
713        }
714        PatKind::Ref(subpattern, _ /*mutbl*/) => {
715            try_visit!(visitor.visit_pat(subpattern));
716        }
717        PatKind::Ident(_bmode, ident, optional_subpattern) => {
718            try_visit!(visitor.visit_ident(ident));
719            visit_opt!(visitor, visit_pat, optional_subpattern);
720        }
721        PatKind::Expr(expression) => try_visit!(visitor.visit_expr(expression)),
722        PatKind::Range(lower_bound, upper_bound, _end) => {
723            visit_opt!(visitor, visit_expr, lower_bound);
724            visit_opt!(visitor, visit_expr, upper_bound);
725        }
726        PatKind::Guard(subpattern, guard_condition) => {
727            try_visit!(visitor.visit_pat(subpattern));
728            try_visit!(visitor.visit_expr(guard_condition));
729        }
730        PatKind::Wild | PatKind::Rest | PatKind::Never => {}
731        PatKind::Err(_guar) => {}
732        PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
733            walk_list!(visitor, visit_pat, elems);
734        }
735        PatKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
736    }
737    V::Result::output()
738}
739
740impl WalkItemKind for ForeignItemKind {
741    type Ctxt = ();
742    fn walk<'a, V: Visitor<'a>>(
743        &'a self,
744        span: Span,
745        id: NodeId,
746        ident: &'a Ident,
747        vis: &'a Visibility,
748        _ctxt: Self::Ctxt,
749        visitor: &mut V,
750    ) -> V::Result {
751        match self {
752            ForeignItemKind::Static(box StaticItem {
753                ty,
754                mutability: _,
755                expr,
756                safety: _,
757                define_opaque,
758            }) => {
759                try_visit!(visitor.visit_ty(ty));
760                visit_opt!(visitor, visit_expr, expr);
761                try_visit!(walk_define_opaques(visitor, define_opaque));
762            }
763            ForeignItemKind::Fn(func) => {
764                let kind = FnKind::Fn(FnCtxt::Foreign, ident, vis, &*func);
765                try_visit!(visitor.visit_fn(kind, span, id));
766            }
767            ForeignItemKind::TyAlias(box TyAlias {
768                generics,
769                bounds,
770                ty,
771                defaultness: _,
772                where_clauses: _,
773            }) => {
774                try_visit!(visitor.visit_generics(generics));
775                walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
776                visit_opt!(visitor, visit_ty, ty);
777            }
778            ForeignItemKind::MacCall(mac) => {
779                try_visit!(visitor.visit_mac_call(mac));
780            }
781        }
782        V::Result::output()
783    }
784}
785
786pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) -> V::Result {
787    match bound {
788        GenericBound::Trait(trait_ref) => visitor.visit_poly_trait_ref(trait_ref),
789        GenericBound::Outlives(lifetime) => visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound),
790        GenericBound::Use(args, _span) => {
791            walk_list!(visitor, visit_precise_capturing_arg, args);
792            V::Result::output()
793        }
794    }
795}
796
797pub fn walk_precise_capturing_arg<'a, V: Visitor<'a>>(
798    visitor: &mut V,
799    arg: &'a PreciseCapturingArg,
800) -> V::Result {
801    match arg {
802        PreciseCapturingArg::Lifetime(lt) => visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg),
803        PreciseCapturingArg::Arg(path, id) => visitor.visit_path(path, *id),
804    }
805}
806
807pub fn walk_generic_param<'a, V: Visitor<'a>>(
808    visitor: &mut V,
809    param: &'a GenericParam,
810) -> V::Result {
811    let GenericParam { id: _, ident, attrs, bounds, is_placeholder: _, kind, colon_span: _ } =
812        param;
813    walk_list!(visitor, visit_attribute, attrs);
814    try_visit!(visitor.visit_ident(ident));
815    walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
816    match kind {
817        GenericParamKind::Lifetime => (),
818        GenericParamKind::Type { default } => visit_opt!(visitor, visit_ty, default),
819        GenericParamKind::Const { ty, default, kw_span: _ } => {
820            try_visit!(visitor.visit_ty(ty));
821            visit_opt!(visitor, visit_anon_const, default);
822        }
823    }
824    V::Result::output()
825}
826
827pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) -> V::Result {
828    let Generics { params, where_clause, span: _ } = generics;
829    let WhereClause { has_where_token: _, predicates, span: _ } = where_clause;
830    walk_list!(visitor, visit_generic_param, params);
831    walk_list!(visitor, visit_where_predicate, predicates);
832    V::Result::output()
833}
834
835pub fn walk_closure_binder<'a, V: Visitor<'a>>(
836    visitor: &mut V,
837    binder: &'a ClosureBinder,
838) -> V::Result {
839    match binder {
840        ClosureBinder::NotPresent => {}
841        ClosureBinder::For { generic_params, span: _ } => {
842            walk_list!(visitor, visit_generic_param, generic_params)
843        }
844    }
845    V::Result::output()
846}
847
848pub fn walk_contract<'a, V: Visitor<'a>>(visitor: &mut V, c: &'a FnContract) -> V::Result {
849    let FnContract { requires, ensures } = c;
850    if let Some(pred) = requires {
851        visitor.visit_expr(pred);
852    }
853    if let Some(pred) = ensures {
854        visitor.visit_expr(pred);
855    }
856    V::Result::output()
857}
858
859pub fn walk_where_predicate<'a, V: Visitor<'a>>(
860    visitor: &mut V,
861    predicate: &'a WherePredicate,
862) -> V::Result {
863    let WherePredicate { attrs, kind, id: _, span: _, is_placeholder: _ } = predicate;
864    walk_list!(visitor, visit_attribute, attrs);
865    visitor.visit_where_predicate_kind(kind)
866}
867
868pub fn walk_where_predicate_kind<'a, V: Visitor<'a>>(
869    visitor: &mut V,
870    kind: &'a WherePredicateKind,
871) -> V::Result {
872    match kind {
873        WherePredicateKind::BoundPredicate(WhereBoundPredicate {
874            bounded_ty,
875            bounds,
876            bound_generic_params,
877        }) => {
878            walk_list!(visitor, visit_generic_param, bound_generic_params);
879            try_visit!(visitor.visit_ty(bounded_ty));
880            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
881        }
882        WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => {
883            try_visit!(visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound));
884            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
885        }
886        WherePredicateKind::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty }) => {
887            try_visit!(visitor.visit_ty(lhs_ty));
888            try_visit!(visitor.visit_ty(rhs_ty));
889        }
890    }
891    V::Result::output()
892}
893
894pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy) -> V::Result {
895    match ret_ty {
896        FnRetTy::Default(_span) => {}
897        FnRetTy::Ty(output_ty) => try_visit!(visitor.visit_ty(output_ty)),
898    }
899    V::Result::output()
900}
901
902pub fn walk_fn_header<'a, V: Visitor<'a>>(visitor: &mut V, fn_header: &'a FnHeader) -> V::Result {
903    let FnHeader { safety: _, coroutine_kind, constness: _, ext: _ } = fn_header;
904    visit_opt!(visitor, visit_coroutine_kind, coroutine_kind.as_ref());
905    V::Result::output()
906}
907
908pub fn walk_fn_decl<'a, V: Visitor<'a>>(
909    visitor: &mut V,
910    FnDecl { inputs, output }: &'a FnDecl,
911) -> V::Result {
912    walk_list!(visitor, visit_param, inputs);
913    visitor.visit_fn_ret_ty(output)
914}
915
916pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Result {
917    match kind {
918        FnKind::Fn(
919            _ctxt,
920            _ident,
921            _vis,
922            Fn {
923                defaultness: _,
924                sig: FnSig { header, decl, span: _ },
925                generics,
926                contract,
927                body,
928                define_opaque,
929            },
930        ) => {
931            // Identifier and visibility are visited as a part of the item.
932            try_visit!(visitor.visit_fn_header(header));
933            try_visit!(visitor.visit_generics(generics));
934            try_visit!(visitor.visit_fn_decl(decl));
935            visit_opt!(visitor, visit_contract, contract);
936            visit_opt!(visitor, visit_block, body);
937            try_visit!(walk_define_opaques(visitor, define_opaque));
938        }
939        FnKind::Closure(binder, coroutine_kind, decl, body) => {
940            try_visit!(visitor.visit_closure_binder(binder));
941            visit_opt!(visitor, visit_coroutine_kind, coroutine_kind.as_ref());
942            try_visit!(visitor.visit_fn_decl(decl));
943            try_visit!(visitor.visit_expr(body));
944        }
945    }
946    V::Result::output()
947}
948
949impl WalkItemKind for AssocItemKind {
950    type Ctxt = AssocCtxt;
951    fn walk<'a, V: Visitor<'a>>(
952        &'a self,
953        span: Span,
954        id: NodeId,
955        ident: &'a Ident,
956        vis: &'a Visibility,
957        ctxt: Self::Ctxt,
958        visitor: &mut V,
959    ) -> V::Result {
960        match self {
961            AssocItemKind::Const(box ConstItem {
962                defaultness: _,
963                generics,
964                ty,
965                expr,
966                define_opaque,
967            }) => {
968                try_visit!(visitor.visit_generics(generics));
969                try_visit!(visitor.visit_ty(ty));
970                visit_opt!(visitor, visit_expr, expr);
971                try_visit!(walk_define_opaques(visitor, define_opaque));
972            }
973            AssocItemKind::Fn(func) => {
974                let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, vis, &*func);
975                try_visit!(visitor.visit_fn(kind, span, id));
976            }
977            AssocItemKind::Type(box TyAlias {
978                generics,
979                bounds,
980                ty,
981                defaultness: _,
982                where_clauses: _,
983            }) => {
984                try_visit!(visitor.visit_generics(generics));
985                walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
986                visit_opt!(visitor, visit_ty, ty);
987            }
988            AssocItemKind::MacCall(mac) => {
989                try_visit!(visitor.visit_mac_call(mac));
990            }
991            AssocItemKind::Delegation(box Delegation {
992                id,
993                qself,
994                path,
995                rename,
996                body,
997                from_glob: _,
998            }) => {
999                try_visit!(visitor.visit_qself(qself));
1000                try_visit!(visitor.visit_path(path, *id));
1001                visit_opt!(visitor, visit_ident, rename);
1002                visit_opt!(visitor, visit_block, body);
1003            }
1004            AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
1005                try_visit!(visitor.visit_qself(qself));
1006                try_visit!(visitor.visit_path(prefix, id));
1007                if let Some(suffixes) = suffixes {
1008                    for (ident, rename) in suffixes {
1009                        visitor.visit_ident(ident);
1010                        if let Some(rename) = rename {
1011                            visitor.visit_ident(rename);
1012                        }
1013                    }
1014                }
1015                visit_opt!(visitor, visit_block, body);
1016            }
1017        }
1018        V::Result::output()
1019    }
1020}
1021
1022pub fn walk_item<'a, V: Visitor<'a>>(
1023    visitor: &mut V,
1024    item: &'a Item<impl WalkItemKind<Ctxt = ()>>,
1025) -> V::Result {
1026    walk_item_ctxt(visitor, item, ())
1027}
1028
1029pub fn walk_assoc_item<'a, V: Visitor<'a>>(
1030    visitor: &mut V,
1031    item: &'a AssocItem,
1032    ctxt: AssocCtxt,
1033) -> V::Result {
1034    walk_item_ctxt(visitor, item, ctxt)
1035}
1036
1037fn walk_item_ctxt<'a, V: Visitor<'a>, K: WalkItemKind>(
1038    visitor: &mut V,
1039    item: &'a Item<K>,
1040    ctxt: K::Ctxt,
1041) -> V::Result {
1042    let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item;
1043    walk_list!(visitor, visit_attribute, attrs);
1044    try_visit!(visitor.visit_vis(vis));
1045    try_visit!(visitor.visit_ident(ident));
1046    try_visit!(kind.walk(*span, *id, ident, vis, ctxt, visitor));
1047    V::Result::output()
1048}
1049
1050pub fn walk_struct_def<'a, V: Visitor<'a>>(
1051    visitor: &mut V,
1052    struct_definition: &'a VariantData,
1053) -> V::Result {
1054    walk_list!(visitor, visit_field_def, struct_definition.fields());
1055    V::Result::output()
1056}
1057
1058pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) -> V::Result {
1059    let FieldDef { attrs, id: _, span: _, vis, ident, ty, is_placeholder: _, safety: _, default } =
1060        field;
1061    walk_list!(visitor, visit_attribute, attrs);
1062    try_visit!(visitor.visit_vis(vis));
1063    visit_opt!(visitor, visit_ident, ident);
1064    try_visit!(visitor.visit_ty(ty));
1065    visit_opt!(visitor, visit_anon_const, &*default);
1066    V::Result::output()
1067}
1068
1069pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) -> V::Result {
1070    let Block { stmts, id: _, rules: _, span: _, tokens: _ } = block;
1071    walk_list!(visitor, visit_stmt, stmts);
1072    V::Result::output()
1073}
1074
1075pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result {
1076    let Stmt { id: _, kind, span: _ } = statement;
1077    match kind {
1078        StmtKind::Let(local) => try_visit!(visitor.visit_local(local)),
1079        StmtKind::Item(item) => try_visit!(visitor.visit_item(item)),
1080        StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)),
1081        StmtKind::Empty => {}
1082        StmtKind::MacCall(mac) => {
1083            let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac;
1084            walk_list!(visitor, visit_attribute, attrs);
1085            try_visit!(visitor.visit_mac_call(mac));
1086        }
1087    }
1088    V::Result::output()
1089}
1090
1091pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) -> V::Result {
1092    let MacCall { path, args: _ } = mac;
1093    visitor.visit_path(path, DUMMY_NODE_ID)
1094}
1095
1096pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) -> V::Result {
1097    let AnonConst { id: _, value } = constant;
1098    visitor.visit_expr(value)
1099}
1100
1101pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) -> V::Result {
1102    let InlineAsm {
1103        asm_macro: _,
1104        template: _,
1105        template_strs: _,
1106        operands,
1107        clobber_abis: _,
1108        options: _,
1109        line_spans: _,
1110    } = asm;
1111    for (op, _span) in operands {
1112        match op {
1113            InlineAsmOperand::In { expr, reg: _ }
1114            | InlineAsmOperand::Out { expr: Some(expr), reg: _, late: _ }
1115            | InlineAsmOperand::InOut { expr, reg: _, late: _ } => {
1116                try_visit!(visitor.visit_expr(expr))
1117            }
1118            InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {}
1119            InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
1120                try_visit!(visitor.visit_expr(in_expr));
1121                visit_opt!(visitor, visit_expr, out_expr);
1122            }
1123            InlineAsmOperand::Const { anon_const } => {
1124                try_visit!(visitor.visit_anon_const(anon_const))
1125            }
1126            InlineAsmOperand::Sym { sym } => try_visit!(visitor.visit_inline_asm_sym(sym)),
1127            InlineAsmOperand::Label { block } => try_visit!(visitor.visit_block(block)),
1128        }
1129    }
1130    V::Result::output()
1131}
1132
1133pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(
1134    visitor: &mut V,
1135    InlineAsmSym { id, qself, path }: &'a InlineAsmSym,
1136) -> V::Result {
1137    try_visit!(visitor.visit_qself(qself));
1138    visitor.visit_path(path, *id)
1139}
1140
1141pub fn walk_format_args<'a, V: Visitor<'a>>(visitor: &mut V, fmt: &'a FormatArgs) -> V::Result {
1142    let FormatArgs { span: _, template: _, arguments, uncooked_fmt_str: _ } = fmt;
1143    for FormatArgument { kind, expr } in arguments.all_args() {
1144        match kind {
1145            FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => {
1146                try_visit!(visitor.visit_ident(ident))
1147            }
1148            FormatArgumentKind::Normal => {}
1149        }
1150        try_visit!(visitor.visit_expr(expr));
1151    }
1152    V::Result::output()
1153}
1154
1155pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V::Result {
1156    let Expr { id, kind, span, attrs, tokens: _ } = expression;
1157    walk_list!(visitor, visit_attribute, attrs);
1158    match kind {
1159        ExprKind::Array(subexpressions) => {
1160            walk_list!(visitor, visit_expr, subexpressions);
1161        }
1162        ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_anon_const(anon_const)),
1163        ExprKind::Repeat(element, count) => {
1164            try_visit!(visitor.visit_expr(element));
1165            try_visit!(visitor.visit_anon_const(count));
1166        }
1167        ExprKind::Struct(se) => {
1168            let StructExpr { qself, path, fields, rest } = &**se;
1169            try_visit!(visitor.visit_qself(qself));
1170            try_visit!(visitor.visit_path(path, *id));
1171            walk_list!(visitor, visit_expr_field, fields);
1172            match rest {
1173                StructRest::Base(expr) => try_visit!(visitor.visit_expr(expr)),
1174                StructRest::Rest(_span) => {}
1175                StructRest::None => {}
1176            }
1177        }
1178        ExprKind::Tup(subexpressions) => {
1179            walk_list!(visitor, visit_expr, subexpressions);
1180        }
1181        ExprKind::Call(callee_expression, arguments) => {
1182            try_visit!(visitor.visit_expr(callee_expression));
1183            walk_list!(visitor, visit_expr, arguments);
1184        }
1185        ExprKind::MethodCall(box MethodCall { seg, receiver, args, span: _ }) => {
1186            try_visit!(visitor.visit_expr(receiver));
1187            try_visit!(visitor.visit_path_segment(seg));
1188            walk_list!(visitor, visit_expr, args);
1189        }
1190        ExprKind::Binary(_op, left_expression, right_expression) => {
1191            try_visit!(visitor.visit_expr(left_expression));
1192            try_visit!(visitor.visit_expr(right_expression));
1193        }
1194        ExprKind::AddrOf(_kind, _mutbl, subexpression) => {
1195            try_visit!(visitor.visit_expr(subexpression));
1196        }
1197        ExprKind::Unary(_op, subexpression) => {
1198            try_visit!(visitor.visit_expr(subexpression));
1199        }
1200        ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) => {
1201            try_visit!(visitor.visit_expr(subexpression));
1202            try_visit!(visitor.visit_ty(typ));
1203        }
1204        ExprKind::Let(pat, expr, _span, _recovered) => {
1205            try_visit!(visitor.visit_pat(pat));
1206            try_visit!(visitor.visit_expr(expr));
1207        }
1208        ExprKind::If(head_expression, if_block, optional_else) => {
1209            try_visit!(visitor.visit_expr(head_expression));
1210            try_visit!(visitor.visit_block(if_block));
1211            visit_opt!(visitor, visit_expr, optional_else);
1212        }
1213        ExprKind::While(subexpression, block, opt_label) => {
1214            visit_opt!(visitor, visit_label, opt_label);
1215            try_visit!(visitor.visit_expr(subexpression));
1216            try_visit!(visitor.visit_block(block));
1217        }
1218        ExprKind::ForLoop { pat, iter, body, label, kind: _ } => {
1219            visit_opt!(visitor, visit_label, label);
1220            try_visit!(visitor.visit_pat(pat));
1221            try_visit!(visitor.visit_expr(iter));
1222            try_visit!(visitor.visit_block(body));
1223        }
1224        ExprKind::Loop(block, opt_label, _span) => {
1225            visit_opt!(visitor, visit_label, opt_label);
1226            try_visit!(visitor.visit_block(block));
1227        }
1228        ExprKind::Match(subexpression, arms, _kind) => {
1229            try_visit!(visitor.visit_expr(subexpression));
1230            walk_list!(visitor, visit_arm, arms);
1231        }
1232        ExprKind::Closure(box Closure {
1233            binder,
1234            capture_clause,
1235            coroutine_kind,
1236            constness: _,
1237            movability: _,
1238            fn_decl,
1239            body,
1240            fn_decl_span: _,
1241            fn_arg_span: _,
1242        }) => {
1243            try_visit!(visitor.visit_capture_by(capture_clause));
1244            try_visit!(visitor.visit_fn(
1245                FnKind::Closure(binder, coroutine_kind, fn_decl, body),
1246                *span,
1247                *id
1248            ));
1249        }
1250        ExprKind::Block(block, opt_label) => {
1251            visit_opt!(visitor, visit_label, opt_label);
1252            try_visit!(visitor.visit_block(block));
1253        }
1254        ExprKind::Gen(_capt, body, _kind, _decl_span) => try_visit!(visitor.visit_block(body)),
1255        ExprKind::Await(expr, _span) => try_visit!(visitor.visit_expr(expr)),
1256        ExprKind::Use(expr, _span) => try_visit!(visitor.visit_expr(expr)),
1257        ExprKind::Assign(lhs, rhs, _span) => {
1258            try_visit!(visitor.visit_expr(lhs));
1259            try_visit!(visitor.visit_expr(rhs));
1260        }
1261        ExprKind::AssignOp(_op, left_expression, right_expression) => {
1262            try_visit!(visitor.visit_expr(left_expression));
1263            try_visit!(visitor.visit_expr(right_expression));
1264        }
1265        ExprKind::Field(subexpression, ident) => {
1266            try_visit!(visitor.visit_expr(subexpression));
1267            try_visit!(visitor.visit_ident(ident));
1268        }
1269        ExprKind::Index(main_expression, index_expression, _span) => {
1270            try_visit!(visitor.visit_expr(main_expression));
1271            try_visit!(visitor.visit_expr(index_expression));
1272        }
1273        ExprKind::Range(start, end, _limit) => {
1274            visit_opt!(visitor, visit_expr, start);
1275            visit_opt!(visitor, visit_expr, end);
1276        }
1277        ExprKind::Underscore => {}
1278        ExprKind::Path(maybe_qself, path) => {
1279            try_visit!(visitor.visit_qself(maybe_qself));
1280            try_visit!(visitor.visit_path(path, *id));
1281        }
1282        ExprKind::Break(opt_label, opt_expr) => {
1283            visit_opt!(visitor, visit_label, opt_label);
1284            visit_opt!(visitor, visit_expr, opt_expr);
1285        }
1286        ExprKind::Continue(opt_label) => {
1287            visit_opt!(visitor, visit_label, opt_label);
1288        }
1289        ExprKind::Ret(optional_expression) => {
1290            visit_opt!(visitor, visit_expr, optional_expression);
1291        }
1292        ExprKind::Yeet(optional_expression) => {
1293            visit_opt!(visitor, visit_expr, optional_expression);
1294        }
1295        ExprKind::Become(expr) => try_visit!(visitor.visit_expr(expr)),
1296        ExprKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
1297        ExprKind::Paren(subexpression) => try_visit!(visitor.visit_expr(subexpression)),
1298        ExprKind::InlineAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)),
1299        ExprKind::FormatArgs(f) => try_visit!(visitor.visit_format_args(f)),
1300        ExprKind::OffsetOf(container, fields) => {
1301            try_visit!(visitor.visit_ty(container));
1302            walk_list!(visitor, visit_ident, fields.iter());
1303        }
1304        ExprKind::Yield(kind) => {
1305            visit_opt!(visitor, visit_expr, kind.expr());
1306        }
1307        ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)),
1308        ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)),
1309        ExprKind::Lit(_token) => {}
1310        ExprKind::IncludedBytes(_bytes) => {}
1311        ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
1312            try_visit!(visitor.visit_expr(expr));
1313            visit_opt!(visitor, visit_ty, ty);
1314        }
1315        ExprKind::Err(_guar) => {}
1316        ExprKind::Dummy => {}
1317    }
1318
1319    V::Result::output()
1320}
1321
1322pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) -> V::Result {
1323    let Param { attrs, ty, pat, id: _, span: _, is_placeholder: _ } = param;
1324    walk_list!(visitor, visit_attribute, attrs);
1325    try_visit!(visitor.visit_pat(pat));
1326    try_visit!(visitor.visit_ty(ty));
1327    V::Result::output()
1328}
1329
1330pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) -> V::Result {
1331    let Arm { attrs, pat, guard, body, span: _, id: _, is_placeholder: _ } = arm;
1332    walk_list!(visitor, visit_attribute, attrs);
1333    try_visit!(visitor.visit_pat(pat));
1334    visit_opt!(visitor, visit_expr, guard);
1335    visit_opt!(visitor, visit_expr, body);
1336    V::Result::output()
1337}
1338
1339pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) -> V::Result {
1340    let Visibility { kind, span: _, tokens: _ } = vis;
1341    match kind {
1342        VisibilityKind::Restricted { path, id, shorthand: _ } => {
1343            try_visit!(visitor.visit_path(path, *id));
1344        }
1345        VisibilityKind::Public | VisibilityKind::Inherited => {}
1346    }
1347    V::Result::output()
1348}
1349
1350pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) -> V::Result {
1351    let Attribute { kind, id: _, style: _, span: _ } = attr;
1352    match kind {
1353        AttrKind::Normal(normal) => {
1354            let NormalAttr { item, tokens: _ } = &**normal;
1355            let AttrItem { unsafety: _, path, args, tokens: _ } = item;
1356            try_visit!(visitor.visit_path(path, DUMMY_NODE_ID));
1357            try_visit!(walk_attr_args(visitor, args));
1358        }
1359        AttrKind::DocComment(_kind, _sym) => {}
1360    }
1361    V::Result::output()
1362}
1363
1364pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) -> V::Result {
1365    match args {
1366        AttrArgs::Empty => {}
1367        AttrArgs::Delimited(_args) => {}
1368        AttrArgs::Eq { expr, .. } => try_visit!(visitor.visit_expr(expr)),
1369    }
1370    V::Result::output()
1371}
1372
1373fn walk_define_opaques<'a, V: Visitor<'a>>(
1374    visitor: &mut V,
1375    define_opaque: &'a Option<ThinVec<(NodeId, Path)>>,
1376) -> V::Result {
1377    if let Some(define_opaque) = define_opaque {
1378        for (id, path) in define_opaque {
1379            try_visit!(visitor.visit_path(path, *id));
1380        }
1381    }
1382    V::Result::output()
1383}