about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-07-24 09:36:57 +0000
committerbors <bors@rust-lang.org>2024-07-24 09:36:57 +0000
commitd24930ceb473b7b361d108d573308e3529cb5ef7 (patch)
tree04a17f3518922c7bc81530c016835f9233ec3280
parent08a9ca7c18a30a23a72a43b65be616c9a6a36a5a (diff)
parente9f32d0ca6f5ffdb3714e9817b4a93a59b247112 (diff)
Auto merge of #127524 - oli-obk:feed_item_attrs2, r=petrochenkov
Make ast `MutVisitor` have the same method name and style as `Visitor`

It doesn't map 100% because some `MutVisitor` methods can filter or even expand to multiple items, but consistency seems nicer.

tracking issue: https://github.com/rust-lang/rust/issues/127615
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs571
-rw-r--r--compiler/rustc_builtin_macros/src/cfg_eval.rs71
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs12
-rw-r--r--compiler/rustc_builtin_macros/src/util.rs3
-rw-r--r--compiler/rustc_expand/src/base.rs20
-rw-r--r--compiler/rustc_expand/src/expand.rs142
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs4
-rw-r--r--compiler/rustc_expand/src/placeholders.rs57
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs12
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs8
-rw-r--r--tests/ui-fulldeps/pprust-expr-roundtrip.rs19
12 files changed, 478 insertions, 445 deletions
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 39d0f2c7305..8387e4499ae 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -11,6 +11,7 @@ use crate::ast::*;
 use crate::ptr::P;
 use crate::token::{self, Token};
 use crate::tokenstream::*;
+use crate::visit::{AssocCtxt, BoundKind};
 
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -34,8 +35,8 @@ impl<A: Array> ExpectOne<A> for SmallVec<A> {
     }
 }
 
