about summary refs log tree commit diff
path: root/compiler/rustc_ast/src/visit.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_ast/src/visit.rs')
-rw-r--r--compiler/rustc_ast/src/visit.rs1873
1 files changed, 1060 insertions, 813 deletions
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index d2f22b04a67..d0c2b2bf68b 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -15,11 +15,13 @@
 
 pub use rustc_ast_ir::visit::VisitorResult;
 pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
+use rustc_span::source_map::Spanned;
 use rustc_span::{Ident, Span};
 use thin_vec::ThinVec;
 
 use crate::ast::*;
 use crate::ptr::P;
+use crate::tokenstream::DelimSpan;
 
 #[derive(Copy, Clone, Debug, PartialEq)]
 pub enum AssocCtxt {
@@ -64,45 +66,6 @@ impl BoundKind {
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum FnKind<'a> {
-    /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
-    Fn(FnCtxt, &'a Visibility, &'a Fn),
-
-    /// E.g., `|x, y| body`.
-    Closure(&'a ClosureBinder, &'a Option<CoroutineKind>, &'a FnDecl, &'a Expr),
-}
-
-impl<'a> FnKind<'a> {
-    pub fn header(&self) -> Option<&'a FnHeader> {
-        match *self {
-            FnKind::Fn(_, _, Fn { sig, .. }) => Some(&sig.header),
-            FnKind::Closure(..) => None,
-        }
-    }
-
-    pub fn ident(&self) -> Option<&Ident> {
-        match self {
-            FnKind::Fn(_, _, Fn { ident, .. }) => Some(ident),
-            _ => None,
-        }
-    }
-
-    pub fn decl(&self) -> &'a FnDecl {
-        match self {
-            FnKind::Fn(_, _, Fn { sig, .. }) => &sig.decl,
-            FnKind::Closure(_, _, decl, _) => decl,
-        }
-    }
-
-    pub fn ctxt(&self) -> Option<FnCtxt> {
-        match self {
-            FnKind::Fn(ctxt, ..) => Some(*ctxt),
-            FnKind::Closure(..) => None,
-        }
-    }
-}
-
-#[derive(Copy, Clone, Debug)]
 pub enum LifetimeCtxt {
     /// Appears in a reference type.
     Ref,
@@ -112,206 +75,405 @@ pub enum LifetimeCtxt {
     GenericArg,
 }
 
-/// Each method of the `Visitor` trait is a hook to be potentially
-/// overridden. Each method's default implementation recursively visits
-/// the substructure of the input via the corresponding `walk` method;
-/// e.g., the `visit_item` method by default calls `visit::walk_item`.
-///
-/// If you want to ensure that your code handles every variant
-/// explicitly, you need to override each method. (And you also need
-/// to monitor future changes to `Visitor` in case a new method with a
-/// new default implementation gets introduced.)
-///
-/// Every `walk_*` method uses deconstruction to access fields of structs and
-/// enums. This will result in a compile error if a field is added, which makes
-/// it more likely the appropriate visit call will be added for it.
-pub trait Visitor<'ast>: Sized {
-    /// The result type of the `visit_*` methods. Can be either `()`,
-    /// or `ControlFlow<T>`.
-    type Result: VisitorResult = ();
-
-    fn visit_ident(&mut self, _ident: &'ast Ident) -> Self::Result {
-        Self::Result::output()
-    }
-    fn visit_foreign_mod(&mut self, nm: &'ast ForeignMod) -> Self::Result {
-        walk_foreign_mod(self, nm)
-    }
-    fn visit_foreign_item(&mut self, i: &'ast ForeignItem) -> Self::Result {
-        walk_item(self, i)
-    }
-    fn visit_item(&mut self, i: &'ast Item) -> Self::Result {
-        walk_item(self, i)
-    }
-    fn visit_local(&mut self, l: &'ast Local) -> Self::Result {
-        walk_local(self, l)
-    }
-    fn visit_block(&mut self, b: &'ast Block) -> Self::Result {
-        walk_block(self, b)
-    }
-    fn visit_stmt(&mut self, s: &'ast Stmt) -> Self::Result {
-        walk_stmt(self, s)
-    }
-    fn visit_param(&mut self, param: &'ast Param) -> Self::Result {
-        walk_param(self, param)
-    }
-    fn visit_arm(&mut self, a: &'ast Arm) -> Self::Result {
-        walk_arm(self, a)
-    }
-    fn visit_pat(&mut self, p: &'ast Pat) -> Self::Result {
-        walk_pat(self, p)
-    }
-    fn visit_anon_const(&mut self, c: &'ast AnonConst) -> Self::Result {
-        walk_anon_const(self, c)
-    }
-    fn visit_expr(&mut self, ex: &'ast Expr) -> Self::Result {
-        walk_expr(self, ex)
-    }
-    /// This method is a hack to workaround unstable of `stmt_expr_attributes`.
-    /// It can be removed once that feature is stabilized.
-    fn visit_method_receiver_expr(&mut self, ex: &'ast Expr) -> Self::Result {
-        self.visit_expr(ex)
-    }
-    fn visit_ty(&mut self, t: &'ast Ty) -> Self::Result {
-        walk_ty(self, t)
-    }
-    fn visit_ty_pat(&mut self, t: &'ast TyPat) -> Self::Result {
-        walk_ty_pat(self, t)
-    }
-    fn visit_generic_param(&mut self, param: &'ast GenericParam) -> Self::Result {
-        walk_generic_param(self, param)
-    }
-    fn visit_generics(&mut self, g: &'ast Generics) -> Self::Result {
-        walk_generics(self, g)
-    }
-    fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) -> Self::Result {
-        walk_closure_binder(self, b)
-    }
-    fn visit_contract(&mut self, c: &'ast FnContract) -> Self::Result {
-        walk_contract(self, c)
-    }
-    fn visit_where_predicate(&mut self, p: &'ast WherePredicate) -> Self::Result {
-        walk_where_predicate(self, p)
-    }
-    fn visit_where_predicate_kind(&mut self, k: &'ast WherePredicateKind) -> Self::Result {
-        walk_where_predicate_kind(self, k)
-    }
-    fn visit_fn(&mut self, fk: FnKind<'ast>, _: Span, _: NodeId) -> Self::Result {
-        walk_fn(self, fk)
-    }
-    fn visit_assoc_item(&mut self, i: &'ast AssocItem, ctxt: AssocCtxt) -> Self::Result {
-        walk_assoc_item(self, i, ctxt)
-    }
-    fn visit_trait_ref(&mut self, t: &'ast TraitRef) -> Self::Result {
-        walk_trait_ref(self, t)
-    }
-    fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) -> Self::Result {
-        walk_param_bound(self, bounds)
-    }
-    fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) -> Self::Result {
-        walk_precise_capturing_arg(self, arg)
-    }
-    fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) -> Self::Result {
-        walk_poly_trait_ref(self, t)
-    }
-    fn visit_variant_data(&mut self, s: &'ast VariantData) -> Self::Result {
-        walk_variant_data(self, s)
-    }
-    fn visit_field_def(&mut self, s: &'ast FieldDef) -> Self::Result {
-        walk_field_def(self, s)
-    }
-    fn visit_variant(&mut self, v: &'ast Variant) -> Self::Result {
-        walk_variant(self, v)
-    }
-    fn visit_variant_discr(&mut self, discr: &'ast AnonConst) -> Self::Result {
-        self.visit_anon_const(discr)
-    }
-    fn visit_label(&mut self, label: &'ast Label) -> Self::Result {
-        walk_label(self, label)
-    }
-    fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) -> Self::Result {
-        walk_lifetime(self, lifetime)
-    }
-    fn visit_mac_call(&mut self, mac: &'ast MacCall) -> Self::Result {
-        walk_mac(self, mac)
-    }
-    fn visit_id(&mut self, _id: NodeId) -> Self::Result {
-        Self::Result::output()
-    }
-    fn visit_macro_def(&mut self, _mac: &'ast MacroDef) -> Self::Result {
-        Self::Result::output()
-    }
-    fn visit_path(&mut self, path: &'ast Path) -> Self::Result {
-        walk_path(self, path)
-    }
-    fn visit_use_tree(&mut self, use_tree: &'ast UseTree) -> Self::Result {
-        walk_use_tree(self, use_tree)
-    }
-    fn visit_nested_use_tree(&mut self, use_tree: &'ast UseTree, id: NodeId) -> Self::Result {
-        try_visit!(self.visit_id(id));
-        self.visit_use_tree(use_tree)
-    }
-    fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) -> Self::Result {
-        walk_path_segment(self, path_segment)
-    }
-    fn visit_generic_args(&mut self, generic_args: &'ast GenericArgs) -> Self::Result {
-        walk_generic_args(self, generic_args)
-    }
-    fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) -> Self::Result {
-        walk_generic_arg(self, generic_arg)
-    }
-    fn visit_assoc_item_constraint(
-        &mut self,
-        constraint: &'ast AssocItemConstraint,
-    ) -> Self::Result {
-        walk_assoc_item_constraint(self, constraint)
-    }
-    fn visit_attribute(&mut self, attr: &'ast Attribute) -> Self::Result {
-        walk_attribute(self, attr)
-    }
-    fn visit_vis(&mut self, vis: &'ast Visibility) -> Self::Result {
-        walk_vis(self, vis)
-    }
-    fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FnRetTy) -> Self::Result {
-        walk_fn_ret_ty(self, ret_ty)
-    }
-    fn visit_fn_header(&mut self, header: &'ast FnHeader) -> Self::Result {
-        walk_fn_header(self, header)
-    }
-    fn visit_expr_field(&mut self, f: &'ast ExprField) -> Self::Result {
-        walk_expr_field(self, f)
-    }
-    fn visit_pat_field(&mut self, fp: &'ast PatField) -> Self::Result {
-        walk_pat_field(self, fp)
-    }
-    fn visit_crate(&mut self, krate: &'ast Crate) -> Self::Result {
-        walk_crate(self, krate)
-    }
-    fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) -> Self::Result {
-        walk_inline_asm(self, asm)
-    }
-    fn visit_format_args(&mut self, fmt: &'ast FormatArgs) -> Self::Result {
-        walk_format_args(self, fmt)
-    }
-    fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) -> Self::Result {
-        walk_inline_asm_sym(self, sym)
-    }
-    fn visit_capture_by(&mut self, _capture_by: &'ast CaptureBy) -> Self::Result {
-        Self::Result::output()
-    }
-    fn visit_coroutine_kind(&mut self, coroutine_kind: &'ast CoroutineKind) -> Self::Result {
-        walk_coroutine_kind(self, coroutine_kind)
-    }
-    fn visit_fn_decl(&mut self, fn_decl: &'ast FnDecl) -> Self::Result {
-        walk_fn_decl(self, fn_decl)
-    }
-    fn visit_qself(&mut self, qs: &'ast Option<P<QSelf>>) -> Self::Result {
-        walk_qself(self, qs)
-    }
-}
-
 #[macro_export]
 macro_rules! common_visitor_and_walkers {
     ($(($mut: ident))? $Visitor:ident$(<$lt:lifetime>)?) => {
+        $(${ignore($lt)}
+            #[derive(Copy, Clone)]
+        )?
+        #[derive(Debug)]
+        pub enum FnKind<'a> {
+            /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
+            Fn(FnCtxt, &'a $($mut)? Visibility, &'a $($mut)? Fn),
+
+            /// E.g., `|x, y| body`.
+            Closure(&'a $($mut)? ClosureBinder, &'a $($mut)? Option<CoroutineKind>, &'a $($mut)? P<FnDecl>, &'a $($mut)? P<Expr>),
+        }
+
+        impl<'a> FnKind<'a> {
+            pub fn header(&'a $($mut)? self) -> Option<&'a $($mut)? FnHeader> {
+                match *self {
+                    FnKind::Fn(_, _, Fn { sig, .. }) => Some(&$($mut)? sig.header),
+                    FnKind::Closure(..) => None,
+                }
+            }
+
+            pub fn ident(&'a $($mut)? self) -> Option<&'a $($mut)? Ident> {
+                match self {
+                    FnKind::Fn(_, _, Fn { ident, .. }) => Some(ident),
+                    _ => None,
+                }
+            }
+
+            pub fn decl(&'a $($mut)? self) -> &'a $($mut)? FnDecl {
+                match self {
+                    FnKind::Fn(_, _, Fn { sig, .. }) => &$($mut)? sig.decl,
+                    FnKind::Closure(_, _, decl, _) => decl,
+                }
+            }
+
+            pub fn ctxt(&self) -> Option<FnCtxt> {
+                match self {
+                    FnKind::Fn(ctxt, ..) => Some(*ctxt),
+                    FnKind::Closure(..) => None,
+                }
+            }
+        }
+
+        /// Each method of this trait is a hook to be potentially
+        /// overridden. Each method's default implementation recursively visits
+        /// the substructure of the input via the corresponding `walk` method;
+        #[doc = concat!(" e.g., the `visit_item` method by default calls `visit"$(, "_", stringify!($mut))?, "::walk_item`.")]
+        ///
+        /// If you want to ensure that your code handles every variant
+        /// explicitly, you need to override each method. (And you also need
+        /// to monitor future changes to this trait in case a new method with a
+        /// new default implementation gets introduced.)
+        ///
+        /// Every `walk_*` method uses deconstruction to access fields of structs and
+        /// enums. This will result in a compile error if a field is added, which makes
+        /// it more likely the appropriate visit call will be added for it.
+        pub trait $Visitor<$($lt)?> : Sized $(${ignore($mut)} + MutVisitorResult<Result = ()>)? {
+            $(
+                ${ignore($lt)}
+                /// The result type of the `visit_*` methods. Can be either `()`,
+                /// or `ControlFlow<T>`.
+                type Result: VisitorResult = ();
+            )?
+
+            // Methods in this trait have one of three forms, with the last two forms
+            // only occuring on `MutVisitor`:
+            //
+            //   fn visit_t(&mut self, t: &mut T);                      // common
+            //   fn flat_map_t(&mut self, t: T) -> SmallVec<[T; 1]>;    // rare
+            //   fn filter_map_t(&mut self, t: T) -> Option<T>;         // rarest
+            //
+            // When writing these methods, it is better to use destructuring like this:
+            //
+            //   fn visit_abc(&mut self, ABC { a, b, c: _ }: &mut ABC) {
+            //       visit_a(a);
+            //       visit_b(b);
+            //   }
+            //
+            // than to use field access like this:
+            //
+            //   fn visit_abc(&mut self, abc: &mut ABC) {
+            //       visit_a(&mut abc.a);
+            //       visit_b(&mut abc.b);
+            //       // ignore abc.c
+            //   }
+            //
+            // As well as being more concise, the former is explicit about which fields
+            // are skipped. Furthermore, if a new field is added, the destructuring
+            // version will cause a compile error, which is good. In comparison, the
+            // field access version will continue working and it would be easy to
+            // forget to add handling for it.
+            fn visit_ident(&mut self, Ident { name: _, span }: &$($lt)? $($mut)? Ident) -> Self::Result {
+                visit_span(self, span)
+            }
+
+            fn visit_foreign_mod(&mut self, nm: &$($lt)? $($mut)? ForeignMod) -> Self::Result {
+                walk_foreign_mod(self, nm)
+            }
+
+            fn visit_foreign_item(&mut self, i: &$($lt)? $($mut)? ForeignItem) -> Self::Result {
+                walk_item(self, i)
+            }
+
+            fn visit_item(&mut self, i: &$($lt)? $($mut)? Item) -> Self::Result {
+                walk_item(self, i)
+            }
+
+            fn visit_local(&mut self, l: &$($lt)? $($mut)? Local) -> Self::Result {
+                walk_local(self, l)
+            }
+
+            fn visit_block(&mut self, b: &$($lt)? $($mut)? Block) -> Self::Result {
+                walk_block(self, b)
+            }
+
+            fn visit_param(&mut self, param: &$($lt)? $($mut)? Param) -> Self::Result {
+                walk_param(self, param)
+            }
+
+            fn visit_arm(&mut self, a: &$($lt)? $($mut)? Arm) -> Self::Result {
+                walk_arm(self, a)
+            }
+
+            fn visit_pat(&mut self, p: &$($lt)? $($mut)? Pat) -> Self::Result {
+                walk_pat(self, p)
+            }
+
+            fn visit_anon_const(&mut self, c: &$($lt)? $($mut)? AnonConst) -> Self::Result {
+                walk_anon_const(self, c)
+            }
+
+            fn visit_expr(&mut self, ex: &$($lt)? $($mut)? Expr) -> Self::Result {
+                walk_expr(self, ex)
+            }
+
+            /// This method is a hack to workaround unstable of `stmt_expr_attributes`.
+            /// It can be removed once that feature is stabilized.
+            fn visit_method_receiver_expr(&mut self, ex: &$($lt)? $($mut)? Expr) -> Self::Result {
+                self.visit_expr(ex)
+            }
+
+            fn visit_ty(&mut self, t: &$($lt)? $($mut)? Ty) -> Self::Result {
+                walk_ty(self, t)
+            }
+
+            fn visit_ty_pat(&mut self, t: &$($lt)? $($mut)? TyPat) -> Self::Result {
+                walk_ty_pat(self, t)
+            }
+
+            fn visit_generic_param(&mut self, param: &$($lt)? $($mut)? GenericParam) -> Self::Result {
+                walk_generic_param(self, param)
+            }
+
+            fn visit_generics(&mut self, g: &$($lt)? $($mut)? Generics) -> Self::Result {
+                walk_generics(self, g)
+            }
+            fn visit_closure_binder(&mut self, b: &$($lt)? $($mut)? ClosureBinder) -> Self::Result {
+                walk_closure_binder(self, b)
+            }
+            fn visit_contract(&mut self, c: &$($lt)? $($mut)? FnContract) -> Self::Result {
+                walk_contract(self, c)
+            }
+
+            fn visit_where_predicate(&mut self, p: &$($lt)? $($mut)? WherePredicate) -> Self::Result {
+                walk_where_predicate(self, p)
+            }
+
+            fn visit_where_predicate_kind(&mut self, k: &$($lt)? $($mut)? WherePredicateKind) -> Self::Result {
+                walk_where_predicate_kind(self, k)
+            }
+
+            // for `MutVisitor`: `Span` and `NodeId` are mutated at the caller site.
+            fn visit_fn(
+                &mut self,
+                fk: FnKind<$($lt)? $(${ignore($mut)} '_)?>,
+                _: Span,
+                _: NodeId
+            ) -> Self::Result {
+                walk_fn(self, fk)
+            }
+
+            fn visit_assoc_item(&mut self, i: &$($lt)? $($mut)? AssocItem, ctxt: AssocCtxt) -> Self::Result {
+                walk_assoc_item(self, i, ctxt)
+            }
+
+            fn visit_trait_ref(&mut self, t: &$($lt)? $($mut)? TraitRef) -> Self::Result {
+                walk_trait_ref(self, t)
+            }
+
+            fn visit_param_bound(&mut self, bounds: &$($lt)? $($mut)? GenericBound, _ctxt: BoundKind) -> Self::Result {
+                walk_param_bound(self, bounds)
+            }
+
+            fn visit_precise_capturing_arg(&mut self, arg: &$($lt)? $($mut)? PreciseCapturingArg) -> Self::Result {
+                walk_precise_capturing_arg(self, arg)
+            }
+
+            fn visit_poly_trait_ref(&mut self, t: &$($lt)? $($mut)? PolyTraitRef) -> Self::Result {
+                walk_poly_trait_ref(self, t)
+            }
+
+            fn visit_variant_data(&mut self, s: &$($lt)? $($mut)? VariantData) -> Self::Result {
+                walk_variant_data(self, s)
+            }
+
+            fn visit_field_def(&mut self, s: &$($lt)? $($mut)? FieldDef) -> Self::Result {
+                walk_field_def(self, s)
+            }
+
+            fn visit_variant(&mut self, v: &$($lt)? $($mut)? Variant) -> Self::Result {
+                walk_variant(self, v)
+            }
+
+            fn visit_label(&mut self, label: &$($lt)? $($mut)? Label) -> Self::Result {
+                walk_label(self, label)
+            }
+
+            fn visit_lifetime(&mut self, lifetime: &$($lt)? $($mut)? Lifetime, $(${ignore($lt)} _: LifetimeCtxt )?) -> Self::Result {
+                walk_lifetime(self, lifetime)
+            }
+
+            fn visit_mac_call(&mut self, mac: &$($lt)? $($mut)? MacCall) -> Self::Result {
+                walk_mac(self, mac)
+            }
+
+            fn visit_id(&mut self, _id: $(&$mut)? NodeId) -> Self::Result {
+                Self::Result::output()
+            }
+
+            fn visit_macro_def(&mut self, macro_def: &$($lt)? $($mut)? MacroDef) -> Self::Result {
+                walk_macro_def(self, macro_def)
+            }
+
+            fn visit_path(&mut self, path: &$($lt)? $($mut)? Path) -> Self::Result {
+                walk_path(self, path)
+            }
+
+            fn visit_use_tree(&mut self, use_tree: &$($lt)? $($mut)? UseTree) -> Self::Result {
+                walk_use_tree(self, use_tree)
+            }
+
+            fn visit_path_segment(&mut self, path_segment: &$($lt)? $($mut)? PathSegment) -> Self::Result {
+                walk_path_segment(self, path_segment)
+            }
+
+            fn visit_generic_args(&mut self, generic_args: &$($lt)? $($mut)? GenericArgs) -> Self::Result {
+                walk_generic_args(self, generic_args)
+            }
+
+            fn visit_generic_arg(&mut self, generic_arg: &$($lt)? $($mut)? GenericArg) -> Self::Result {
+                walk_generic_arg(self, generic_arg)
+            }
+
+            fn visit_assoc_item_constraint(
+                &mut self,
+                constraint: &$($lt)? $($mut)? AssocItemConstraint,
+            ) -> Self::Result {
+                walk_assoc_item_constraint(self, constraint)
+            }
+
+            fn visit_attribute(&mut self, attr: &$($lt)? $($mut)? Attribute) -> Self::Result {
+                walk_attribute(self, attr)
+            }
+
+            fn visit_vis(&mut self, vis: &$($lt)? $($mut)? Visibility) -> Self::Result {
+                walk_vis(self, vis)
+            }
+
+            fn visit_fn_ret_ty(&mut self, ret_ty: &$($lt)? $($mut)? FnRetTy) -> Self::Result {
+                walk_fn_ret_ty(self, ret_ty)
+            }
+
+            fn visit_fn_header(&mut self, header: &$($lt)? $($mut)? FnHeader) -> Self::Result {
+                walk_fn_header(self, header)
+            }
+
+            fn visit_expr_field(&mut self, f: &$($lt)? $($mut)? ExprField) -> Self::Result {
+                walk_expr_field(self, f)
+            }
+
+            fn visit_pat_field(&mut self, fp: &$($lt)? $($mut)? PatField) -> Self::Result {
+                walk_pat_field(self, fp)
+            }
+
+            fn visit_crate(&mut self, krate: &$($lt)? $($mut)? Crate) -> Self::Result {
+                walk_crate(self, krate)
+            }
+
+            fn visit_inline_asm(&mut self, asm: &$($lt)? $($mut)? InlineAsm) -> Self::Result {
+                walk_inline_asm(self, asm)
+            }
+
+            fn visit_format_args(&mut self, fmt: &$($lt)? $($mut)? FormatArgs) -> Self::Result {
+                walk_format_args(self, fmt)
+            }
+
+            fn visit_inline_asm_sym(&mut self, sym: &$($lt)? $($mut)? InlineAsmSym) -> Self::Result {
+                walk_inline_asm_sym(self, sym)
+            }
+
+            fn visit_capture_by(&mut self, capture_by: &$($lt)? $($mut)? CaptureBy) -> Self::Result {
+                walk_capture_by(self, capture_by)
+            }
+
+            fn visit_coroutine_kind(&mut self, coroutine_kind: &$($lt)? $($mut)? CoroutineKind) -> Self::Result {
+                walk_coroutine_kind(self, coroutine_kind)
+            }
+
+            fn visit_fn_decl(&mut self, fn_decl: &$($lt)? $($mut)? FnDecl) -> Self::Result {
+                walk_fn_decl(self, fn_decl)
+            }
+
+            fn visit_qself(&mut self, qs: &$($lt)? $($mut)? Option<P<QSelf>>) -> Self::Result {
+                walk_qself(self, qs)
+            }
+
+            // (non-mut) `Visitor`-only methods
+            $(
+                fn visit_stmt(&mut self, s: &$lt Stmt) -> Self::Result {
+                    walk_stmt(self, s)
+                }
+
+                fn visit_nested_use_tree(&mut self, use_tree: &$lt UseTree, id: NodeId) -> Self::Result {
+                    try_visit!(self.visit_id(id));
+                    self.visit_use_tree(use_tree)
+                }
+            )?
+
+            // `MutVisitor`-only methods
+            $(
+                fn flat_map_foreign_item(&mut self, ni: P<ForeignItem>) -> SmallVec<[P<ForeignItem>; 1]> {
+                    walk_flat_map_foreign_item(self, ni)
+                }
+
+                fn flat_map_item(&mut self, i: P<Item>) -> SmallVec<[P<Item>; 1]> {
+                    walk_flat_map_item(self, i)
+                }
+
+                fn flat_map_field_def(&mut self, fd: FieldDef) -> SmallVec<[FieldDef; 1]> {
+                    walk_flat_map_field_def(self, fd)
+                }
+
+                fn flat_map_assoc_item(
+                    &mut self,
+                    i: P<AssocItem>,
+                    ctxt: AssocCtxt,
+                ) -> SmallVec<[P<AssocItem>; 1]> {
+                    walk_flat_map_assoc_item(self, i, ctxt)
+                }
+
+                fn flat_map_stmt(&mut self, s: Stmt) -> SmallVec<[Stmt; 1]> {
+                    walk_flat_map_stmt(self, s)
+                }
+
+                fn flat_map_arm(&mut self, arm: Arm) -> SmallVec<[Arm; 1]> {
+                    walk_flat_map_arm(self, arm)
+                }
+
+                fn filter_map_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> {
+                    walk_filter_map_expr(self, e)
+                }
+
+                fn flat_map_variant(&mut self, v: Variant) -> SmallVec<[Variant; 1]> {
+                    walk_flat_map_variant(self, v)
+                }
+
+                fn flat_map_param(&mut self, param: Param) -> SmallVec<[Param; 1]> {
+                    walk_flat_map_param(self, param)
+                }
+
+                fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> {
+                    walk_flat_map_generic_param(self, param)
+                }
+
+                fn flat_map_expr_field(&mut self, f: ExprField) -> SmallVec<[ExprField; 1]> {
+                    walk_flat_map_expr_field(self, f)
+                }
+
+                fn flat_map_where_predicate(
+                    &mut self,
+                    where_predicate: WherePredicate,
+                ) -> SmallVec<[WherePredicate; 1]> {
+                    walk_flat_map_where_predicate(self, where_predicate)
+                }
+
+                // Span visiting is no longer used, but we keep it for now,
+                // in case it's needed for something like #127241.
+                fn visit_span(&mut self, _sp: &$mut Span) {
+                    // Do nothing.
+                }
+
+                fn flat_map_pat_field(&mut self, fp: PatField) -> SmallVec<[PatField; 1]> {
+                    walk_flat_map_pat_field(self, fp)
+                }
+            )?
+        }
+
         pub trait WalkItemKind {
             type Ctxt;
             fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
@@ -320,8 +482,8 @@ macro_rules! common_visitor_and_walkers {
                 id: NodeId,
                 visibility: &$($lt)? $($mut)? Visibility,
                 ctxt: Self::Ctxt,
-                visitor: &mut V,
-            ) $(-> <V as Visitor<$lt>>::Result)?;
+                vis: &mut V,
+            ) -> V::Result;
         }
 
         // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier
@@ -329,12 +491,12 @@ macro_rules! common_visitor_and_walkers {
             #[expect(unused, rustc::pass_by_value)]
             #[inline]
         )?
-        fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, span: &$($lt)? $($mut)? Span) $(-> <V as Visitor<$lt>>::Result)? {
+        fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, span: &$($lt)? $($mut)? Span) -> V::Result {
             $(
                 ${ignore($mut)}
-                visitor.visit_span(span);
+                vis.visit_span(span);
             )?
-            $(${ignore($lt)}V::Result::output())?
+            V::Result::output()
         }
 
         /// helper since `Visitor` wants `NodeId` but `MutVisitor` wants `&mut NodeId`
@@ -342,34 +504,34 @@ macro_rules! common_visitor_and_walkers {
             #[expect(rustc::pass_by_value)]
         )?
         #[inline]
-        fn visit_id<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, id: &$($lt)? $($mut)? NodeId) $(-> <V as Visitor<$lt>>::Result)? {
+        fn visit_id<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, id: &$($lt)? $($mut)? NodeId) -> V::Result {
             // deref `&NodeId` into `NodeId` only for `Visitor`
-            visitor.visit_id( $(${ignore($lt)} * )? id)
+            vis.visit_id( $(${ignore($lt)} * )? id)
         }
 
         // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier
-        fn visit_safety<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, safety: &$($lt)? $($mut)? Safety) $(-> <V as Visitor<$lt>>::Result)? {
+        fn visit_safety<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, safety: &$($lt)? $($mut)? Safety) -> V::Result {
             match safety {
                 Safety::Unsafe(span) => visit_span(vis, span),
                 Safety::Safe(span) => visit_span(vis, span),
-                Safety::Default => { $(${ignore($lt)}V::Result::output())? }
+                Safety::Default => { V::Result::output() }
             }
         }
 
-        fn visit_constness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, constness: &$($lt)? $($mut)? Const) $(-> <V as Visitor<$lt>>::Result)? {
+        fn visit_constness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, constness: &$($lt)? $($mut)? Const) -> V::Result {
             match constness {
                 Const::Yes(span) => visit_span(vis, span),
                 Const::No => {
-                    $(<V as Visitor<$lt>>::Result::output())?
+                    V::Result::output()
                 }
             }
         }
 
