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::source_map::Spanned;
19use rustc_span::{Ident, Span, Symbol};
20use thin_vec::ThinVec;
21
22use crate::ast::*;
23use crate::tokenstream::DelimSpan;
24
25#[derive(Copy, Clone, Debug, PartialEq)]
26pub enum AssocCtxt {
27    Trait,
28    Impl { of_trait: bool },
29}
30
31#[derive(Copy, Clone, Debug, PartialEq)]
32pub enum FnCtxt {
33    Free,
34    Foreign,
35    Assoc(AssocCtxt),
36}
37
38#[derive(Copy, Clone, Debug)]
39pub enum BoundKind {
40    /// Trait bounds in generics bounds and type/trait alias.
41    /// E.g., `<T: Bound>`, `type A: Bound`, or `where T: Bound`.
42    Bound,
43
44    /// Trait bounds in `impl` type.
45    /// E.g., `type Foo = impl Bound1 + Bound2 + Bound3`.
46    Impl,
47
48    /// Trait bounds in trait object type.
49    /// E.g., `dyn Bound1 + Bound2 + Bound3`.
50    TraitObject,
51
52    /// Super traits of a trait.
53    /// E.g., `trait A: B`
54    SuperTraits,
55}
56impl BoundKind {
57    pub fn descr(self) -> &'static str {
58        match self {
59            BoundKind::Bound => "bounds",
60            BoundKind::Impl => "`impl Trait`",
61            BoundKind::TraitObject => "`dyn` trait object bounds",
62            BoundKind::SuperTraits => "supertrait bounds",
63        }
64    }
65}
66
67#[derive(Copy, Clone, Debug)]
68pub enum LifetimeCtxt {
69    /// Appears in a reference type.
70    Ref,
71    /// Appears as a bound on a type or another lifetime.
72    Bound,
73    /// Appears as a generic argument.
74    GenericArg,
75}
76
77pub(crate) trait Visitable<'a, V: Visitor<'a>> {
78    type Extra: Copy;
79
80    #[must_use]
81    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result;
82}
83
84impl<'a, V: Visitor<'a>, T: ?Sized> Visitable<'a, V> for Box<T>
85where
86    T: Visitable<'a, V>,
87{
88    type Extra = T::Extra;
89    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
90        (**self).visit(visitor, extra)
91    }
92}
93
94impl<'a, V: Visitor<'a>, T> Visitable<'a, V> for Option<T>
95where
96    T: Visitable<'a, V>,
97{
98    type Extra = T::Extra;
99    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
100        if let Some(this) = self {
101            try_visit!(this.visit(visitor, extra));
102        }
103        V::Result::output()
104    }
105}
106
107impl<'a, V: Visitor<'a>, T> Visitable<'a, V> for Spanned<T>
108where
109    T: Visitable<'a, V>,
110{
111    type Extra = T::Extra;
112    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
113        let Spanned { span: _, node } = self;
114        node.visit(visitor, extra)
115    }
116}
117
118impl<'a, V: Visitor<'a>, T> Visitable<'a, V> for [T]
119where
120    T: Visitable<'a, V>,
121{
122    type Extra = T::Extra;
123    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
124        for item in self {
125            try_visit!(item.visit(visitor, extra));
126        }
127        V::Result::output()
128    }
129}
130
131impl<'a, V: Visitor<'a>, T> Visitable<'a, V> for Vec<T>
132where
133    T: Visitable<'a, V>,
134{
135    type Extra = T::Extra;
136    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
137        for item in self {
138            try_visit!(item.visit(visitor, extra));
139        }
140        V::Result::output()
141    }
142}
143
144impl<'a, V: Visitor<'a>, T> Visitable<'a, V> for (T,)
145where
146    T: Visitable<'a, V>,
147{
148    type Extra = T::Extra;
149    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
150        self.0.visit(visitor, extra)
151    }
152}
153
154impl<'a, V: Visitor<'a>, T1, T2> Visitable<'a, V> for (T1, T2)
155where
156    T1: Visitable<'a, V, Extra = ()>,
157    T2: Visitable<'a, V, Extra = ()>,
158{
159    type Extra = ();
160    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
161        try_visit!(self.0.visit(visitor, extra));
162        try_visit!(self.1.visit(visitor, extra));
163        V::Result::output()
164    }
165}
166
167impl<'a, V: Visitor<'a>, T1, T2, T3> Visitable<'a, V> for (T1, T2, T3)
168where
169    T1: Visitable<'a, V, Extra = ()>,
170    T2: Visitable<'a, V, Extra = ()>,
171    T3: Visitable<'a, V, Extra = ()>,
172{
173    type Extra = ();
174    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
175        try_visit!(self.0.visit(visitor, extra));
176        try_visit!(self.1.visit(visitor, extra));
177        try_visit!(self.2.visit(visitor, extra));
178        V::Result::output()
179    }
180}
181
182impl<'a, V: Visitor<'a>, T1, T2, T3, T4> Visitable<'a, V> for (T1, T2, T3, T4)
183where
184    T1: Visitable<'a, V, Extra = ()>,
185    T2: Visitable<'a, V, Extra = ()>,
186    T3: Visitable<'a, V, Extra = ()>,
187    T4: Visitable<'a, V, Extra = ()>,
188{
189    type Extra = ();
190    fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result {
191        try_visit!(self.0.visit(visitor, extra));
192        try_visit!(self.1.visit(visitor, extra));
193        try_visit!(self.2.visit(visitor, extra));
194        try_visit!(self.3.visit(visitor, extra));
195        V::Result::output()
196    }
197}
198
199pub(crate) trait Walkable<'a, V: Visitor<'a>> {
200    #[must_use]
201    fn walk_ref(&'a self, visitor: &mut V) -> V::Result;
202}
203
204macro_rules! visit_visitable {
205    ($visitor:expr, $($expr:expr),* $(,)?) => {{
206        $(try_visit!(Visitable::visit($expr, $visitor, ()));)*
207    }};
208}
209
210macro_rules! visit_visitable_with {
211    ($visitor:expr, $expr:expr, $extra:expr $(,)?) => {
212        try_visit!(Visitable::visit($expr, $visitor, $extra))
213    };
214}
215
216macro_rules! walk_walkable {
217    ($visitor:expr, $expr:expr, ) => {
218        Walkable::walk_ref($expr, $visitor)
219    };
220}
221
222macro_rules! impl_visitable {
223    (|&$lt:lifetime $self:ident: $self_ty:ty,
224      $vis:ident: &mut $vis_ty:ident,
225      $extra:ident: $extra_ty:ty| $block:block) => {
226        #[allow(unused_parens, non_local_definitions)]
227        impl<$lt, $vis_ty: Visitor<$lt>> Visitable<$lt, $vis_ty> for $self_ty {
228            type Extra = $extra_ty;
229            fn visit(&$lt $self, $vis: &mut $vis_ty, $extra: Self::Extra) -> V::Result {
230                $block
231            }
232        }
233    };
234}
235
236macro_rules! impl_walkable {
237    ($(<$K:ident: $Kb:ident>)? |&$lt:lifetime $self:ident: $self_ty:ty,
238      $vis:ident: &mut $vis_ty:ident| $block:block) => {
239        #[allow(unused_parens, non_local_definitions)]
240        impl<$($K: $Kb,)? $lt, $vis_ty: Visitor<$lt>> Walkable<$lt, $vis_ty> for $self_ty {
241            fn walk_ref(&$lt $self, $vis: &mut $vis_ty) -> V::Result {
242                $block
243            }
244        }
245    };
246}
247
248macro_rules! impl_visitable_noop {
249    (<$lt:lifetime> $($ty:ty,)*) => {
250        $(
251            impl_visitable!(|&$lt self: $ty, _vis: &mut V, _extra: ()| {
252                V::Result::output()
253            });
254        )*
255    };
256}
257
258macro_rules! impl_visitable_list {
259    (<$lt:lifetime> $($ty:ty,)*) => {
260        $(impl<$lt, V: Visitor<$lt>, T> Visitable<$lt, V> for $ty
261        where
262            &$lt $ty: IntoIterator<Item = &$lt T>,
263            T: $lt + Visitable<$lt, V>,
264        {
265            type Extra = <T as Visitable<$lt, V>>::Extra;
266
267            #[inline]
268            fn visit(&$lt self, visitor: &mut V, extra: Self::Extra) -> V::Result {
269                for i in self {
270                    try_visit!(i.visit(visitor, extra));
271                }
272                V::Result::output()
273            }
274        })*
275    };
276}
277
278macro_rules! impl_visitable_direct {
279    (<$lt:lifetime> $($ty:ty,)*) => {
280        $(impl_visitable!(
281            |&$lt self: $ty, visitor: &mut V, _extra: ()| {
282                Walkable::walk_ref(self, visitor)
283            }
284        );)*
285    };
286}
287
288macro_rules! impl_visitable_calling_walkable {
289    (<$lt:lifetime>
290        $( fn $method:ident($ty:ty $(, $extra_name:ident: $extra_ty:ty)?); )*
291    ) => {
292        $(fn $method(&mut self, node: &$lt $ty $(, $extra_name:$extra_ty)?) -> Self::Result {
293            impl_visitable!(|&$lt self: $ty, visitor: &mut V, extra: ($($extra_ty)?)| {
294                let ($($extra_name)?) = extra;
295                visitor.$method(self $(, $extra_name)?)
296            });
297            walk_walkable!(self, node, )
298        })*
299    };
300}
301
302macro_rules! define_named_walk {
303    ($Visitor:ident<$lt:lifetime>
304        $( pub fn $method:ident($ty:ty); )*
305    ) => {
306        $(pub fn $method<$lt, V: $Visitor<$lt>>(visitor: &mut V, node: &$lt $ty) -> V::Result {
307            walk_walkable!(visitor, node,)
308        })*
309    };
310}
311
312#[macro_export]
313macro_rules! common_visitor_and_walkers {
314    ($(($mut: ident))? $Visitor:ident$(<$lt:lifetime>)?) => {
315        $(${ignore($lt)}
316            #[derive(Copy, Clone)]
317        )?
318        #[derive(Debug)]
319        pub enum FnKind<'a> {
320            /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
321            Fn(FnCtxt, &'a $($mut)? Visibility, &'a $($mut)? Fn),
322
323            /// E.g., `|x, y| body`.
324            Closure(&'a $($mut)? ClosureBinder, &'a $($mut)? Option<CoroutineKind>, &'a $($mut)? Box<FnDecl>, &'a $($mut)? Box<Expr>),
325        }
326
327        impl<'a> FnKind<'a> {
328            pub fn header(&'a $($mut)? self) -> Option<&'a $($mut)? FnHeader> {
329                match *self {
330                    FnKind::Fn(_, _, Fn { sig, .. }) => Some(&$($mut)? sig.header),
331                    FnKind::Closure(..) => None,
332                }
333            }
334
335            pub fn ident(&'a $($mut)? self) -> Option<&'a $($mut)? Ident> {
336                match self {
337                    FnKind::Fn(_, _, Fn { ident, .. }) => Some(ident),
338                    _ => None,
339                }
340            }
341
342            pub fn decl(&'a $($mut)? self) -> &'a $($mut)? FnDecl {
343                match self {
344                    FnKind::Fn(_, _, Fn { sig, .. }) => &$($mut)? sig.decl,
345                    FnKind::Closure(_, _, decl, _) => decl,
346                }
347            }
348
349            pub fn ctxt(&self) -> Option<FnCtxt> {
350                match self {
351                    FnKind::Fn(ctxt, ..) => Some(*ctxt),
352                    FnKind::Closure(..) => None,
353                }
354            }
355        }
356
357        // This macro generates `impl Visitable` and `impl MutVisitable` that do nothing.
358        impl_visitable_noop!(<$($lt)? $($mut)?>
359            AttrId,
360            bool,
361            rustc_span::ByteSymbol,
362            char,
363            crate::token::CommentKind,
364            crate::token::Delimiter,
365            crate::token::Lit,
366            crate::token::LitKind,
367            crate::tokenstream::LazyAttrTokenStream,
368            crate::tokenstream::TokenStream,
369            EarlyParsedAttribute,
370            Movability,
371            Mutability,
372            Pinnedness,
373            Result<(), rustc_span::ErrorGuaranteed>,
374            rustc_data_structures::fx::FxHashMap<Symbol, usize>,
375            rustc_span::ErrorGuaranteed,
376            std::borrow::Cow<'_, str>,
377            Symbol,
378            u8,
379            usize,
380        );
381        // `Span` is only a no-op for the non-mutable visitor.
382        $(impl_visitable_noop!(<$lt> Span,);)?
383
384        // This macro generates `impl Visitable` and `impl MutVisitable` that simply iterate over
385        // their contents. We do not use a generic impl for `ThinVec` because we want to allow
386        // custom visits for the `MutVisitor`.
387        impl_visitable_list!(<$($lt)? $($mut)?>
388            ThinVec<AngleBracketedArg>,
389            ThinVec<Attribute>,
390            ThinVec<(Ident, Option<Ident>)>,
391            ThinVec<(NodeId, Path)>,
392            ThinVec<PathSegment>,
393            ThinVec<PreciseCapturingArg>,
394            ThinVec<Pat>,
395            ThinVec<Box<Ty>>,
396            ThinVec<TyPat>,
397            ThinVec<EiiImpl>,
398        );
399
400        // This macro generates `impl Visitable` and `impl MutVisitable` that forward to `Walkable`
401        // or `MutWalkable`. By default, all types that do not have a custom visit method in the
402        // visitor should appear here.
403        impl_visitable_direct!(<$($lt)? $($mut)?>
404            AngleBracketedArg,
405            AngleBracketedArgs,
406            AsmMacro,
407            AssignOpKind,
408            AssocItemConstraintKind,
409            AttrArgs,
410            AttrItem,
411            AttrKind,
412            AttrStyle,
413            FnPtrTy,
414            BindingMode,
415            GenBlockKind,
416            RangeLimits,
417            UnsafeBinderCastKind,
418            BinOpKind,
419            BlockCheckMode,
420            MgcaDisambiguation,
421            BorrowKind,
422            BoundAsyncness,
423            BoundConstness,
424            BoundPolarity,
425            ByRef,
426            Closure,
427            Const,
428            ConstItem,
429            ConstItemRhs,
430            Defaultness,
431            Delegation,
432            DelegationMac,
433            DelimArgs,
434            DelimSpan,
435            EnumDef,
436            Extern,
437            ForLoopKind,
438            FormatArgPosition,
439            FormatArgsPiece,
440            FormatArgument,
441            FormatArgumentKind,
442            FormatArguments,
443            FormatPlaceholder,
444            GenericParamKind,
445            Impl,
446            ImplPolarity,
447            Inline,
448            InlineAsmOperand,
449            InlineAsmRegOrRegClass,
450            InlineAsmTemplatePiece,
451            IsAuto,
452            LocalKind,
453            MacCallStmt,
454            MacStmtStyle,
455            MatchKind,
456            MethodCall,
457            ModKind,
458            ModSpans,
459            MutTy,
460            NormalAttr,
461            AttrItemKind,
462            Parens,
463            ParenthesizedArgs,
464            PatFieldsRest,
465            PatKind,
466            RangeEnd,
467            RangeSyntax,
468            Recovered,
469            Safety,
470            StaticItem,
471            StrLit,
472            StrStyle,
473            StructExpr,
474            StructRest,
475            Term,
476            Trait,
477            TraitBoundModifiers,
478            TraitObjectSyntax,
479            TyAlias,
480            TyKind,
481            TyPatKind,
482            UnOp,
483            UnsafeBinderTy,
484            UnsafeSource,
485            UseTreeKind,
486            VisibilityKind,
487            WhereBoundPredicate,
488            WhereClause,
489            WhereEqPredicate,
490            WhereRegionPredicate,
491            YieldKind,
492            EiiDecl,
493            EiiImpl,
494        );
495
496        /// Each method of this trait is a hook to be potentially
497        /// overridden. Each method's default implementation recursively visits
498        /// the substructure of the input via the corresponding `walk` method;
499        #[doc = concat!(" e.g., the `visit_item` method by default calls `visit"$(, "_", stringify!($mut))?, "::walk_item`.")]
500        ///
501        /// If you want to ensure that your code handles every variant
502        /// explicitly, you need to override each method. (And you also need
503        /// to monitor future changes to this trait in case a new method with a
504        /// new default implementation gets introduced.)
505        ///
506        /// Every `walk_*` method uses deconstruction to access fields of structs and
507        /// enums. This will result in a compile error if a field is added, which makes
508        /// it more likely the appropriate visit call will be added for it.
509        pub trait $Visitor<$($lt)?> : Sized $(${ignore($mut)} + MutVisitorResult<Result = ()>)? {
510            $(
511                ${ignore($lt)}
512                /// The result type of the `visit_*` methods. Can be either `()`,
513                /// or `ControlFlow<T>`.
514                type Result: VisitorResult = ();
515            )?
516
517            // Methods in this trait have one of three forms, with the last two forms
518            // only occurring on `MutVisitor`:
519            //
520            //   fn visit_t(&mut self, t: &mut T);                      // common
521            //   fn flat_map_t(&mut self, t: T) -> SmallVec<[T; 1]>;    // rare
522            //   fn filter_map_t(&mut self, t: T) -> Option<T>;         // rarest
523            //
524            // When writing these methods, it is better to use destructuring like this:
525            //
526            //   fn visit_abc(&mut self, ABC { a, b, c: _ }: &mut ABC) {
527            //       visit_a(a);
528            //       visit_b(b);
529            //   }
530            //
531            // than to use field access like this:
532            //
533            //   fn visit_abc(&mut self, abc: &mut ABC) {
534            //       visit_a(&mut abc.a);
535            //       visit_b(&mut abc.b);
536            //       // ignore abc.c
537            //   }
538            //
539            // As well as being more concise, the former is explicit about which fields
540            // are skipped. Furthermore, if a new field is added, the destructuring
541            // version will cause a compile error, which is good. In comparison, the
542            // field access version will continue working and it would be easy to
543            // forget to add handling for it.
544            fn visit_ident(&mut self, Ident { name: _, span }: &$($lt)? $($mut)? Ident) -> Self::Result {
545                impl_visitable!(|&$($lt)? $($mut)? self: Ident, visitor: &mut V, _extra: ()| {
546                    visitor.visit_ident(self)
547                });
548                visit_span(self, span)
549            }
550
551            // This macro defines a custom visit method for each listed type.
552            // It implements `impl Visitable` and `impl MutVisitable` to call those methods on the
553            // visitor.
554            impl_visitable_calling_walkable!(<$($lt)? $($mut)?>
555                fn visit_anon_const(AnonConst);
556                fn visit_arm(Arm);
557                //fn visit_assoc_item(AssocItem, _ctxt: AssocCtxt);
558                fn visit_assoc_item_constraint(AssocItemConstraint);
559                fn visit_attribute(Attribute);
560                fn visit_block(Block);
561                //fn visit_nested_use_tree((UseTree, NodeId));
562                fn visit_capture_by(CaptureBy);
563                fn visit_closure_binder(ClosureBinder);
564                fn visit_contract(FnContract);
565                fn visit_coroutine_kind(CoroutineKind);
566                fn visit_crate(Crate);
567                fn visit_expr(Expr);
568                fn visit_expr_field(ExprField);
569                fn visit_field_def(FieldDef);
570                fn visit_fn_decl(FnDecl);
571                fn visit_fn_header(FnHeader);
572                fn visit_fn_ret_ty(FnRetTy);
573                //fn visit_foreign_item(ForeignItem);
574                fn visit_foreign_mod(ForeignMod);
575                fn visit_format_args(FormatArgs);
576                fn visit_generic_arg(GenericArg);
577                fn visit_generic_args(GenericArgs);
578                fn visit_generic_param(GenericParam);
579                fn visit_generics(Generics);
580                fn visit_inline_asm(InlineAsm);
581                fn visit_inline_asm_sym(InlineAsmSym);
582                //fn visit_item(Item);
583                fn visit_label(Label);
584                fn visit_lifetime(Lifetime, _ctxt: LifetimeCtxt);
585                fn visit_local(Local);
586                fn visit_mac_call(MacCall);
587                fn visit_macro_def(MacroDef);
588                fn visit_param_bound(GenericBound, _ctxt: BoundKind);
589                fn visit_param(Param);
590                fn visit_pat_field(PatField);
591                fn visit_path(Path);
592                fn visit_path_segment(PathSegment);
593                fn visit_pat(Pat);
594                fn visit_poly_trait_ref(PolyTraitRef);
595                fn visit_precise_capturing_arg(PreciseCapturingArg);
596                fn visit_qself(QSelf);
597                fn visit_trait_ref(TraitRef);
598                fn visit_ty_pat(TyPat);
599                fn visit_ty(Ty);
600                fn visit_use_tree(UseTree);
601                fn visit_variant_data(VariantData);
602                fn visit_variant(Variant);
603                fn visit_vis(Visibility);
604                fn visit_where_predicate_kind(WherePredicateKind);
605                fn visit_where_predicate(WherePredicate);
606            );
607
608            // We want `Visitor` to take the `NodeId` by value.
609            fn visit_id(&mut self, _id: $(&$mut)? NodeId) -> Self::Result {
610                $(impl_visitable!(
611                    |&$lt self: NodeId, visitor: &mut V, _extra: ()| {
612                        visitor.visit_id(*self)
613                    }
614                );)?
615                $(impl_visitable!(
616                    |&$mut self: NodeId, visitor: &mut V, _extra: ()| {
617                        visitor.visit_id(self)
618                    }
619                );)?
620                Self::Result::output()
621            }
622
623            /// This method is a hack to workaround unstable of `stmt_expr_attributes`.
624            /// It can be removed once that feature is stabilized.
625            fn visit_method_receiver_expr(&mut self, ex: &$($lt)? $($mut)? Expr) -> Self::Result {
626                self.visit_expr(ex)
627            }
628
629            fn visit_item(&mut self, item: &$($lt)? $($mut)? Item) -> Self::Result {
630                impl_visitable!(|&$($lt)? $($mut)? self: Item, vis: &mut V, _extra: ()| {
631                    vis.visit_item(self)
632                });
633                walk_item(self, item)
634            }
635
636            fn visit_foreign_item(&mut self, item: &$($lt)? $($mut)? ForeignItem) -> Self::Result {
637                impl_visitable!(|&$($lt)? $($mut)? self: ForeignItem, vis: &mut V, _extra: ()| {
638                    vis.visit_foreign_item(self)
639                });
640                walk_item(self, item)
641            }
642
643            fn visit_assoc_item(&mut self, item: &$($lt)? $($mut)? AssocItem, ctxt: AssocCtxt) -> Self::Result {
644                impl_visitable!(|&$($lt)? $($mut)? self: AssocItem, vis: &mut V, ctxt: AssocCtxt| {
645                    vis.visit_assoc_item(self, ctxt)
646                });
647                walk_assoc_item(self, item, ctxt)
648            }
649
650            // for `MutVisitor`: `Span` and `NodeId` are mutated at the caller site.
651            fn visit_fn(
652                &mut self,
653                fk: FnKind<$($lt)? $(${ignore($mut)} '_)?>,
654                _: &AttrVec,
655                _: Span,
656                _: NodeId,
657            ) -> Self::Result {
658                walk_fn(self, fk)
659            }
660
661            // (non-mut) `Visitor`-only methods
662            $(
663                fn visit_stmt(&mut self, s: &$lt Stmt) -> Self::Result {
664                    walk_stmt(self, s)
665                }
666
667                fn visit_nested_use_tree(&mut self, use_tree: &$lt UseTree, id: NodeId) -> Self::Result {
668                    try_visit!(self.visit_id(id));
669                    self.visit_use_tree(use_tree)
670                }
671            )?
672
673            // `MutVisitor`-only methods
674            $(
675                // Span visiting is no longer used, but we keep it for now,
676                // in case it's needed for something like #127241.
677                #[inline]
678                fn visit_span(&mut self, _sp: &$mut Span) {
679                    impl_visitable!(|&mut self: Span, visitor: &mut V, _extra: ()| {
680                        visitor.visit_span(self)
681                    });
682                    // Do nothing.
683                }
684
685                fn flat_map_foreign_item(&mut self, ni: Box<ForeignItem>) -> SmallVec<[Box<ForeignItem>; 1]> {
686                    walk_flat_map_foreign_item(self, ni)
687                }
688
689                fn flat_map_item(&mut self, i: Box<Item>) -> SmallVec<[Box<Item>; 1]> {
690                    walk_flat_map_item(self, i)
691                }
692
693                fn flat_map_field_def(&mut self, fd: FieldDef) -> SmallVec<[FieldDef; 1]> {
694                    walk_flat_map_field_def(self, fd)
695                }
696
697                fn flat_map_assoc_item(
698                    &mut self,
699                    i: Box<AssocItem>,
700                    ctxt: AssocCtxt,
701                ) -> SmallVec<[Box<AssocItem>; 1]> {
702                    walk_flat_map_assoc_item(self, i, ctxt)
703                }
704
705                fn flat_map_stmt(&mut self, s: Stmt) -> SmallVec<[Stmt; 1]> {
706                    walk_flat_map_stmt(self, s)
707                }
708
709                fn flat_map_arm(&mut self, arm: Arm) -> SmallVec<[Arm; 1]> {
710                    walk_flat_map_arm(self, arm)
711                }
712
713                fn filter_map_expr(&mut self, e: Box<Expr>) -> Option<Box<Expr>> {
714                    walk_filter_map_expr(self, e)
715                }
716
717                fn flat_map_variant(&mut self, v: Variant) -> SmallVec<[Variant; 1]> {
718                    walk_flat_map_variant(self, v)
719                }
720
721                fn flat_map_param(&mut self, param: Param) -> SmallVec<[Param; 1]> {
722                    walk_flat_map_param(self, param)
723                }
724
725                fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> {
726                    walk_flat_map_generic_param(self, param)
727                }
728
729                fn flat_map_expr_field(&mut self, f: ExprField) -> SmallVec<[ExprField; 1]> {
730                    walk_flat_map_expr_field(self, f)
731                }
732
733                fn flat_map_where_predicate(
734                    &mut self,
735                    where_predicate: WherePredicate,
736                ) -> SmallVec<[WherePredicate; 1]> {
737                    walk_flat_map_where_predicate(self, where_predicate)
738                }
739
740                fn flat_map_pat_field(&mut self, fp: PatField) -> SmallVec<[PatField; 1]> {
741                    walk_flat_map_pat_field(self, fp)
742                }
743            )?
744        }
745
746        pub trait WalkItemKind {
747            type Ctxt;
748            fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
749                &$($lt)? $($mut)? self,
750                attrs: &AttrVec,
751                span: Span,
752                id: NodeId,
753                visibility: &$($lt)? $($mut)? Visibility,
754                ctxt: Self::Ctxt,
755                vis: &mut V,
756            ) -> V::Result;
757        }
758
759        // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier
760        $(${ignore($lt)}
761            #[expect(unused, rustc::pass_by_value)]
762            #[inline]
763        )?
764        fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, span: &$($lt)? $($mut)? Span) -> V::Result {
765            $(${ignore($mut)} vis.visit_span(span))?;
766            V::Result::output()
767        }
768
769        $(impl_visitable!(|&$lt self: ThinVec<(UseTree, NodeId)>, vis: &mut V, _extra: ()| {
770            for (nested_tree, nested_id) in self {
771                try_visit!(vis.visit_nested_use_tree(nested_tree, *nested_id));
772            }
773            V::Result::output()
774        });)?
775        $(impl_visitable_list!(<$mut> ThinVec<(UseTree, NodeId)>,);)?
776
777        fn walk_item_inner<$($lt,)? K: WalkItemKind, V: $Visitor$(<$lt>)?>(
778            visitor: &mut V,
779            item: &$($mut)? $($lt)? Item<K>,
780            ctxt: K::Ctxt,
781        ) -> V::Result {
782            let Item { attrs, id, kind, vis, span, tokens: _ } = item;
783            visit_visitable!($($mut)? visitor, id, attrs, vis);
784            try_visit!(kind.walk(attrs, *span, *id, vis, ctxt, visitor));
785            visit_visitable!($($mut)? visitor, span);
786            V::Result::output()
787        }
788
789        // Do not implement `Walkable`/`MutWalkable` for *Item to avoid confusion.
790        pub fn walk_item<$($lt,)? K: WalkItemKind<Ctxt = ()>, V: $Visitor$(<$lt>)?>(
791            visitor: &mut V,
792            item: &$($mut)? $($lt)? Item<K>,
793        ) -> V::Result {
794            walk_item_inner(visitor, item, ())
795        }
796
797        // Do not implement `Walkable`/`MutWalkable` for *Item to avoid confusion.
798        pub fn walk_assoc_item<$($lt,)? K: WalkItemKind<Ctxt = AssocCtxt>, V: $Visitor$(<$lt>)?>(
799            visitor: &mut V,
800            item: &$($mut)? $($lt)? Item<K>,
801            ctxt: AssocCtxt,
802        ) -> V::Result {
803            walk_item_inner(visitor, item, ctxt)
804        }
805
806        impl WalkItemKind for ItemKind {
807            type Ctxt = ();
808            fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
809                &$($lt)? $($mut)? self,
810                attrs: &AttrVec,
811                span: Span,
812                id: NodeId,
813                visibility: &$($lt)? $($mut)? Visibility,
814                _ctxt: Self::Ctxt,
815                vis: &mut V,
816            ) -> V::Result {
817                match self {
818                    ItemKind::Fn(func) => {
819                        let kind = FnKind::Fn(FnCtxt::Free, visibility, &$($mut)? *func);
820                        try_visit!(vis.visit_fn(kind, attrs, span, id));
821                    }
822                    ItemKind::ExternCrate(orig_name, ident) =>
823                        visit_visitable!($($mut)? vis, orig_name, ident),
824                    ItemKind::Use(use_tree) =>
825                        visit_visitable!($($mut)? vis, use_tree),
826                    ItemKind::Static(item) =>
827                        visit_visitable!($($mut)? vis, item),
828                    ItemKind::Const(item) =>
829                        visit_visitable!($($mut)? vis, item),
830                    ItemKind::Mod(safety, ident, mod_kind) =>
831                        visit_visitable!($($mut)? vis, safety, ident, mod_kind),
832                    ItemKind::ForeignMod(nm) =>
833                        visit_visitable!($($mut)? vis, nm),
834                    ItemKind::GlobalAsm(asm) =>
835                        visit_visitable!($($mut)? vis, asm),
836                    ItemKind::TyAlias(ty_alias) =>
837                        visit_visitable!($($mut)? vis, ty_alias),
838                    ItemKind::Enum(ident, generics, enum_definition) =>
839                        visit_visitable!($($mut)? vis, ident, generics, enum_definition),
840                    ItemKind::Struct(ident, generics, variant_data)
841                    | ItemKind::Union(ident, generics, variant_data) =>
842                        visit_visitable!($($mut)? vis, ident, generics, variant_data),
843                    ItemKind::Impl(impl_) =>
844                        visit_visitable!($($mut)? vis, impl_),
845                    ItemKind::Trait(trait_) =>
846                        visit_visitable!($($mut)? vis, trait_),
847                    ItemKind::TraitAlias(box TraitAlias { constness, ident, generics, bounds}) => {
848                        visit_visitable!($($mut)? vis, constness, ident, generics);
849                        visit_visitable_with!($($mut)? vis, bounds, BoundKind::Bound)
850                    }
851                    ItemKind::MacCall(m) =>
852                        visit_visitable!($($mut)? vis, m),
853                    ItemKind::MacroDef(ident, def) =>
854                        visit_visitable!($($mut)? vis, ident, def),
855                    ItemKind::Delegation(delegation) =>
856                        visit_visitable!($($mut)? vis, delegation),
857                    ItemKind::DelegationMac(dm) =>
858                        visit_visitable!($($mut)? vis, dm),
859                }
860                V::Result::output()
861            }
862        }
863
864        impl WalkItemKind for AssocItemKind {
865            type Ctxt = AssocCtxt;
866            fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
867                &$($lt)? $($mut)? self,
868                attrs: &AttrVec,
869                span: Span,
870                id: NodeId,
871                visibility: &$($lt)? $($mut)? Visibility,
872                ctxt: Self::Ctxt,
873                vis: &mut V,
874            ) -> V::Result {
875                match self {
876                    AssocItemKind::Const(item) =>
877                        visit_visitable!($($mut)? vis, item),
878                    AssocItemKind::Fn(func) => {
879                        let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), visibility, &$($mut)? *func);
880                        try_visit!(vis.visit_fn(kind, attrs, span, id))
881                    }
882                    AssocItemKind::Type(alias) =>
883                        visit_visitable!($($mut)? vis, alias),
884                    AssocItemKind::MacCall(mac) =>
885                        visit_visitable!($($mut)? vis, mac),
886                    AssocItemKind::Delegation(delegation) =>
887                        visit_visitable!($($mut)? vis, delegation),
888                    AssocItemKind::DelegationMac(dm) =>
889                        visit_visitable!($($mut)? vis, dm),
890                }
891                V::Result::output()
892            }
893        }
894
895        impl WalkItemKind for ForeignItemKind {
896            type Ctxt = ();
897            fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
898                &$($lt)? $($mut)? self,
899                attrs: &AttrVec,
900                span: Span,
901                id: NodeId,
902                visibility: &$($lt)? $($mut)? Visibility,
903                _ctxt: Self::Ctxt,
904                vis: &mut V,
905            ) -> V::Result {
906                match self {
907                    ForeignItemKind::Static(item) =>
908                        visit_visitable!($($mut)? vis, item),
909                    ForeignItemKind::Fn(func) => {
910                        let kind = FnKind::Fn(FnCtxt::Foreign, visibility, &$($mut)?*func);
911                        try_visit!(vis.visit_fn(kind, attrs, span, id))
912                    }
913                    ForeignItemKind::TyAlias(alias) =>
914                        visit_visitable!($($mut)? vis, alias),
915                    ForeignItemKind::MacCall(mac) =>
916                        visit_visitable!($($mut)? vis, mac),
917                }
918                V::Result::output()
919            }
920        }
921
922        pub fn walk_fn<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, kind: FnKind<$($lt)? $(${ignore($mut)} '_)?>) -> V::Result {
923            match kind {
924                FnKind::Fn(
925                    _ctxt,
926                    // Visibility is visited as a part of the item.
927                    _vis,
928                    Fn { defaultness, ident, sig, generics, contract, body, define_opaque, eii_impls },
929                ) => {
930                    let FnSig { header, decl, span } = sig;
931                    visit_visitable!($($mut)? vis,
932                        defaultness, ident, header, generics, decl,
933                        contract, body, span, define_opaque, eii_impls
934                    );
935                }
936                FnKind::Closure(binder, coroutine_kind, decl, body) =>
937                    visit_visitable!($($mut)? vis, binder, coroutine_kind, decl, body),
938            }
939            V::Result::output()
940        }
941
942        impl_walkable!(|&$($mut)? $($lt)? self: Impl, vis: &mut V| {
943            let Impl { generics, of_trait, self_ty, items, constness: _ } = self;
944            try_visit!(vis.visit_generics(generics));
945            if let Some(box of_trait) = of_trait {
946                let TraitImplHeader { defaultness, safety, polarity, trait_ref } = of_trait;
947                visit_visitable!($($mut)? vis, defaultness, safety, polarity, trait_ref);
948            }
949            try_visit!(vis.visit_ty(self_ty));
950            visit_visitable_with!($($mut)? vis, items, AssocCtxt::Impl { of_trait: of_trait.is_some() });
951            V::Result::output()
952        });
953
954        // Special case to call `visit_method_receiver_expr`.
955        impl_walkable!(|&$($mut)? $($lt)? self: MethodCall, vis: &mut V| {
956            let MethodCall { seg, receiver, args, span } = self;
957            try_visit!(vis.visit_method_receiver_expr(receiver));
958            visit_visitable!($($mut)? vis, seg, args, span);
959            V::Result::output()
960        });
961
962        impl_walkable!(|&$($mut)? $($lt)? self: Expr, vis: &mut V| {
963            let Expr { id, kind, span, attrs, tokens: _ } = self;
964            visit_visitable!($($mut)? vis, id, attrs);
965            match kind {
966                ExprKind::Array(exprs) =>
967                    visit_visitable!($($mut)? vis, exprs),
968                ExprKind::ConstBlock(anon_const) =>
969                    visit_visitable!($($mut)? vis, anon_const),
970                ExprKind::Repeat(element, count) =>
971                    visit_visitable!($($mut)? vis, element, count),
972                ExprKind::Struct(se) =>
973                    visit_visitable!($($mut)? vis, se),
974                ExprKind::Tup(exprs) =>
975                    visit_visitable!($($mut)? vis, exprs),
976                ExprKind::Call(callee_expression, arguments) =>
977                    visit_visitable!($($mut)? vis, callee_expression, arguments),
978                ExprKind::MethodCall(mc) =>
979                    visit_visitable!($($mut)? vis, mc),
980                ExprKind::Binary(op, lhs, rhs) =>
981                    visit_visitable!($($mut)? vis, op, lhs, rhs),
982                ExprKind::AddrOf(kind, mutbl, subexpression) =>
983                    visit_visitable!($($mut)? vis, kind, mutbl, subexpression),
984                ExprKind::Unary(op, subexpression) =>
985                    visit_visitable!($($mut)? vis, op, subexpression),
986                ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) =>
987                    visit_visitable!($($mut)? vis, subexpression, typ),
988                ExprKind::Let(pat, expr, span, _recovered) =>
989                    visit_visitable!($($mut)? vis, pat, expr, span),
990                ExprKind::If(head_expression, if_block, optional_else) =>
991                    visit_visitable!($($mut)? vis, head_expression, if_block, optional_else),
992                ExprKind::While(subexpression, block, opt_label) =>
993                    visit_visitable!($($mut)? vis, subexpression, block, opt_label),
994                ExprKind::ForLoop { pat, iter, body, label, kind } =>
995                    visit_visitable!($($mut)? vis, pat, iter, body, label, kind),
996                ExprKind::Loop(block, opt_label, span) =>
997                    visit_visitable!($($mut)? vis, block, opt_label, span),
998                ExprKind::Match(subexpression, arms, kind) =>
999                    visit_visitable!($($mut)? vis, subexpression, arms, kind),
1000                ExprKind::Closure(box Closure {
1001                    binder,
1002                    capture_clause,
1003                    coroutine_kind,
1004                    constness,
1005                    movability,
1006                    fn_decl,
1007                    body,
1008                    fn_decl_span,
1009                    fn_arg_span,
1010                }) => {
1011                    visit_visitable!($($mut)? vis, constness, movability, capture_clause);
1012                    let kind = FnKind::Closure(binder, coroutine_kind, fn_decl, body);
1013                    try_visit!(vis.visit_fn(kind, attrs, *span, *id));
1014                    visit_visitable!($($mut)? vis, fn_decl_span, fn_arg_span);
1015                }
1016                ExprKind::Block(block, opt_label) =>
1017                    visit_visitable!($($mut)? vis, block, opt_label),
1018                ExprKind::Gen(capt, body, kind, decl_span) =>
1019                    visit_visitable!($($mut)? vis, capt, body, kind, decl_span),
1020                ExprKind::Await(expr, span) | ExprKind::Use(expr, span) =>
1021                    visit_visitable!($($mut)? vis, expr, span),
1022                ExprKind::Assign(lhs, rhs, span) =>
1023                    visit_visitable!($($mut)? vis, lhs, rhs, span),
1024                ExprKind::AssignOp(op, lhs, rhs) =>
1025                    visit_visitable!($($mut)? vis, op, lhs, rhs),
1026                ExprKind::Field(subexpression, ident) =>
1027                    visit_visitable!($($mut)? vis, subexpression, ident),
1028                ExprKind::Index(main_expression, index_expression, span) =>
1029                    visit_visitable!($($mut)? vis, main_expression, index_expression, span),
1030                ExprKind::Range(start, end, limit) =>
1031                    visit_visitable!($($mut)? vis, start, end, limit),
1032                ExprKind::Underscore => {}
1033                ExprKind::Path(maybe_qself, path) =>
1034                    visit_visitable!($($mut)? vis, maybe_qself, path),
1035                ExprKind::Break(opt_label, opt_expr) =>
1036                    visit_visitable!($($mut)? vis, opt_label, opt_expr),
1037                ExprKind::Continue(opt_label) =>
1038                    visit_visitable!($($mut)? vis, opt_label),
1039                ExprKind::Ret(optional_expression) | ExprKind::Yeet(optional_expression) =>
1040                    visit_visitable!($($mut)? vis, optional_expression),
1041                ExprKind::Become(expr) =>
1042                    visit_visitable!($($mut)? vis, expr),
1043                ExprKind::MacCall(mac) =>
1044                    visit_visitable!($($mut)? vis, mac),
1045                ExprKind::Paren(subexpression) =>
1046                    visit_visitable!($($mut)? vis, subexpression),
1047                ExprKind::InlineAsm(asm) =>
1048                    visit_visitable!($($mut)? vis, asm),
1049                ExprKind::FormatArgs(f) =>
1050                    visit_visitable!($($mut)? vis, f),
1051                ExprKind::OffsetOf(container, fields) =>
1052                    visit_visitable!($($mut)? vis, container, fields),
1053                ExprKind::Yield(kind) =>
1054                    visit_visitable!($($mut)? vis, kind),
1055                ExprKind::Try(subexpression) =>
1056                    visit_visitable!($($mut)? vis, subexpression),
1057                ExprKind::TryBlock(body, optional_type) =>
1058                    visit_visitable!($($mut)? vis, body, optional_type),
1059                ExprKind::Lit(token) =>
1060                    visit_visitable!($($mut)? vis, token),
1061                ExprKind::IncludedBytes(bytes) =>
1062                    visit_visitable!($($mut)? vis, bytes),
1063                ExprKind::UnsafeBinderCast(kind, expr, ty) =>
1064                    visit_visitable!($($mut)? vis, kind, expr, ty),
1065                ExprKind::Err(_guar) => {}
1066                ExprKind::Dummy => {}
1067            }
1068
1069            visit_span(vis, span)
1070        });
1071
1072        define_named_walk!($(($mut))? $Visitor$(<$lt>)?
1073            pub fn walk_anon_const(AnonConst);
1074            pub fn walk_arm(Arm);
1075            //pub fn walk_assoc_item(AssocItem, _ctxt: AssocCtxt);
1076            pub fn walk_assoc_item_constraint(AssocItemConstraint);
1077            pub fn walk_attribute(Attribute);
1078            pub fn walk_block(Block);
1079            //pub fn walk_nested_use_tree((UseTree, NodeId));
1080            pub fn walk_capture_by(CaptureBy);
1081            pub fn walk_closure_binder(ClosureBinder);
1082            pub fn walk_contract(FnContract);
1083            pub fn walk_coroutine_kind(CoroutineKind);
1084            pub fn walk_crate(Crate);
1085            pub fn walk_expr(Expr);
1086            pub fn walk_expr_field(ExprField);
1087            pub fn walk_field_def(FieldDef);
1088            pub fn walk_fn_decl(FnDecl);
1089            pub fn walk_fn_header(FnHeader);
1090            pub fn walk_fn_ret_ty(FnRetTy);
1091            //pub fn walk_foreign_item(ForeignItem);
1092            pub fn walk_foreign_mod(ForeignMod);
1093            pub fn walk_format_args(FormatArgs);
1094            pub fn walk_generic_arg(GenericArg);
1095            pub fn walk_generic_args(GenericArgs);
1096            pub fn walk_generic_param(GenericParam);
1097            pub fn walk_generics(Generics);
1098            pub fn walk_inline_asm(InlineAsm);
1099            pub fn walk_inline_asm_sym(InlineAsmSym);
1100            //pub fn walk_item(Item);
1101            pub fn walk_label(Label);
1102            pub fn walk_lifetime(Lifetime);
1103            pub fn walk_local(Local);
1104            pub fn walk_mac(MacCall);
1105            pub fn walk_macro_def(MacroDef);
1106            pub fn walk_param_bound(GenericBound);
1107            pub fn walk_param(Param);
1108            pub fn walk_pat_field(PatField);
1109            pub fn walk_path(Path);
1110            pub fn walk_path_segment(PathSegment);
1111            pub fn walk_pat(Pat);
1112            pub fn walk_poly_trait_ref(PolyTraitRef);
1113            pub fn walk_precise_capturing_arg(PreciseCapturingArg);
1114            pub fn walk_qself(QSelf);
1115            pub fn walk_trait_ref(TraitRef);
1116            pub fn walk_ty_pat(TyPat);
1117            pub fn walk_ty(Ty);
1118            pub fn walk_use_tree(UseTree);
1119            pub fn walk_variant_data(VariantData);
1120            pub fn walk_variant(Variant);
1121            pub fn walk_vis(Visibility);
1122            pub fn walk_where_predicate_kind(WherePredicateKind);
1123            pub fn walk_where_predicate(WherePredicate);
1124        );
1125    };
1126}
1127
1128common_visitor_and_walkers!(Visitor<'a>);
1129
1130macro_rules! generate_list_visit_fns {
1131    ($($name:ident, $Ty:ty, $visit_fn:ident$(, $param:ident: $ParamTy:ty)*;)+) => {
1132        $(
1133            #[allow(unused_parens)]
1134            impl<'a, V: Visitor<'a>> Visitable<'a, V> for ThinVec<$Ty> {
1135                type Extra = ($($ParamTy),*);
1136
1137                #[inline]
1138                fn visit(
1139                    &'a self,
1140                    visitor: &mut V,
1141                    ($($param),*): Self::Extra,
1142                ) -> V::Result {
1143                    $name(visitor, self $(, $param)*)
1144                }
1145            }
1146
1147            fn $name<'a, V: Visitor<'a>>(
1148                vis: &mut V,
1149                values: &'a ThinVec<$Ty>,
1150                $(
1151                    $param: $ParamTy,
1152                )*
1153            ) -> V::Result {
1154                walk_list!(vis, $visit_fn, values$(,$param)*);
1155                V::Result::output()
1156            }
1157        )+
1158    }
1159}
1160
1161generate_list_visit_fns! {
1162    visit_items, Box<Item>, visit_item;
1163    visit_foreign_items, Box<ForeignItem>, visit_foreign_item;
1164    visit_generic_params, GenericParam, visit_generic_param;
1165    visit_stmts, Stmt, visit_stmt;
1166    visit_exprs, Box<Expr>, visit_expr;
1167    visit_expr_fields, ExprField, visit_expr_field;
1168    visit_pat_fields, PatField, visit_pat_field;
1169    visit_variants, Variant, visit_variant;
1170    visit_assoc_items, Box<AssocItem>, visit_assoc_item, ctxt: AssocCtxt;
1171    visit_where_predicates, WherePredicate, visit_where_predicate;
1172    visit_params, Param, visit_param;
1173    visit_field_defs, FieldDef, visit_field_def;
1174    visit_arms, Arm, visit_arm;
1175}
1176
1177pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result {
1178    let Stmt { id, kind, span: _ } = statement;
1179    try_visit!(visitor.visit_id(*id));
1180    match kind {
1181        StmtKind::Let(local) => try_visit!(visitor.visit_local(local)),
1182        StmtKind::Item(item) => try_visit!(visitor.visit_item(item)),
1183        StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)),
1184        StmtKind::Empty => {}
1185        StmtKind::MacCall(mac) => {
1186            let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac;
1187            walk_list!(visitor, visit_attribute, attrs);
1188            try_visit!(visitor.visit_mac_call(mac));
1189        }
1190    }
1191    V::Result::output()
1192}