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::Or(variants) => walk_list!(visitor, visit_ty_pat, variants),
612        TyPatKind::Err(_) => {}
613    }
614    V::Result::output()
615}
616
617fn walk_qself<'a, V: Visitor<'a>>(visitor: &mut V, qself: &'a Option<P<QSelf>>) -> V::Result {
618    if let Some(qself) = qself {
619        let QSelf { ty, path_span: _, position: _ } = &**qself;
620        try_visit!(visitor.visit_ty(ty));
621    }
622    V::Result::output()
623}
624
625pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) -> V::Result {
626    let Path { span: _, segments, tokens: _ } = path;
627    walk_list!(visitor, visit_path_segment, segments);
628    V::Result::output()
629}
630
631pub fn walk_use_tree<'a, V: Visitor<'a>>(
632    visitor: &mut V,
633    use_tree: &'a UseTree,
634    id: NodeId,
635) -> V::Result {
636    let UseTree { prefix, kind, span: _ } = use_tree;
637    try_visit!(visitor.visit_path(prefix, id));
638    match kind {
639        UseTreeKind::Simple(rename) => {
640            // The extra IDs are handled during AST lowering.
641            visit_opt!(visitor, visit_ident, rename);
642        }
643        UseTreeKind::Glob => {}
644        UseTreeKind::Nested { items, span: _ } => {
645            for &(ref nested_tree, nested_id) in items {
646                try_visit!(visitor.visit_use_tree(nested_tree, nested_id, true));
647            }
648        }
649    }
650    V::Result::output()
651}
652
653pub fn walk_path_segment<'a, V: Visitor<'a>>(
654    visitor: &mut V,
655    segment: &'a PathSegment,
656) -> V::Result {
657    let PathSegment { ident, id: _, args } = segment;
658    try_visit!(visitor.visit_ident(ident));
659    visit_opt!(visitor, visit_generic_args, args);
660    V::Result::output()
661}
662
663pub fn walk_generic_args<'a, V>(visitor: &mut V, generic_args: &'a GenericArgs) -> V::Result
664where
665    V: Visitor<'a>,
666{
667    match generic_args {
668        GenericArgs::AngleBracketed(AngleBracketedArgs { span: _, args }) => {
669            for arg in args {
670                match arg {
671                    AngleBracketedArg::Arg(a) => try_visit!(visitor.visit_generic_arg(a)),
672                    AngleBracketedArg::Constraint(c) => {
673                        try_visit!(visitor.visit_assoc_item_constraint(c))
674                    }
675                }
676            }
677        }
678        GenericArgs::Parenthesized(data) => {
679            let ParenthesizedArgs { span: _, inputs, inputs_span: _, output } = data;
680            walk_list!(visitor, visit_ty, inputs);
681            try_visit!(visitor.visit_fn_ret_ty(output));
682        }
683        GenericArgs::ParenthesizedElided(_span) => {}
684    }
685    V::Result::output()
686}
687
688pub fn walk_generic_arg<'a, V>(visitor: &mut V, generic_arg: &'a GenericArg) -> V::Result
689where
690    V: Visitor<'a>,
691{
692    match generic_arg {
693        GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg),
694        GenericArg::Type(ty) => visitor.visit_ty(ty),
695        GenericArg::Const(ct) => visitor.visit_anon_const(ct),
696    }
697}
698
699pub fn walk_assoc_item_constraint<'a, V: Visitor<'a>>(
700    visitor: &mut V,
701    constraint: &'a AssocItemConstraint,
702) -> V::Result {
703    let AssocItemConstraint { id: _, ident, gen_args, kind, span: _ } = constraint;
704    try_visit!(visitor.visit_ident(ident));
705    visit_opt!(visitor, visit_generic_args, gen_args);
706    match kind {
707        AssocItemConstraintKind::Equality { term } => match term {
708            Term::Ty(ty) => try_visit!(visitor.visit_ty(ty)),
709            Term::Const(c) => try_visit!(visitor.visit_anon_const(c)),
710        },
711        AssocItemConstraintKind::Bound { bounds } => {
712            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
713        }
714    }
715    V::Result::output()
716}
717
718pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Result {
719    let Pat { id, kind, span: _, tokens: _ } = pattern;
720    match kind {
721        PatKind::TupleStruct(opt_qself, path, elems) => {
722            try_visit!(visitor.visit_qself(opt_qself));
723            try_visit!(visitor.visit_path(path, *id));
724            walk_list!(visitor, visit_pat, elems);
725        }
726        PatKind::Path(opt_qself, path) => {
727            try_visit!(visitor.visit_qself(opt_qself));
728            try_visit!(visitor.visit_path(path, *id))
729        }
730        PatKind::Struct(opt_qself, path, fields, _rest) => {
731            try_visit!(visitor.visit_qself(opt_qself));
732            try_visit!(visitor.visit_path(path, *id));
733            walk_list!(visitor, visit_pat_field, fields);
734        }
735        PatKind::Box(subpattern) | PatKind::Deref(subpattern) | PatKind::Paren(subpattern) => {
736            try_visit!(visitor.visit_pat(subpattern));
737        }
738        PatKind::Ref(subpattern, _ /*mutbl*/) => {
739            try_visit!(visitor.visit_pat(subpattern));
740        }
741        PatKind::Ident(_bmode, ident, optional_subpattern) => {
742            try_visit!(visitor.visit_ident(ident));
743            visit_opt!(visitor, visit_pat, optional_subpattern);
744        }
745        PatKind::Expr(expression) => try_visit!(visitor.visit_expr(expression)),
746        PatKind::Range(lower_bound, upper_bound, _end) => {
747            visit_opt!(visitor, visit_expr, lower_bound);
748            visit_opt!(visitor, visit_expr, upper_bound);
749        }
750        PatKind::Guard(subpattern, guard_condition) => {
751            try_visit!(visitor.visit_pat(subpattern));
752            try_visit!(visitor.visit_expr(guard_condition));
753        }
754        PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {}
755        PatKind::Err(_guar) => {}
756        PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
757            walk_list!(visitor, visit_pat, elems);
758        }
759        PatKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
760    }
761    V::Result::output()
762}
763
764impl WalkItemKind for ForeignItemKind {
765    type Ctxt = ();
766    fn walk<'a, V: Visitor<'a>>(
767        &'a self,
768        span: Span,
769        id: NodeId,
770        vis: &'a Visibility,
771        _ctxt: Self::Ctxt,
772        visitor: &mut V,
773    ) -> V::Result {
774        match self {
775            ForeignItemKind::Static(box StaticItem {
776                ident,
777                ty,
778                mutability: _,
779                expr,
780                safety: _,
781                define_opaque,
782            }) => {
783                try_visit!(visitor.visit_ident(ident));
784                try_visit!(visitor.visit_ty(ty));
785                visit_opt!(visitor, visit_expr, expr);
786                try_visit!(walk_define_opaques(visitor, define_opaque));
787            }
788            ForeignItemKind::Fn(func) => {
789                let kind = FnKind::Fn(FnCtxt::Foreign, vis, &*func);
790                try_visit!(visitor.visit_fn(kind, span, id));
791            }
792            ForeignItemKind::TyAlias(box TyAlias {
793                generics,
794                ident,
795                bounds,
796                ty,
797                defaultness: _,
798                where_clauses: _,
799            }) => {
800                try_visit!(visitor.visit_ident(ident));
801                try_visit!(visitor.visit_generics(generics));
802                walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
803                visit_opt!(visitor, visit_ty, ty);
804            }
805            ForeignItemKind::MacCall(mac) => {
806                try_visit!(visitor.visit_mac_call(mac));
807            }
808        }
809        V::Result::output()
810    }
811}
812
813pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) -> V::Result {
814    match bound {
815        GenericBound::Trait(trait_ref) => visitor.visit_poly_trait_ref(trait_ref),
816        GenericBound::Outlives(lifetime) => visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound),
817        GenericBound::Use(args, _span) => {
818            walk_list!(visitor, visit_precise_capturing_arg, args);
819            V::Result::output()
820        }
821    }
822}
823
824pub fn walk_precise_capturing_arg<'a, V: Visitor<'a>>(
825    visitor: &mut V,
826    arg: &'a PreciseCapturingArg,
827) -> V::Result {
828    match arg {
829        PreciseCapturingArg::Lifetime(lt) => visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg),
830        PreciseCapturingArg::Arg(path, id) => visitor.visit_path(path, *id),
831    }
832}
833
834pub fn walk_generic_param<'a, V: Visitor<'a>>(
835    visitor: &mut V,
836    param: &'a GenericParam,
837) -> V::Result {
838    let GenericParam { id: _, ident, attrs, bounds, is_placeholder: _, kind, colon_span: _ } =
839        param;
840    walk_list!(visitor, visit_attribute, attrs);
841    try_visit!(visitor.visit_ident(ident));
842    walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
843    match kind {
844        GenericParamKind::Lifetime => (),
845        GenericParamKind::Type { default } => visit_opt!(visitor, visit_ty, default),
846        GenericParamKind::Const { ty, default, kw_span: _ } => {
847            try_visit!(visitor.visit_ty(ty));
848            visit_opt!(visitor, visit_anon_const, default);
849        }
850    }
851    V::Result::output()
852}
853
854pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) -> V::Result {
855    let Generics { params, where_clause, span: _ } = generics;
856    let WhereClause { has_where_token: _, predicates, span: _ } = where_clause;
857    walk_list!(visitor, visit_generic_param, params);
858    walk_list!(visitor, visit_where_predicate, predicates);
859    V::Result::output()
860}
861
862pub fn walk_closure_binder<'a, V: Visitor<'a>>(
863    visitor: &mut V,
864    binder: &'a ClosureBinder,
865) -> V::Result {
866    match binder {
867        ClosureBinder::NotPresent => {}
868        ClosureBinder::For { generic_params, span: _ } => {
869            walk_list!(visitor, visit_generic_param, generic_params)
870        }
871    }
872    V::Result::output()
873}
874
875pub fn walk_contract<'a, V: Visitor<'a>>(visitor: &mut V, c: &'a FnContract) -> V::Result {
876    let FnContract { requires, ensures } = c;
877    if let Some(pred) = requires {
878        visitor.visit_expr(pred);
879    }
880    if let Some(pred) = ensures {
881        visitor.visit_expr(pred);
882    }
883    V::Result::output()
884}
885
886pub fn walk_where_predicate<'a, V: Visitor<'a>>(
887    visitor: &mut V,
888    predicate: &'a WherePredicate,
889) -> V::Result {
890    let WherePredicate { attrs, kind, id: _, span: _, is_placeholder: _ } = predicate;
891    walk_list!(visitor, visit_attribute, attrs);
892    visitor.visit_where_predicate_kind(kind)
893}
894
895pub fn walk_where_predicate_kind<'a, V: Visitor<'a>>(
896    visitor: &mut V,
897    kind: &'a WherePredicateKind,
898) -> V::Result {
899    match kind {
900        WherePredicateKind::BoundPredicate(WhereBoundPredicate {
901            bounded_ty,
902            bounds,
903            bound_generic_params,
904        }) => {
905            walk_list!(visitor, visit_generic_param, bound_generic_params);
906            try_visit!(visitor.visit_ty(bounded_ty));
907            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
908        }
909        WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => {
910            try_visit!(visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound));
911            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
912        }
913        WherePredicateKind::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty }) => {
914            try_visit!(visitor.visit_ty(lhs_ty));
915            try_visit!(visitor.visit_ty(rhs_ty));
916        }
917    }
918    V::Result::output()
919}
920
921pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy) -> V::Result {
922    match ret_ty {
923        FnRetTy::Default(_span) => {}
924        FnRetTy::Ty(output_ty) => try_visit!(visitor.visit_ty(output_ty)),
925    }
926    V::Result::output()
927}
928
929pub fn walk_fn_header<'a, V: Visitor<'a>>(visitor: &mut V, fn_header: &'a FnHeader) -> V::Result {
930    let FnHeader { safety: _, coroutine_kind, constness: _, ext: _ } = fn_header;
931    visit_opt!(visitor, visit_coroutine_kind, coroutine_kind.as_ref());
932    V::Result::output()
933}
934
935pub fn walk_fn_decl<'a, V: Visitor<'a>>(
936    visitor: &mut V,
937    FnDecl { inputs, output }: &'a FnDecl,
938) -> V::Result {
939    walk_list!(visitor, visit_param, inputs);
940    visitor.visit_fn_ret_ty(output)
941}
942
943pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Result {
944    match kind {
945        FnKind::Fn(
946            _ctxt,
947            _vis,
948            Fn {
949                defaultness: _,
950                ident,
951                sig: FnSig { header, decl, span: _ },
952                generics,
953                contract,
954                body,
955                define_opaque,
956            },
957        ) => {
958            // Visibility is visited as a part of the item.
959            try_visit!(visitor.visit_ident(ident));
960            try_visit!(visitor.visit_fn_header(header));
961            try_visit!(visitor.visit_generics(generics));
962            try_visit!(visitor.visit_fn_decl(decl));
963            visit_opt!(visitor, visit_contract, contract);
964            visit_opt!(visitor, visit_block, body);
965            try_visit!(walk_define_opaques(visitor, define_opaque));
966        }
967        FnKind::Closure(binder, coroutine_kind, decl, body) => {
968            try_visit!(visitor.visit_closure_binder(binder));
969            visit_opt!(visitor, visit_coroutine_kind, coroutine_kind.as_ref());
970            try_visit!(visitor.visit_fn_decl(decl));
971            try_visit!(visitor.visit_expr(body));
972        }
973    }
974    V::Result::output()
975}
976
977impl WalkItemKind for AssocItemKind {
978    type Ctxt = AssocCtxt;
979    fn walk<'a, V: Visitor<'a>>(
980        &'a self,
981        span: Span,
982        id: NodeId,
983        vis: &'a Visibility,
984        ctxt: Self::Ctxt,
985        visitor: &mut V,
986    ) -> V::Result {
987        match self {
988            AssocItemKind::Const(box ConstItem {
989                defaultness: _,
990                ident,
991                generics,
992                ty,
993                expr,
994                define_opaque,
995            }) => {
996                try_visit!(visitor.visit_ident(ident));
997                try_visit!(visitor.visit_generics(generics));
998                try_visit!(visitor.visit_ty(ty));
999                visit_opt!(visitor, visit_expr, expr);
1000                try_visit!(walk_define_opaques(visitor, define_opaque));
1001            }
1002            AssocItemKind::Fn(func) => {
1003                let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), vis, &*func);
1004                try_visit!(visitor.visit_fn(kind, span, id));
1005            }
1006            AssocItemKind::Type(box TyAlias {
1007                generics,
1008                ident,
1009                bounds,
1010                ty,
1011                defaultness: _,
1012                where_clauses: _,
1013            }) => {
1014                try_visit!(visitor.visit_generics(generics));
1015                try_visit!(visitor.visit_ident(ident));
1016                walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
1017                visit_opt!(visitor, visit_ty, ty);
1018            }
1019            AssocItemKind::MacCall(mac) => {
1020                try_visit!(visitor.visit_mac_call(mac));
1021            }
1022            AssocItemKind::Delegation(box Delegation {
1023                id,
1024                qself,
1025                path,
1026                ident,
1027                rename,
1028                body,
1029                from_glob: _,
1030            }) => {
1031                try_visit!(visitor.visit_qself(qself));
1032                try_visit!(visitor.visit_path(path, *id));
1033                try_visit!(visitor.visit_ident(ident));
1034                visit_opt!(visitor, visit_ident, rename);
1035                visit_opt!(visitor, visit_block, body);
1036            }
1037            AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
1038                try_visit!(visitor.visit_qself(qself));
1039                try_visit!(visitor.visit_path(prefix, id));
1040                if let Some(suffixes) = suffixes {
1041                    for (ident, rename) in suffixes {
1042                        visitor.visit_ident(ident);
1043                        if let Some(rename) = rename {
1044                            visitor.visit_ident(rename);
1045                        }
1046                    }
1047                }
1048                visit_opt!(visitor, visit_block, body);
1049            }
1050        }
1051        V::Result::output()
1052    }
1053}
1054
1055pub fn walk_item<'a, V: Visitor<'a>>(
1056    visitor: &mut V,
1057    item: &'a Item<impl WalkItemKind<Ctxt = ()>>,
1058) -> V::Result {
1059    walk_item_ctxt(visitor, item, ())
1060}
1061
1062pub fn walk_assoc_item<'a, V: Visitor<'a>>(
1063    visitor: &mut V,
1064    item: &'a AssocItem,
1065    ctxt: AssocCtxt,
1066) -> V::Result {
1067    walk_item_ctxt(visitor, item, ctxt)
1068}
1069
1070fn walk_item_ctxt<'a, V: Visitor<'a>, K: WalkItemKind>(
1071    visitor: &mut V,
1072    item: &'a Item<K>,
1073    ctxt: K::Ctxt,
1074) -> V::Result {
1075    let Item { id, span, vis, attrs, kind, tokens: _ } = item;
1076    walk_list!(visitor, visit_attribute, attrs);
1077    try_visit!(visitor.visit_vis(vis));
1078    try_visit!(kind.walk(*span, *id, vis, ctxt, visitor));
1079    V::Result::output()
1080}
1081
1082pub fn walk_struct_def<'a, V: Visitor<'a>>(
1083    visitor: &mut V,
1084    struct_definition: &'a VariantData,
1085) -> V::Result {
1086    walk_list!(visitor, visit_field_def, struct_definition.fields());
1087    V::Result::output()
1088}
1089
1090pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) -> V::Result {
1091    let FieldDef { attrs, id: _, span: _, vis, ident, ty, is_placeholder: _, safety: _, default } =
1092        field;
1093    walk_list!(visitor, visit_attribute, attrs);
1094    try_visit!(visitor.visit_vis(vis));
1095    visit_opt!(visitor, visit_ident, ident);
1096    try_visit!(visitor.visit_ty(ty));
1097    visit_opt!(visitor, visit_anon_const, &*default);
1098    V::Result::output()
1099}
1100
1101pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) -> V::Result {
1102    let Block { stmts, id: _, rules: _, span: _, tokens: _ } = block;
1103    walk_list!(visitor, visit_stmt, stmts);
1104    V::Result::output()
1105}
1106
1107pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result {
1108    let Stmt { id: _, kind, span: _ } = statement;
1109    match kind {
1110        StmtKind::Let(local) => try_visit!(visitor.visit_local(local)),
1111        StmtKind::Item(item) => try_visit!(visitor.visit_item(item)),
1112        StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)),
1113        StmtKind::Empty => {}
1114        StmtKind::MacCall(mac) => {
1115            let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac;
1116            walk_list!(visitor, visit_attribute, attrs);
1117            try_visit!(visitor.visit_mac_call(mac));
1118        }
1119    }
1120    V::Result::output()
1121}
1122
1123pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) -> V::Result {
1124    let MacCall { path, args: _ } = mac;
1125    visitor.visit_path(path, DUMMY_NODE_ID)
1126}
1127
1128pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) -> V::Result {
1129    let AnonConst { id: _, value } = constant;
1130    visitor.visit_expr(value)
1131}
1132
1133pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) -> V::Result {
1134    let InlineAsm {
1135        asm_macro: _,
1136        template: _,
1137        template_strs: _,
1138        operands,
1139        clobber_abis: _,
1140        options: _,
1141        line_spans: _,
1142    } = asm;
1143    for (op, _span) in operands {
1144        match op {
1145            InlineAsmOperand::In { expr, reg: _ }
1146            | InlineAsmOperand::Out { expr: Some(expr), reg: _, late: _ }
1147            | InlineAsmOperand::InOut { expr, reg: _, late: _ } => {
1148                try_visit!(visitor.visit_expr(expr))
1149            }
1150            InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {}
1151            InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
1152                try_visit!(visitor.visit_expr(in_expr));
1153                visit_opt!(visitor, visit_expr, out_expr);
1154            }
1155            InlineAsmOperand::Const { anon_const } => {
1156                try_visit!(visitor.visit_anon_const(anon_const))
1157            }
1158            InlineAsmOperand::Sym { sym } => try_visit!(visitor.visit_inline_asm_sym(sym)),
1159            InlineAsmOperand::Label { block } => try_visit!(visitor.visit_block(block)),
1160        }
1161    }
1162    V::Result::output()
1163}
1164
1165pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(
1166    visitor: &mut V,
1167    InlineAsmSym { id, qself, path }: &'a InlineAsmSym,
1168) -> V::Result {
1169    try_visit!(visitor.visit_qself(qself));
1170    visitor.visit_path(path, *id)
1171}
1172
1173pub fn walk_format_args<'a, V: Visitor<'a>>(visitor: &mut V, fmt: &'a FormatArgs) -> V::Result {
1174    let FormatArgs { span: _, template: _, arguments, uncooked_fmt_str: _ } = fmt;
1175    for FormatArgument { kind, expr } in arguments.all_args() {
1176        match kind {
1177            FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => {
1178                try_visit!(visitor.visit_ident(ident))
1179            }
1180            FormatArgumentKind::Normal => {}
1181        }
1182        try_visit!(visitor.visit_expr(expr));
1183    }
1184    V::Result::output()
1185}
1186
1187pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V::Result {
1188    let Expr { id, kind, span, attrs, tokens: _ } = expression;
1189    walk_list!(visitor, visit_attribute, attrs);
1190    match kind {
1191        ExprKind::Array(subexpressions) => {
1192            walk_list!(visitor, visit_expr, subexpressions);
1193        }
1194        ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_anon_const(anon_const)),
1195        ExprKind::Repeat(element, count) => {
1196            try_visit!(visitor.visit_expr(element));
1197            try_visit!(visitor.visit_anon_const(count));
1198        }
1199        ExprKind::Struct(se) => {
1200            let StructExpr { qself, path, fields, rest } = &**se;
1201            try_visit!(visitor.visit_qself(qself));
1202            try_visit!(visitor.visit_path(path, *id));
1203            walk_list!(visitor, visit_expr_field, fields);
1204            match rest {
1205                StructRest::Base(expr) => try_visit!(visitor.visit_expr(expr)),
1206                StructRest::Rest(_span) => {}
1207                StructRest::None => {}
1208            }
1209        }
1210        ExprKind::Tup(subexpressions) => {
1211            walk_list!(visitor, visit_expr, subexpressions);
1212        }
1213        ExprKind::Call(callee_expression, arguments) => {
1214            try_visit!(visitor.visit_expr(callee_expression));
1215            walk_list!(visitor, visit_expr, arguments);
1216        }
1217        ExprKind::MethodCall(box MethodCall { seg, receiver, args, span: _ }) => {
1218            try_visit!(visitor.visit_expr(receiver));
1219            try_visit!(visitor.visit_path_segment(seg));
1220            walk_list!(visitor, visit_expr, args);
1221        }
1222        ExprKind::Binary(_op, left_expression, right_expression) => {
1223            try_visit!(visitor.visit_expr(left_expression));
1224            try_visit!(visitor.visit_expr(right_expression));
1225        }
1226        ExprKind::AddrOf(_kind, _mutbl, subexpression) => {
1227            try_visit!(visitor.visit_expr(subexpression));
1228        }
1229        ExprKind::Unary(_op, subexpression) => {
1230            try_visit!(visitor.visit_expr(subexpression));
1231        }
1232        ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) => {
1233            try_visit!(visitor.visit_expr(subexpression));
1234            try_visit!(visitor.visit_ty(typ));
1235        }
1236        ExprKind::Let(pat, expr, _span, _recovered) => {
1237            try_visit!(visitor.visit_pat(pat));
1238            try_visit!(visitor.visit_expr(expr));
1239        }
1240        ExprKind::If(head_expression, if_block, optional_else) => {
1241            try_visit!(visitor.visit_expr(head_expression));
1242            try_visit!(visitor.visit_block(if_block));
1243            visit_opt!(visitor, visit_expr, optional_else);
1244        }
1245        ExprKind::While(subexpression, block, opt_label) => {
1246            visit_opt!(visitor, visit_label, opt_label);
1247            try_visit!(visitor.visit_expr(subexpression));
1248            try_visit!(visitor.visit_block(block));
1249        }
1250        ExprKind::ForLoop { pat, iter, body, label, kind: _ } => {
1251            visit_opt!(visitor, visit_label, label);
1252            try_visit!(visitor.visit_pat(pat));
1253            try_visit!(visitor.visit_expr(iter));
1254            try_visit!(visitor.visit_block(body));
1255        }
1256        ExprKind::Loop(block, opt_label, _span) => {
1257            visit_opt!(visitor, visit_label, opt_label);
1258            try_visit!(visitor.visit_block(block));
1259        }
1260        ExprKind::Match(subexpression, arms, _kind) => {
1261            try_visit!(visitor.visit_expr(subexpression));
1262            walk_list!(visitor, visit_arm, arms);
1263        }
1264        ExprKind::Closure(box Closure {
1265            binder,
1266            capture_clause,
1267            coroutine_kind,
1268            constness: _,
1269            movability: _,
1270            fn_decl,
1271            body,
1272            fn_decl_span: _,
1273            fn_arg_span: _,
1274        }) => {
1275            try_visit!(visitor.visit_capture_by(capture_clause));
1276            try_visit!(visitor.visit_fn(
1277                FnKind::Closure(binder, coroutine_kind, fn_decl, body),
1278                *span,
1279                *id
1280            ));
1281        }
1282        ExprKind::Block(block, opt_label) => {
1283            visit_opt!(visitor, visit_label, opt_label);
1284            try_visit!(visitor.visit_block(block));
1285        }
1286        ExprKind::Gen(_capt, body, _kind, _decl_span) => try_visit!(visitor.visit_block(body)),
1287        ExprKind::Await(expr, _span) => try_visit!(visitor.visit_expr(expr)),
1288        ExprKind::Use(expr, _span) => try_visit!(visitor.visit_expr(expr)),
1289        ExprKind::Assign(lhs, rhs, _span) => {
1290            try_visit!(visitor.visit_expr(lhs));
1291            try_visit!(visitor.visit_expr(rhs));
1292        }
1293        ExprKind::AssignOp(_op, left_expression, right_expression) => {
1294            try_visit!(visitor.visit_expr(left_expression));
1295            try_visit!(visitor.visit_expr(right_expression));
1296        }
1297        ExprKind::Field(subexpression, ident) => {
1298            try_visit!(visitor.visit_expr(subexpression));
1299            try_visit!(visitor.visit_ident(ident));
1300        }
1301        ExprKind::Index(main_expression, index_expression, _span) => {
1302            try_visit!(visitor.visit_expr(main_expression));
1303            try_visit!(visitor.visit_expr(index_expression));
1304        }
1305        ExprKind::Range(start, end, _limit) => {
1306            visit_opt!(visitor, visit_expr, start);
1307            visit_opt!(visitor, visit_expr, end);
1308        }
1309        ExprKind::Underscore => {}
1310        ExprKind::Path(maybe_qself, path) => {
1311            try_visit!(visitor.visit_qself(maybe_qself));
1312            try_visit!(visitor.visit_path(path, *id));
1313        }
1314        ExprKind::Break(opt_label, opt_expr) => {
1315            visit_opt!(visitor, visit_label, opt_label);
1316            visit_opt!(visitor, visit_expr, opt_expr);
1317        }
1318        ExprKind::Continue(opt_label) => {
1319            visit_opt!(visitor, visit_label, opt_label);
1320        }
1321        ExprKind::Ret(optional_expression) => {
1322            visit_opt!(visitor, visit_expr, optional_expression);
1323        }
1324        ExprKind::Yeet(optional_expression) => {
1325            visit_opt!(visitor, visit_expr, optional_expression);
1326        }
1327        ExprKind::Become(expr) => try_visit!(visitor.visit_expr(expr)),
1328        ExprKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
1329        ExprKind::Paren(subexpression) => try_visit!(visitor.visit_expr(subexpression)),
1330        ExprKind::InlineAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)),
1331        ExprKind::FormatArgs(f) => try_visit!(visitor.visit_format_args(f)),
1332        ExprKind::OffsetOf(container, fields) => {
1333            try_visit!(visitor.visit_ty(container));
1334            walk_list!(visitor, visit_ident, fields.iter());
1335        }
1336        ExprKind::Yield(kind) => {
1337            visit_opt!(visitor, visit_expr, kind.expr());
1338        }
1339        ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)),
1340        ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)),
1341        ExprKind::Lit(_token) => {}
1342        ExprKind::IncludedBytes(_bytes) => {}
1343        ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
1344            try_visit!(visitor.visit_expr(expr));
1345            visit_opt!(visitor, visit_ty, ty);
1346        }
1347        ExprKind::Err(_guar) => {}
1348        ExprKind::Dummy => {}
1349    }
1350
1351    V::Result::output()
1352}
1353
1354pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) -> V::Result {
1355    let Param { attrs, ty, pat, id: _, span: _, is_placeholder: _ } = param;
1356    walk_list!(visitor, visit_attribute, attrs);
1357    try_visit!(visitor.visit_pat(pat));
1358    try_visit!(visitor.visit_ty(ty));
1359    V::Result::output()
1360}
1361
1362pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) -> V::Result {
1363    let Arm { attrs, pat, guard, body, span: _, id: _, is_placeholder: _ } = arm;
1364    walk_list!(visitor, visit_attribute, attrs);
1365    try_visit!(visitor.visit_pat(pat));
1366    visit_opt!(visitor, visit_expr, guard);
1367    visit_opt!(visitor, visit_expr, body);
1368    V::Result::output()
1369}
1370
1371pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) -> V::Result {
1372    let Visibility { kind, span: _, tokens: _ } = vis;
1373    match kind {
1374        VisibilityKind::Restricted { path, id, shorthand: _ } => {
1375            try_visit!(visitor.visit_path(path, *id));
1376        }
1377        VisibilityKind::Public | VisibilityKind::Inherited => {}
1378    }
1379    V::Result::output()
1380}
1381
1382pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) -> V::Result {
1383    let Attribute { kind, id: _, style: _, span: _ } = attr;
1384    match kind {
1385        AttrKind::Normal(normal) => {
1386            let NormalAttr { item, tokens: _ } = &**normal;
1387            let AttrItem { unsafety: _, path, args, tokens: _ } = item;
1388            try_visit!(visitor.visit_path(path, DUMMY_NODE_ID));
1389            try_visit!(walk_attr_args(visitor, args));
1390        }
1391        AttrKind::DocComment(_kind, _sym) => {}
1392    }
1393    V::Result::output()
1394}
1395
1396pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) -> V::Result {
1397    match args {
1398        AttrArgs::Empty => {}
1399        AttrArgs::Delimited(_args) => {}
1400        AttrArgs::Eq { expr, .. } => try_visit!(visitor.visit_expr(expr)),
1401    }
1402    V::Result::output()
1403}
1404
1405fn walk_define_opaques<'a, V: Visitor<'a>>(
1406    visitor: &mut V,
1407    define_opaque: &'a Option<ThinVec<(NodeId, Path)>>,
1408) -> V::Result {
1409    if let Some(define_opaque) = define_opaque {
1410        for (id, path) in define_opaque {
1411            try_visit!(visitor.visit_path(path, *id));
1412        }
1413    }
1414    V::Result::output()
1415}