-        fn visit_defaultness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, defaultness: &$($lt)? $($mut)? Defaultness) $(-> <V as Visitor<$lt>>::Result)? {
+        fn visit_defaultness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, defaultness: &$($lt)? $($mut)? Defaultness) -> V::Result {
             match defaultness {
                 Defaultness::Default(span) => visit_span(vis, span),
                 Defaultness::Final => {
-                    $(<V as Visitor<$lt>>::Result::output())?
+                    V::Result::output()
                 }
             }
         }
@@ -377,9 +539,9 @@ macro_rules! common_visitor_and_walkers {
         fn visit_polarity<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             polarity: &$($lt)? $($mut)? ImplPolarity,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             match polarity {
-                ImplPolarity::Positive => { $(<V as Visitor<$lt>>::Result::output())? }
+                ImplPolarity::Positive => { V::Result::output() }
                 ImplPolarity::Negative(span) => visit_span(vis, span),
             }
         }
@@ -390,7 +552,7 @@ macro_rules! common_visitor_and_walkers {
         fn visit_modifiers<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             m: &$($lt)? $($mut)? TraitBoundModifiers
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let TraitBoundModifiers { constness, asyncness, polarity } = m;
             match constness {
                 BoundConstness::Never => {}
@@ -404,26 +566,44 @@ macro_rules! common_visitor_and_walkers {
                 BoundPolarity::Positive => {}
                 BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => try_visit!(visit_span(vis, span)),
             }
-            $(<V as Visitor<$lt>>::Result::output())?
+            V::Result::output()
         }
 
-        fn visit_bounds<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, bounds: &$($lt)? $($mut)? GenericBounds, ctxt: BoundKind) $(-> <V as Visitor<$lt>>::Result)? {
+        $(${ignore($lt)}
+            #[inline]
+        )?
+        fn walk_capture_by<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            capture_by: &$($lt)? $($mut)? CaptureBy
+        ) -> V::Result {
+            match capture_by {
+                CaptureBy::Ref => { V::Result::output() }
+                CaptureBy::Value { move_kw } => {
+                    visit_span(vis, move_kw)
+                }
+                CaptureBy::Use { use_kw } => {
+                    visit_span(vis, use_kw)
+                }
+            }
+        }
+
+        fn visit_bounds<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, bounds: &$($lt)? $($mut)? GenericBounds, ctxt: BoundKind) -> V::Result {
             walk_list!(visitor, visit_param_bound, bounds, ctxt);
-            $(<V as Visitor<$lt>>::Result::output())?
+            V::Result::output()
         }
 
