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