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