-        pub fn walk_label<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Label { ident }: &$($lt)? $($mut)? Label) $(-> <V as Visitor<$lt>>::Result)? {
+        pub fn walk_label<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Label { ident }: &$($lt)? $($mut)? Label) -> V::Result {
             visitor.visit_ident(ident)
         }
 
-        pub fn walk_fn_header<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, header: &$($lt)? $($mut)? FnHeader) $(-> <V as Visitor<$lt>>::Result)? {
+        pub fn walk_fn_header<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, header: &$($lt)? $($mut)? FnHeader) -> V::Result {
             let FnHeader { safety, coroutine_kind, constness, ext: _ } = header;
             try_visit!(visit_constness(visitor, constness));
             visit_opt!(visitor, visit_coroutine_kind, coroutine_kind);
             visit_safety(visitor, safety)
         }
 
-        pub fn walk_lifetime<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Lifetime { id, ident }: &$($lt)? $($mut)? Lifetime) $(-> <V as Visitor<$lt>>::Result)? {
+        pub fn walk_lifetime<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Lifetime { id, ident }: &$($lt)? $($mut)? Lifetime) -> V::Result {
             try_visit!(visit_id(visitor, id));
             visitor.visit_ident(ident)
         }
@@ -432,7 +612,7 @@ macro_rules! common_visitor_and_walkers {
             visitor: &mut V,
             item: &$($mut)? $($lt)? Item<K>,
             ctxt: K::Ctxt,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let Item { attrs, id, kind, vis, span, tokens: _ } = item;
             try_visit!(visit_id(visitor, id));
             walk_list!(visitor, visit_attribute, attrs);
@@ -444,7 +624,7 @@ macro_rules! common_visitor_and_walkers {
         pub fn walk_item<$($lt,)? V: $Visitor$(<$lt>)?, K: WalkItemKind<Ctxt = ()>>(
             visitor: &mut V,
             item: &$($mut)? $($lt)? Item<K>,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             walk_item_ctxt(visitor, item, ())
         }
 
@@ -452,7 +632,7 @@ macro_rules! common_visitor_and_walkers {
             visitor: &mut V,
             item: &$($mut)? $($lt)? AssocItem,
             ctxt: AssocCtxt,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             walk_item_ctxt(visitor, item, ctxt)
         }
 
@@ -465,7 +645,7 @@ macro_rules! common_visitor_and_walkers {
                 visibility: &$($lt)? $($mut)? Visibility,
                 _ctxt: Self::Ctxt,
                 vis: &mut V,
-            ) $(-> <V as Visitor<$lt>>::Result)? {
+            ) -> V::Result {
                 match self {
                     ItemKind::ExternCrate(_orig_name, ident) => vis.visit_ident(ident),
                     ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
@@ -505,7 +685,7 @@ macro_rules! common_visitor_and_walkers {
                             }
                             ModKind::Unloaded => {}
                         }
-                        $(<V as Visitor<$lt>>::Result::output())?
+                        V::Result::output()
                     }
                     ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
                     ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm),
@@ -526,7 +706,7 @@ macro_rules! common_visitor_and_walkers {
                         $(${ignore($mut)}
                             walk_ty_alias_where_clauses(vis, where_clauses);
                         )?
-                        $(<V as Visitor<$lt>>::Result::output())?
+                        V::Result::output()
                     }
                     ItemKind::Enum(ident, generics, enum_definition) => {
                         try_visit!(vis.visit_ident(ident));
@@ -590,7 +770,7 @@ macro_rules! common_visitor_and_walkers {
                         try_visit!(vis.visit_ident(ident));
                         visit_opt!(vis, visit_ident, rename);
                         visit_opt!(vis, visit_block, body);
-                        $(<V as Visitor<$lt>>::Result::output())?
+                        V::Result::output()
                     }
                     ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
                         try_visit!(vis.visit_qself(qself));
@@ -602,7 +782,7 @@ macro_rules! common_visitor_and_walkers {
                             }
                         }
                         visit_opt!(vis, visit_block, body);
-                        $(<V as Visitor<$lt>>::Result::output())?
+                        V::Result::output()
                     }
                 }
             }
