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