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            Movability,
370            Mutability,
371            Pinnedness,
372            Result<(), rustc_span::ErrorGuaranteed>,
373            rustc_data_structures::fx::FxHashMap<Symbol, usize>,
374            rustc_span::ErrorGuaranteed,
375            std::borrow::Cow<'_, str>,
376            Symbol,
377            u8,
378            usize,
379        );
380        // `Span` is only a no-op for the non-mutable visitor.
381        $(impl_visitable_noop!(<$lt> Span,);)?
382
383        // This macro generates `impl Visitable` and `impl MutVisitable` that simply iterate over
384        // their contents. We do not use a generic impl for `ThinVec` because we want to allow
385        // custom visits for the `MutVisitor`.
386        impl_visitable_list!(<$($lt)? $($mut)?>
387            ThinVec<AngleBracketedArg>,
388            ThinVec<Attribute>,
389            ThinVec<(Ident, Option<Ident>)>,
390            ThinVec<(NodeId, Path)>,
391            ThinVec<PathSegment>,
392            ThinVec<PreciseCapturingArg>,
393            ThinVec<Pat>,
394            ThinVec<Box<Ty>>,
395            ThinVec<TyPat>,
396            ThinVec<EiiImpl>,
397        );
398
399        // This macro generates `impl Visitable` and `impl MutVisitable` that forward to `Walkable`
400        // or `MutWalkable`. By default, all types that do not have a custom visit method in the
401        // visitor should appear here.
402        impl_visitable_direct!(<$($lt)? $($mut)?>
403            AngleBracketedArg,
404            AngleBracketedArgs,
405            AsmMacro,
406            AssignOpKind,
407            AssocItemConstraintKind,
408            AttrArgs,
409            AttrItem,
410            AttrKind,
411            AttrStyle,
412            FnPtrTy,
413            BindingMode,
414            GenBlockKind,
415            RangeLimits,
416            UnsafeBinderCastKind,
417            BinOpKind,
418            BlockCheckMode,
419            MgcaDisambiguation,
420            BorrowKind,
421            BoundAsyncness,
422            BoundConstness,
423            BoundPolarity,
424            ByRef,
425            Closure,
426            Const,
427            ConstItem,
428            ConstItemRhs,
429            Defaultness,
430            Delegation,
431            DelegationMac,
432            DelimArgs,
433            DelimSpan,
434            EnumDef,
435            Extern,
436            ForLoopKind,
437            FormatArgPosition,
438            FormatArgsPiece,
439            FormatArgument,
440            FormatArgumentKind,
441            FormatArguments,
442            FormatPlaceholder,
443            GenericParamKind,
444            Impl,
445            ImplPolarity,
446            Inline,
447            InlineAsmOperand,
448            InlineAsmRegOrRegClass,
449            InlineAsmTemplatePiece,
450            IsAuto,
451            LocalKind,
452            MacCallStmt,
453            MacStmtStyle,
454            MatchKind,
455            MethodCall,
456            ModKind,
457            ModSpans,
458            MutTy,
459            NormalAttr,
460            Parens,
461            ParenthesizedArgs,
462            PatFieldsRest,
463            PatKind,
464            RangeEnd,
465            RangeSyntax,
466            Recovered,
467            Safety,
468            StaticItem,
469            StrLit,
470            StrStyle,
471            StructExpr,
472            StructRest,
473            Term,
474            Trait,
475            TraitBoundModifiers,
476            TraitObjectSyntax,
477            TyAlias,
478            TyKind,
479            TyPatKind,
480            UnOp,
481            UnsafeBinderTy,
482            UnsafeSource,
483            UseTreeKind,
484            VisibilityKind,
485            WhereBoundPredicate,
486            WhereClause,
487            WhereEqPredicate,
488            WhereRegionPredicate,
489            YieldKind,
490            EiiExternTarget,
491            EiiImpl,
492        );
493
494        /// Each method of this trait is a hook to be potentially
495        /// overridden. Each method's default implementation recursively visits
496        /// the substructure of the input via the corresponding `walk` method;
497        #[doc = concat!(" e.g., the `visit_item` method by default calls `visit"$(, "_", stringify!($mut))?, "::walk_item`.")]
498        ///
499        /// If you want to ensure that your code handles every variant
500        /// explicitly, you need to override each method. (And you also need
501        /// to monitor future changes to this trait in case a new method with a
502        /// new default implementation gets introduced.)
503        ///
504        /// Every `walk_*` method uses deconstruction to access fields of structs and
505        /// enums. This will result in a compile error if a field is added, which makes
506        /// it more likely the appropriate visit call will be added for it.
507        pub trait $Visitor<$($lt)?> : Sized $(${ignore($mut)} + MutVisitorResult<Result = ()>)? {
508            $(
509                ${ignore($lt)}
510                /// The result type of the `visit_*` methods. Can be either `()`,
511                /// or `ControlFlow<T>`.
512                type Result: VisitorResult = ();
513            )?
514
515            // Methods in this trait have one of three forms, with the last two forms
516            // only occurring on `MutVisitor`:
517            //
518            //   fn visit_t(&mut self, t: &mut T);                      // common
519            //   fn flat_map_t(&mut self, t: T) -> SmallVec<[T; 1]>;    // rare
520            //   fn filter_map_t(&mut self, t: T) -> Option<T>;         // rarest
521            //
522            // When writing these methods, it is better to use destructuring like this:
523            //
524            //   fn visit_abc(&mut self, ABC { a, b, c: _ }: &mut ABC) {
525            //       visit_a(a);
526            //       visit_b(b);
527            //   }
528            //
529            // than to use field access like this:
530            //
531            //   fn visit_abc(&mut self, abc: &mut ABC) {
532            //       visit_a(&mut abc.a);
533            //       visit_b(&mut abc.b);
534            //       // ignore abc.c
535            //   }
536            //
537            // As well as being more concise, the former is explicit about which fields
538            // are skipped. Furthermore, if a new field is added, the destructuring
539            // version will cause a compile error, which is good. In comparison, the
540            // field access version will continue working and it would be easy to
541            // forget to add handling for it.
542            fn visit_ident(&mut self, Ident { name: _, span }: &$($lt)? $($mut)? Ident) -> Self::Result {
543                impl_visitable!(|&$($lt)? $($mut)? self: Ident, visitor: &mut V, _extra: ()| {
544                    visitor.visit_ident(self)
545                });
546                visit_span(self, span)
547            }
548
549            // This macro defines a custom visit method for each listed type.
550            // It implements `impl Visitable` and `impl MutVisitable` to call those methods on the
551            // visitor.
552            impl_visitable_calling_walkable!(<$($lt)? $($mut)?>
553                fn visit_anon_const(AnonConst);
554                fn visit_arm(Arm);
555                //fn visit_assoc_item(AssocItem, _ctxt: AssocCtxt);
556                fn visit_assoc_item_constraint(AssocItemConstraint);
557                fn visit_attribute(Attribute);
558                fn visit_block(Block);
559                //fn visit_nested_use_tree((UseTree, NodeId));
560                fn visit_capture_by(CaptureBy);
561                fn visit_closure_binder(ClosureBinder);
562                fn visit_contract(FnContract);
563                fn visit_coroutine_kind(CoroutineKind);
564                fn visit_crate(Crate);
565                fn visit_expr(Expr);
566                fn visit_expr_field(ExprField);
567                fn visit_field_def(FieldDef);
568                fn visit_fn_decl(FnDecl);
569                fn visit_fn_header(FnHeader);
570                fn visit_fn_ret_ty(FnRetTy);
571                //fn visit_foreign_item(ForeignItem);
572                fn visit_foreign_mod(ForeignMod);
573                fn visit_format_args(FormatArgs);
574                fn visit_generic_arg(GenericArg);
575                fn visit_generic_args(GenericArgs);
576                fn visit_generic_param(GenericParam);
577                fn visit_generics(Generics);
578                fn visit_inline_asm(InlineAsm);
579                fn visit_inline_asm_sym(InlineAsmSym);
580                //fn visit_item(Item);
581                fn visit_label(Label);
582                fn visit_lifetime(Lifetime, _ctxt: LifetimeCtxt);
583                fn visit_local(Local);
584                fn visit_mac_call(MacCall);
585                fn visit_macro_def(MacroDef);
586                fn visit_param_bound(GenericBound, _ctxt: BoundKind);
587                fn visit_param(Param);
588                fn visit_pat_field(PatField);
589                fn visit_path(Path);
590                fn visit_path_segment(PathSegment);
591                fn visit_pat(Pat);
592                fn visit_poly_trait_ref(PolyTraitRef);
593                fn visit_precise_capturing_arg(PreciseCapturingArg);
594                fn visit_qself(QSelf);
595                fn visit_trait_ref(TraitRef);
596                fn visit_ty_pat(TyPat);
597                fn visit_ty(Ty);
598                fn visit_use_tree(UseTree);
599                fn visit_variant_data(VariantData);
600                fn visit_variant(Variant);
601                fn visit_vis(Visibility);
602                fn visit_where_predicate_kind(WherePredicateKind);
603                fn visit_where_predicate(WherePredicate);
604            );
605
606            // We want `Visitor` to take the `NodeId` by value.
607            fn visit_id(&mut self, _id: $(&$mut)? NodeId) -> Self::Result {
608                $(impl_visitable!(
609                    |&$lt self: NodeId, visitor: &mut V, _extra: ()| {
610                        visitor.visit_id(*self)
611                    }
612                );)?
613                $(impl_visitable!(
614                    |&$mut self: NodeId, visitor: &mut V, _extra: ()| {
615                        visitor.visit_id(self)
616                    }
617                );)?
618                Self::Result::output()
619            }
620
621            /// This method is a hack to workaround unstable of `stmt_expr_attributes`.
622            /// It can be removed once that feature is stabilized.
623            fn visit_method_receiver_expr(&mut self, ex: &$($lt)? $($mut)? Expr) -> Self::Result {
624                self.visit_expr(ex)
625            }
626
627            fn visit_item(&mut self, item: &$($lt)? $($mut)? Item) -> Self::Result {
628                impl_visitable!(|&$($lt)? $($mut)? self: Item, vis: &mut V, _extra: ()| {
629                    vis.visit_item(self)
630                });
631                walk_item(self, item)
632            }
633
634            fn visit_foreign_item(&mut self, item: &$($lt)? $($mut)? ForeignItem) -> Self::Result {
635                impl_visitable!(|&$($lt)? $($mut)? self: ForeignItem, vis: &mut V, _extra: ()| {
636                    vis.visit_foreign_item(self)
637                });
638                walk_item(self, item)
639            }
640
641            fn visit_assoc_item(&mut self, item: &$($lt)? $($mut)? AssocItem, ctxt: AssocCtxt) -> Self::Result {
642                impl_visitable!(|&$($lt)? $($mut)? self: AssocItem, vis: &mut V, ctxt: AssocCtxt| {
643                    vis.visit_assoc_item(self, ctxt)
644                });
645                walk_assoc_item(self, item, ctxt)
646            }
647
648            // for `MutVisitor`: `Span` and `NodeId` are mutated at the caller site.
649            fn visit_fn(
650                &mut self,
651                fk: FnKind<$($lt)? $(${ignore($mut)} '_)?>,
652                _: &AttrVec,
653                _: Span,
654                _: NodeId,
655            ) -> Self::Result {
656                walk_fn(self, fk)
657            }
658
659            // (non-mut) `Visitor`-only methods
660            $(
661                fn visit_stmt(&mut self, s: &$lt Stmt) -> Self::Result {
662                    walk_stmt(self, s)
663                }
664
665                fn visit_nested_use_tree(&mut self, use_tree: &$lt UseTree, id: NodeId) -> Self::Result {
666                    try_visit!(self.visit_id(id));
667                    self.visit_use_tree(use_tree)
668                }
669            )?
670
671            // `MutVisitor`-only methods
672            $(
673                // Span visiting is no longer used, but we keep it for now,
674                // in case it's needed for something like #127241.
675                #[inline]
676                fn visit_span(&mut self, _sp: &$mut Span) {
677                    impl_visitable!(|&mut self: Span, visitor: &mut V, _extra: ()| {
678                        visitor.visit_span(self)
679                    });
680                    // Do nothing.
681                }
682
683                fn flat_map_foreign_item(&mut self, ni: Box<ForeignItem>) -> SmallVec<[Box<ForeignItem>; 1]> {
684                    walk_flat_map_foreign_item(self, ni)
685                }
686
687                fn flat_map_item(&mut self, i: Box<Item>) -> SmallVec<[Box<Item>; 1]> {
688                    walk_flat_map_item(self, i)
689                }
690
691                fn flat_map_field_def(&mut self, fd: FieldDef) -> SmallVec<[FieldDef; 1]> {
692                    walk_flat_map_field_def(self, fd)
693                }
694
695                fn flat_map_assoc_item(
696                    &mut self,
697                    i: Box<AssocItem>,
698                    ctxt: AssocCtxt,
699                ) -> SmallVec<[Box<AssocItem>; 1]> {
700                    walk_flat_map_assoc_item(self, i, ctxt)
701                }
702
703                fn flat_map_stmt(&mut self, s: Stmt) -> SmallVec<[Stmt; 1]> {
704                    walk_flat_map_stmt(self, s)
705                }
706
707                fn flat_map_arm(&mut self, arm: Arm) -> SmallVec<[Arm; 1]> {
708                    walk_flat_map_arm(self, arm)
709                }
710
711                fn filter_map_expr(&mut self, e: Box<Expr>) -> Option<Box<Expr>> {
712                    walk_filter_map_expr(self, e)
713                }
714
715                fn flat_map_variant(&mut self, v: Variant) -> SmallVec<[Variant; 1]> {
716                    walk_flat_map_variant(self, v)
717                }
718
719                fn flat_map_param(&mut self, param: Param) -> SmallVec<[Param; 1]> {
720                    walk_flat_map_param(self, param)
721                }
722
723                fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> {
724                    walk_flat_map_generic_param(self, param)
725                }
726
727                fn flat_map_expr_field(&mut self, f: ExprField) -> SmallVec<[ExprField; 1]> {
728                    walk_flat_map_expr_field(self, f)
729                }
730
731                fn flat_map_where_predicate(
732                    &mut self,
733                    where_predicate: WherePredicate,
734                ) -> SmallVec<[WherePredicate; 1]> {
735                    walk_flat_map_where_predicate(self, where_predicate)
736                }
737
738                fn flat_map_pat_field(&mut self, fp: PatField) -> SmallVec<[PatField; 1]> {
739                    walk_flat_map_pat_field(self, fp)
740                }
741            )?
742        }
743
744        pub trait WalkItemKind {
745            type Ctxt;
746            fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
747                &$($lt)? $($mut)? self,
748                attrs: &AttrVec,
749                span: Span,
750                id: NodeId,
751                visibility: &$($lt)? $($mut)? Visibility,
752                ctxt: Self::Ctxt,
753                vis: &mut V,
754            ) -> V::Result;
755        }
756
757        // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier
758        $(${ignore($lt)}
759            #[expect(unused, rustc::pass_by_value)]
760            #[inline]
761        )?
762        fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, span: &$($lt)? $($mut)? Span) -> V::Result {
763            $(${ignore($mut)} vis.visit_span(span))?;
764            V::Result::output()
765        }
766
767        $(impl_visitable!(|&$lt self: ThinVec<(UseTree, NodeId)>, vis: &mut V, _extra: ()| {
768            for (nested_tree, nested_id) in self {
769                try_visit!(vis.visit_nested_use_tree(nested_tree, *nested_id));
770            }
771            V::Result::output()
772        });)?
773        $(impl_visitable_list!(<$mut> ThinVec<(UseTree, NodeId)>,);)?
774
775        fn walk_item_inner<$($lt,)? K: WalkItemKind, V: $Visitor$(<$lt>)?>(
776            visitor: &mut V,
777            item: &$($mut)? $($lt)? Item<K>,
778            ctxt: K::Ctxt,
779        ) -> V::Result {
780            let Item { attrs, id, kind, vis, span, tokens: _ } = item;
781            visit_visitable!($($mut)? visitor, id, attrs, vis);
782            try_visit!(kind.walk(attrs, *span, *id, vis, ctxt, visitor));
783            visit_visitable!($($mut)? visitor, span);
784            V::Result::output()
785        }
786
787        // Do not implement `Walkable`/`MutWalkable` for *Item to avoid confusion.
788        pub fn walk_item<$($lt,)? K: WalkItemKind<Ctxt = ()>, V: $Visitor$(<$lt>)?>(
789            visitor: &mut V,
790            item: &$($mut)? $($lt)? Item<K>,
791        ) -> V::Result {
792            walk_item_inner(visitor, item, ())
793        }
794
795        // Do not implement `Walkable`/`MutWalkable` for *Item to avoid confusion.
796        pub fn walk_assoc_item<$($lt,)? K: WalkItemKind<Ctxt = AssocCtxt>, V: $Visitor$(<$lt>)?>(
797            visitor: &mut V,
798            item: &$($mut)? $($lt)? Item<K>,
799            ctxt: AssocCtxt,
800        ) -> V::Result {
801            walk_item_inner(visitor, item, ctxt)
802        }
803
804        impl WalkItemKind for ItemKind {
805            type Ctxt = ();
806            fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
807                &$($lt)? $($mut)? self,
808                attrs: &AttrVec,
809                span: Span,
810                id: NodeId,
811                visibility: &$($lt)? $($mut)? Visibility,
812                _ctxt: Self::Ctxt,
813                vis: &mut V,
814            ) -> V::Result {
815                match self {
816                    ItemKind::Fn(func) => {
817                        let kind = FnKind::Fn(FnCtxt::Free, visibility, &$($mut)? *func);
818                        try_visit!(vis.visit_fn(kind, attrs, span, id));
819                    }
820                    ItemKind::ExternCrate(orig_name, ident) =>
821                        visit_visitable!($($mut)? vis, orig_name, ident),
822                    ItemKind::Use(use_tree) =>
823                        visit_visitable!($($mut)? vis, use_tree),
824                    ItemKind::Static(item) =>
825                        visit_visitable!($($mut)? vis, item),
826                    ItemKind::Const(item) =>
827                        visit_visitable!($($mut)? vis, item),
828                    ItemKind::Mod(safety, ident, mod_kind) =>
829                        visit_visitable!($($mut)? vis, safety, ident, mod_kind),
830                    ItemKind::ForeignMod(nm) =>
831                        visit_visitable!($($mut)? vis, nm),
832                    ItemKind::GlobalAsm(asm) =>
833                        visit_visitable!($($mut)? vis, asm),
834                    ItemKind::TyAlias(ty_alias) =>
835                        visit_visitable!($($mut)? vis, ty_alias),
836                    ItemKind::Enum(ident, generics, enum_definition) =>
837                        visit_visitable!($($mut)? vis, ident, generics, enum_definition),
838                    ItemKind::Struct(ident, generics, variant_data)
839                    | ItemKind::Union(ident, generics, variant_data) =>
840                        visit_visitable!($($mut)? vis, ident, generics, variant_data),
841                    ItemKind::Impl(impl_) =>
842                        visit_visitable!($($mut)? vis, impl_),
843                    ItemKind::Trait(trait_) =>
844                        visit_visitable!($($mut)? vis, trait_),
845                    ItemKind::TraitAlias(box TraitAlias { constness, ident, generics, bounds}) => {
846                        visit_visitable!($($mut)? vis, constness, ident, generics);
847                        visit_visitable_with!($($mut)? vis, bounds, BoundKind::Bound)
848                    }
849                    ItemKind::MacCall(m) =>
850                        visit_visitable!($($mut)? vis, m),
851                    ItemKind::MacroDef(ident, def) =>
852                        visit_visitable!($($mut)? vis, ident, def),
853                    ItemKind::Delegation(delegation) =>
854                        visit_visitable!($($mut)? vis, delegation),
855                    ItemKind::DelegationMac(dm) =>
856                        visit_visitable!($($mut)? vis, dm),
857                }
858                V::Result::output()
859            }
860        }
861
862        impl WalkItemKind for AssocItemKind {
863            type Ctxt = AssocCtxt;
864            fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
865                &$($lt)? $($mut)? self,
866                attrs: &AttrVec,
867                span: Span,
868                id: NodeId,
869                visibility: &$($lt)? $($mut)? Visibility,
870                ctxt: Self::Ctxt,
871                vis: &mut V,
872            ) -> V::Result {
873                match self {
874                    AssocItemKind::Const(item) =>
875                        visit_visitable!($($mut)? vis, item),
876                    AssocItemKind::Fn(func) => {
877                        let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), visibility, &$($mut)? *func);
878                        try_visit!(vis.visit_fn(kind, attrs, span, id))
879                    }
880                    AssocItemKind::Type(alias) =>
881                        visit_visitable!($($mut)? vis, alias),
882                    AssocItemKind::MacCall(mac) =>
883                        visit_visitable!($($mut)? vis, mac),
884                    AssocItemKind::Delegation(delegation) =>
885                        visit_visitable!($($mut)? vis, delegation),
886                    AssocItemKind::DelegationMac(dm) =>
887                        visit_visitable!($($mut)? vis, dm),
888                }
889                V::Result::output()
890            }
891        }
892
893        impl WalkItemKind for ForeignItemKind {
894            type Ctxt = ();
895            fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
896                &$($lt)? $($mut)? self,
897                attrs: &AttrVec,
898                span: Span,
899                id: NodeId,
900                visibility: &$($lt)? $($mut)? Visibility,
901                _ctxt: Self::Ctxt,
902                vis: &mut V,
903            ) -> V::Result {
904                match self {
905                    ForeignItemKind::Static(item) =>
906                        visit_visitable!($($mut)? vis, item),
907                    ForeignItemKind::Fn(func) => {
908                        let kind = FnKind::Fn(FnCtxt::Foreign, visibility, &$($mut)?*func);
909                        try_visit!(vis.visit_fn(kind, attrs, span, id))
910                    }
911                    ForeignItemKind::TyAlias(alias) =>
912                        visit_visitable!($($mut)? vis, alias),
913                    ForeignItemKind::MacCall(mac) =>
914                        visit_visitable!($($mut)? vis, mac),
915                }
916                V::Result::output()
917            }
918        }
919
920        pub fn walk_fn<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, kind: FnKind<$($lt)? $(${ignore($mut)} '_)?>) -> V::Result {
921            match kind {
922                FnKind::Fn(
923                    _ctxt,
924                    // Visibility is visited as a part of the item.
925                    _vis,
926                    Fn { defaultness, ident, sig, generics, contract, body, define_opaque, eii_impls },
927                ) => {
928                    let FnSig { header, decl, span } = sig;
929                    visit_visitable!($($mut)? vis,
930                        defaultness, ident, header, generics, decl,
931                        contract, body, span, define_opaque, eii_impls
932                    );
933                }
934                FnKind::Closure(binder, coroutine_kind, decl, body) =>
935                    visit_visitable!($($mut)? vis, binder, coroutine_kind, decl, body),
936            }
937            V::Result::output()
938        }
939
940        impl_walkable!(|&$($mut)? $($lt)? self: Impl, vis: &mut V| {
941            let Impl { generics, of_trait, self_ty, items, constness: _ } = self;
942            try_visit!(vis.visit_generics(generics));
943            if let Some(box of_trait) = of_trait {
944                let TraitImplHeader { defaultness, safety, polarity, trait_ref } = of_trait;
945                visit_visitable!($($mut)? vis, defaultness, safety, polarity, trait_ref);
946            }
947            try_visit!(vis.visit_ty(self_ty));
948            visit_visitable_with!($($mut)? vis, items, AssocCtxt::Impl { of_trait: of_trait.is_some() });
949            V::Result::output()
950        });
951
952        // Special case to call `visit_method_receiver_expr`.
953        impl_walkable!(|&$($mut)? $($lt)? self: MethodCall, vis: &mut V| {
954            let MethodCall { seg, receiver, args, span } = self;
955            try_visit!(vis.visit_method_receiver_expr(receiver));
956            visit_visitable!($($mut)? vis, seg, args, span);
957            V::Result::output()
958        });
959
960        impl_walkable!(|&$($mut)? $($lt)? self: Expr, vis: &mut V| {
961            let Expr { id, kind, span, attrs, tokens: _ } = self;
962            visit_visitable!($($mut)? vis, id, attrs);
963            match kind {
964                ExprKind::Array(exprs) =>
965                    visit_visitable!($($mut)? vis, exprs),
966                ExprKind::ConstBlock(anon_const) =>
967                    visit_visitable!($($mut)? vis, anon_const),
968                ExprKind::Repeat(element, count) =>
969                    visit_visitable!($($mut)? vis, element, count),
970                ExprKind::Struct(se) =>
971                    visit_visitable!($($mut)? vis, se),
972                ExprKind::Tup(exprs) =>
973                    visit_visitable!($($mut)? vis, exprs),
974                ExprKind::Call(callee_expression, arguments) =>
975                    visit_visitable!($($mut)? vis, callee_expression, arguments),
976                ExprKind::MethodCall(mc) =>
977                    visit_visitable!($($mut)? vis, mc),
978                ExprKind::Binary(op, lhs, rhs) =>
979                    visit_visitable!($($mut)? vis, op, lhs, rhs),
980                ExprKind::AddrOf(kind, mutbl, subexpression) =>
981                    visit_visitable!($($mut)? vis, kind, mutbl, subexpression),
982                ExprKind::Unary(op, subexpression) =>
983                    visit_visitable!($($mut)? vis, op, subexpression),
984                ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) =>
985                    visit_visitable!($($mut)? vis, subexpression, typ),
986                ExprKind::Let(pat, expr, span, _recovered) =>
987                    visit_visitable!($($mut)? vis, pat, expr, span),
988                ExprKind::If(head_expression, if_block, optional_else) =>
989                    visit_visitable!($($mut)? vis, head_expression, if_block, optional_else),
990                ExprKind::While(subexpression, block, opt_label) =>
991                    visit_visitable!($($mut)? vis, subexpression, block, opt_label),
992                ExprKind::ForLoop { pat, iter, body, label, kind } =>
993                    visit_visitable!($($mut)? vis, pat, iter, body, label, kind),
994                ExprKind::Loop(block, opt_label, span) =>
995                    visit_visitable!($($mut)? vis, block, opt_label, span),
996                ExprKind::Match(subexpression, arms, kind) =>
997                    visit_visitable!($($mut)? vis, subexpression, arms, kind),
998                ExprKind::Closure(box Closure {
999                    binder,
1000                    capture_clause,
1001                    coroutine_kind,
1002                    constness,
1003                    movability,
1004                    fn_decl,
1005                    body,
1006                    fn_decl_span,
1007                    fn_arg_span,
1008                }) => {
1009                    visit_visitable!($($mut)? vis, constness, movability, capture_clause);
1010                    let kind = FnKind::Closure(binder, coroutine_kind, fn_decl, body);
1011                    try_visit!(vis.visit_fn(kind, attrs, *span, *id));
1012                    visit_visitable!($($mut)? vis, fn_decl_span, fn_arg_span);
1013                }
1014                ExprKind::Block(block, opt_label) =>
1015                    visit_visitable!($($mut)? vis, block, opt_label),
1016                ExprKind::Gen(capt, body, kind, decl_span) =>
1017                    visit_visitable!($($mut)? vis, capt, body, kind, decl_span),
1018                ExprKind::Await(expr, span) | ExprKind::Use(expr, span) =>
1019                    visit_visitable!($($mut)? vis, expr, span),
1020                ExprKind::Assign(lhs, rhs, span) =>
1021                    visit_visitable!($($mut)? vis, lhs, rhs, span),
1022                ExprKind::AssignOp(op, lhs, rhs) =>
1023                    visit_visitable!($($mut)? vis, op, lhs, rhs),
1024                ExprKind::Field(subexpression, ident) =>
1025                    visit_visitable!($($mut)? vis, subexpression, ident),
1026                ExprKind::Index(main_expression, index_expression, span) =>
1027                    visit_visitable!($($mut)? vis, main_expression, index_expression, span),
1028                ExprKind::Range(start, end, limit) =>
1029                    visit_visitable!($($mut)? vis, start, end, limit),
1030                ExprKind::Underscore => {}
1031                ExprKind::Path(maybe_qself, path) =>
1032                    visit_visitable!($($mut)? vis, maybe_qself, path),
1033                ExprKind::Break(opt_label, opt_expr) =>
1034                    visit_visitable!($($mut)? vis, opt_label, opt_expr),
1035                ExprKind::Continue(opt_label) =>
1036                    visit_visitable!($($mut)? vis, opt_label),
1037                ExprKind::Ret(optional_expression) | ExprKind::Yeet(optional_expression) =>
1038                    visit_visitable!($($mut)? vis, optional_expression),
1039                ExprKind::Become(expr) =>
1040                    visit_visitable!($($mut)? vis, expr),
1041                ExprKind::MacCall(mac) =>
1042                    visit_visitable!($($mut)? vis, mac),
1043                ExprKind::Paren(subexpression) =>
1044                    visit_visitable!($($mut)? vis, subexpression),
1045                ExprKind::InlineAsm(asm) =>
1046                    visit_visitable!($($mut)? vis, asm),
1047                ExprKind::FormatArgs(f) =>
1048                    visit_visitable!($($mut)? vis, f),
1049                ExprKind::OffsetOf(container, fields) =>
1050                    visit_visitable!($($mut)? vis, container, fields),
1051                ExprKind::Yield(kind) =>
1052                    visit_visitable!($($mut)? vis, kind),
1053                ExprKind::Try(subexpression) =>
1054                    visit_visitable!($($mut)? vis, subexpression),
1055                ExprKind::TryBlock(body, optional_type) =>
1056                    visit_visitable!($($mut)? vis, body, optional_type),
1057                ExprKind::Lit(token) =>
1058                    visit_visitable!($($mut)? vis, token),
1059                ExprKind::IncludedBytes(bytes) =>
1060                    visit_visitable!($($mut)? vis, bytes),
1061                ExprKind::UnsafeBinderCast(kind, expr, ty) =>
1062                    visit_visitable!($($mut)? vis, kind, expr, ty),
1063                ExprKind::Err(_guar) => {}
1064                ExprKind::Dummy => {}
1065            }
1066
1067            visit_span(vis, span)
1068        });
1069
1070        define_named_walk!($(($mut))? $Visitor$(<$lt>)?
1071            pub fn walk_anon_const(AnonConst);
1072            pub fn walk_arm(Arm);
1073            //pub fn walk_assoc_item(AssocItem, _ctxt: AssocCtxt);
1074            pub fn walk_assoc_item_constraint(AssocItemConstraint);
1075            pub fn walk_attribute(Attribute);
1076            pub fn walk_block(Block);
1077            //pub fn walk_nested_use_tree((UseTree, NodeId));
1078            pub fn walk_capture_by(CaptureBy);
1079            pub fn walk_closure_binder(ClosureBinder);
1080            pub fn walk_contract(FnContract);
1081            pub fn walk_coroutine_kind(CoroutineKind);
1082            pub fn walk_crate(Crate);
1083            pub fn walk_expr(Expr);
1084            pub fn walk_expr_field(ExprField);
1085            pub fn walk_field_def(FieldDef);
1086            pub fn walk_fn_decl(FnDecl);
1087            pub fn walk_fn_header(FnHeader);
1088            pub fn walk_fn_ret_ty(FnRetTy);
1089            //pub fn walk_foreign_item(ForeignItem);
1090            pub fn walk_foreign_mod(ForeignMod);
1091            pub fn walk_format_args(FormatArgs);
1092            pub fn walk_generic_arg(GenericArg);
1093            pub fn walk_generic_args(GenericArgs);
1094            pub fn walk_generic_param(GenericParam);
1095            pub fn walk_generics(Generics);
1096            pub fn walk_inline_asm(InlineAsm);
1097            pub fn walk_inline_asm_sym(InlineAsmSym);
1098            //pub fn walk_item(Item);
1099            pub fn walk_label(Label);
1100            pub fn walk_lifetime(Lifetime);
1101            pub fn walk_local(Local);
1102            pub fn walk_mac(MacCall);
1103            pub fn walk_macro_def(MacroDef);
1104            pub fn walk_param_bound(GenericBound);
1105            pub fn walk_param(Param);
1106            pub fn walk_pat_field(PatField);
1107            pub fn walk_path(Path);
1108            pub fn walk_path_segment(PathSegment);
1109            pub fn walk_pat(Pat);
1110            pub fn walk_poly_trait_ref(PolyTraitRef);
1111            pub fn walk_precise_capturing_arg(PreciseCapturingArg);
1112            pub fn walk_qself(QSelf);
1113            pub fn walk_trait_ref(TraitRef);
1114            pub fn walk_ty_pat(TyPat);
1115            pub fn walk_ty(Ty);
1116            pub fn walk_use_tree(UseTree);
1117            pub fn walk_variant_data(VariantData);
1118            pub fn walk_variant(Variant);
1119            pub fn walk_vis(Visibility);
1120            pub fn walk_where_predicate_kind(WherePredicateKind);
1121            pub fn walk_where_predicate(WherePredicate);
1122        );
1123    };
1124}
1125
1126common_visitor_and_walkers!(Visitor<'a>);
1127
1128macro_rules! generate_list_visit_fns {
1129    ($($name:ident, $Ty:ty, $visit_fn:ident$(, $param:ident: $ParamTy:ty)*;)+) => {
1130        $(
1131            #[allow(unused_parens)]
1132            impl<'a, V: Visitor<'a>> Visitable<'a, V> for ThinVec<$Ty> {
1133                type Extra = ($($ParamTy),*);
1134
1135                #[inline]
1136                fn visit(
1137                    &'a self,
1138                    visitor: &mut V,
1139                    ($($param),*): Self::Extra,
1140                ) -> V::Result {
1141                    $name(visitor, self $(, $param)*)
1142                }
1143            }
1144
1145            fn $name<'a, V: Visitor<'a>>(
1146                vis: &mut V,
1147                values: &'a ThinVec<$Ty>,
1148                $(
1149                    $param: $ParamTy,
1150                )*
1151            ) -> V::Result {
1152                walk_list!(vis, $visit_fn, values$(,$param)*);
1153                V::Result::output()
1154            }
1155        )+
1156    }
1157}
1158
1159generate_list_visit_fns! {
1160    visit_items, Box<Item>, visit_item;
1161    visit_foreign_items, Box<ForeignItem>, visit_foreign_item;
1162    visit_generic_params, GenericParam, visit_generic_param;
1163    visit_stmts, Stmt, visit_stmt;
1164    visit_exprs, Box<Expr>, visit_expr;
1165    visit_expr_fields, ExprField, visit_expr_field;
1166    visit_pat_fields, PatField, visit_pat_field;
1167    visit_variants, Variant, visit_variant;
1168    visit_assoc_items, Box<AssocItem>, visit_assoc_item, ctxt: AssocCtxt;
1169    visit_where_predicates, WherePredicate, visit_where_predicate;
1170    visit_params, Param, visit_param;
1171    visit_field_defs, FieldDef, visit_field_def;
1172    visit_arms, Arm, visit_arm;
1173}
1174
1175pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result {
1176    let Stmt { id, kind, span: _ } = statement;
1177    try_visit!(visitor.visit_id(*id));
1178    match kind {
1179        StmtKind::Let(local) => try_visit!(visitor.visit_local(local)),
1180        StmtKind::Item(item) => try_visit!(visitor.visit_item(item)),
1181        StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)),
1182        StmtKind::Empty => {}
1183        StmtKind::MacCall(mac) => {
1184            let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac;
1185            walk_list!(visitor, visit_attribute, attrs);
1186            try_visit!(visitor.visit_mac_call(mac));
1187        }
1188    }
1189    V::Result::output()
1190}