@@ -611,7 +791,7 @@ macro_rules! common_visitor_and_walkers {
         fn walk_const_item<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             item: &$($lt)? $($mut)? ConstItem,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let ConstItem { defaultness, ident, generics, ty, expr, define_opaque } = item;
             try_visit!(visit_defaultness(vis, defaultness));
             try_visit!(vis.visit_ident(ident));
@@ -621,7 +801,7 @@ macro_rules! common_visitor_and_walkers {
             walk_define_opaques(vis, define_opaque)
         }
 
-        fn walk_foreign_mod<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, foreign_mod: &$($lt)? $($mut)? ForeignMod) $(-> <V as Visitor<$lt>>::Result)? {
+        fn walk_foreign_mod<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, foreign_mod: &$($lt)? $($mut)? ForeignMod) -> V::Result {
             let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod;
             try_visit!(visit_safety(vis, safety));
             visit_foreign_items(vis, items)
@@ -630,14 +810,14 @@ macro_rules! common_visitor_and_walkers {
         fn walk_define_opaques<$($lt,)? V: $Visitor$(<$lt>)?>(
             visitor: &mut V,
             define_opaque: &$($lt)? $($mut)? Option<ThinVec<(NodeId, Path)>>,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             if let Some(define_opaque) = define_opaque {
                 for (id, path) in define_opaque {
                     try_visit!(visit_id(visitor, id));
                     try_visit!(visitor.visit_path(path));
                 }
             }
-            $(<V as Visitor<$lt>>::Result::output())?
+            V::Result::output()
         }
 
         impl WalkItemKind for AssocItemKind {
@@ -649,7 +829,7 @@ macro_rules! common_visitor_and_walkers {
                 visibility: &$($lt)? $($mut)? Visibility,
                 ctxt: Self::Ctxt,
                 vis: &mut V,
-            ) $(-> <V as Visitor<$lt>>::Result)? {
+            ) -> V::Result {
                 match self {
                     AssocItemKind::Const(item) => {
                         walk_const_item(vis, item)
@@ -674,7 +854,7 @@ macro_rules! common_visitor_and_walkers {
                         $(${ignore($mut)}
                             walk_ty_alias_where_clauses(vis, where_clauses);
                         )?
-                        $(<V as Visitor<$lt>>::Result::output())?
+                        V::Result::output()
                     }
                     AssocItemKind::MacCall(mac) => {
                         vis.visit_mac_call(mac)
@@ -694,7 +874,7 @@ macro_rules! common_visitor_and_walkers {
                         try_visit!(vis.visit_ident(ident));
                         visit_opt!(vis, visit_ident, rename);
                         visit_opt!(vis, visit_block, body);
-                        $(<V as Visitor<$lt>>::Result::output())?
+                        V::Result::output()
                     }
                     AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
                         try_visit!(vis.visit_qself(qself));
@@ -706,7 +886,7 @@ macro_rules! common_visitor_and_walkers {
                             }
                         }
                         visit_opt!(vis, visit_block, body);
-                        $(<V as Visitor<$lt>>::Result::output())?
+                        V::Result::output()
                     }
                 }
             }
@@ -721,7 +901,7 @@ macro_rules! common_visitor_and_walkers {
                 visibility: &$($lt)? $($mut)? Visibility,
                 _ctxt: Self::Ctxt,
                 vis: &mut V,
-            ) $(-> <V as Visitor<$lt>>::Result)? {
+            ) -> V::Result {
                 match self {
                     ForeignItemKind::Static(box StaticItem {
                         ident,
@@ -756,7 +936,7 @@ macro_rules! common_visitor_and_walkers {
                         $(${ignore($mut)}
                             walk_ty_alias_where_clauses(vis, where_clauses);
                         )?
-                        $(<V as Visitor<$lt>>::Result::output())?
+                        V::Result::output()
                     }
                     ForeignItemKind::MacCall(mac) => {
                         vis.visit_mac_call(mac)
@@ -768,7 +948,7 @@ macro_rules! common_visitor_and_walkers {
         fn walk_coroutine_kind<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             coroutine_kind: &$($lt)? $($mut)? CoroutineKind,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let (CoroutineKind::Async { span, closure_id, return_impl_trait_id }
                 | CoroutineKind::Gen { span, closure_id, return_impl_trait_id }
                 | CoroutineKind::AsyncGen { span, closure_id, return_impl_trait_id })
@@ -781,7 +961,7 @@ macro_rules! common_visitor_and_walkers {
         pub fn walk_pat<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             pattern: &$($lt)? $($mut)? Pat
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let Pat { id, kind, span, tokens: _ } = pattern;
             try_visit!(visit_id(vis, id));
             match kind {
@@ -832,7 +1012,7 @@ macro_rules! common_visitor_and_walkers {
         pub fn walk_anon_const<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             constant: &$($lt)? $($mut)? AnonConst,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let AnonConst { id, value } = constant;
             try_visit!(visit_id(vis, id));
             vis.visit_expr(value)
@@ -841,18 +1021,18 @@ macro_rules! common_visitor_and_walkers {
         pub fn walk_path_segment<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             segment: &$($lt)? $($mut)? PathSegment,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let PathSegment { ident, id, args } = segment;
             try_visit!(visit_id(vis, id));
             try_visit!(vis.visit_ident(ident));
             visit_opt!(vis, visit_generic_args, args);
-            $(<V as Visitor<$lt>>::Result::output())?
+            V::Result::output()
         }
 
         pub fn walk_block<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             block: &$($lt)? $($mut)? Block
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let Block { stmts, id, rules: _, span, tokens: _ } = block;
             try_visit!(visit_id(vis, id));
             try_visit!(visit_stmts(vis, stmts));
@@ -862,7 +1042,7 @@ macro_rules! common_visitor_and_walkers {
 
         pub fn walk_ty<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V, ty: &$($lt)? $($mut)? Ty
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let Ty { id, kind, span, tokens: _ } = ty;
             try_visit!(visit_id(vis, id));
             match kind {
@@ -882,7 +1062,7 @@ macro_rules! common_visitor_and_walkers {
                 TyKind::BareFn(function_declaration) => {
                     let BareFnTy { safety, ext: _, generic_params, decl, decl_span } =
                         &$($mut)? **function_declaration;
-                    visit_safety(vis, safety);
+                    try_visit!(visit_safety(vis, safety));
                     try_visit!(visit_generic_params(vis, generic_params));
                     try_visit!(vis.visit_fn_decl(decl));
                     try_visit!(visit_span(vis, decl_span));
@@ -920,7 +1100,7 @@ macro_rules! common_visitor_and_walkers {
         pub fn walk_crate<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             krate: &$($lt)? $($mut)? Crate,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let Crate { attrs, items, spans, id, is_placeholder: _ } = krate;
             try_visit!(visit_id(vis, id));
             walk_list!(vis, visit_attribute, attrs);
@@ -933,7 +1113,7 @@ macro_rules! common_visitor_and_walkers {
         pub fn walk_local<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             local: &$($lt)? $($mut)? Local,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let Local { id, super_, pat, ty, kind, span, colon_sp, attrs, tokens: _ } = local;
             if let Some(sp) = super_ {
                 try_visit!(visit_span(vis, sp));
@@ -961,7 +1141,7 @@ macro_rules! common_visitor_and_walkers {
         pub fn walk_poly_trait_ref<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             p: &$($lt)? $($mut)? PolyTraitRef,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let PolyTraitRef { bound_generic_params, modifiers, trait_ref, span } = p;
             try_visit!(visit_modifiers(vis, modifiers));
             try_visit!(visit_generic_params(vis, bound_generic_params));
@@ -972,7 +1152,7 @@ macro_rules! common_visitor_and_walkers {
         pub fn walk_trait_ref<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             TraitRef { path, ref_id }: &$($lt)? $($mut)? TraitRef,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             try_visit!(vis.visit_path(path));
             visit_id(vis, ref_id)
         }
@@ -980,22 +1160,21 @@ macro_rules! common_visitor_and_walkers {
         pub fn walk_variant<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             variant: &$($lt)? $($mut)? Variant,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let Variant { attrs, id, span, vis: visibility, ident, data, disr_expr, is_placeholder: _ } = variant;
             try_visit!(visit_id(vis, id));
             walk_list!(vis, visit_attribute, attrs);
             try_visit!(vis.visit_vis(visibility));
             try_visit!(vis.visit_ident(ident));
             try_visit!(vis.visit_variant_data(data));
-            $(${ignore($lt)} visit_opt!(vis, visit_variant_discr, disr_expr); )?
-            $(${ignore($mut)} visit_opt!(vis, visit_anon_const, disr_expr); )?
+            visit_opt!(vis, visit_anon_const, disr_expr);
             visit_span(vis, span)
         }
 
         pub fn walk_expr_field<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             f: &$($lt)? $($mut)? ExprField,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let ExprField { attrs, id, span, ident, expr, is_shorthand: _, is_placeholder: _ } = f;
             try_visit!(visit_id(vis, id));
             walk_list!(vis, visit_attribute, attrs);
@@ -1007,7 +1186,7 @@ macro_rules! common_visitor_and_walkers {
         pub fn walk_pat_field<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             fp: &$($lt)? $($mut)? PatField,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let PatField { ident, pat, is_shorthand: _, attrs, id, span, is_placeholder: _ } = fp;
             try_visit!(visit_id(vis, id));
             walk_list!(vis, visit_attribute, attrs);
@@ -1019,7 +1198,7 @@ macro_rules! common_visitor_and_walkers {
         pub fn walk_ty_pat<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             tp: &$($lt)? $($mut)? TyPat,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let TyPat { id, kind, span, tokens: _ } = tp;
             try_visit!(visit_id(vis, id));
             match kind {
@@ -1036,19 +1215,19 @@ macro_rules! common_visitor_and_walkers {
         fn walk_qself<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             qself: &$($lt)? $($mut)? Option<P<QSelf>>,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             if let Some(qself) = qself {
                 let QSelf { ty, path_span, position: _ } = &$($mut)? **qself;
                 try_visit!(vis.visit_ty(ty));
                 try_visit!(visit_span(vis, path_span));
             }
-            $(<V as Visitor<$lt>>::Result::output())?
+            V::Result::output()
         }
 
         pub fn walk_path<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             path: &$($lt)? $($mut)? Path,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let Path { span, segments, tokens: _ } = path;
             walk_list!(vis, visit_path_segment, segments);
             visit_span(vis, span)
@@ -1057,7 +1236,7 @@ macro_rules! common_visitor_and_walkers {
         pub fn walk_use_tree<$($lt,)? V: $Visitor$(<$lt>)?>(
             vis: &mut V,
             use_tree: &$($lt)? $($mut)? UseTree,
-        ) $(-> <V as Visitor<$lt>>::Result)? {
+        ) -> V::Result {
             let UseTree { prefix, kind, span } = use_tree;
             try_visit!(vis.visit_path(prefix));
             match kind {
@@ -1075,573 +1254,641 @@ macro_rules! common_visitor_and_walkers {
             }
             visit_span(vis, span)
         }
-    };
-}
-
-common_visitor_and_walkers!(Visitor<'a>);
 
-macro_rules! generate_list_visit_fns {
-    ($($name:ident, $Ty:ty, $visit_fn:ident$(, $param:ident: $ParamTy:ty)*;)+) => {
-        $(
-            fn $name<'a, V: Visitor<'a>>(
-                vis: &mut V,
-                values: &'a ThinVec<$Ty>,
-                $(
-                    $param: $ParamTy,
-                )*
-            ) -> V::Result {
-                walk_list!(vis, $visit_fn, values$(,$param)*);
-                V::Result::output()
+        pub fn walk_generic_args<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            generic_args: &$($lt)? $($mut)? GenericArgs
+        ) -> V::Result {
+            match generic_args {
+                GenericArgs::AngleBracketed(AngleBracketedArgs { span, args }) => {
+                    for arg in args {
+                        match arg {
+                            AngleBracketedArg::Arg(a) => try_visit!(vis.visit_generic_arg(a)),
+                            AngleBracketedArg::Constraint(c) => {
+                                try_visit!(vis.visit_assoc_item_constraint(c))
+                            }
+                        }
+                    }
+                    visit_span(vis, span)
+                }
+                GenericArgs::Parenthesized(data) => {
+                    let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
+                    walk_list!(vis, visit_ty, inputs);
+                    try_visit!(vis.visit_fn_ret_ty(output));
+                    try_visit!(visit_span(vis, span));
+                    visit_span(vis, inputs_span)
+                }
+                GenericArgs::ParenthesizedElided(span) => visit_span(vis, span)
             }
-        )+
-    }
-}
+        }
 
-generate_list_visit_fns! {
-    visit_items, P<Item>, visit_item;
-    visit_foreign_items, P<ForeignItem>, visit_foreign_item;
-    visit_generic_params, GenericParam, visit_generic_param;
-    visit_stmts, Stmt, visit_stmt;
-    visit_pat_fields, PatField, visit_pat_field;
-    visit_variants, Variant, visit_variant;
-    visit_assoc_items, P<AssocItem>, visit_assoc_item, ctxt: AssocCtxt;
-}
+        pub fn walk_generic_arg<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            generic_arg: &$($lt)? $($mut)? GenericArg,
+        ) -> V::Result {
+            match generic_arg {
+                GenericArg::Lifetime(lt) => vis.visit_lifetime(lt, $(${ignore($lt)} LifetimeCtxt::GenericArg)? ),
+                GenericArg::Type(ty) => vis.visit_ty(ty),
+                GenericArg::Const(ct) => vis.visit_anon_const(ct),
+            }
+        }
 
-#[expect(rustc::pass_by_value)] // needed for symmetry with mut_visit
-fn visit_nested_use_tree<'a, V: Visitor<'a>>(
-    vis: &mut V,
-    nested_tree: &'a UseTree,
-    &nested_id: &NodeId,
-) -> V::Result {
-    vis.visit_nested_use_tree(nested_tree, nested_id)
-}
+        pub fn walk_assoc_item_constraint<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            constraint: &$($lt)? $($mut)? AssocItemConstraint,
+        ) -> V::Result {
+            let AssocItemConstraint { id, ident, gen_args, kind, span } = constraint;
+            try_visit!(visit_id(vis, id));
+            try_visit!(vis.visit_ident(ident));
+            visit_opt!(vis, visit_generic_args, gen_args);
+            match kind {
+                AssocItemConstraintKind::Equality { term } => match term {
+                    Term::Ty(ty) => try_visit!(vis.visit_ty(ty)),
+                    Term::Const(c) => try_visit!(vis.visit_anon_const(c)),
+                },
+                AssocItemConstraintKind::Bound { bounds } => {
+                    try_visit!(visit_bounds(vis, bounds, BoundKind::Bound));
+                }
+            }
+            visit_span(vis, span)
+        }
 
-pub fn walk_generic_args<'a, V>(visitor: &mut V, generic_args: &'a GenericArgs) -> V::Result
-where
-    V: Visitor<'a>,
-{
-    match generic_args {
-        GenericArgs::AngleBracketed(AngleBracketedArgs { span: _, args }) => {
-            for arg in args {
-                match arg {
-                    AngleBracketedArg::Arg(a) => try_visit!(visitor.visit_generic_arg(a)),
-                    AngleBracketedArg::Constraint(c) => {
-                        try_visit!(visitor.visit_assoc_item_constraint(c))
-                    }
+        pub fn walk_param_bound<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, bound: &$($lt)? $($mut)? GenericBound) -> V::Result {
+            match bound {
+                GenericBound::Trait(trait_ref) => vis.visit_poly_trait_ref(trait_ref),
+                GenericBound::Outlives(lifetime) => vis.visit_lifetime(lifetime, $(${ignore($lt)} LifetimeCtxt::Bound)?),
+                GenericBound::Use(args, span) => {
+                    walk_list!(vis, visit_precise_capturing_arg, args);
+                    visit_span(vis, span)
                 }
             }
         }
-        GenericArgs::Parenthesized(data) => {
-            let ParenthesizedArgs { span: _, inputs, inputs_span: _, output } = data;
-            walk_list!(visitor, visit_ty, inputs);
-            try_visit!(visitor.visit_fn_ret_ty(output));
+
+        pub fn walk_precise_capturing_arg<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            arg: &$($lt)? $($mut)? PreciseCapturingArg,
+        ) -> V::Result {
+            match arg {
+                PreciseCapturingArg::Lifetime(lt) => vis.visit_lifetime(lt, $(${ignore($lt)} LifetimeCtxt::GenericArg)?),
+                PreciseCapturingArg::Arg(path, id) => {
+                    try_visit!(visit_id(vis, id));
+                    vis.visit_path(path)
+                }
+            }
         }
-        GenericArgs::ParenthesizedElided(_span) => {}
-    }
-    V::Result::output()
-}
 
-pub fn walk_generic_arg<'a, V>(visitor: &mut V, generic_arg: &'a GenericArg) -> V::Result
-where
-    V: Visitor<'a>,
-{
-    match generic_arg {
-        GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg),
-        GenericArg::Type(ty) => visitor.visit_ty(ty),
-        GenericArg::Const(ct) => visitor.visit_anon_const(ct),
-    }
-}
+        pub fn walk_generic_param<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            param: &$($lt)? $($mut)? GenericParam,
+        ) -> V::Result {
+            let GenericParam { id, ident, attrs, bounds, is_placeholder: _, kind, colon_span } =
+                param;
+            try_visit!(visit_id(vis, id));
+            walk_list!(vis, visit_attribute, attrs);
+            try_visit!(vis.visit_ident(ident));
+            walk_list!(vis, visit_param_bound, bounds, BoundKind::Bound);
+            match kind {
+                GenericParamKind::Lifetime => (),
+                GenericParamKind::Type { default } => visit_opt!(vis, visit_ty, default),
+                GenericParamKind::Const { ty, default, kw_span: _ } => {
+                    try_visit!(vis.visit_ty(ty));
+                    visit_opt!(vis, visit_anon_const, default);
+                }
+            }
+            if let Some(sp) = colon_span {
+                try_visit!(visit_span(vis, sp))
+            }
+            V::Result::output()
+        }
 
-pub fn walk_assoc_item_constraint<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    constraint: &'a AssocItemConstraint,
-) -> V::Result {
-    let AssocItemConstraint { id: _, ident, gen_args, kind, span: _ } = constraint;
-    try_visit!(visitor.visit_ident(ident));
-    visit_opt!(visitor, visit_generic_args, gen_args);
-    match kind {
-        AssocItemConstraintKind::Equality { term } => match term {
-            Term::Ty(ty) => try_visit!(visitor.visit_ty(ty)),
-            Term::Const(c) => try_visit!(visitor.visit_anon_const(c)),
-        },
-        AssocItemConstraintKind::Bound { bounds } => {
-            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
+        pub fn walk_generics<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, generics: &$($lt)? $($mut)? Generics) -> V::Result {
+            let Generics { params, where_clause, span } = generics;
+            let WhereClause { has_where_token: _, predicates, span: where_clause_span } = where_clause;
+            try_visit!(visit_generic_params(vis, params));
+            try_visit!(visit_where_predicates(vis, predicates));
+            try_visit!(visit_span(vis, span));
+            visit_span(vis, where_clause_span)
         }
-    }
-    V::Result::output()
-}
 
-pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) -> V::Result {
-    match bound {
-        GenericBound::Trait(trait_ref) => visitor.visit_poly_trait_ref(trait_ref),
-        GenericBound::Outlives(lifetime) => visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound),
-        GenericBound::Use(args, _span) => {
-            walk_list!(visitor, visit_precise_capturing_arg, args);
+        pub fn walk_contract<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, c: &$($lt)? $($mut)? FnContract) -> V::Result {
+            let FnContract { requires, ensures } = c;
+            visit_opt!(vis, visit_expr, requires);
+            visit_opt!(vis, visit_expr, ensures);
             V::Result::output()
         }
-    }
-}
 
-pub fn walk_precise_capturing_arg<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    arg: &'a PreciseCapturingArg,
-) -> V::Result {
-    match arg {
-        PreciseCapturingArg::Lifetime(lt) => visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg),
-        PreciseCapturingArg::Arg(path, id) => {
-            try_visit!(visitor.visit_id(*id));
-            visitor.visit_path(path)
+        pub fn walk_where_predicate<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            predicate: &$($lt)? $($mut)? WherePredicate,
+        ) -> V::Result {
+            let WherePredicate { attrs, kind, id, span, is_placeholder: _ } = predicate;
+            try_visit!(visit_id(vis, id));
+            walk_list!(vis, visit_attribute, attrs);
+            try_visit!(visit_span(vis, span));
+            vis.visit_where_predicate_kind(kind)
         }
-    }
-}
 
-pub fn walk_generic_param<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    param: &'a GenericParam,
-) -> V::Result {
-    let GenericParam { id: _, ident, attrs, bounds, is_placeholder: _, kind, colon_span: _ } =
-        param;
-    walk_list!(visitor, visit_attribute, attrs);
-    try_visit!(visitor.visit_ident(ident));
-    walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
-    match kind {
-        GenericParamKind::Lifetime => (),
-        GenericParamKind::Type { default } => visit_opt!(visitor, visit_ty, default),
-        GenericParamKind::Const { ty, default, kw_span: _ } => {
-            try_visit!(visitor.visit_ty(ty));
-            visit_opt!(visitor, visit_anon_const, default);
+        pub fn walk_closure_binder<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            binder: &$($lt)? $($mut)? ClosureBinder,
+        ) -> V::Result {
+            match binder {
+                ClosureBinder::NotPresent => {}
+                ClosureBinder::For { generic_params, span } => {
+                    try_visit!(visit_generic_params(vis, generic_params));
+                    try_visit!(visit_span(vis, span));
+                }
+            }
+            V::Result::output()
         }
-    }
-    V::Result::output()
-}
 
-pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) -> V::Result {
-    let Generics { params, where_clause, span: _ } = generics;
-    let WhereClause { has_where_token: _, predicates, span: _ } = where_clause;
-    walk_list!(visitor, visit_generic_param, params);
-    walk_list!(visitor, visit_where_predicate, predicates);
-    V::Result::output()
-}
+        pub fn walk_where_predicate_kind<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            kind: &$($lt)? $($mut)? WherePredicateKind,
+        ) -> V::Result {
+            match kind {
+                WherePredicateKind::BoundPredicate(WhereBoundPredicate {
+                    bounded_ty,
+                    bounds,
+                    bound_generic_params,
+                }) => {
+                    try_visit!(visit_generic_params(vis, bound_generic_params));
+                    try_visit!(vis.visit_ty(bounded_ty));
+                    walk_list!(vis, visit_param_bound, bounds, BoundKind::Bound);
+                }
+                WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => {
+                    try_visit!(vis.visit_lifetime(lifetime, $(${ignore($lt)} LifetimeCtxt::Bound )?));
+                    walk_list!(vis, visit_param_bound, bounds, BoundKind::Bound);
+                }
+                WherePredicateKind::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty }) => {
+                    try_visit!(vis.visit_ty(lhs_ty));
+                    try_visit!(vis.visit_ty(rhs_ty));
+                }
+            }
+            V::Result::output()
+        }
 
-pub fn walk_closure_binder<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    binder: &'a ClosureBinder,
-) -> V::Result {
-    match binder {
-        ClosureBinder::NotPresent => {}
-        ClosureBinder::For { generic_params, span: _ } => {
-            walk_list!(visitor, visit_generic_param, generic_params)
+        pub fn walk_fn_decl<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            FnDecl { inputs, output }: &$($lt)? $($mut)? FnDecl,
+        ) -> V::Result {
+            try_visit!(visit_params(vis, inputs));
+            vis.visit_fn_ret_ty(output)
         }
-    }
-    V::Result::output()
-}
 
-pub fn walk_contract<'a, V: Visitor<'a>>(visitor: &mut V, c: &'a FnContract) -> V::Result {
-    let FnContract { requires, ensures } = c;
-    if let Some(pred) = requires {
-        visitor.visit_expr(pred);
-    }
-    if let Some(pred) = ensures {
-        visitor.visit_expr(pred);
-    }
-    V::Result::output()
-}
+        pub fn walk_fn_ret_ty<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, ret_ty: &$($lt)? $($mut)? FnRetTy) -> V::Result {
+            match ret_ty {
+                FnRetTy::Default(span) => visit_span(vis, span),
+                FnRetTy::Ty(output_ty) => vis.visit_ty(output_ty),
+            }
+        }
 
-pub fn walk_where_predicate<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    predicate: &'a WherePredicate,
-) -> V::Result {
-    let WherePredicate { attrs, kind, id: _, span: _, is_placeholder: _ } = predicate;
-    walk_list!(visitor, visit_attribute, attrs);
-    visitor.visit_where_predicate_kind(kind)
-}
+        pub fn walk_fn<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, kind: FnKind<$($lt)? $(${ignore($mut)} '_)?>) -> V::Result {
+            match kind {
+                FnKind::Fn(
+                    _ctxt,
+                    _vis,
+                    Fn {
+                        defaultness,
+                        ident,
+                        sig: FnSig { header, decl, span },
+                        generics,
+                        contract,
+                        body,
+                        define_opaque,
+                    },
+                ) => {
+                    // Visibility is visited as a part of the item.
+                    try_visit!(visit_defaultness(vis, defaultness));
+                    try_visit!(vis.visit_ident(ident));
+                    try_visit!(vis.visit_fn_header(header));
+                    try_visit!(vis.visit_generics(generics));
+                    try_visit!(vis.visit_fn_decl(decl));
+                    visit_opt!(vis, visit_contract, contract);
+                    visit_opt!(vis, visit_block, body);
+                    try_visit!(visit_span(vis, span));
+                    walk_define_opaques(vis, define_opaque)
+                }
+                FnKind::Closure(binder, coroutine_kind, decl, body) => {
+                    try_visit!(vis.visit_closure_binder(binder));
+                    visit_opt!(vis, visit_coroutine_kind, coroutine_kind);
+                    try_visit!(vis.visit_fn_decl(decl));
+                    vis.visit_expr(body)
+                }
+            }
+        }
 
-pub fn walk_where_predicate_kind<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    kind: &'a WherePredicateKind,
-) -> V::Result {
-    match kind {
-        WherePredicateKind::BoundPredicate(WhereBoundPredicate {
-            bounded_ty,
-            bounds,
-            bound_generic_params,
-        }) => {
-            walk_list!(visitor, visit_generic_param, bound_generic_params);
-            try_visit!(visitor.visit_ty(bounded_ty));
-            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
-        }
-        WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => {
-            try_visit!(visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound));
-            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
-        }
-        WherePredicateKind::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty }) => {
-            try_visit!(visitor.visit_ty(lhs_ty));
-            try_visit!(visitor.visit_ty(rhs_ty));
+        pub fn walk_variant_data<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, data: &$($lt)? $($mut)? VariantData) -> V::Result {
+            match data {
+                VariantData::Struct { fields, recovered: _ } => {
+                    visit_field_defs(vis, fields)
+                }
+                VariantData::Tuple(fields, id) => {
+                    try_visit!(visit_id(vis, id));
+                    visit_field_defs(vis, fields)
+                }
+                VariantData::Unit(id) => visit_id(vis, id),
+            }
         }
-    }
-    V::Result::output()
-}
 
-pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy) -> V::Result {
-    match ret_ty {
-        FnRetTy::Default(_span) => {}
-        FnRetTy::Ty(output_ty) => try_visit!(visitor.visit_ty(output_ty)),
-    }
-    V::Result::output()
-}
+        pub fn walk_field_def<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, field: &$($lt)? $($mut)? FieldDef) -> V::Result {
+            let FieldDef { attrs, id, span, vis: visibility, ident, ty, is_placeholder: _, safety: _, default } =
+                field;
+            try_visit!(visit_id(vis, id));
+            walk_list!(vis, visit_attribute, attrs);
+            try_visit!(vis.visit_vis(visibility));
+            visit_opt!(vis, visit_ident, ident);
+            try_visit!(vis.visit_ty(ty));
+            visit_opt!(vis, visit_anon_const, default);
+            visit_span(vis, span)
+        }
 
-pub fn walk_fn_decl<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    FnDecl { inputs, output }: &'a FnDecl,
-) -> V::Result {
-    walk_list!(visitor, visit_param, inputs);
-    visitor.visit_fn_ret_ty(output)
-}
+        fn visit_delim_args<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, args: &$($lt)? $($mut)? DelimArgs) -> V::Result {
+            let DelimArgs { dspan, delim: _, tokens: _ } = args;
+            let DelimSpan { open, close } = dspan;
+            try_visit!(visit_span(vis, open));
+            visit_span(vis, close)
+        }
 
-pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Result {
-    match kind {
-        FnKind::Fn(
-            _ctxt,
-            _vis,
-            Fn {
-                defaultness: _,
-                ident,
-                sig: FnSig { header, decl, span: _ },
-                generics,
-                contract,
-                body,
-                define_opaque,
-            },
-        ) => {
-            // Visibility is visited as a part of the item.
-            try_visit!(visitor.visit_ident(ident));
-            try_visit!(visitor.visit_fn_header(header));
-            try_visit!(visitor.visit_generics(generics));
-            try_visit!(visitor.visit_fn_decl(decl));
-            visit_opt!(visitor, visit_contract, contract);
-            visit_opt!(visitor, visit_block, body);
-            try_visit!(walk_define_opaques(visitor, define_opaque));
-        }
-        FnKind::Closure(binder, coroutine_kind, decl, body) => {
-            try_visit!(visitor.visit_closure_binder(binder));
-            visit_opt!(visitor, visit_coroutine_kind, coroutine_kind.as_ref());
-            try_visit!(visitor.visit_fn_decl(decl));
-            try_visit!(visitor.visit_expr(body));
+        pub fn walk_mac<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, mac: &$($lt)? $($mut)? MacCall) -> V::Result {
+            let MacCall { path, args } = mac;
+            try_visit!(vis.visit_path(path));
+            visit_delim_args(vis, args)
+        }
+
+        fn walk_macro_def<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, macro_def: &$($lt)? $($mut)? MacroDef) -> V::Result {
+            let MacroDef { body, macro_rules: _ } = macro_def;
+            visit_delim_args(vis, body)
+        }
+
+        pub fn walk_inline_asm<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, asm: &$($lt)? $($mut)? InlineAsm) -> V::Result {
+            // FIXME: Visit spans inside all this currently ignored stuff.
+            let InlineAsm {
+                asm_macro: _,
+                template: _,
+                template_strs: _,
+                operands,
+                clobber_abis: _,
+                options: _,
+                line_spans: _,
+            } = asm;
+            for (op, span) in operands {
+                match op {
+                    InlineAsmOperand::In { expr, reg: _ }
+                    | InlineAsmOperand::Out { expr: Some(expr), reg: _, late: _ }
+                    | InlineAsmOperand::InOut { expr, reg: _, late: _ } => {
+                        try_visit!(vis.visit_expr(expr))
+                    }
+                    InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {}
+                    InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
+                        try_visit!(vis.visit_expr(in_expr));
+                        visit_opt!(vis, visit_expr, out_expr);
+                    }
+                    InlineAsmOperand::Const { anon_const } => {
+                        try_visit!(vis.visit_anon_const(anon_const))
+                    }
+                    InlineAsmOperand::Sym { sym } => try_visit!(vis.visit_inline_asm_sym(sym)),
+                    InlineAsmOperand::Label { block } => try_visit!(vis.visit_block(block)),
+                }
+                try_visit!(visit_span(vis, span));
+            }
+            V::Result::output()
         }