-pub trait NoopVisitItemKind {
-    fn noop_visit(&mut self, visitor: &mut impl MutVisitor);
+pub trait WalkItemKind {
+    fn walk(&mut self, span: Span, id: NodeId, visitor: &mut impl MutVisitor);
 }
 
 pub trait MutVisitor: Sized {
@@ -78,79 +79,84 @@ pub trait MutVisitor: Sized {
     // forget to add handling for it.
 
     fn visit_crate(&mut self, c: &mut Crate) {
-        noop_visit_crate(c, self)
+        walk_crate(self, c)
     }
 
     fn visit_meta_list_item(&mut self, list_item: &mut NestedMetaItem) {
-        noop_visit_meta_list_item(list_item, self);
+        walk_meta_list_item(self, list_item);
     }
 
     fn visit_meta_item(&mut self, meta_item: &mut MetaItem) {
-        noop_visit_meta_item(meta_item, self);
+        walk_meta_item(self, meta_item);
     }
 
     fn visit_use_tree(&mut self, use_tree: &mut UseTree) {
-        noop_visit_use_tree(use_tree, self);
+        walk_use_tree(self, use_tree);
     }
 
     fn flat_map_foreign_item(&mut self, ni: P<ForeignItem>) -> SmallVec<[P<ForeignItem>; 1]> {
-        noop_flat_map_item(ni, self)
+        walk_flat_map_item(self, ni)
     }
 
     fn flat_map_item(&mut self, i: P<Item>) -> SmallVec<[P<Item>; 1]> {
-        noop_flat_map_item(i, self)
+        walk_flat_map_item(self, i)
     }
 
     fn visit_fn_header(&mut self, header: &mut FnHeader) {
-        noop_visit_fn_header(header, self);
+        walk_fn_header(self, header);
     }
 
     fn flat_map_field_def(&mut self, fd: FieldDef) -> SmallVec<[FieldDef; 1]> {
-        noop_flat_map_field_def(fd, self)
+        walk_flat_map_field_def(self, fd)
     }
 
-    fn flat_map_trait_item(&mut self, i: P<AssocItem>) -> SmallVec<[P<AssocItem>; 1]> {
-        noop_flat_map_item(i, self)
+    fn flat_map_assoc_item(
+        &mut self,
+        i: P<AssocItem>,
+        _ctxt: AssocCtxt,
+    ) -> SmallVec<[P<AssocItem>; 1]> {
+        walk_flat_map_item(self, i)
     }
 
-    fn flat_map_impl_item(&mut self, i: P<AssocItem>) -> SmallVec<[P<AssocItem>; 1]> {
-        noop_flat_map_item(i, self)
+    fn visit_fn_decl(&mut self, d: &mut P<FnDecl>) {
+        walk_fn_decl(self, d);
     }
 
-    fn visit_fn_decl(&mut self, d: &mut P<FnDecl>) {
-        noop_visit_fn_decl(d, self);
+    /// `Span` and `NodeId` are mutated at the caller site.
+    fn visit_fn(&mut self, fk: FnKind<'_>, _: Span, _: NodeId) {
+        walk_fn(self, fk)
     }
 
     fn visit_coroutine_kind(&mut self, a: &mut CoroutineKind) {
-        noop_visit_coroutine_kind(a, self);
+        walk_coroutine_kind(self, a);
     }
 
     fn visit_closure_binder(&mut self, b: &mut ClosureBinder) {
-        noop_visit_closure_binder(b, self);
+        walk_closure_binder(self, b);
     }
 
     fn visit_block(&mut self, b: &mut P<Block>) {
-        noop_visit_block(b, self);
+        walk_block(self, b);
     }
 
     fn flat_map_stmt(&mut self, s: Stmt) -> SmallVec<[Stmt; 1]> {
-        noop_flat_map_stmt(s, self)
+        walk_flat_map_stmt(self, s)
     }
 
     fn flat_map_arm(&mut self, arm: Arm) -> SmallVec<[Arm; 1]> {
-        noop_flat_map_arm(arm, self)
+        walk_flat_map_arm(self, arm)
     }
 
     fn visit_pat(&mut self, p: &mut P<Pat>) {
-        noop_visit_pat(p, self);
+        walk_pat(self, p);
     }
 
     fn visit_anon_const(&mut self, c: &mut AnonConst) {
-        noop_visit_anon_const(c, self);
+        walk_anon_const(self, c);
     }
 
     fn visit_expr(&mut self, e: &mut P<Expr>) {
-        noop_visit_expr(e, self);
+        walk_expr(self, e);
     }
 
     /// This method is a hack to workaround unstable of `stmt_expr_attributes`.
@@ -160,127 +166,131 @@ pub trait MutVisitor: Sized {
     }
 
     fn filter_map_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> {
-        noop_filter_map_expr(e, self)
+        noop_filter_map_expr(self, e)
     }
 
     fn visit_generic_arg(&mut self, arg: &mut GenericArg) {
-        noop_visit_generic_arg(arg, self);
+        walk_generic_arg(self, arg);
     }
 
     fn visit_ty(&mut self, t: &mut P<Ty>) {
-        noop_visit_ty(t, self);
+        walk_ty(self, t);
     }
 
     fn visit_lifetime(&mut self, l: &mut Lifetime) {
-        noop_visit_lifetime(l, self);
+        walk_lifetime(self, l);
     }
 
     fn visit_assoc_item_constraint(&mut self, c: &mut AssocItemConstraint) {
-        noop_visit_assoc_item_constraint(c, self);
+        walk_assoc_item_constraint(self, c);
     }
 
     fn visit_foreign_mod(&mut self, nm: &mut ForeignMod) {
-        noop_visit_foreign_mod(nm, self);
+        walk_foreign_mod(self, nm);
     }
 
     fn flat_map_variant(&mut self, v: Variant) -> SmallVec<[Variant; 1]> {
-        noop_flat_map_variant(v, self)
+        walk_flat_map_variant(self, v)
     }
 
     fn visit_ident(&mut self, i: &mut Ident) {
-        noop_visit_ident(i, self);
+        walk_ident(self, i);
     }
 
     fn visit_path(&mut self, p: &mut Path) {
-        noop_visit_path(p, self);
+        walk_path(self, p);
+    }
+
+    fn visit_path_segment(&mut self, p: &mut PathSegment) {
+        walk_path_segment(self, p)
     }
 
     fn visit_qself(&mut self, qs: &mut Option<P<QSelf>>) {
-        noop_visit_qself(qs, self);
+        walk_qself(self, qs);
     }
 
     fn visit_generic_args(&mut self, p: &mut GenericArgs) {
-        noop_visit_generic_args(p, self);
+        walk_generic_args(self, p);
     }
 
     fn visit_angle_bracketed_parameter_data(&mut self, p: &mut AngleBracketedArgs) {
-        noop_visit_angle_bracketed_parameter_data(p, self);
+        walk_angle_bracketed_parameter_data(self, p);
     }
 
     fn visit_parenthesized_parameter_data(&mut self, p: &mut ParenthesizedArgs) {
-        noop_visit_parenthesized_parameter_data(p, self);
+        walk_parenthesized_parameter_data(self, p);
     }
 
     fn visit_local(&mut self, l: &mut P<Local>) {
-        noop_visit_local(l, self);
+        walk_local(self, l);
     }
 
     fn visit_mac_call(&mut self, mac: &mut MacCall) {
-        noop_visit_mac(mac, self);
+        walk_mac(self, mac);
     }
 
     fn visit_macro_def(&mut self, def: &mut MacroDef) {
-        noop_visit_macro_def(def, self);
+        walk_macro_def(self, def);
     }
 
     fn visit_label(&mut self, label: &mut Label) {
-        noop_visit_label(label, self);
+        walk_label(self, label);
     }
 
     fn visit_attribute(&mut self, at: &mut Attribute) {
-        noop_visit_attribute(at, self);
+        walk_attribute(self, at);
     }
 
     fn flat_map_param(&mut self, param: Param) -> SmallVec<[Param; 1]> {
-        noop_flat_map_param(param, self)
+        walk_flat_map_param(self, param)
     }
 
     fn visit_generics(&mut self, generics: &mut Generics) {
-        noop_visit_generics(generics, self);
+        walk_generics(self, generics);
     }
 
     fn visit_trait_ref(&mut self, tr: &mut TraitRef) {
-        noop_visit_trait_ref(tr, self);
+        walk_trait_ref(self, tr);
     }
 
     fn visit_poly_trait_ref(&mut self, p: &mut PolyTraitRef) {
-        noop_visit_poly_trait_ref(p, self);
+        walk_poly_trait_ref(self, p);
     }
 
     fn visit_variant_data(&mut self, vdata: &mut VariantData) {
-        noop_visit_variant_data(vdata, self);
+        walk_variant_data(self, vdata);
     }
 
     fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> {
-        noop_flat_map_generic_param(param, self)
+        walk_flat_map_generic_param(self, param)
     }
 
-    fn visit_param_bound(&mut self, tpb: &mut GenericBound) {
-        noop_visit_param_bound(tpb, self);
+    fn visit_param_bound(&mut self, tpb: &mut GenericBound, _ctxt: BoundKind) {
+        walk_param_bound(self, tpb);
     }
 
     fn visit_precise_capturing_arg(&mut self, arg: &mut PreciseCapturingArg) {
-        noop_visit_precise_capturing_arg(arg, self);
+        walk_precise_capturing_arg(self, arg);
     }
 
     fn visit_mt(&mut self, mt: &mut MutTy) {
-        noop_visit_mt(mt, self);
+        walk_mt(self, mt);
     }
 
     fn flat_map_expr_field(&mut self, f: ExprField) -> SmallVec<[ExprField; 1]> {
-        noop_flat_map_expr_field(f, self)
+        walk_flat_map_expr_field(self, f)
     }
 
     fn visit_where_clause(&mut self, where_clause: &mut WhereClause) {
-        noop_visit_where_clause(where_clause, self);
+        walk_where_clause(self, where_clause);
     }
 
     fn visit_where_predicate(&mut self, where_predicate: &mut WherePredicate) {
-        noop_visit_where_predicate(where_predicate, self);
+        walk_where_predicate(self, where_predicate);
     }
 
     fn visit_vis(&mut self, vis: &mut Visibility) {
-        noop_visit_vis(vis, self);
+        walk_vis(self, vis);
     }
 
     fn visit_id(&mut self, _id: &mut NodeId) {
@@ -292,23 +302,23 @@ pub trait MutVisitor: Sized {
     }
 
     fn flat_map_pat_field(&mut self, fp: PatField) -> SmallVec<[PatField; 1]> {
-        noop_flat_map_pat_field(fp, self)
+        walk_flat_map_pat_field(self, fp)
     }
 
     fn visit_inline_asm(&mut self, asm: &mut InlineAsm) {
-        noop_visit_inline_asm(asm, self)
+        walk_inline_asm(self, asm)
     }
 
     fn visit_inline_asm_sym(&mut self, sym: &mut InlineAsmSym) {
-        noop_visit_inline_asm_sym(sym, self)
+        walk_inline_asm_sym(self, sym)
     }
 
     fn visit_format_args(&mut self, fmt: &mut FormatArgs) {
-        noop_visit_format_args(fmt, self)
+        walk_format_args(self, fmt)
     }
 
     fn visit_capture_by(&mut self, capture_by: &mut CaptureBy) {
-        noop_visit_capture_by(capture_by, self)
+        walk_capture_by(self, capture_by)
     }
 }
 
@@ -356,7 +366,7 @@ where
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_attrs<T: MutVisitor>(attrs: &mut AttrVec, vis: &mut T) {
+fn visit_attrs<T: MutVisitor>(vis: &mut T, attrs: &mut AttrVec) {
     for attr in attrs.iter_mut() {
         vis.visit_attribute(attr);
     }
@@ -364,32 +374,25 @@ fn visit_attrs<T: MutVisitor>(attrs: &mut AttrVec, vis: &mut T) {
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
 #[allow(unused)]
-fn visit_exprs<T: MutVisitor>(exprs: &mut Vec<P<Expr>>, vis: &mut T) {
+fn visit_exprs<T: MutVisitor>(vis: &mut T, exprs: &mut Vec<P<Expr>>) {
     exprs.flat_map_in_place(|expr| vis.filter_map_expr(expr))
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_thin_exprs<T: MutVisitor>(exprs: &mut ThinVec<P<Expr>>, vis: &mut T) {
+fn visit_thin_exprs<T: MutVisitor>(vis: &mut T, exprs: &mut ThinVec<P<Expr>>) {
     exprs.flat_map_in_place(|expr| vis.filter_map_expr(expr))
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_bounds<T: MutVisitor>(bounds: &mut GenericBounds, vis: &mut T) {
-    visit_vec(bounds, |bound| vis.visit_param_bound(bound));
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_fn_sig<T: MutVisitor>(FnSig { header, decl, span }: &mut FnSig, vis: &mut T) {
-    vis.visit_fn_header(header);
-    vis.visit_fn_decl(decl);
-    vis.visit_span(span);
+fn visit_bounds<T: MutVisitor>(vis: &mut T, bounds: &mut GenericBounds, ctxt: BoundKind) {
+    visit_vec(bounds, |bound| vis.visit_param_bound(bound, ctxt));
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_attr_args<T: MutVisitor>(args: &mut AttrArgs, vis: &mut T) {
+fn visit_attr_args<T: MutVisitor>(vis: &mut T, args: &mut AttrArgs) {
     match args {
         AttrArgs::Empty => {}
-        AttrArgs::Delimited(args) => visit_delim_args(args, vis),
+        AttrArgs::Delimited(args) => visit_delim_args(vis, args),
         AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => {
             vis.visit_expr(expr);
             vis.visit_span(eq_span);
@@ -401,31 +404,31 @@ fn visit_attr_args<T: MutVisitor>(args: &mut AttrArgs, vis: &mut T) {
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_delim_args<T: MutVisitor>(args: &mut DelimArgs, vis: &mut T) {
+fn visit_delim_args<T: MutVisitor>(vis: &mut T, args: &mut DelimArgs) {
     let DelimArgs { dspan, delim: _, tokens } = args;
-    visit_tts(tokens, vis);
-    visit_delim_span(dspan, vis);
+    visit_tts(vis, tokens);
+    visit_delim_span(vis, dspan);
 }
 
-pub fn visit_delim_span<T: MutVisitor>(DelimSpan { open, close }: &mut DelimSpan, vis: &mut T) {
+pub fn visit_delim_span<T: MutVisitor>(vis: &mut T, DelimSpan { open, close }: &mut DelimSpan) {
     vis.visit_span(open);
     vis.visit_span(close);
 }
 
-pub fn noop_flat_map_pat_field<T: MutVisitor>(
-    mut fp: PatField,
+pub fn walk_flat_map_pat_field<T: MutVisitor>(
     vis: &mut T,
+    mut fp: PatField,
 ) -> SmallVec<[PatField; 1]> {
     let PatField { attrs, id, ident, is_placeholder: _, is_shorthand: _, pat, span } = &mut fp;
     vis.visit_id(id);
-    visit_attrs(attrs, vis);
+    visit_attrs(vis, attrs);
     vis.visit_ident(ident);
     vis.visit_pat(pat);
     vis.visit_span(span);
     smallvec![fp]
 }
 
-fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
+fn walk_use_tree<T: MutVisitor>(vis: &mut T, use_tree: &mut UseTree) {
     let UseTree { prefix, kind, span } = use_tree;
     vis.visit_path(prefix);
     match kind {
@@ -442,10 +445,10 @@ fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
     vis.visit_span(span);
 }
 
-pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> {
+pub fn walk_flat_map_arm<T: MutVisitor>(vis: &mut T, mut arm: Arm) -> SmallVec<[Arm; 1]> {
     let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm;
     vis.visit_id(id);
-    visit_attrs(attrs, vis);
+    visit_attrs(vis, attrs);
     vis.visit_pat(pat);
     visit_opt(guard, |guard| vis.visit_expr(guard));
     visit_opt(body, |body| vis.visit_expr(body));
@@ -453,9 +456,9 @@ pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[
     smallvec![arm]
 }
 
-fn noop_visit_assoc_item_constraint<T: MutVisitor>(
-    AssocItemConstraint { id, ident, gen_args, kind, span }: &mut AssocItemConstraint,
+fn walk_assoc_item_constraint<T: MutVisitor>(
     vis: &mut T,
+    AssocItemConstraint { id, ident, gen_args, kind, span }: &mut AssocItemConstraint,
 ) {
     vis.visit_id(id);
     vis.visit_ident(ident);
@@ -467,12 +470,12 @@ fn noop_visit_assoc_item_constraint<T: MutVisitor>(
             Term::Ty(ty) => vis.visit_ty(ty),
             Term::Const(c) => vis.visit_anon_const(c),
         },
-        AssocItemConstraintKind::Bound { bounds } => visit_bounds(bounds, vis),
+        AssocItemConstraintKind::Bound { bounds } => visit_bounds(vis, bounds, BoundKind::Bound),
     }
     vis.visit_span(span);
 }
 
-pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
+pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
     let Ty { id, kind, span, tokens } = ty.deref_mut();
     vis.visit_id(id);
     match kind {
@@ -487,7 +490,7 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
         }
         TyKind::BareFn(bft) => {
             let BareFnTy { safety, ext: _, generic_params, decl, decl_span } = bft.deref_mut();
-            visit_safety(safety, vis);
+            visit_safety(vis, safety);
             generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
             vis.visit_fn_decl(decl);
             vis.visit_span(decl_span);
@@ -508,11 +511,11 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
         }
         TyKind::Typeof(expr) => vis.visit_anon_const(expr),
         TyKind::TraitObject(bounds, _syntax) => {
-            visit_vec(bounds, |bound| vis.visit_param_bound(bound))
+            visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::TraitObject))
         }
         TyKind::ImplTrait(id, bounds) => {
             vis.visit_id(id);
-            visit_vec(bounds, |bound| vis.visit_param_bound(bound));
+            visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Impl));
         }
         TyKind::MacCall(mac) => vis.visit_mac_call(mac),
         TyKind::AnonStruct(id, fields) | TyKind::AnonUnion(id, fields) => {
@@ -520,23 +523,23 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
             fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
         }
     }
-    visit_lazy_tts(tokens, vis);
+    visit_lazy_tts(vis, tokens);
     vis.visit_span(span);
 }
 
-fn noop_visit_foreign_mod<T: MutVisitor>(foreign_mod: &mut ForeignMod, vis: &mut T) {
+fn walk_foreign_mod<T: MutVisitor>(vis: &mut T, foreign_mod: &mut ForeignMod) {
     let ForeignMod { safety, abi: _, items } = foreign_mod;
-    visit_safety(safety, vis);
+    visit_safety(vis, safety);
     items.flat_map_in_place(|item| vis.flat_map_foreign_item(item));
 }
 
-pub fn noop_flat_map_variant<T: MutVisitor>(
-    mut variant: Variant,
+pub fn walk_flat_map_variant<T: MutVisitor>(
     visitor: &mut T,
+    mut variant: Variant,
 ) -> SmallVec<[Variant; 1]> {
     let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
     visitor.visit_id(id);
-    visit_attrs(attrs, visitor);
+    visit_attrs(visitor, attrs);
     visitor.visit_vis(vis);
     visitor.visit_ident(ident);
     visitor.visit_variant_data(data);
@@ -545,21 +548,26 @@ pub fn noop_flat_map_variant<T: MutVisitor>(
     smallvec![variant]
 }
 
-fn noop_visit_ident<T: MutVisitor>(Ident { name: _, span }: &mut Ident, vis: &mut T) {
+fn walk_ident<T: MutVisitor>(vis: &mut T, Ident { name: _, span }: &mut Ident) {
     vis.visit_span(span);
 }
 
-fn noop_visit_path<T: MutVisitor>(Path { segments, span, tokens }: &mut Path, vis: &mut T) {
-    for PathSegment { ident, id, args } in segments {
-        vis.visit_id(id);
-        vis.visit_ident(ident);
-        visit_opt(args, |args| vis.visit_generic_args(args));
+fn walk_path_segment<T: MutVisitor>(vis: &mut T, segment: &mut PathSegment) {
+    let PathSegment { ident, id, args } = segment;
+    vis.visit_id(id);
+    vis.visit_ident(ident);
+    visit_opt(args, |args| vis.visit_generic_args(args));
+}
+
+fn walk_path<T: MutVisitor>(vis: &mut T, Path { segments, span, tokens }: &mut Path) {
+    for segment in segments {
+        vis.visit_path_segment(segment);
     }
-    visit_lazy_tts(tokens, vis);
+    visit_lazy_tts(vis, tokens);
     vis.visit_span(span);
 }
 
-fn noop_visit_qself<T: MutVisitor>(qself: &mut Option<P<QSelf>>, vis: &mut T) {
+fn walk_qself<T: MutVisitor>(vis: &mut T, qself: &mut Option<P<QSelf>>) {
     visit_opt(qself, |qself| {
         let QSelf { ty, path_span, position: _ } = &mut **qself;
         vis.visit_ty(ty);
@@ -567,7 +575,7 @@ fn noop_visit_qself<T: MutVisitor>(qself: &mut Option<P<QSelf>>, vis: &mut T) {
     })
 }
 
-fn noop_visit_generic_args<T: MutVisitor>(generic_args: &mut GenericArgs, vis: &mut T) {
+fn walk_generic_args<T: MutVisitor>(vis: &mut T, generic_args: &mut GenericArgs) {
     match generic_args {
         GenericArgs::AngleBracketed(data) => vis.visit_angle_bracketed_parameter_data(data),
         GenericArgs::Parenthesized(data) => vis.visit_parenthesized_parameter_data(data),
@@ -575,7 +583,7 @@ fn noop_visit_generic_args<T: MutVisitor>(generic_args: &mut GenericArgs, vis: &
     }
 }
 
-fn noop_visit_generic_arg<T: MutVisitor>(arg: &mut GenericArg, vis: &mut T) {
+fn walk_generic_arg<T: MutVisitor>(vis: &mut T, arg: &mut GenericArg) {
     match arg {
         GenericArg::Lifetime(lt) => vis.visit_lifetime(lt),
         GenericArg::Type(ty) => vis.visit_ty(ty),
@@ -583,10 +591,7 @@ fn noop_visit_generic_arg<T: MutVisitor>(arg: &mut GenericArg, vis: &mut T) {
     }
 }
 
-fn noop_visit_angle_bracketed_parameter_data<T: MutVisitor>(
-    data: &mut AngleBracketedArgs,
-    vis: &mut T,
-) {
+fn walk_angle_bracketed_parameter_data<T: MutVisitor>(vis: &mut T, data: &mut AngleBracketedArgs) {
     let AngleBracketedArgs { args, span } = data;
     visit_thin_vec(args, |arg| match arg {
         AngleBracketedArg::Arg(arg) => vis.visit_generic_arg(arg),
@@ -595,21 +600,18 @@ fn noop_visit_angle_bracketed_parameter_data<T: MutVisitor>(
     vis.visit_span(span);
 }
 
-fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(
-    args: &mut ParenthesizedArgs,
-    vis: &mut T,
-) {
+fn walk_parenthesized_parameter_data<T: MutVisitor>(vis: &mut T, args: &mut ParenthesizedArgs) {
     let ParenthesizedArgs { inputs, output, span, inputs_span } = args;
     visit_thin_vec(inputs, |input| vis.visit_ty(input));
-    noop_visit_fn_ret_ty(output, vis);
+    walk_fn_ret_ty(vis, output);
     vis.visit_span(span);
     vis.visit_span(inputs_span);
 }
 
-fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
+fn walk_local<T: MutVisitor>(vis: &mut T, local: &mut P<Local>) {
     let Local { id, pat, ty, kind, span, colon_sp, attrs, tokens } = local.deref_mut();
     vis.visit_id(id);
-    visit_attrs(attrs, vis);
+    visit_attrs(vis, attrs);
     vis.visit_pat(pat);
     visit_opt(ty, |ty| vis.visit_ty(ty));
     match kind {
@@ -622,12 +624,12 @@ fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
             vis.visit_block(els);
         }
     }
-    visit_lazy_tts(tokens, vis);
+    visit_lazy_tts(vis, tokens);
     visit_opt(colon_sp, |sp| vis.visit_span(sp));
     vis.visit_span(span);
 }
 
-fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
+fn walk_attribute<T: MutVisitor>(vis: &mut T, attr: &mut Attribute) {
     let Attribute { kind, id: _, style: _, span } = attr;
     match kind {
         AttrKind::Normal(normal) => {
@@ -636,34 +638,34 @@ fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
                 tokens: attr_tokens,
             } = &mut **normal;
             vis.visit_path(path);
-            visit_attr_args(args, vis);
-            visit_lazy_tts(tokens, vis);
-            visit_lazy_tts(attr_tokens, vis);
+            visit_attr_args(vis, args);
+            visit_lazy_tts(vis, tokens);
+            visit_lazy_tts(vis, attr_tokens);
         }
         AttrKind::DocComment(_kind, _sym) => {}
     }
     vis.visit_span(span);
 }
 
-fn noop_visit_mac<T: MutVisitor>(mac: &mut MacCall, vis: &mut T) {
+fn walk_mac<T: MutVisitor>(vis: &mut T, mac: &mut MacCall) {
     let MacCall { path, args } = mac;
     vis.visit_path(path);
-    visit_delim_args(args, vis);
+    visit_delim_args(vis, args);
 }
 
-fn noop_visit_macro_def<T: MutVisitor>(macro_def: &mut MacroDef, vis: &mut T) {
+fn walk_macro_def<T: MutVisitor>(vis: &mut T, macro_def: &mut MacroDef) {
     let MacroDef { body, macro_rules: _ } = macro_def;
-    visit_delim_args(body, vis);
+    visit_delim_args(vis, body);
 }
 
-fn noop_visit_meta_list_item<T: MutVisitor>(li: &mut NestedMetaItem, vis: &mut T) {
+fn walk_meta_list_item<T: MutVisitor>(vis: &mut T, li: &mut NestedMetaItem) {
     match li {
         NestedMetaItem::MetaItem(mi) => vis.visit_meta_item(mi),
         NestedMetaItem::Lit(_lit) => {}
     }
 }
 
-fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
+fn walk_meta_item<T: MutVisitor>(vis: &mut T, mi: &mut MetaItem) {
     let MetaItem { unsafety: _, path: _, kind, span } = mi;
     match kind {
         MetaItemKind::Word => {}
@@ -673,10 +675,10 @@ fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
     vis.visit_span(span);
 }
 
-pub fn noop_flat_map_param<T: MutVisitor>(mut param: Param, vis: &mut T) -> SmallVec<[Param; 1]> {
+pub fn walk_flat_map_param<T: MutVisitor>(vis: &mut T, mut param: Param) -> SmallVec<[Param; 1]> {
     let Param { attrs, id, pat, span, ty, is_placeholder: _ } = &mut param;
     vis.visit_id(id);
-    visit_attrs(attrs, vis);
+    visit_attrs(vis, attrs);
     vis.visit_pat(pat);
     vis.visit_ty(ty);
     vis.visit_span(span);
@@ -684,69 +686,69 @@ pub fn noop_flat_map_param<T: MutVisitor>(mut param: Param, vis: &mut T) -> Smal
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_attr_tt<T: MutVisitor>(tt: &mut AttrTokenTree, vis: &mut T) {
+fn visit_attr_tt<T: MutVisitor>(vis: &mut T, tt: &mut AttrTokenTree) {
     match tt {
         AttrTokenTree::Token(token, _spacing) => {
-            visit_token(token, vis);
+            visit_token(vis, token);
         }
         AttrTokenTree::Delimited(dspan, _spacing, _delim, tts) => {
-            visit_attr_tts(tts, vis);
-            visit_delim_span(dspan, vis);
+            visit_attr_tts(vis, tts);
+            visit_delim_span(vis, dspan);
         }
         AttrTokenTree::AttrsTarget(AttrsTarget { attrs, tokens }) => {
-            visit_attrs(attrs, vis);
-            visit_lazy_tts_opt_mut(Some(tokens), vis);
+            visit_attrs(vis, attrs);
+            visit_lazy_tts_opt_mut(vis, Some(tokens));
         }
     }
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_tt<T: MutVisitor>(tt: &mut TokenTree, vis: &mut T) {
+fn visit_tt<T: MutVisitor>(vis: &mut T, tt: &mut TokenTree) {
     match tt {
         TokenTree::Token(token, _spacing) => {
-            visit_token(token, vis);
+            visit_token(vis, token);
         }
         TokenTree::Delimited(dspan, _spacing, _delim, tts) => {
-            visit_tts(tts, vis);
-            visit_delim_span(dspan, vis);
+            visit_tts(vis, tts);
+            visit_delim_span(vis, dspan);
         }
     }
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_tts<T: MutVisitor>(TokenStream(tts): &mut TokenStream, vis: &mut T) {
+fn visit_tts<T: MutVisitor>(vis: &mut T, TokenStream(tts): &mut TokenStream) {
     if T::VISIT_TOKENS && !tts.is_empty() {
         let tts = Lrc::make_mut(tts);
-        visit_vec(tts, |tree| visit_tt(tree, vis));
+        visit_vec(tts, |tree| visit_tt(vis, tree));
     }
 }
 
-fn visit_attr_tts<T: MutVisitor>(AttrTokenStream(tts): &mut AttrTokenStream, vis: &mut T) {
+fn visit_attr_tts<T: MutVisitor>(vis: &mut T, AttrTokenStream(tts): &mut AttrTokenStream) {
     if T::VISIT_TOKENS && !tts.is_empty() {
         let tts = Lrc::make_mut(tts);
-        visit_vec(tts, |tree| visit_attr_tt(tree, vis));
+        visit_vec(tts, |tree| visit_attr_tt(vis, tree));
     }
 }
 
-fn visit_lazy_tts_opt_mut<T: MutVisitor>(lazy_tts: Option<&mut LazyAttrTokenStream>, vis: &mut T) {
+fn visit_lazy_tts_opt_mut<T: MutVisitor>(vis: &mut T, lazy_tts: Option<&mut LazyAttrTokenStream>) {
     if T::VISIT_TOKENS {
         if let Some(lazy_tts) = lazy_tts {
             let mut tts = lazy_tts.to_attr_token_stream();
-            visit_attr_tts(&mut tts, vis);
+            visit_attr_tts(vis, &mut tts);
             *lazy_tts = LazyAttrTokenStream::new(tts);
         }
     }
 }
 
-fn visit_lazy_tts<T: MutVisitor>(lazy_tts: &mut Option<LazyAttrTokenStream>, vis: &mut T) {
-    visit_lazy_tts_opt_mut(lazy_tts.as_mut(), vis);
+fn visit_lazy_tts<T: MutVisitor>(vis: &mut T, lazy_tts: &mut Option<LazyAttrTokenStream>) {
+    visit_lazy_tts_opt_mut(vis, lazy_tts.as_mut());
 }
 
 /// Applies ident visitor if it's an ident; applies other visits to interpolated nodes.
 /// In practice the ident part is not actually used by specific visitors right now,
 /// but there's a test below checking that it works.
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
+pub fn visit_token<T: MutVisitor>(vis: &mut T, t: &mut Token) {
     let Token { kind, span } = t;
     match kind {
         token::Ident(name, _ /*raw*/) | token::Lifetime(name) => {
@@ -764,7 +766,7 @@ pub fn visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
         }
         token::Interpolated(nt) => {
             let nt = Lrc::make_mut(nt);
-            visit_nonterminal(nt, vis);
+            visit_nonterminal(vis, nt);
         }
         _ => {}
     }
@@ -795,7 +797,7 @@ pub fn visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
 // contain multiple items, but decided against it when I looked at
 // `parse_item_or_view_item` and tried to figure out what I would do with
 // multiple items there....
-fn visit_nonterminal<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T) {
+fn visit_nonterminal<T: MutVisitor>(vis: &mut T, nt: &mut token::Nonterminal) {
     match nt {
         token::NtItem(item) => visit_clobber(item, |item| {
             // This is probably okay, because the only visitors likely to
@@ -817,8 +819,8 @@ fn visit_nonterminal<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T) {
         token::NtMeta(item) => {
             let AttrItem { unsafety: _, path, args, tokens } = item.deref_mut();
             vis.visit_path(path);
-            visit_attr_args(args, vis);
-            visit_lazy_tts(tokens, vis);
+            visit_attr_args(vis, args);
+            visit_lazy_tts(vis, tokens);
         }
         token::NtPath(path) => vis.visit_path(path),
         token::NtVis(visib) => vis.visit_vis(visib),
@@ -826,7 +828,7 @@ fn visit_nonterminal<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T) {
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_defaultness<T: MutVisitor>(defaultness: &mut Defaultness, vis: &mut T) {
+fn visit_defaultness<T: MutVisitor>(vis: &mut T, defaultness: &mut Defaultness) {
     match defaultness {
         Defaultness::Default(span) => vis.visit_span(span),
         Defaultness::Final => {}
@@ -834,7 +836,7 @@ fn visit_defaultness<T: MutVisitor>(defaultness: &mut Defaultness, vis: &mut T)
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_safety<T: MutVisitor>(safety: &mut Safety, vis: &mut T) {
+fn visit_safety<T: MutVisitor>(vis: &mut T, safety: &mut Safety) {
     match safety {
         Safety::Unsafe(span) => vis.visit_span(span),
         Safety::Safe(span) => vis.visit_span(span),
@@ -843,7 +845,7 @@ fn visit_safety<T: MutVisitor>(safety: &mut Safety, vis: &mut T) {
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_polarity<T: MutVisitor>(polarity: &mut ImplPolarity, vis: &mut T) {
+fn visit_polarity<T: MutVisitor>(vis: &mut T, polarity: &mut ImplPolarity) {
     match polarity {
         ImplPolarity::Positive => {}
         ImplPolarity::Negative(span) => vis.visit_span(span),
@@ -851,14 +853,14 @@ fn visit_polarity<T: MutVisitor>(polarity: &mut ImplPolarity, vis: &mut T) {
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_constness<T: MutVisitor>(constness: &mut Const, vis: &mut T) {
+fn visit_constness<T: MutVisitor>(vis: &mut T, constness: &mut Const) {
     match constness {
         Const::Yes(span) => vis.visit_span(span),
         Const::No => {}
     }
 }
 
-fn noop_visit_closure_binder<T: MutVisitor>(binder: &mut ClosureBinder, vis: &mut T) {
+fn walk_closure_binder<T: MutVisitor>(vis: &mut T, binder: &mut ClosureBinder) {
     match binder {
         ClosureBinder::NotPresent => {}
         ClosureBinder::For { span: _, generic_params } => {
@@ -867,7 +869,7 @@ fn noop_visit_closure_binder<T: MutVisitor>(binder: &mut ClosureBinder, vis: &mu
     }
 }
 
-fn noop_visit_coroutine_kind<T: MutVisitor>(coroutine_kind: &mut CoroutineKind, vis: &mut T) {
+fn walk_coroutine_kind<T: MutVisitor>(vis: &mut T, coroutine_kind: &mut CoroutineKind) {
     match coroutine_kind {
         CoroutineKind::Async { span, closure_id, return_impl_trait_id }
         | CoroutineKind::Gen { span, closure_id, return_impl_trait_id }
@@ -879,23 +881,43 @@ fn noop_visit_coroutine_kind<T: MutVisitor>(coroutine_kind: &mut CoroutineKind,
     }
 }
 
-fn noop_visit_fn_decl<T: MutVisitor>(decl: &mut P<FnDecl>, vis: &mut T) {
+fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
+    match kind {
+        FnKind::Fn(FnSig { header, decl, span }, generics, body) => {
+            // Identifier and visibility are visited as a part of the item.
+            vis.visit_fn_header(header);
+            vis.visit_generics(generics);
+            vis.visit_fn_decl(decl);
+            if let Some(body) = body {
+                vis.visit_block(body);
+            }
+            vis.visit_span(span);
+        }
+        FnKind::Closure(binder, decl, body) => {
+            vis.visit_closure_binder(binder);
+            vis.visit_fn_decl(decl);
+            vis.visit_expr(body);
+        }
+    }
+}
+
+fn walk_fn_decl<T: MutVisitor>(vis: &mut T, decl: &mut P<FnDecl>) {
     let FnDecl { inputs, output } = decl.deref_mut();
     inputs.flat_map_in_place(|param| vis.flat_map_param(param));
-    noop_visit_fn_ret_ty(output, vis);
+    walk_fn_ret_ty(vis, output);
 }
 
-fn noop_visit_fn_ret_ty<T: MutVisitor>(fn_ret_ty: &mut FnRetTy, vis: &mut T) {
+fn walk_fn_ret_ty<T: MutVisitor>(vis: &mut T, fn_ret_ty: &mut FnRetTy) {
     match fn_ret_ty {
         FnRetTy::Default(span) => vis.visit_span(span),
         FnRetTy::Ty(ty) => vis.visit_ty(ty),
     }
 }
 
-fn noop_visit_param_bound<T: MutVisitor>(pb: &mut GenericBound, vis: &mut T) {
+fn walk_param_bound<T: MutVisitor>(vis: &mut T, pb: &mut GenericBound) {
     match pb {
         GenericBound::Trait(ty, _modifier) => vis.visit_poly_trait_ref(ty),
-        GenericBound::Outlives(lifetime) => noop_visit_lifetime(lifetime, vis),
+        GenericBound::Outlives(lifetime) => walk_lifetime(vis, lifetime),
         GenericBound::Use(args, span) => {
             for arg in args {
                 vis.visit_precise_capturing_arg(arg);
@@ -905,7 +927,7 @@ fn noop_visit_param_bound<T: MutVisitor>(pb: &mut GenericBound, vis: &mut T) {
     }
 }
 
-fn noop_visit_precise_capturing_arg<T: MutVisitor>(arg: &mut PreciseCapturingArg, vis: &mut T) {
+fn walk_precise_capturing_arg<T: MutVisitor>(vis: &mut T, arg: &mut PreciseCapturingArg) {
     match arg {
         PreciseCapturingArg::Lifetime(lt) => {
             vis.visit_lifetime(lt);
@@ -917,15 +939,15 @@ fn noop_visit_precise_capturing_arg<T: MutVisitor>(arg: &mut PreciseCapturingArg
     }
 }
 
-pub fn noop_flat_map_generic_param<T: MutVisitor>(
-    mut param: GenericParam,
+pub fn walk_flat_map_generic_param<T: MutVisitor>(
     vis: &mut T,
+    mut param: GenericParam,
 ) -> SmallVec<[GenericParam; 1]> {
     let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = &mut param;
     vis.visit_id(id);
-    visit_attrs(attrs, vis);
+    visit_attrs(vis, attrs);
     vis.visit_ident(ident);
-    visit_vec(bounds, |bound| vis.visit_param_bound(bound));
+    visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound));
     match kind {
         GenericParamKind::Lifetime => {}
         GenericParamKind::Type { default } => {
@@ -942,23 +964,23 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
     smallvec![param]
 }
 
-fn noop_visit_label<T: MutVisitor>(Label { ident }: &mut Label, vis: &mut T) {
+fn walk_label<T: MutVisitor>(vis: &mut T, Label { ident }: &mut Label) {
     vis.visit_ident(ident);
 }
 
-fn noop_visit_lifetime<T: MutVisitor>(Lifetime { id, ident }: &mut Lifetime, vis: &mut T) {
+fn walk_lifetime<T: MutVisitor>(vis: &mut T, Lifetime { id, ident }: &mut Lifetime) {
     vis.visit_id(id);
     vis.visit_ident(ident);
 }
 
-fn noop_visit_generics<T: MutVisitor>(generics: &mut Generics, vis: &mut T) {
+fn walk_generics<T: MutVisitor>(vis: &mut T, generics: &mut Generics) {
     let Generics { params, where_clause, span } = generics;
     params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
     vis.visit_where_clause(where_clause);
     vis.visit_span(span);
 }
 
-fn noop_visit_ty_alias_where_clauses<T: MutVisitor>(tawcs: &mut TyAliasWhereClauses, vis: &mut T) {
+fn walk_ty_alias_where_clauses<T: MutVisitor>(vis: &mut T, tawcs: &mut TyAliasWhereClauses) {
     let TyAliasWhereClauses { before, after, split: _ } = tawcs;
     let TyAliasWhereClause { has_where_token: _, span: span_before } = before;
     let TyAliasWhereClause { has_where_token: _, span: span_after } = after;
@@ -966,25 +988,25 @@ fn noop_visit_ty_alias_where_clauses<T: MutVisitor>(tawcs: &mut TyAliasWhereClau
     vis.visit_span(span_after);
 }
 
-fn noop_visit_where_clause<T: MutVisitor>(wc: &mut WhereClause, vis: &mut T) {
+fn walk_where_clause<T: MutVisitor>(vis: &mut T, wc: &mut WhereClause) {
     let WhereClause { has_where_token: _, predicates, span } = wc;
     visit_thin_vec(predicates, |predicate| vis.visit_where_predicate(predicate));
     vis.visit_span(span);
 }
 
-fn noop_visit_where_predicate<T: MutVisitor>(pred: &mut WherePredicate, vis: &mut T) {
+fn walk_where_predicate<T: MutVisitor>(vis: &mut T, pred: &mut WherePredicate) {
     match pred {
         WherePredicate::BoundPredicate(bp) => {
             let WhereBoundPredicate { span, bound_generic_params, bounded_ty, bounds } = bp;
             bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
             vis.visit_ty(bounded_ty);
-            visit_vec(bounds, |bound| vis.visit_param_bound(bound));
+            visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound));
             vis.visit_span(span);
         }
         WherePredicate::RegionPredicate(rp) => {
             let WhereRegionPredicate { span, lifetime, bounds } = rp;
             vis.visit_lifetime(lifetime);
-            visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
+            visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound));
             vis.visit_span(span);
         }
         WherePredicate::EqPredicate(ep) => {
@@ -996,7 +1018,7 @@ fn noop_visit_where_predicate<T: MutVisitor>(pred: &mut WherePredicate, vis: &mu
     }
 }
 
-fn noop_visit_variant_data<T: MutVisitor>(vdata: &mut VariantData, vis: &mut T) {
+fn walk_variant_data<T: MutVisitor>(vis: &mut T, vdata: &mut VariantData) {
     match vdata {
         VariantData::Struct { fields, recovered: _ } => {
             fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
@@ -1009,25 +1031,25 @@ fn noop_visit_variant_data<T: MutVisitor>(vdata: &mut VariantData, vis: &mut T)
     }
 }
 
-fn noop_visit_trait_ref<T: MutVisitor>(TraitRef { path, ref_id }: &mut TraitRef, vis: &mut T) {
+fn walk_trait_ref<T: MutVisitor>(vis: &mut T, TraitRef { path, ref_id }: &mut TraitRef) {
     vis.visit_id(ref_id);
     vis.visit_path(path);
 }
 
-fn noop_visit_poly_trait_ref<T: MutVisitor>(p: &mut PolyTraitRef, vis: &mut T) {
+fn walk_poly_trait_ref<T: MutVisitor>(vis: &mut T, p: &mut PolyTraitRef) {
     let PolyTraitRef { bound_generic_params, trait_ref, span } = p;
     bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
     vis.visit_trait_ref(trait_ref);
     vis.visit_span(span);
 }
 
-pub fn noop_flat_map_field_def<T: MutVisitor>(
-    mut fd: FieldDef,
+pub fn walk_flat_map_field_def<T: MutVisitor>(
     visitor: &mut T,
+    mut fd: FieldDef,
 ) -> SmallVec<[FieldDef; 1]> {
     let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _ } = &mut fd;
     visitor.visit_id(id);
-    visit_attrs(attrs, visitor);
+    visit_attrs(visitor, attrs);
     visitor.visit_vis(vis);
     visit_opt(ident, |ident| visitor.visit_ident(ident));
     visitor.visit_ty(ty);
@@ -1035,37 +1057,42 @@ pub fn noop_flat_map_field_def<T: MutVisitor>(
     smallvec![fd]
 }
 
-pub fn noop_flat_map_expr_field<T: MutVisitor>(
-    mut f: ExprField,
+pub fn walk_flat_map_expr_field<T: MutVisitor>(
     vis: &mut T,
+    mut f: ExprField,
 ) -> SmallVec<[ExprField; 1]> {
     let ExprField { ident, expr, span, is_shorthand: _, attrs, id, is_placeholder: _ } = &mut f;
     vis.visit_id(id);
-    visit_attrs(attrs, vis);
+    visit_attrs(vis, attrs);
     vis.visit_ident(ident);
     vis.visit_expr(expr);
     vis.visit_span(span);
     smallvec![f]
 }
 
-fn noop_visit_mt<T: MutVisitor>(MutTy { ty, mutbl: _ }: &mut MutTy, vis: &mut T) {
+fn walk_mt<T: MutVisitor>(vis: &mut T, MutTy { ty, mutbl: _ }: &mut MutTy) {
     vis.visit_ty(ty);
 }
 
-pub fn noop_visit_block<T: MutVisitor>(block: &mut P<Block>, vis: &mut T) {
+pub fn walk_block<T: MutVisitor>(vis: &mut T, block: &mut P<Block>) {
     let Block { id, stmts, rules: _, span, tokens, could_be_bare_literal: _ } = block.deref_mut();
     vis.visit_id(id);
     stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt));
-    visit_lazy_tts(tokens, vis);
+    visit_lazy_tts(vis, tokens);
     vis.visit_span(span);
 }
 
-pub fn noop_visit_item_kind(kind: &mut impl NoopVisitItemKind, vis: &mut impl MutVisitor) {
-    kind.noop_visit(vis)
+pub fn walk_item_kind(
+    kind: &mut impl WalkItemKind,
+    span: Span,
+    id: NodeId,
+    vis: &mut impl MutVisitor,
+) {
+    kind.walk(span, id, vis)
 }
 
-impl NoopVisitItemKind for ItemKind {
-    fn noop_visit(&mut self, vis: &mut impl MutVisitor) {
+impl WalkItemKind for ItemKind {
+    fn walk(&mut self, span: Span, id: NodeId, vis: &mut impl MutVisitor) {
         match self {
             ItemKind::ExternCrate(_orig_name) => {}
             ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
@@ -1077,13 +1104,11 @@ impl NoopVisitItemKind for ItemKind {
                 visit_const_item(item, vis);
             }
             ItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
-                visit_defaultness(defaultness, vis);
-                vis.visit_generics(generics);
-                visit_fn_sig(sig, vis);
-                visit_opt(body, |body| vis.visit_block(body));
+                visit_defaultness(vis, defaultness);
+                vis.visit_fn(FnKind::Fn(sig, generics, body), span, id);
             }
             ItemKind::Mod(safety, mod_kind) => {
-                visit_safety(safety, vis);
+                visit_safety(vis, safety);
                 match mod_kind {
                     ModKind::Loaded(items, _inline, ModSpans { inner_span, inject_use_span }) => {
                         items.flat_map_in_place(|item| vis.flat_map_item(item));
@@ -1096,11 +1121,11 @@ impl NoopVisitItemKind for ItemKind {
             ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
             ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm),
             ItemKind::TyAlias(box TyAlias { defaultness, generics, where_clauses, bounds, ty }) => {
-                visit_defaultness(defaultness, vis);
+                visit_defaultness(vis, defaultness);
                 vis.visit_generics(generics);
-                visit_bounds(bounds, vis);
+                visit_bounds(vis, bounds, BoundKind::Bound);
                 visit_opt(ty, |ty| vis.visit_ty(ty));
-                noop_visit_ty_alias_where_clauses(where_clauses, vis);
+                walk_ty_alias_where_clauses(vis, where_clauses);
             }
             ItemKind::Enum(EnumDef { variants }, generics) => {
                 vis.visit_generics(generics);
@@ -1120,24 +1145,24 @@ impl NoopVisitItemKind for ItemKind {
                 self_ty,
                 items,
             }) => {
-                visit_defaultness(defaultness, vis);
-                visit_safety(safety, vis);
+                visit_defaultness(vis, defaultness);
+                visit_safety(vis, safety);
                 vis.visit_generics(generics);
-                visit_constness(constness, vis);
-                visit_polarity(polarity, vis);
+                visit_constness(vis, constness);
+                visit_polarity(vis, polarity);
                 visit_opt(of_trait, |trait_ref| vis.visit_trait_ref(trait_ref));
                 vis.visit_ty(self_ty);
-                items.flat_map_in_place(|item| vis.flat_map_impl_item(item));
+                items.flat_map_in_place(|item| vis.flat_map_assoc_item(item, AssocCtxt::Impl));
             }
             ItemKind::Trait(box Trait { safety, is_auto: _, generics, bounds, items }) => {
-                visit_safety(safety, vis);
+                visit_safety(vis, safety);
                 vis.visit_generics(generics);
-                visit_bounds(bounds, vis);
-                items.flat_map_in_place(|item| vis.flat_map_trait_item(item));
+                visit_bounds(vis, bounds, BoundKind::Bound);
+                items.flat_map_in_place(|item| vis.flat_map_assoc_item(item, AssocCtxt::Trait));
             }
             ItemKind::TraitAlias(generics, bounds) => {
                 vis.visit_generics(generics);
-                visit_bounds(bounds, vis);
+                visit_bounds(vis, bounds, BoundKind::Bound);
             }
             ItemKind::MacCall(m) => vis.visit_mac_call(m),
             ItemKind::MacroDef(def) => vis.visit_macro_def(def),
@@ -1178,17 +1203,15 @@ impl NoopVisitItemKind for ItemKind {
     }
 }
 
-impl NoopVisitItemKind for AssocItemKind {
-    fn noop_visit(&mut self, visitor: &mut impl MutVisitor) {
+impl WalkItemKind for AssocItemKind {
+    fn walk(&mut self, span: Span, id: NodeId, visitor: &mut impl MutVisitor) {
         match self {
             AssocItemKind::Const(item) => {
                 visit_const_item(item, visitor);
             }
             AssocItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
-                visit_defaultness(defaultness, visitor);
-                visitor.visit_generics(generics);
-                visit_fn_sig(sig, visitor);
-                visit_opt(body, |body| visitor.visit_block(body));
+                visit_defaultness(visitor, defaultness);
+                visitor.visit_fn(FnKind::Fn(sig, generics, body), span, id);
             }
             AssocItemKind::Type(box TyAlias {
                 defaultness,
@@ -1197,11 +1220,11 @@ impl NoopVisitItemKind for AssocItemKind {
                 bounds,
                 ty,
             }) => {
-                visit_defaultness(defaultness, visitor);
+                visit_defaultness(visitor, defaultness);
                 visitor.visit_generics(generics);
-                visit_bounds(bounds, visitor);
+                visit_bounds(visitor, bounds, BoundKind::Bound);
                 visit_opt(ty, |ty| visitor.visit_ty(ty));
-                noop_visit_ty_alias_where_clauses(where_clauses, visitor);
+                walk_ty_alias_where_clauses(visitor, where_clauses);
             }
             AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
             AssocItemKind::Delegation(box Delegation {
@@ -1245,57 +1268,55 @@ fn visit_const_item<T: MutVisitor>(
     ConstItem { defaultness, generics, ty, expr }: &mut ConstItem,
     visitor: &mut T,
 ) {
-    visit_defaultness(defaultness, visitor);
+    visit_defaultness(visitor, defaultness);
     visitor.visit_generics(generics);
     visitor.visit_ty(ty);
     visit_opt(expr, |expr| visitor.visit_expr(expr));
 }
 
-fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
+fn walk_fn_header<T: MutVisitor>(vis: &mut T, header: &mut FnHeader) {
     let FnHeader { safety, coroutine_kind, constness, ext: _ } = header;
-    visit_constness(constness, vis);
+    visit_constness(vis, constness);
     coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind));
-    visit_safety(safety, vis);
+    visit_safety(vis, safety);
 }
 
-pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
+pub fn walk_crate<T: MutVisitor>(vis: &mut T, krate: &mut Crate) {
     let Crate { attrs, items, spans, id, is_placeholder: _ } = krate;
     vis.visit_id(id);
-    visit_attrs(attrs, vis);
+    visit_attrs(vis, attrs);
     items.flat_map_in_place(|item| vis.flat_map_item(item));
     let ModSpans { inner_span, inject_use_span } = spans;
     vis.visit_span(inner_span);
     vis.visit_span(inject_use_span);
 }
 
-// Mutates one item into possibly many items.
-pub fn noop_flat_map_item<K: NoopVisitItemKind>(
-    mut item: P<Item<K>>,
+/// Mutates one item, returning the item again.
+pub fn walk_flat_map_item<K: WalkItemKind>(
     visitor: &mut impl MutVisitor,
+    mut item: P<Item<K>>,
 ) -> SmallVec<[P<Item<K>>; 1]> {
     let Item { ident, attrs, id, kind, vis, span, tokens } = item.deref_mut();
     visitor.visit_id(id);
-    visit_attrs(attrs, visitor);
+    visit_attrs(visitor, attrs);
     visitor.visit_vis(vis);
     visitor.visit_ident(ident);
-    kind.noop_visit(visitor);
-    visit_lazy_tts(tokens, visitor);
+    kind.walk(*span, *id, visitor);
+    visit_lazy_tts(visitor, tokens);
     visitor.visit_span(span);
     smallvec![item]
 }
 
-impl NoopVisitItemKind for ForeignItemKind {
-    fn noop_visit(&mut self, visitor: &mut impl MutVisitor) {
+impl WalkItemKind for ForeignItemKind {
+    fn walk(&mut self, span: Span, id: NodeId, visitor: &mut impl MutVisitor) {
         match self {
             ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => {
                 visitor.visit_ty(ty);
                 visit_opt(expr, |expr| visitor.visit_expr(expr));
             }
             ForeignItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
-                visit_defaultness(defaultness, visitor);
-                visitor.visit_generics(generics);
-                visit_fn_sig(sig, visitor);
-                visit_opt(body, |body| visitor.visit_block(body));
+                visit_defaultness(visitor, defaultness);
+                visitor.visit_fn(FnKind::Fn(sig, generics, body), span, id);
             }
             ForeignItemKind::TyAlias(box TyAlias {
                 defaultness,
@@ -1304,18 +1325,18 @@ impl NoopVisitItemKind for ForeignItemKind {
                 bounds,
                 ty,
             }) => {
-                visit_defaultness(defaultness, visitor);
+                visit_defaultness(visitor, defaultness);
                 visitor.visit_generics(generics);
-                visit_bounds(bounds, visitor);
+                visit_bounds(visitor, bounds, BoundKind::Bound);
                 visit_opt(ty, |ty| visitor.visit_ty(ty));
-                noop_visit_ty_alias_where_clauses(where_clauses, visitor);
+                walk_ty_alias_where_clauses(visitor, where_clauses);
             }
             ForeignItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
         }
     }
 }
 
-pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
+pub fn walk_pat<T: MutVisitor>(vis: &mut T, pat: &mut P<Pat>) {
     let Pat { id, kind, span, tokens } = pat.deref_mut();
     vis.visit_id(id);
     match kind {
@@ -1354,16 +1375,16 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
         PatKind::Paren(inner) => vis.visit_pat(inner),
         PatKind::MacCall(mac) => vis.visit_mac_call(mac),
     }
-    visit_lazy_tts(tokens, vis);
+    visit_lazy_tts(vis, tokens);
     vis.visit_span(span);
 }
 
-fn noop_visit_anon_const<T: MutVisitor>(AnonConst { id, value }: &mut AnonConst, vis: &mut T) {
+fn walk_anon_const<T: MutVisitor>(vis: &mut T, AnonConst { id, value }: &mut AnonConst) {
     vis.visit_id(id);
     vis.visit_expr(value);
 }
 
-fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
+fn walk_inline_asm<T: MutVisitor>(vis: &mut T, asm: &mut InlineAsm) {
     // FIXME: Visit spans inside all this currently ignored stuff.
     let InlineAsm {
         template: _,
@@ -1393,16 +1414,16 @@ fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
     }
 }
 
-fn noop_visit_inline_asm_sym<T: MutVisitor>(
-    InlineAsmSym { id, qself, path }: &mut InlineAsmSym,
+fn walk_inline_asm_sym<T: MutVisitor>(
     vis: &mut T,
+    InlineAsmSym { id, qself, path }: &mut InlineAsmSym,
 ) {
     vis.visit_id(id);
     vis.visit_qself(qself);
     vis.visit_path(path);
 }
 
-fn noop_visit_format_args<T: MutVisitor>(fmt: &mut FormatArgs, vis: &mut T) {
+fn walk_format_args<T: MutVisitor>(vis: &mut T, fmt: &mut FormatArgs) {
     // FIXME: visit the template exhaustively.
     let FormatArgs { span, template: _, arguments } = fmt;
     for FormatArgument { kind, expr } in arguments.all_args_mut() {
@@ -1417,14 +1438,11 @@ fn noop_visit_format_args<T: MutVisitor>(fmt: &mut FormatArgs, vis: &mut T) {
     vis.visit_span(span);
 }
 
-pub fn noop_visit_expr<T: MutVisitor>(
-    Expr { kind, id, span, attrs, tokens }: &mut Expr,
-    vis: &mut T,
-) {
+pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, tokens }: &mut Expr) {
     vis.visit_id(id);
-    visit_attrs(attrs, vis);
+    visit_attrs(vis, attrs);
     match kind {
-        ExprKind::Array(exprs) => visit_thin_exprs(exprs, vis),
+        ExprKind::Array(exprs) => visit_thin_exprs(vis, exprs),
         ExprKind::ConstBlock(anon_const) => {
             vis.visit_anon_const(anon_const);
         }
@@ -1432,10 +1450,10 @@ pub fn noop_visit_expr<T: MutVisitor>(
             vis.visit_expr(expr);
             vis.visit_anon_const(count);
         }
-        ExprKind::Tup(exprs) => visit_thin_exprs(exprs, vis),
+        ExprKind::Tup(exprs) => visit_thin_exprs(vis, exprs),
         ExprKind::Call(f, args) => {
             vis.visit_expr(f);
-            visit_thin_exprs(args, vis);
+            visit_thin_exprs(vis, args);
         }
         ExprKind::MethodCall(box MethodCall {
             seg: PathSegment { ident, id, args: seg_args },
@@ -1447,7 +1465,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
             vis.visit_id(id);
             vis.visit_ident(ident);
             visit_opt(seg_args, |args| vis.visit_generic_args(args));
-            visit_thin_exprs(call_args, vis);
+            visit_thin_exprs(vis, call_args);
             vis.visit_span(span);
         }
         ExprKind::Binary(_binop, lhs, rhs) => {
@@ -1505,12 +1523,10 @@ pub fn noop_visit_expr<T: MutVisitor>(
             fn_decl_span,
             fn_arg_span,
         }) => {
-            vis.visit_closure_binder(binder);
-            visit_constness(constness, vis);
+            visit_constness(vis, constness);
             coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind));
             vis.visit_capture_by(capture_clause);
-            vis.visit_fn_decl(fn_decl);
-            vis.visit_expr(body);
+            vis.visit_fn(FnKind::Closure(binder, fn_decl, body), *span, *id);
             vis.visit_span(fn_decl_span);
             vis.visit_span(fn_arg_span);
         }
@@ -1600,23 +1616,23 @@ pub fn noop_visit_expr<T: MutVisitor>(
         ExprKind::Err(_guar) => {}
         ExprKind::Dummy => {}
     }
-    visit_lazy_tts(tokens, vis);
+    visit_lazy_tts(vis, tokens);
     vis.visit_span(span);
 }
 
-pub fn noop_filter_map_expr<T: MutVisitor>(mut e: P<Expr>, vis: &mut T) -> Option<P<Expr>> {
+pub fn noop_filter_map_expr<T: MutVisitor>(vis: &mut T, mut e: P<Expr>) -> Option<P<Expr>> {
     Some({
         vis.visit_expr(&mut e);
         e
     })
 }
 
-pub fn noop_flat_map_stmt<T: MutVisitor>(
-    Stmt { kind, mut span, mut id }: Stmt,
+pub fn walk_flat_map_stmt<T: MutVisitor>(
     vis: &mut T,
+    Stmt { kind, mut span, mut id }: Stmt,
 ) -> SmallVec<[Stmt; 1]> {
     vis.visit_id(&mut id);
-    let stmts: SmallVec<_> = noop_flat_map_stmt_kind(kind, vis)
+    let stmts: SmallVec<_> = walk_flat_map_stmt_kind(vis, kind)
         .into_iter()
         .map(|kind| Stmt { id, kind, span })
         .collect();
@@ -1630,7 +1646,7 @@ pub fn noop_flat_map_stmt<T: MutVisitor>(
     stmts
 }
 
-fn noop_flat_map_stmt_kind<T: MutVisitor>(kind: StmtKind, vis: &mut T) -> SmallVec<[StmtKind; 1]> {
+fn walk_flat_map_stmt_kind<T: MutVisitor>(vis: &mut T, kind: StmtKind) -> SmallVec<[StmtKind; 1]> {
     match kind {
         StmtKind::Let(mut local) => smallvec![StmtKind::Let({
             vis.visit_local(&mut local);
@@ -1642,15 +1658,15 @@ fn noop_flat_map_stmt_kind<T: MutVisitor>(kind: StmtKind, vis: &mut T) -> SmallV
         StmtKind::Empty => smallvec![StmtKind::Empty],
         StmtKind::MacCall(mut mac) => {
             let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut();
-            visit_attrs(attrs, vis);
+            visit_attrs(vis, attrs);
             vis.visit_mac_call(mac_);
-            visit_lazy_tts(tokens, vis);
+            visit_lazy_tts(vis, tokens);
             smallvec![StmtKind::MacCall(mac)]
         }
     }
 }
 
-fn noop_visit_vis<T: MutVisitor>(visibility: &mut Visibility, vis: &mut T) {
+fn walk_vis<T: MutVisitor>(vis: &mut T, visibility: &mut Visibility) {
     let Visibility { kind, span, tokens } = visibility;
     match kind {
         VisibilityKind::Public | VisibilityKind::Inherited => {}
@@ -1659,11 +1675,11 @@ fn noop_visit_vis<T: MutVisitor>(visibility: &mut Visibility, vis: &mut T) {
             vis.visit_path(path);
         }
     }
-    visit_lazy_tts(tokens, vis);
+    visit_lazy_tts(vis, tokens);
     vis.visit_span(span);
 }
 
-fn noop_visit_capture_by<T: MutVisitor>(capture_by: &mut CaptureBy, vis: &mut T) {
+fn walk_capture_by<T: MutVisitor>(vis: &mut T, capture_by: &mut CaptureBy) {
     match capture_by {
         CaptureBy::Ref => {}
         CaptureBy::Value { move_kw } => {
@@ -1767,3 +1783,12 @@ impl<N: DummyAstNode, T: DummyAstNode> DummyAstNode for crate::ast_traits::AstNo
         crate::ast_traits::AstNodeWrapper::new(N::dummy(), T::dummy())
     }
 }
+
+#[derive(Debug)]
+pub enum FnKind<'a> {
+    /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
+    Fn(&'a mut FnSig, &'a mut Generics, &'a mut Option<P<Block>>),
+
+    /// E.g., `|x, y| body`.
+    Closure(&'a mut ClosureBinder, &'a mut P<FnDecl>, &'a mut P<Expr>),
+}
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index b09975c0ba7..b3d252e06a5 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -4,7 +4,7 @@ use core::ops::ControlFlow;
 use rustc_ast as ast;
 use rustc_ast::mut_visit::MutVisitor;
 use rustc_ast::ptr::P;
-use rustc_ast::visit::Visitor;
+use rustc_ast::visit::{AssocCtxt, Visitor};
 use rustc_ast::NodeId;
 use rustc_ast::{mut_visit, visit};
 use rustc_ast::{Attribute, HasAttrs, HasTokens};
@@ -53,11 +53,8 @@ fn flat_map_annotatable(
 ) -> Option<Annotatable> {
     match annotatable {
         Annotatable::Item(item) => vis.flat_map_item(item).pop().map(Annotatable::Item),
-        Annotatable::TraitItem(item) => {
-            vis.flat_map_trait_item(item).pop().map(Annotatable::TraitItem)
-        }
-        Annotatable::ImplItem(item) => {
-            vis.flat_map_impl_item(item).pop().map(Annotatable::ImplItem)
+        Annotatable::AssocItem(item, ctxt) => {
+            Some(Annotatable::AssocItem(vis.flat_map_assoc_item(item, ctxt).pop()?, ctxt))
         }
         Annotatable::ForeignItem(item) => {
             vis.flat_map_foreign_item(item).pop().map(Annotatable::ForeignItem)
@@ -106,8 +103,7 @@ fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool {
 
     let res = match annotatable {
         Annotatable::Item(item) => CfgFinder.visit_item(item),
-        Annotatable::TraitItem(item) => CfgFinder.visit_assoc_item(item, visit::AssocCtxt::Trait),
-        Annotatable::ImplItem(item) => CfgFinder.visit_assoc_item(item, visit::AssocCtxt::Impl),
+        Annotatable::AssocItem(item, ctxt) => CfgFinder.visit_assoc_item(item, *ctxt),
         Annotatable::ForeignItem(item) => CfgFinder.visit_foreign_item(item),
         Annotatable::Stmt(stmt) => CfgFinder.visit_stmt(stmt),
         Annotatable::Expr(expr) => CfgFinder.visit_expr(expr),
@@ -150,14 +146,16 @@ impl CfgEval<'_> {
                 Annotatable::Item(_) => {
                     |parser| Ok(Annotatable::Item(parser.parse_item(ForceCollect::Yes)?.unwrap()))
                 }
-                Annotatable::TraitItem(_) => |parser| {
-                    Ok(Annotatable::TraitItem(
+                Annotatable::AssocItem(_, AssocCtxt::Trait) => |parser| {
+                    Ok(Annotatable::AssocItem(
                         parser.parse_trait_item(ForceCollect::Yes)?.unwrap().unwrap(),
+                        AssocCtxt::Trait,
                     ))
                 },
-                Annotatable::ImplItem(_) => |parser| {
-                    Ok(Annotatable::ImplItem(
+                Annotatable::AssocItem(_, AssocCtxt::Impl) => |parser| {
+                    Ok(Annotatable::AssocItem(
                         parser.parse_impl_item(ForceCollect::Yes)?.unwrap().unwrap(),
+                        AssocCtxt::Impl,
                     ))
                 },
                 Annotatable::ForeignItem(_) => |parser| {
@@ -214,18 +212,18 @@ impl MutVisitor for CfgEval<'_> {
     #[instrument(level = "trace", skip(self))]
     fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
         self.0.configure_expr(expr, false);
-        mut_visit::noop_visit_expr(expr, self);
+        mut_visit::walk_expr(self, expr);
     }
 
     #[instrument(level = "trace", skip(self))]
     fn visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>) {
         self.0.configure_expr(expr, true);
-        mut_visit::noop_visit_expr(expr, self);
+        mut_visit::walk_expr(self, expr);
     }
 
     fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
         let mut expr = configure!(self, expr);
-        mut_visit::noop_visit_expr(&mut expr, self);
+        mut_visit::walk_expr(self, &mut expr);
         Some(expr)
     }
 
@@ -233,53 +231,64 @@ impl MutVisitor for CfgEval<'_> {
         &mut self,
         param: ast::GenericParam,
     ) -> SmallVec<[ast::GenericParam; 1]> {
-        mut_visit::noop_flat_map_generic_param(configure!(self, param), self)
+        let param = configure!(self, param);
+        mut_visit::walk_flat_map_generic_param(self, param)
     }
 
     fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
-        mut_visit::noop_flat_map_stmt(configure!(self, stmt), self)
+        let stmt = configure!(self, stmt);
+        mut_visit::walk_flat_map_stmt(self, stmt)
     }
 
     fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
-        mut_visit::noop_flat_map_item(configure!(self, item), self)
-    }
-
-    fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
-        mut_visit::noop_flat_map_item(configure!(self, item), self)
+        let item = configure!(self, item);
+        mut_visit::walk_flat_map_item(self, item)
     }
 
-    fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
-        mut_visit::noop_flat_map_item(configure!(self, item), self)
+    fn flat_map_assoc_item(
+        &mut self,
+        item: P<ast::AssocItem>,
+        _ctxt: AssocCtxt,
+    ) -> SmallVec<[P<ast::AssocItem>; 1]> {
+        let item = configure!(self, item);
+        mut_visit::walk_flat_map_item(self, item)
     }
 
     fn flat_map_foreign_item(
         &mut self,
         foreign_item: P<ast::ForeignItem>,
     ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
-        mut_visit::noop_flat_map_item(configure!(self, foreign_item), self)
+        let foreign_item = configure!(self, foreign_item);
+        mut_visit::walk_flat_map_item(self, foreign_item)
     }
 
     fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
-        mut_visit::noop_flat_map_arm(configure!(self, arm), self)
+        let arm = configure!(self, arm);
+        mut_visit::walk_flat_map_arm(self, arm)
     }
 
     fn flat_map_expr_field(&mut self, field: ast::ExprField) -> SmallVec<[ast::ExprField; 1]> {
-        mut_visit::noop_flat_map_expr_field(configure!(self, field), self)
+        let field = configure!(self, field);
+        mut_visit::walk_flat_map_expr_field(self, field)
     }
 
     fn flat_map_pat_field(&mut self, fp: ast::PatField) -> SmallVec<[ast::PatField; 1]> {
-        mut_visit::noop_flat_map_pat_field(configure!(self, fp), self)
+        let fp = configure!(self, fp);
+        mut_visit::walk_flat_map_pat_field(self, fp)
     }
 
     fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
-        mut_visit::noop_flat_map_param(configure!(self, p), self)
+        let p = configure!(self, p);
+        mut_visit::walk_flat_map_param(self, p)
     }
 
     fn flat_map_field_def(&mut self, sf: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
-        mut_visit::noop_flat_map_field_def(configure!(self, sf), self)
+        let sf = configure!(self, sf);
+        mut_visit::walk_flat_map_field_def(self, sf)
     }
 
     fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
-        mut_visit::noop_flat_map_variant(configure!(self, variant), self)
+        let variant = configure!(self, variant);
+        mut_visit::walk_flat_map_variant(self, variant)
     }
 }
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 9d032eb190a..bbafb0ac299 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -122,15 +122,15 @@ impl TestHarnessGenerator<'_> {
 impl<'a> MutVisitor for TestHarnessGenerator<'a> {
     fn visit_crate(&mut self, c: &mut ast::Crate) {
         let prev_tests = mem::take(&mut self.tests);
-        noop_visit_crate(c, self);
+        walk_crate(self, c);
         self.add_test_cases(ast::CRATE_NODE_ID, c.spans.inner_span, prev_tests);
 
         // Create a main function to run our tests
         c.items.push(mk_main(&mut self.cx));
     }
 
-    fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
-        let mut item = i.into_inner();
+    fn flat_map_item(&mut self, mut i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
+        let item = &mut *i;
         if let Some(name) = get_test_name(&item) {
             debug!("this is a test item");
 
@@ -144,13 +144,13 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
             item.kind
         {
             let prev_tests = mem::take(&mut self.tests);
-            noop_visit_item_kind(&mut item.kind, self);
+            walk_item_kind(&mut item.kind, item.span, item.id, self);
             self.add_test_cases(item.id, span, prev_tests);
         } else {
             // But in those cases, we emit a lint to warn the user of these missing tests.
             walk_item(&mut InnerItemLinter { sess: self.cx.ext_cx.sess }, &item);
         }
-        smallvec![P(item)]
+        smallvec![i]
     }
 }
 
@@ -192,7 +192,7 @@ struct EntryPointCleaner<'a> {
 impl<'a> MutVisitor for EntryPointCleaner<'a> {
     fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
         self.depth += 1;
-        let item = noop_flat_map_item(i, self).expect_one("noop did something");
+        let item = walk_flat_map_item(self, i).expect_one("noop did something");
         self.depth -= 1;
 
         // Remove any #[rustc_main] or #[start] from the AST so it doesn't
diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs
index 652e34268ea..fabcb6a4b70 100644
--- a/compiler/rustc_builtin_macros/src/util.rs
+++ b/compiler/rustc_builtin_macros/src/util.rs
@@ -27,8 +27,7 @@ pub(crate) fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaI
 pub(crate) fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable, name: Symbol) {
     let attrs: Option<&[Attribute]> = match item {
         Annotatable::Item(item) => Some(&item.attrs),
-        Annotatable::TraitItem(item) => Some(&item.attrs),
-        Annotatable::ImplItem(item) => Some(&item.attrs),
+        Annotatable::AssocItem(item, _) => Some(&item.attrs),
         Annotatable::ForeignItem(item) => Some(&item.attrs),
         Annotatable::Expr(expr) => Some(&expr.attrs),
         Annotatable::Arm(arm) => Some(&arm.attrs),
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index d8e6d3525da..b439ec74ffa 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -37,8 +37,7 @@ use thin_vec::ThinVec;
 #[derive(Debug, Clone)]
 pub enum Annotatable {
     Item(P<ast::Item>),
-    TraitItem(P<ast::AssocItem>),
-    ImplItem(P<ast::AssocItem>),
+    AssocItem(P<ast::AssocItem>, AssocCtxt),
     ForeignItem(P<ast::ForeignItem>),
     Stmt(P<ast::Stmt>),
     Expr(P<ast::Expr>),
@@ -56,8 +55,7 @@ impl Annotatable {
     pub fn span(&self) -> Span {
         match self {
             Annotatable::Item(item) => item.span,
-            Annotatable::TraitItem(trait_item) => trait_item.span,
-            Annotatable::ImplItem(impl_item) => impl_item.span,
+            Annotatable::AssocItem(assoc_item, _) => assoc_item.span,
             Annotatable::ForeignItem(foreign_item) => foreign_item.span,
             Annotatable::Stmt(stmt) => stmt.span,
             Annotatable::Expr(expr) => expr.span,
@@ -75,8 +73,7 @@ impl Annotatable {
     pub fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
         match self {
             Annotatable::Item(item) => item.visit_attrs(f),
-            Annotatable::TraitItem(trait_item) => trait_item.visit_attrs(f),
-            Annotatable::ImplItem(impl_item) => impl_item.visit_attrs(f),
+            Annotatable::AssocItem(assoc_item, _) => assoc_item.visit_attrs(f),
             Annotatable::ForeignItem(foreign_item) => foreign_item.visit_attrs(f),
             Annotatable::Stmt(stmt) => stmt.visit_attrs(f),
             Annotatable::Expr(expr) => expr.visit_attrs(f),
@@ -94,8 +91,7 @@ impl Annotatable {
     pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) -> V::Result {
         match self {
             Annotatable::Item(item) => visitor.visit_item(item),
-            Annotatable::TraitItem(item) => visitor.visit_assoc_item(item, AssocCtxt::Trait),
-            Annotatable::ImplItem(item) => visitor.visit_assoc_item(item, AssocCtxt::Impl),
+            Annotatable::AssocItem(item, ctxt) => visitor.visit_assoc_item(item, *ctxt),
             Annotatable::ForeignItem(foreign_item) => visitor.visit_foreign_item(foreign_item),
             Annotatable::Stmt(stmt) => visitor.visit_stmt(stmt),
             Annotatable::Expr(expr) => visitor.visit_expr(expr),
@@ -113,9 +109,7 @@ impl Annotatable {
     pub fn to_tokens(&self) -> TokenStream {
         match self {
             Annotatable::Item(node) => TokenStream::from_ast(node),
-            Annotatable::TraitItem(node) | Annotatable::ImplItem(node) => {
-                TokenStream::from_ast(node)
-            }
+            Annotatable::AssocItem(node, _) => TokenStream::from_ast(node),
             Annotatable::ForeignItem(node) => TokenStream::from_ast(node),
             Annotatable::Stmt(node) => {
                 assert!(!matches!(node.kind, ast::StmtKind::Empty));
@@ -142,14 +136,14 @@ impl Annotatable {
 
     pub fn expect_trait_item(self) -> P<ast::AssocItem> {
         match self {
-            Annotatable::TraitItem(i) => i,
+            Annotatable::AssocItem(i, AssocCtxt::Trait) => i,
             _ => panic!("expected Item"),
         }
     }
 
     pub fn expect_impl_item(self) -> P<ast::AssocItem> {
         match self {
-            Annotatable::ImplItem(i) => i,
+            Annotatable::AssocItem(i, AssocCtxt::Impl) => i,
             _ => panic!("expected Item"),
         }
     }
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 26fc77c7f33..3c43d47292f 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -140,7 +140,7 @@ macro_rules! ast_fragments {
                     AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr),
                     $($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)*
                     $($(AstFragment::$Kind(ast) =>
-                        ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast)),)?)*
+                        ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast, $($args)*)),)?)*
                 }
             }
 
@@ -177,13 +177,13 @@ ast_fragments! {
     }
     TraitItems(SmallVec<[P<ast::AssocItem>; 1]>) {
         "trait item";
-        many fn flat_map_trait_item;
+        many fn flat_map_assoc_item;
         fn visit_assoc_item(AssocCtxt::Trait);
         fn make_trait_items;
     }
     ImplItems(SmallVec<[P<ast::AssocItem>; 1]>) {
         "impl item";
-        many fn flat_map_impl_item;
+        many fn flat_map_assoc_item;
         fn visit_assoc_item(AssocCtxt::Impl);
         fn make_impl_items;
     }
@@ -833,7 +833,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                     self.cx, deleg, &item, &suffixes, item.span, true,
                 );
                 fragment_kind.expect_from_annotatables(
-                    single_delegations.map(|item| Annotatable::ImplItem(P(item))),
+                    single_delegations.map(|item| Annotatable::AssocItem(P(item), AssocCtxt::Impl)),
                 )
             }
         })
@@ -843,8 +843,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
     fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
         let kind = match item {
             Annotatable::Item(_)
-            | Annotatable::TraitItem(_)
-            | Annotatable::ImplItem(_)
+            | Annotatable::AssocItem(..)
             | Annotatable::ForeignItem(_)
             | Annotatable::Crate(..) => return,
             Annotatable::Stmt(stmt) => {
@@ -1037,7 +1036,7 @@ pub(crate) fn ensure_complete_parse<'a>(
     }
 }
 
-/// Wraps a call to `noop_visit_*` / `noop_flat_map_*`
+/// Wraps a call to `walk_*` / `walk_flat_map_*`
 /// for an AST node that supports attributes
 /// (see the `Annotatable` enum)
 /// This method assigns a `NodeId`, and sets that `NodeId`
@@ -1057,7 +1056,7 @@ pub(crate) fn ensure_complete_parse<'a>(
 /// * `id` is a mutable reference to the `NodeId` field
 ///    of the current AST node.
 /// * `closure` is a closure that executes the
-///   `noop_visit_*` / `noop_flat_map_*` method
+///   `walk_*` / `walk_flat_map_*` method
 ///   for the current AST node.
 macro_rules! assign_id {
     ($self:ident, $id:expr, $closure:expr) => {{
@@ -1091,10 +1090,10 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
     fn descr() -> &'static str {
         unreachable!()
     }
-    fn noop_flat_map<V: MutVisitor>(self, _visitor: &mut V) -> Self::OutputTy {
+    fn walk_flat_map<V: MutVisitor>(self, _visitor: &mut V) -> Self::OutputTy {
         unreachable!()
     }
-    fn noop_visit<V: MutVisitor>(&mut self, _visitor: &mut V) {
+    fn walk<V: MutVisitor>(&mut self, _visitor: &mut V) {
         unreachable!()
     }
     fn is_mac_call(&self) -> bool {
@@ -1118,12 +1117,12 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
     fn pre_flat_map_node_collect_attr(_cfg: &StripUnconfigured<'_>, _attr: &ast::Attribute) {}
     fn post_flat_map_node_collect_bang(_output: &mut Self::OutputTy, _add_semicolon: AddSemicolon) {
     }
-    fn wrap_flat_map_node_noop_flat_map(
+    fn wrap_flat_map_node_walk_flat_map(
         node: Self,
         collector: &mut InvocationCollector<'_, '_>,
-        noop_flat_map: impl FnOnce(Self, &mut InvocationCollector<'_, '_>) -> Self::OutputTy,
+        walk_flat_map: impl FnOnce(Self, &mut InvocationCollector<'_, '_>) -> Self::OutputTy,
     ) -> Result<Self::OutputTy, Self> {
-        Ok(noop_flat_map(node, collector))
+        Ok(walk_flat_map(node, collector))
     }
     fn expand_cfg_false(
         &mut self,
@@ -1149,8 +1148,8 @@ impl InvocationCollectorNode for P<ast::Item> {
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_items()
     }
-    fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
-        noop_flat_map_item(self, visitor)
+    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
+        walk_flat_map_item(visitor, self)
     }
     fn is_mac_call(&self) -> bool {
         matches!(self.kind, ItemKind::MacCall(..))
@@ -1177,13 +1176,13 @@ impl InvocationCollectorNode for P<ast::Item> {
     fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
         items.flatten().collect()
     }
-    fn wrap_flat_map_node_noop_flat_map(
+    fn wrap_flat_map_node_walk_flat_map(
         mut node: Self,
         collector: &mut InvocationCollector<'_, '_>,
-        noop_flat_map: impl FnOnce(Self, &mut InvocationCollector<'_, '_>) -> Self::OutputTy,
+        walk_flat_map: impl FnOnce(Self, &mut InvocationCollector<'_, '_>) -> Self::OutputTy,
     ) -> Result<Self::OutputTy, Self> {
         if !matches!(node.kind, ItemKind::Mod(..)) {
-            return Ok(noop_flat_map(node, collector));
+            return Ok(walk_flat_map(node, collector));
         }
 
         // Work around borrow checker not seeing through `P`'s deref.
@@ -1253,7 +1252,7 @@ impl InvocationCollectorNode for P<ast::Item> {
         let orig_dir_ownership =
             mem::replace(&mut ecx.current_expansion.dir_ownership, dir_ownership);
 
-        let res = Ok(noop_flat_map(node, collector));
+        let res = Ok(walk_flat_map(node, collector));
 
         collector.cx.current_expansion.dir_ownership = orig_dir_ownership;
         collector.cx.current_expansion.module = orig_module;
@@ -1288,13 +1287,13 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitItemTag>
     type ItemKind = AssocItemKind;
     const KIND: AstFragmentKind = AstFragmentKind::TraitItems;
     fn to_annotatable(self) -> Annotatable {
-        Annotatable::TraitItem(self.wrapped)
+        Annotatable::AssocItem(self.wrapped, AssocCtxt::Trait)
     }
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_trait_items()
     }
-    fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
-        noop_flat_map_item(self.wrapped, visitor)
+    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
+        walk_flat_map_item(visitor, self.wrapped)
     }
     fn is_mac_call(&self) -> bool {
         matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
@@ -1329,13 +1328,13 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag>
     type ItemKind = AssocItemKind;
     const KIND: AstFragmentKind = AstFragmentKind::ImplItems;
     fn to_annotatable(self) -> Annotatable {
-        Annotatable::ImplItem(self.wrapped)
+        Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl)
     }
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_impl_items()
     }
-    fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
-        noop_flat_map_item(self.wrapped, visitor)
+    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
+        walk_flat_map_item(visitor, self.wrapped)
     }
     fn is_mac_call(&self) -> bool {
         matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
@@ -1372,8 +1371,8 @@ impl InvocationCollectorNode for P<ast::ForeignItem> {
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_foreign_items()
     }
-    fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
-        noop_flat_map_item(self, visitor)
+    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
+        walk_flat_map_item(visitor, self)
     }
     fn is_mac_call(&self) -> bool {
         matches!(self.kind, ForeignItemKind::MacCall(..))
@@ -1395,8 +1394,8 @@ impl InvocationCollectorNode for ast::Variant {
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_variants()
     }
-    fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
-        noop_flat_map_variant(self, visitor)
+    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
+        walk_flat_map_variant(visitor, self)
     }
 }
 
@@ -1408,8 +1407,8 @@ impl InvocationCollectorNode for ast::FieldDef {
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_field_defs()
     }
-    fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
-        noop_flat_map_field_def(self, visitor)
+    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
+        walk_flat_map_field_def(visitor, self)
     }
 }
 
@@ -1421,8 +1420,8 @@ impl InvocationCollectorNode for ast::PatField {
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_pat_fields()
     }
-    fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
-        noop_flat_map_pat_field(self, visitor)
+    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
+        walk_flat_map_pat_field(visitor, self)
     }
 }
 
@@ -1434,8 +1433,8 @@ impl InvocationCollectorNode for ast::ExprField {
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_expr_fields()
     }
-    fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
-        noop_flat_map_expr_field(self, visitor)
+    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
+        walk_flat_map_expr_field(visitor, self)
     }
 }
 
@@ -1447,8 +1446,8 @@ impl InvocationCollectorNode for ast::Param {
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_params()
     }
-    fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
-        noop_flat_map_param(self, visitor)
+    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
+        walk_flat_map_param(visitor, self)
     }
 }
 
@@ -1460,8 +1459,8 @@ impl InvocationCollectorNode for ast::GenericParam {
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_generic_params()
     }
-    fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
-        noop_flat_map_generic_param(self, visitor)
+    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
+        walk_flat_map_generic_param(visitor, self)
     }
 }
 
@@ -1473,8 +1472,8 @@ impl InvocationCollectorNode for ast::Arm {
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_arms()
     }
-    fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
-        noop_flat_map_arm(self, visitor)
+    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
+        walk_flat_map_arm(visitor, self)
     }
 }
 
@@ -1487,8 +1486,8 @@ impl InvocationCollectorNode for ast::Stmt {
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_stmts()
     }
-    fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
-        noop_flat_map_stmt(self, visitor)
+    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
+        walk_flat_map_stmt(visitor, self)
     }
     fn is_mac_call(&self) -> bool {
         match &self.kind {
@@ -1561,8 +1560,8 @@ impl InvocationCollectorNode for ast::Crate {
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_crate()
     }
-    fn noop_visit<V: MutVisitor>(&mut self, visitor: &mut V) {
-        noop_visit_crate(self, visitor)
+    fn walk<V: MutVisitor>(&mut self, visitor: &mut V) {
+        walk_crate(visitor, self)
     }
     fn expand_cfg_false(
         &mut self,
@@ -1587,8 +1586,8 @@ impl InvocationCollectorNode for P<ast::Ty> {
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_ty()
     }
-    fn noop_visit<V: MutVisitor>(&mut self, visitor: &mut V) {
-        noop_visit_ty(self, visitor)
+    fn walk<V: MutVisitor>(&mut self, visitor: &mut V) {
+        walk_ty(visitor, self)
     }
     fn is_mac_call(&self) -> bool {
         matches!(self.kind, ast::TyKind::MacCall(..))
@@ -1611,8 +1610,8 @@ impl InvocationCollectorNode for P<ast::Pat> {
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_pat()
     }
-    fn noop_visit<V: MutVisitor>(&mut self, visitor: &mut V) {
-        noop_visit_pat(self, visitor)
+    fn walk<V: MutVisitor>(&mut self, visitor: &mut V) {
+        walk_pat(visitor, self)
     }
     fn is_mac_call(&self) -> bool {
         matches!(self.kind, PatKind::MacCall(..))
@@ -1639,8 +1638,8 @@ impl InvocationCollectorNode for P<ast::Expr> {
     fn descr() -> &'static str {
         "an expression"
     }
-    fn noop_visit<V: MutVisitor>(&mut self, visitor: &mut V) {
-        noop_visit_expr(self, visitor)
+    fn walk<V: MutVisitor>(&mut self, visitor: &mut V) {
+        walk_expr(visitor, self)
     }
     fn is_mac_call(&self) -> bool {
         matches!(self.kind, ExprKind::MacCall(..))
@@ -1665,8 +1664,8 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> {
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_opt_expr()
     }
-    fn noop_flat_map<V: MutVisitor>(mut self, visitor: &mut V) -> Self::OutputTy {
-        noop_visit_expr(&mut self.wrapped, visitor);
+    fn walk_flat_map<V: MutVisitor>(mut self, visitor: &mut V) -> Self::OutputTy {
+        walk_expr(visitor, &mut self.wrapped);
         Some(self.wrapped)
     }
     fn is_mac_call(&self) -> bool {
@@ -1705,8 +1704,8 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, MethodReceiverTag>
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         AstNodeWrapper::new(fragment.make_method_receiver_expr(), MethodReceiverTag)
     }
-    fn noop_visit<V: MutVisitor>(&mut self, visitor: &mut V) {
-        noop_visit_expr(&mut self.wrapped, visitor)
+    fn walk<V: MutVisitor>(&mut self, visitor: &mut V) {
+        walk_expr(visitor, &mut self.wrapped)
     }
     fn is_mac_call(&self) -> bool {
         matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
@@ -1993,9 +1992,9 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                         let traitless_qself =
                             matches!(&deleg.qself, Some(qself) if qself.position == 0);
                         let item = match node.to_annotatable() {
-                            Annotatable::ImplItem(item) => item,
+                            Annotatable::AssocItem(item, AssocCtxt::Impl) => item,
                             ann @ (Annotatable::Item(_)
-                            | Annotatable::TraitItem(_)
+                            | Annotatable::AssocItem(..)
                             | Annotatable::Stmt(_)) => {
                                 let span = ann.span();
                                 self.cx.dcx().emit_err(GlobDelegationOutsideImpls { span });
@@ -2016,12 +2015,12 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                     );
                     Node::flatten_outputs(single_delegations.map(|item| {
                         let mut item = Node::from_item(item);
-                        assign_id!(self, item.node_id_mut(), || item.noop_flat_map(self))
+                        assign_id!(self, item.node_id_mut(), || item.walk_flat_map(self))
                     }))
                 }
                 None => {
-                    match Node::wrap_flat_map_node_noop_flat_map(node, self, |mut node, this| {
-                        assign_id!(this, node.node_id_mut(), || node.noop_flat_map(this))
+                    match Node::wrap_flat_map_node_walk_flat_map(node, self, |mut node, this| {
+                        assign_id!(this, node.node_id_mut(), || node.walk_flat_map(this))
                     }) {
                         Ok(output) => output,
                         Err(returned_node) => {
@@ -2069,7 +2068,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                 }
                 None if node.delegation().is_some() => unreachable!(),
                 None => {
-                    assign_id!(self, node.node_id_mut(), || node.noop_visit(self))
+                    assign_id!(self, node.node_id_mut(), || node.walk(self))
                 }
             };
         }
@@ -2081,12 +2080,15 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         self.flat_map_node(node)
     }
 
-    fn flat_map_trait_item(&mut self, node: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
-        self.flat_map_node(AstNodeWrapper::new(node, TraitItemTag))
-    }
-
-    fn flat_map_impl_item(&mut self, node: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
-        self.flat_map_node(AstNodeWrapper::new(node, ImplItemTag))
+    fn flat_map_assoc_item(
+        &mut self,
+        node: P<ast::AssocItem>,
+        ctxt: AssocCtxt,
+    ) -> SmallVec<[P<ast::AssocItem>; 1]> {
+        match ctxt {
+            AssocCtxt::Trait => self.flat_map_node(AstNodeWrapper::new(node, TraitItemTag)),
+            AssocCtxt::Impl => self.flat_map_node(AstNodeWrapper::new(node, ImplItemTag)),
+        }
     }
 
     fn flat_map_foreign_item(
@@ -2145,11 +2147,11 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
                     self.cx.current_expansion.is_trailing_mac = true;
                     // Don't use `assign_id` for this statement - it may get removed
                     // entirely due to a `#[cfg]` on the contained expression
-                    let res = noop_flat_map_stmt(node, self);
+                    let res = walk_flat_map_stmt(self, node);
                     self.cx.current_expansion.is_trailing_mac = false;
                     res
                 }
-                _ => noop_flat_map_stmt(node, self),
+                _ => walk_flat_map_stmt(self, node),
             };
         }
 
@@ -2193,7 +2195,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
             &mut self.cx.current_expansion.dir_ownership,
             DirOwnership::UnownedViaBlock,
         );
-        noop_visit_block(node, self);
+        walk_block(self, node);
         self.cx.current_expansion.dir_ownership = orig_dir_ownership;
     }
 
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 62337756cd8..0da542d379d 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -333,7 +333,7 @@ pub(super) fn transcribe<'a>(
             // jump back out of the Delimited, pop the result_stack and add the new results back to
             // the previous results (from outside the Delimited).
             mbe::TokenTree::Delimited(mut span, spacing, delimited) => {
-                mut_visit::visit_delim_span(&mut span, &mut marker);
+                mut_visit::visit_delim_span(&mut marker, &mut span);
                 stack.push(Frame::new_delimited(delimited, span, *spacing));
                 result_stack.push(mem::take(&mut result));
             }
@@ -342,7 +342,7 @@ pub(super) fn transcribe<'a>(
             // preserve syntax context.
             mbe::TokenTree::Token(token) => {
                 let mut token = token.clone();
-                mut_visit::visit_token(&mut token, &mut marker);
+                mut_visit::visit_token(&mut marker, &mut token);
                 let tt = TokenTree::Token(token, Spacing::Alone);
                 result.push(tt);
             }
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index e21f041d69a..3fa909877cc 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -1,8 +1,8 @@
 use crate::expand::{AstFragment, AstFragmentKind};
-use rustc_ast as ast;
 use rustc_ast::mut_visit::*;
 use rustc_ast::ptr::P;
 use rustc_ast::token::Delimiter;
+use rustc_ast::{self as ast, visit::AssocCtxt};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_span::symbol::Ident;
 use rustc_span::DUMMY_SP;
@@ -209,7 +209,7 @@ impl MutVisitor for PlaceholderExpander {
         if arm.is_placeholder {
             self.remove(arm.id).make_arms()
         } else {
-            noop_flat_map_arm(arm, self)
+            walk_flat_map_arm(self, arm)
         }
     }
 
@@ -217,7 +217,7 @@ impl MutVisitor for PlaceholderExpander {
         if field.is_placeholder {
             self.remove(field.id).make_expr_fields()
         } else {
-            noop_flat_map_expr_field(field, self)
+            walk_flat_map_expr_field(self, field)
         }
     }
 
@@ -225,7 +225,7 @@ impl MutVisitor for PlaceholderExpander {
         if fp.is_placeholder {
             self.remove(fp.id).make_pat_fields()
         } else {
-            noop_flat_map_pat_field(fp, self)
+            walk_flat_map_pat_field(self, fp)
         }
     }
 
@@ -236,7 +236,7 @@ impl MutVisitor for PlaceholderExpander {
         if param.is_placeholder {
             self.remove(param.id).make_generic_params()
         } else {
-            noop_flat_map_generic_param(param, self)
+            walk_flat_map_generic_param(self, param)
         }
     }
 
@@ -244,7 +244,7 @@ impl MutVisitor for PlaceholderExpander {
         if p.is_placeholder {
             self.remove(p.id).make_params()
         } else {
-            noop_flat_map_param(p, self)
+            walk_flat_map_param(self, p)
         }
     }
 
@@ -252,7 +252,7 @@ impl MutVisitor for PlaceholderExpander {
         if sf.is_placeholder {
             self.remove(sf.id).make_field_defs()
         } else {
-            noop_flat_map_field_def(sf, self)
+            walk_flat_map_field_def(self, sf)
         }
     }
 
@@ -260,28 +260,31 @@ impl MutVisitor for PlaceholderExpander {
         if variant.is_placeholder {
             self.remove(variant.id).make_variants()
         } else {
-            noop_flat_map_variant(variant, self)
+            walk_flat_map_variant(self, variant)
         }
     }
 
     fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
         match item.kind {
             ast::ItemKind::MacCall(_) => self.remove(item.id).make_items(),
-            _ => noop_flat_map_item(item, self),
+            _ => walk_flat_map_item(self, item),
         }
     }
 
-    fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
-        match item.kind {
-            ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_trait_items(),
-            _ => noop_flat_map_item(item, self),
-        }
-    }
-
-    fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
+    fn flat_map_assoc_item(
+        &mut self,
+        item: P<ast::AssocItem>,
+        ctxt: AssocCtxt,
+    ) -> SmallVec<[P<ast::AssocItem>; 1]> {
         match item.kind {
-            ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_impl_items(),
-            _ => noop_flat_map_item(item, self),
+            ast::AssocItemKind::MacCall(_) => {
+                let it = self.remove(item.id);
+                match ctxt {
+                    AssocCtxt::Trait => it.make_trait_items(),
+                    AssocCtxt::Impl => it.make_impl_items(),
+                }
+            }
+            _ => walk_flat_map_item(self, item),
         }
     }
 
@@ -291,35 +294,35 @@ impl MutVisitor for PlaceholderExpander {
     ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
         match item.kind {
             ast::ForeignItemKind::MacCall(_) => self.remove(item.id).make_foreign_items(),
-            _ => noop_flat_map_item(item, self),
+            _ => walk_flat_map_item(self, item),
         }
     }
 
     fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
         match expr.kind {
             ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_expr(),
-            _ => noop_visit_expr(expr, self),
+            _ => walk_expr(self, expr),
         }
     }
 
     fn visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>) {
         match expr.kind {
             ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_method_receiver_expr(),
-            _ => noop_visit_expr(expr, self),
+            _ => walk_expr(self, expr),
         }
     }
 
     fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
         match expr.kind {
             ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(),
-            _ => noop_filter_map_expr(expr, self),
+            _ => noop_filter_map_expr(self, expr),
         }
     }
 
     fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
         let (style, mut stmts) = match stmt.kind {
             ast::StmtKind::MacCall(mac) => (mac.style, self.remove(stmt.id).make_stmts()),
-            _ => return noop_flat_map_stmt(stmt, self),
+            _ => return walk_flat_map_stmt(self, stmt),
         };
 
         if style == ast::MacStmtStyle::Semicolon {
@@ -365,14 +368,14 @@ impl MutVisitor for PlaceholderExpander {
     fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
         match pat.kind {
             ast::PatKind::MacCall(_) => *pat = self.remove(pat.id).make_pat(),
-            _ => noop_visit_pat(pat, self),
+            _ => walk_pat(self, pat),
         }
     }
 
     fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
         match ty.kind {
             ast::TyKind::MacCall(_) => *ty = self.remove(ty.id).make_ty(),
-            _ => noop_visit_ty(ty, self),
+            _ => walk_ty(self, ty),
         }
     }
 
@@ -380,7 +383,7 @@ impl MutVisitor for PlaceholderExpander {
         if krate.is_placeholder {
             *krate = self.remove(krate.id).make_crate();
         } else {
-            noop_visit_crate(krate, self)
+            walk_crate(self, krate)
         }
     }
 }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 2542108728f..389a6d11e19 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -10,7 +10,7 @@ use super::{
 
 use crate::errors;
 use crate::maybe_recover_from_interpolated_ty_qpath;
-use ast::mut_visit::{noop_visit_expr, MutVisitor};
+use ast::mut_visit::{self, MutVisitor};
 use ast::token::IdentIsRaw;
 use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered};
 use core::mem;
@@ -3939,14 +3939,14 @@ impl MutVisitor for CondChecker<'_> {
                 }
             }
             ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, _, _) => {
-                noop_visit_expr(e, self);
+                mut_visit::walk_expr(self, e);
             }
             ExprKind::Binary(Spanned { node: BinOpKind::Or, span: or_span }, _, _)
                 if let None | Some(NotSupportedOr(_)) = self.forbid_let_reason =>
             {
                 let forbid_let_reason = self.forbid_let_reason;
                 self.forbid_let_reason = Some(NotSupportedOr(or_span));
-                noop_visit_expr(e, self);
+                mut_visit::walk_expr(self, e);
                 self.forbid_let_reason = forbid_let_reason;
             }
             ExprKind::Paren(ref inner)
@@ -3954,7 +3954,7 @@ impl MutVisitor for CondChecker<'_> {
             {
                 let forbid_let_reason = self.forbid_let_reason;
                 self.forbid_let_reason = Some(NotSupportedParentheses(inner.span));
-                noop_visit_expr(e, self);
+                mut_visit::walk_expr(self, e);
                 self.forbid_let_reason = forbid_let_reason;
             }
             ExprKind::Assign(ref lhs, _, span) => {
@@ -3972,7 +3972,7 @@ impl MutVisitor for CondChecker<'_> {
                 }
                 let comparison = self.comparison;
                 self.comparison = Some(errors::MaybeComparison { span: span.shrink_to_hi() });
-                noop_visit_expr(e, self);
+                mut_visit::walk_expr(self, e);
                 self.forbid_let_reason = forbid_let_reason;
                 self.missing_let = missing_let;
                 self.comparison = comparison;
@@ -3992,7 +3992,7 @@ impl MutVisitor for CondChecker<'_> {
             | ExprKind::Paren(_) => {
                 let forbid_let_reason = self.forbid_let_reason;
                 self.forbid_let_reason = Some(OtherForbidden);
-                noop_visit_expr(e, self);
+                mut_visit::walk_expr(self, e);
                 self.forbid_let_reason = forbid_let_reason;
             }
             ExprKind::Cast(ref mut op, _) | ExprKind::Type(ref mut op, _) => {
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 18d531faeaa..aa818878cd8 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -12,7 +12,7 @@ use crate::errors::{
 };
 use crate::parser::expr::{could_be_unclosed_char_literal, LhsExpr};
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
-use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
+use rustc_ast::mut_visit::{walk_pat, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, BinOpToken, Delimiter, Token};
 use rustc_ast::{
@@ -810,7 +810,7 @@ impl<'a> Parser<'a> {
                     self.0 = true;
                     *m = Mutability::Mut;
                 }
-                noop_visit_pat(pat, self);
+                walk_pat(self, pat);
             }
         }
 
diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
index fcc41b51542..842046c941d 100644
--- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
@@ -121,7 +121,7 @@ fn remove_all_parens(pat: &mut P<Pat>) {
     struct Visitor;
     impl MutVisitor for Visitor {
         fn visit_pat(&mut self, pat: &mut P<Pat>) {
-            noop_visit_pat(pat, self);
+            walk_pat(self, pat);
             let inner = match &mut pat.kind {
                 Paren(i) => mem::replace(&mut i.kind, Wild),
                 _ => return,
@@ -138,7 +138,7 @@ fn insert_necessary_parens(pat: &mut P<Pat>) {
     impl MutVisitor for Visitor {
         fn visit_pat(&mut self, pat: &mut P<Pat>) {
             use ast::BindingMode;
-            noop_visit_pat(pat, self);
+            walk_pat(self, pat);
             let target = match &mut pat.kind {
                 // `i @ a | b`, `box a | b`, and `& mut? a | b`.
                 Ident(.., Some(p)) | Box(p) | Ref(p, _) if matches!(&p.kind, Or(ps) if ps.len() > 1) => p,
@@ -160,7 +160,7 @@ fn unnest_or_patterns(pat: &mut P<Pat>) -> bool {
     impl MutVisitor for Visitor {
         fn visit_pat(&mut self, p: &mut P<Pat>) {
             // This is a bottom up transformation, so recurse first.
-            noop_visit_pat(p, self);
+            walk_pat(self, p);
 
             // Don't have an or-pattern? Just quit early on.
             let Or(alternatives) = &mut p.kind else { return };
@@ -189,7 +189,7 @@ fn unnest_or_patterns(pat: &mut P<Pat>) -> bool {
 
             // Deal with `Some(Some(0)) | Some(Some(1))`.
             if this_level_changed {
-                noop_visit_pat(p, self);
+                walk_pat(self, p);
             }
         }
     }
diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
index 762ad0b79ec..8379ca86494 100644
--- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -46,9 +46,11 @@ use thin_vec::{thin_vec, ThinVec};
 fn parse_expr(psess: &ParseSess, src: &str) -> Option<P<Expr>> {
     let src_as_string = src.to_string();
 
-    let mut p = unwrap_or_emit_fatal(
-        new_parser_from_source_str(psess, FileName::Custom(src_as_string.clone()), src_as_string)
-    );
+    let mut p = unwrap_or_emit_fatal(new_parser_from_source_str(
+        psess,
+        FileName::Custom(src_as_string.clone()),
+        src_as_string,
+    ));
     p.parse_expr().map_err(|e| e.cancel()).ok()
 }
 
@@ -181,10 +183,9 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
             18 => {
                 let pat =
                     P(Pat { id: DUMMY_NODE_ID, kind: PatKind::Wild, span: DUMMY_SP, tokens: None });
-                iter_exprs(
-                    depth - 1,
-                    &mut |e| g(ExprKind::Let(pat.clone(), e, DUMMY_SP, Recovered::No))
-                )
+                iter_exprs(depth - 1, &mut |e| {
+                    g(ExprKind::Let(pat.clone(), e, DUMMY_SP, Recovered::No))
+                })
             }
             _ => panic!("bad counter value in iter_exprs"),
         }
@@ -202,7 +203,7 @@ impl MutVisitor for RemoveParens {
             ExprKind::Paren(inner) => *e = inner,
             _ => {}
         };
-        mut_visit::noop_visit_expr(e, self);
+        mut_visit::walk_expr(self, e);
     }
 }
 
@@ -211,7 +212,7 @@ struct AddParens;
 
 impl MutVisitor for AddParens {
     fn visit_expr(&mut self, e: &mut P<Expr>) {
-        mut_visit::noop_visit_expr(e, self);
+        mut_visit::walk_expr(self, e);
         visit_clobber(e, |e| {
             P(Expr {
                 id: DUMMY_NODE_ID,