-    }
-    V::Result::output()
-}
 
-pub fn walk_variant_data<'a, V: Visitor<'a>>(visitor: &mut V, data: &'a VariantData) -> V::Result {
-    visit_opt!(visitor, visit_id, data.ctor_node_id());
-    walk_list!(visitor, visit_field_def, data.fields());
-    V::Result::output()
-}
+        pub fn walk_inline_asm_sym<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            InlineAsmSym { id, qself, path }: &$($lt)? $($mut)? InlineAsmSym,
+        ) -> V::Result {
+            try_visit!(visit_id(vis, id));
+            try_visit!(vis.visit_qself(qself));
+            vis.visit_path(path)
+        }
+
+        // FIXME: visit the template exhaustively.
+        pub fn walk_format_args<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, fmt: &$($lt)? $($mut)? FormatArgs) -> V::Result {
+            let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _, is_source_literal: _ } = fmt;
+            let args = $(${ignore($mut)} arguments.all_args_mut())? $(${ignore($lt)} arguments.all_args())? ;
+            for FormatArgument { kind, expr } in args {
+                match kind {
+                    FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => {
+                        try_visit!(vis.visit_ident(ident))
+                    }
+                    FormatArgumentKind::Normal => {}
+                }
+                try_visit!(vis.visit_expr(expr));
+            }
+            visit_span(vis, span)
+        }
 
-pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) -> V::Result {
-    let FieldDef { attrs, id: _, span: _, vis, ident, ty, is_placeholder: _, safety: _, default } =
-        field;
-    walk_list!(visitor, visit_attribute, attrs);
-    try_visit!(visitor.visit_vis(vis));
-    visit_opt!(visitor, visit_ident, ident);
-    try_visit!(visitor.visit_ty(ty));
-    visit_opt!(visitor, visit_anon_const, &*default);
-    V::Result::output()
-}
+        pub fn walk_expr<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, expression: &$($lt)? $($mut)? Expr) -> V::Result {
+            let Expr { id, kind, span, attrs, tokens: _ } = expression;
+            try_visit!(visit_id(vis, id));
+            walk_list!(vis, visit_attribute, attrs);
+            match kind {
+                ExprKind::Array(exprs) => {
+                    try_visit!(visit_exprs(vis, exprs));
+                }
+                ExprKind::ConstBlock(anon_const) => try_visit!(vis.visit_anon_const(anon_const)),
+                ExprKind::Repeat(element, count) => {
+                    try_visit!(vis.visit_expr(element));
+                    try_visit!(vis.visit_anon_const(count));
+                }
+                ExprKind::Struct(se) => {
+                    let StructExpr { qself, path, fields, rest } = &$($mut)?**se;
+                    try_visit!(vis.visit_qself(qself));
+                    try_visit!(vis.visit_path(path));
+                    try_visit!(visit_expr_fields(vis, fields));
+                    match rest {
+                        StructRest::Base(expr) => try_visit!(vis.visit_expr(expr)),
+                        StructRest::Rest(_span) => {}
+                        StructRest::None => {}
+                    }
+                }
+                ExprKind::Tup(exprs) => {
+                    try_visit!(visit_exprs(vis, exprs));
+                }
+                ExprKind::Call(callee_expression, arguments) => {
+                    try_visit!(vis.visit_expr(callee_expression));
+                    try_visit!(visit_exprs(vis, arguments));
+                }
+                ExprKind::MethodCall(box MethodCall { seg, receiver, args, span }) => {
+                    try_visit!(vis.visit_method_receiver_expr(receiver));
+                    try_visit!(vis.visit_path_segment(seg));
+                    try_visit!(visit_exprs(vis, args));
+                    try_visit!(visit_span(vis, span));
+                }
+                ExprKind::Binary(Spanned { span, node: _ }, left_expression, right_expression) => {
+                    try_visit!(vis.visit_expr(left_expression));
+                    try_visit!(vis.visit_expr(right_expression));
+                    try_visit!(visit_span(vis, span))
+                }
+                ExprKind::AddrOf(_kind, _mutbl, subexpression) => {
+                    try_visit!(vis.visit_expr(subexpression));
+                }
+                ExprKind::Unary(_op, subexpression) => {
+                    try_visit!(vis.visit_expr(subexpression));
+                }
+                ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) => {
+                    try_visit!(vis.visit_expr(subexpression));
+                    try_visit!(vis.visit_ty(typ));
+                }
+                ExprKind::Let(pat, expr, span, _recovered) => {
+                    try_visit!(vis.visit_pat(pat));
+                    try_visit!(vis.visit_expr(expr));
+                    try_visit!(visit_span(vis, span))
+                }
+                ExprKind::If(head_expression, if_block, optional_else) => {
+                    try_visit!(vis.visit_expr(head_expression));
+                    try_visit!(vis.visit_block(if_block));
+                    visit_opt!(vis, visit_expr, optional_else);
+                }
+                ExprKind::While(subexpression, block, opt_label) => {
+                    visit_opt!(vis, visit_label, opt_label);
+                    try_visit!(vis.visit_expr(subexpression));
+                    try_visit!(vis.visit_block(block));
+                }
+                ExprKind::ForLoop { pat, iter, body, label, kind: _ } => {
+                    visit_opt!(vis, visit_label, label);
+                    try_visit!(vis.visit_pat(pat));
+                    try_visit!(vis.visit_expr(iter));
+                    try_visit!(vis.visit_block(body));
+                }
+                ExprKind::Loop(block, opt_label, span) => {
+                    visit_opt!(vis, visit_label, opt_label);
+                    try_visit!(vis.visit_block(block));
+                    try_visit!(visit_span(vis, span))
+                }
+                ExprKind::Match(subexpression, arms, _kind) => {
+                    try_visit!(vis.visit_expr(subexpression));
+                    try_visit!(visit_arms(vis, arms));
+                }
+                ExprKind::Closure(box Closure {
+                    binder,
+                    capture_clause,
+                    coroutine_kind,
+                    constness,
+                    movability: _,
+                    fn_decl,
+                    body,
+                    fn_decl_span,
+                    fn_arg_span,
+                }) => {
+                    try_visit!(visit_constness(vis, constness));
+                    try_visit!(vis.visit_capture_by(capture_clause));
+                    try_visit!(vis.visit_fn(
+                        FnKind::Closure(binder, coroutine_kind, fn_decl, body),
+                        *span,
+                        *id
+                    ));
+                    try_visit!(visit_span(vis, fn_decl_span));
+                    try_visit!(visit_span(vis, fn_arg_span));
+                }
+                ExprKind::Block(block, opt_label) => {
+                    visit_opt!(vis, visit_label, opt_label);
+                    try_visit!(vis.visit_block(block));
+                }
+                ExprKind::Gen(_capt, body, _kind, decl_span) => {
+                    try_visit!(vis.visit_block(body));
+                    try_visit!(visit_span(vis, decl_span));
+                }
+                ExprKind::Await(expr, span) => {
+                    try_visit!(vis.visit_expr(expr));
+                    try_visit!(visit_span(vis, span));
+                }
+                ExprKind::Use(expr, span) => {
+                    try_visit!(vis.visit_expr(expr));
+                    try_visit!(visit_span(vis, span));
+                }
+                ExprKind::Assign(lhs, rhs, span) => {
+                    try_visit!(vis.visit_expr(lhs));
+                    try_visit!(vis.visit_expr(rhs));
+                    try_visit!(visit_span(vis, span));
+                }
+                ExprKind::AssignOp(_op, left_expression, right_expression) => {
+                    try_visit!(vis.visit_expr(left_expression));
+                    try_visit!(vis.visit_expr(right_expression));
+                }
+                ExprKind::Field(subexpression, ident) => {
+                    try_visit!(vis.visit_expr(subexpression));
+                    try_visit!(vis.visit_ident(ident));
+                }
+                ExprKind::Index(main_expression, index_expression, span) => {
+                    try_visit!(vis.visit_expr(main_expression));
+                    try_visit!(vis.visit_expr(index_expression));
+                    try_visit!(visit_span(vis, span));
+                }
+                ExprKind::Range(start, end, _limit) => {
+                    visit_opt!(vis, visit_expr, start);
+                    visit_opt!(vis, visit_expr, end);
+                }
+                ExprKind::Underscore => {}
+                ExprKind::Path(maybe_qself, path) => {
+                    try_visit!(vis.visit_qself(maybe_qself));
+                    try_visit!(vis.visit_path(path));
+                }
+                ExprKind::Break(opt_label, opt_expr) => {
+                    visit_opt!(vis, visit_label, opt_label);
+                    visit_opt!(vis, visit_expr, opt_expr);
+                }
+                ExprKind::Continue(opt_label) => {
+                    visit_opt!(vis, visit_label, opt_label);
+                }
+                ExprKind::Ret(optional_expression) => {
+                    visit_opt!(vis, visit_expr, optional_expression);
+                }
+                ExprKind::Yeet(optional_expression) => {
+                    visit_opt!(vis, visit_expr, optional_expression);
+                }
+                ExprKind::Become(expr) => try_visit!(vis.visit_expr(expr)),
+                ExprKind::MacCall(mac) => try_visit!(vis.visit_mac_call(mac)),
+                ExprKind::Paren(subexpression) => try_visit!(vis.visit_expr(subexpression)),
+                ExprKind::InlineAsm(asm) => try_visit!(vis.visit_inline_asm(asm)),
+                ExprKind::FormatArgs(f) => try_visit!(vis.visit_format_args(f)),
+                ExprKind::OffsetOf(container, fields) => {
+                    try_visit!(vis.visit_ty(container));
+                    walk_list!(vis, visit_ident, fields);
+                }
+                ExprKind::Yield(kind) => {
+                    match kind {
+                        YieldKind::Postfix(expr) => {
+                            try_visit!(vis.visit_expr(expr));
+                        }
+                        YieldKind::Prefix(expr) => {
+                            visit_opt!(vis, visit_expr, expr);
+                        }
+                    }
+                }
+                ExprKind::Try(subexpression) => try_visit!(vis.visit_expr(subexpression)),
+                ExprKind::TryBlock(body) => try_visit!(vis.visit_block(body)),
+                ExprKind::Lit(_token) => {}
+                ExprKind::IncludedBytes(_bytes) => {}
+                ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
+                    try_visit!(vis.visit_expr(expr));
+                    visit_opt!(vis, visit_ty, ty);
+                }
+                ExprKind::Err(_guar) => {}
+                ExprKind::Dummy => {}
+            }
 
-pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result {
-    let Stmt { id: _, kind, span: _ } = statement;
-    match kind {
-        StmtKind::Let(local) => try_visit!(visitor.visit_local(local)),
-        StmtKind::Item(item) => try_visit!(visitor.visit_item(item)),
-        StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)),
-        StmtKind::Empty => {}
-        StmtKind::MacCall(mac) => {
-            let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac;
-            walk_list!(visitor, visit_attribute, attrs);
-            try_visit!(visitor.visit_mac_call(mac));
+            visit_span(vis, span)
         }
-    }
-    V::Result::output()
-}
-
-pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) -> V::Result {
-    let MacCall { path, args: _ } = mac;
-    visitor.visit_path(path)
-}
 
-pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) -> V::Result {
-    let InlineAsm {
-        asm_macro: _,
-        template: _,
-        template_strs: _,
-        operands,
-        clobber_abis: _,
-        options: _,
-        line_spans: _,
-    } = asm;
-    for (op, _span) in operands {
-        match op {
-            InlineAsmOperand::In { expr, reg: _ }
-            | InlineAsmOperand::Out { expr: Some(expr), reg: _, late: _ }
-            | InlineAsmOperand::InOut { expr, reg: _, late: _ } => {
-                try_visit!(visitor.visit_expr(expr))
-            }
-            InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {}
-            InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
-                try_visit!(visitor.visit_expr(in_expr));
-                visit_opt!(visitor, visit_expr, out_expr);
-            }
-            InlineAsmOperand::Const { anon_const } => {
-                try_visit!(visitor.visit_anon_const(anon_const))
-            }
-            InlineAsmOperand::Sym { sym } => try_visit!(visitor.visit_inline_asm_sym(sym)),
-            InlineAsmOperand::Label { block } => try_visit!(visitor.visit_block(block)),
+        pub fn walk_param<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, param: &$($lt)? $($mut)? Param) -> V::Result {
+            let Param { attrs, ty, pat, id, span, is_placeholder: _ } = param;
+            try_visit!(visit_id(vis, id));
+            walk_list!(vis, visit_attribute, attrs);
+            try_visit!(vis.visit_pat(pat));
+            try_visit!(vis.visit_ty(ty));
+            visit_span(vis, span)
         }
-    }
-    V::Result::output()
-}
 
-pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    InlineAsmSym { id, qself, path }: &'a InlineAsmSym,
-) -> V::Result {
-    try_visit!(visitor.visit_qself(qself));
-    try_visit!(visitor.visit_id(*id));
-    visitor.visit_path(path)
-}
+        pub fn walk_arm<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, arm: &$($lt)? $($mut)? Arm) -> V::Result {
+            let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = arm;
+            try_visit!(visit_id(vis, id));
+            walk_list!(vis, visit_attribute, attrs);
+            try_visit!(vis.visit_pat(pat));
+            visit_opt!(vis, visit_expr, guard);
+            visit_opt!(vis, visit_expr, body);
+            visit_span(vis, span)
+        }
 
-pub fn walk_format_args<'a, V: Visitor<'a>>(visitor: &mut V, fmt: &'a FormatArgs) -> V::Result {
-    let FormatArgs { span: _, template: _, arguments, uncooked_fmt_str: _ } = fmt;
-    for FormatArgument { kind, expr } in arguments.all_args() {
-        match kind {
-            FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => {
-                try_visit!(visitor.visit_ident(ident))
+        pub fn walk_vis<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, visibility: &$($lt)? $($mut)? Visibility) -> V::Result {
+            let Visibility { kind, span, tokens: _ } = visibility;
+            match kind {
+                VisibilityKind::Restricted { path, id, shorthand: _ } => {
+                    try_visit!(visit_id(vis, id));
+                    try_visit!(vis.visit_path(path));
+                }
+                VisibilityKind::Public | VisibilityKind::Inherited => {}
             }
-            FormatArgumentKind::Normal => {}
+            visit_span(vis, span)
         }
-        try_visit!(visitor.visit_expr(expr));
-    }
-    V::Result::output()
-}
 
-pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V::Result {
-    let Expr { id, kind, span, attrs, tokens: _ } = expression;
-    walk_list!(visitor, visit_attribute, attrs);
-    match kind {
-        ExprKind::Array(subexpressions) => {
-            walk_list!(visitor, visit_expr, subexpressions);
-        }
-        ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_anon_const(anon_const)),
-        ExprKind::Repeat(element, count) => {
-            try_visit!(visitor.visit_expr(element));
-            try_visit!(visitor.visit_anon_const(count));
-        }
-        ExprKind::Struct(se) => {
-            let StructExpr { qself, path, fields, rest } = &**se;
-            try_visit!(visitor.visit_qself(qself));
-            try_visit!(visitor.visit_id(*id));
-            try_visit!(visitor.visit_path(path));
-            walk_list!(visitor, visit_expr_field, fields);
-            match rest {
-                StructRest::Base(expr) => try_visit!(visitor.visit_expr(expr)),
-                StructRest::Rest(_span) => {}
-                StructRest::None => {}
-            }
-        }
-        ExprKind::Tup(subexpressions) => {
-            walk_list!(visitor, visit_expr, subexpressions);
-        }
-        ExprKind::Call(callee_expression, arguments) => {
-            try_visit!(visitor.visit_expr(callee_expression));
-            walk_list!(visitor, visit_expr, arguments);
-        }
-        ExprKind::MethodCall(box MethodCall { seg, receiver, args, span: _ }) => {
-            try_visit!(visitor.visit_expr(receiver));
-            try_visit!(visitor.visit_path_segment(seg));
-            walk_list!(visitor, visit_expr, args);
-        }
-        ExprKind::Binary(_op, left_expression, right_expression) => {
-            try_visit!(visitor.visit_expr(left_expression));
-            try_visit!(visitor.visit_expr(right_expression));
-        }
-        ExprKind::AddrOf(_kind, _mutbl, subexpression) => {
-            try_visit!(visitor.visit_expr(subexpression));
-        }
-        ExprKind::Unary(_op, subexpression) => {
-            try_visit!(visitor.visit_expr(subexpression));
-        }
-        ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) => {
-            try_visit!(visitor.visit_expr(subexpression));
-            try_visit!(visitor.visit_ty(typ));
-        }
-        ExprKind::Let(pat, expr, _span, _recovered) => {
-            try_visit!(visitor.visit_pat(pat));
-            try_visit!(visitor.visit_expr(expr));
-        }
-        ExprKind::If(head_expression, if_block, optional_else) => {
-            try_visit!(visitor.visit_expr(head_expression));
-            try_visit!(visitor.visit_block(if_block));
-            visit_opt!(visitor, visit_expr, optional_else);
-        }
-        ExprKind::While(subexpression, block, opt_label) => {
-            visit_opt!(visitor, visit_label, opt_label);
-            try_visit!(visitor.visit_expr(subexpression));
-            try_visit!(visitor.visit_block(block));
-        }
-        ExprKind::ForLoop { pat, iter, body, label, kind: _ } => {
-            visit_opt!(visitor, visit_label, label);
-            try_visit!(visitor.visit_pat(pat));
-            try_visit!(visitor.visit_expr(iter));
-            try_visit!(visitor.visit_block(body));
-        }
-        ExprKind::Loop(block, opt_label, _span) => {
-            visit_opt!(visitor, visit_label, opt_label);
-            try_visit!(visitor.visit_block(block));
-        }
-        ExprKind::Match(subexpression, arms, _kind) => {
-            try_visit!(visitor.visit_expr(subexpression));
-            walk_list!(visitor, visit_arm, arms);
-        }
-        ExprKind::Closure(box Closure {
-            binder,
-            capture_clause,
-            coroutine_kind,
-            constness: _,
-            movability: _,
-            fn_decl,
-            body,
-            fn_decl_span: _,
-            fn_arg_span: _,
-        }) => {
-            try_visit!(visitor.visit_capture_by(capture_clause));
-            try_visit!(visitor.visit_fn(
-                FnKind::Closure(binder, coroutine_kind, fn_decl, body),
-                *span,
-                *id
-            ));
-        }
-        ExprKind::Block(block, opt_label) => {
-            visit_opt!(visitor, visit_label, opt_label);
-            try_visit!(visitor.visit_block(block));
-        }
-        ExprKind::Gen(_capt, body, _kind, _decl_span) => try_visit!(visitor.visit_block(body)),
-        ExprKind::Await(expr, _span) => try_visit!(visitor.visit_expr(expr)),
-        ExprKind::Use(expr, _span) => try_visit!(visitor.visit_expr(expr)),
-        ExprKind::Assign(lhs, rhs, _span) => {
-            try_visit!(visitor.visit_expr(lhs));
-            try_visit!(visitor.visit_expr(rhs));
-        }
-        ExprKind::AssignOp(_op, left_expression, right_expression) => {
-            try_visit!(visitor.visit_expr(left_expression));
-            try_visit!(visitor.visit_expr(right_expression));
-        }
-        ExprKind::Field(subexpression, ident) => {
-            try_visit!(visitor.visit_expr(subexpression));
-            try_visit!(visitor.visit_ident(ident));
-        }
-        ExprKind::Index(main_expression, index_expression, _span) => {
-            try_visit!(visitor.visit_expr(main_expression));
-            try_visit!(visitor.visit_expr(index_expression));
-        }
-        ExprKind::Range(start, end, _limit) => {
-            visit_opt!(visitor, visit_expr, start);
-            visit_opt!(visitor, visit_expr, end);
-        }
-        ExprKind::Underscore => {}
-        ExprKind::Path(maybe_qself, path) => {
-            try_visit!(visitor.visit_qself(maybe_qself));
-            try_visit!(visitor.visit_id(*id));
-            try_visit!(visitor.visit_path(path));
-        }
-        ExprKind::Break(opt_label, opt_expr) => {
-            visit_opt!(visitor, visit_label, opt_label);
-            visit_opt!(visitor, visit_expr, opt_expr);
-        }
-        ExprKind::Continue(opt_label) => {
-            visit_opt!(visitor, visit_label, opt_label);
-        }
-        ExprKind::Ret(optional_expression) => {
-            visit_opt!(visitor, visit_expr, optional_expression);
-        }
-        ExprKind::Yeet(optional_expression) => {
-            visit_opt!(visitor, visit_expr, optional_expression);
-        }
-        ExprKind::Become(expr) => try_visit!(visitor.visit_expr(expr)),
-        ExprKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
-        ExprKind::Paren(subexpression) => try_visit!(visitor.visit_expr(subexpression)),
-        ExprKind::InlineAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)),
-        ExprKind::FormatArgs(f) => try_visit!(visitor.visit_format_args(f)),
-        ExprKind::OffsetOf(container, fields) => {
-            try_visit!(visitor.visit_ty(container));
-            walk_list!(visitor, visit_ident, fields.iter());
-        }
-        ExprKind::Yield(kind) => {
-            visit_opt!(visitor, visit_expr, kind.expr());
-        }
-        ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)),
-        ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)),
-        ExprKind::Lit(_token) => {}
-        ExprKind::IncludedBytes(_bytes) => {}
-        ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
-            try_visit!(visitor.visit_expr(expr));
-            visit_opt!(visitor, visit_ty, ty);
-        }
-        ExprKind::Err(_guar) => {}
-        ExprKind::Dummy => {}
-    }
+        pub fn walk_attribute<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, attr: &$($lt)? $($mut)? Attribute) -> V::Result {
+            let Attribute { kind, id: _, style: _, span } = attr;
+            match kind {
+                AttrKind::Normal(normal) => {
+                    let NormalAttr { item, tokens: _ } = &$($mut)?**normal;
+                    let AttrItem { unsafety: _, path, args, tokens: _ } = item;
+                    try_visit!(vis.visit_path(path));
+                    try_visit!(walk_attr_args(vis, args));
+                }
+                AttrKind::DocComment(_kind, _sym) => {}
+            }
+            visit_span(vis, span)
+        }
 
-    V::Result::output()
+        pub fn walk_attr_args<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, args: &$($lt)? $($mut)? AttrArgs) -> V::Result {
+            match args {
+                AttrArgs::Empty => {}
+                AttrArgs::Delimited(args) => try_visit!(visit_delim_args(vis, args)),
+                AttrArgs::Eq { eq_span, expr } => {
+                    try_visit!(vis.visit_expr(expr));
+                    try_visit!(visit_span(vis, eq_span));
+                }
+            }
+            V::Result::output()
+        }
+    };
 }
 
-pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) -> V::Result {
-    let Param { attrs, ty, pat, id: _, span: _, is_placeholder: _ } = param;
-    walk_list!(visitor, visit_attribute, attrs);
-    try_visit!(visitor.visit_pat(pat));
-    try_visit!(visitor.visit_ty(ty));
-    V::Result::output()
+common_visitor_and_walkers!(Visitor<'a>);
+
+macro_rules! generate_list_visit_fns {
+    ($($name:ident, $Ty:ty, $visit_fn:ident$(, $param:ident: $ParamTy:ty)*;)+) => {
+        $(
+            fn $name<'a, V: Visitor<'a>>(
+                vis: &mut V,
+                values: &'a ThinVec<$Ty>,
+                $(
+                    $param: $ParamTy,
+                )*
+            ) -> V::Result {
+                walk_list!(vis, $visit_fn, values$(,$param)*);
+                V::Result::output()
+            }
+        )+
+    }
 }
 
-pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) -> V::Result {
-    let Arm { attrs, pat, guard, body, span: _, id: _, is_placeholder: _ } = arm;
-    walk_list!(visitor, visit_attribute, attrs);
-    try_visit!(visitor.visit_pat(pat));
-    visit_opt!(visitor, visit_expr, guard);
-    visit_opt!(visitor, visit_expr, body);
-    V::Result::output()
+generate_list_visit_fns! {
+    visit_items, P<Item>, visit_item;
+    visit_foreign_items, P<ForeignItem>, visit_foreign_item;
+    visit_generic_params, GenericParam, visit_generic_param;
+    visit_stmts, Stmt, visit_stmt;
+    visit_exprs, P<Expr>, visit_expr;
+    visit_expr_fields, ExprField, visit_expr_field;
+    visit_pat_fields, PatField, visit_pat_field;
+    visit_variants, Variant, visit_variant;
+    visit_assoc_items, P<AssocItem>, visit_assoc_item, ctxt: AssocCtxt;
+    visit_where_predicates, WherePredicate, visit_where_predicate;
+    visit_params, Param, visit_param;
+    visit_field_defs, FieldDef, visit_field_def;
+    visit_arms, Arm, visit_arm;
 }
 
-pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) -> V::Result {
-    let Visibility { kind, span: _, tokens: _ } = vis;
-    match kind {
-        VisibilityKind::Restricted { path, id, shorthand: _ } => {
-            try_visit!(visitor.visit_id(*id));
-            try_visit!(visitor.visit_path(path));
-        }
-        VisibilityKind::Public | VisibilityKind::Inherited => {}
-    }
-    V::Result::output()
+#[expect(rustc::pass_by_value)] // needed for symmetry with mut_visit
+fn visit_nested_use_tree<'a, V: Visitor<'a>>(
+    vis: &mut V,
+    nested_tree: &'a UseTree,
+    &nested_id: &NodeId,
+) -> V::Result {
+    vis.visit_nested_use_tree(nested_tree, nested_id)
 }
 
-pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) -> V::Result {
-    let Attribute { kind, id: _, style: _, span: _ } = attr;
+pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result {
+    let Stmt { id, kind, span: _ } = statement;
+    try_visit!(visit_id(visitor, id));
     match kind {
-        AttrKind::Normal(normal) => {
-            let NormalAttr { item, tokens: _ } = &**normal;
-            let AttrItem { unsafety: _, path, args, tokens: _ } = item;
-            try_visit!(visitor.visit_path(path));
-            try_visit!(walk_attr_args(visitor, args));
+        StmtKind::Let(local) => try_visit!(visitor.visit_local(local)),
+        StmtKind::Item(item) => try_visit!(visitor.visit_item(item)),
+        StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)),
+        StmtKind::Empty => {}
+        StmtKind::MacCall(mac) => {
+            let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac;
+            walk_list!(visitor, visit_attribute, attrs);
+            try_visit!(visitor.visit_mac_call(mac));
         }
-        AttrKind::DocComment(_kind, _sym) => {}
-    }
-    V::Result::output()
-}
-
-pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) -> V::Result {
-    match args {
-        AttrArgs::Empty => {}
-        AttrArgs::Delimited(_args) => {}
-        AttrArgs::Eq { expr, .. } => try_visit!(visitor.visit_expr(expr)),
     }
     V::Result::output()
 }