diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 064f05ef1f3ef..33c20602dfd23 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -3303,9 +3303,6 @@ pub struct Item<K = ItemKind> {
     pub id: NodeId,
     pub span: Span,
     pub vis: Visibility,
-    /// The name of the item.
-    /// It might be a dummy name in case of anonymous items.
-    pub ident: Ident,
 
     pub kind: K,
 
@@ -3327,23 +3324,23 @@ impl Item {
 
     pub fn opt_generics(&self) -> Option<&Generics> {
         match &self.kind {
-            ItemKind::ExternCrate(_)
+            ItemKind::ExternCrate(..)
             | ItemKind::Use(_)
-            | ItemKind::Mod(_, _)
+            | ItemKind::Mod(..)
             | ItemKind::ForeignMod(_)
             | ItemKind::GlobalAsm(_)
             | ItemKind::MacCall(_)
             | ItemKind::Delegation(_)
             | ItemKind::DelegationMac(_)
-            | ItemKind::MacroDef(_) => None,
+            | ItemKind::MacroDef(..) => None,
             ItemKind::Static(_) => None,
             ItemKind::Const(i) => Some(&i.generics),
             ItemKind::Fn(i) => Some(&i.generics),
             ItemKind::TyAlias(i) => Some(&i.generics),
-            ItemKind::TraitAlias(generics, _)
-            | ItemKind::Enum(_, generics)
-            | ItemKind::Struct(_, generics)
-            | ItemKind::Union(_, generics) => Some(&generics),
+            ItemKind::TraitAlias(_, generics, _)
+            | ItemKind::Enum(_, _, generics)
+            | ItemKind::Struct(_, _, generics)
+            | ItemKind::Union(_, _, generics) => Some(&generics),
             ItemKind::Trait(i) => Some(&i.generics),
             ItemKind::Impl(i) => Some(&i.generics),
         }
@@ -3420,6 +3417,7 @@ impl Default for FnHeader {
 pub struct Trait {
     pub safety: Safety,
     pub is_auto: IsAuto,
+    pub ident: Ident,
     pub generics: Generics,
     pub bounds: GenericBounds,
     pub items: ThinVec<P<AssocItem>>,
@@ -3465,6 +3463,7 @@ pub struct TyAliasWhereClauses {
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct TyAlias {
     pub defaultness: Defaultness,
+    pub ident: Ident,
     pub generics: Generics,
     pub where_clauses: TyAliasWhereClauses,
     pub bounds: GenericBounds,
@@ -3493,6 +3492,7 @@ pub struct FnContract {
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Fn {
     pub defaultness: Defaultness,
+    pub ident: Ident,
     pub generics: Generics,
     pub sig: FnSig,
     pub contract: Option<P<FnContract>>,
@@ -3506,6 +3506,7 @@ pub struct Delegation {
     pub id: NodeId,
     pub qself: Option<P<QSelf>>,
     pub path: Path,
+    pub ident: Ident,
     pub rename: Option<Ident>,
     pub body: Option<P<Block>>,
     /// The item was expanded from a glob delegation item.
@@ -3523,6 +3524,7 @@ pub struct DelegationMac {
 
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct StaticItem {
+    pub ident: Ident,
     pub ty: P<Ty>,
     pub safety: Safety,
     pub mutability: Mutability,
@@ -3533,6 +3535,7 @@ pub struct StaticItem {
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct ConstItem {
     pub defaultness: Defaultness,
+    pub ident: Ident,
     pub generics: Generics,
     pub ty: P<Ty>,
     pub expr: Option<P<Expr>>,
@@ -3545,7 +3548,7 @@ pub enum ItemKind {
     /// An `extern crate` item, with the optional *original* crate name if the crate was renamed.
     ///
     /// E.g., `extern crate foo` or `extern crate foo_bar as foo`.
-    ExternCrate(Option<Symbol>),
+    ExternCrate(Option<Symbol>, Ident),
     /// A use declaration item (`use`).
     ///
     /// E.g., `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`.
@@ -3567,7 +3570,7 @@ pub enum ItemKind {
     /// E.g., `mod foo;` or `mod foo { .. }`.
     /// `unsafe` keyword on modules is accepted syntactically for macro DSLs, but not
     /// semantically by Rust.
-    Mod(Safety, ModKind),
+    Mod(Safety, Ident, ModKind),
     /// An external module (`extern`).
     ///
     /// E.g., `extern {}` or `extern "C" {}`.
@@ -3581,15 +3584,15 @@ pub enum ItemKind {
     /// An enum definition (`enum`).
     ///
     /// E.g., `enum Foo<A, B> { C<A>, D<B> }`.
-    Enum(EnumDef, Generics),
+    Enum(Ident, EnumDef, Generics),
     /// A struct definition (`struct`).
     ///
     /// E.g., `struct Foo<A> { x: A }`.
-    Struct(VariantData, Generics),
+    Struct(Ident, VariantData, Generics),
     /// A union definition (`union`).
     ///
     /// E.g., `union Foo<A, B> { x: A, y: B }`.
-    Union(VariantData, Generics),
+    Union(Ident, VariantData, Generics),
     /// A trait declaration (`trait`).
     ///
     /// E.g., `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`.
@@ -3597,7 +3600,7 @@ pub enum ItemKind {
     /// Trait alias.
     ///
     /// E.g., `trait Foo = Bar + Quux;`.
-    TraitAlias(Generics, GenericBounds),
+    TraitAlias(Ident, Generics, GenericBounds),
     /// An implementation.
     ///
     /// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`.
@@ -3608,7 +3611,7 @@ pub enum ItemKind {
     MacCall(P<MacCall>),
 
     /// A macro definition.
-    MacroDef(MacroDef),
+    MacroDef(Ident, MacroDef),
 
     /// A single delegation item (`reuse`).
     ///
@@ -3620,6 +3623,31 @@ pub enum ItemKind {
 }
 
 impl ItemKind {
+    pub fn ident(&self) -> Option<Ident> {
+        match *self {
+            ItemKind::ExternCrate(_, ident)
+            | ItemKind::Static(box StaticItem { ident, .. })
+            | ItemKind::Const(box ConstItem { ident, .. })
+            | ItemKind::Fn(box Fn { ident, .. })
+            | ItemKind::Mod(_, ident, _)
+            | ItemKind::TyAlias(box TyAlias { ident, .. })
+            | ItemKind::Enum(ident, ..)
+            | ItemKind::Struct(ident, ..)
+            | ItemKind::Union(ident, ..)
+            | ItemKind::Trait(box Trait { ident, .. })
+            | ItemKind::TraitAlias(ident, ..)
+            | ItemKind::MacroDef(ident, _)
+            | ItemKind::Delegation(box Delegation { ident, .. }) => Some(ident),
+
+            ItemKind::Use(_)
+            | ItemKind::ForeignMod(_)
+            | ItemKind::GlobalAsm(_)
+            | ItemKind::Impl(_)
+            | ItemKind::MacCall(_)
+            | ItemKind::DelegationMac(_) => None,
+        }
+    }
+
     /// "a" or "an"
     pub fn article(&self) -> &'static str {
         use ItemKind::*;
@@ -3660,11 +3688,11 @@ impl ItemKind {
             Self::Fn(box Fn { generics, .. })
             | Self::TyAlias(box TyAlias { generics, .. })
             | Self::Const(box ConstItem { generics, .. })
-            | Self::Enum(_, generics)
-            | Self::Struct(_, generics)
-            | Self::Union(_, generics)
+            | Self::Enum(_, _, generics)
+            | Self::Struct(_, _, generics)
+            | Self::Union(_, _, generics)
             | Self::Trait(box Trait { generics, .. })
-            | Self::TraitAlias(generics, _)
+            | Self::TraitAlias(_, generics, _)
             | Self::Impl(box Impl { generics, .. }) => Some(generics),
             _ => None,
         }
@@ -3700,6 +3728,17 @@ pub enum AssocItemKind {
 }
 
 impl AssocItemKind {
+    pub fn ident(&self) -> Option<Ident> {
+        match *self {
+            AssocItemKind::Const(box ConstItem { ident, .. })
+            | AssocItemKind::Fn(box Fn { ident, .. })
+            | AssocItemKind::Type(box TyAlias { ident, .. })
+            | AssocItemKind::Delegation(box Delegation { ident, .. }) => Some(ident),
+
+            AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(_) => None,
+        }
+    }
+
     pub fn defaultness(&self) -> Defaultness {
         match *self {
             Self::Const(box ConstItem { defaultness, .. })
@@ -3746,14 +3785,26 @@ impl TryFrom<ItemKind> for AssocItemKind {
 pub enum ForeignItemKind {
     /// A foreign static item (`static FOO: u8`).
     Static(Box<StaticItem>),
-    /// An foreign function.
+    /// A foreign function.
     Fn(Box<Fn>),
-    /// An foreign type.
+    /// A foreign type.
     TyAlias(Box<TyAlias>),
     /// A macro expanding to foreign items.
     MacCall(P<MacCall>),
 }
 
+impl ForeignItemKind {
+    pub fn ident(&self) -> Option<Ident> {
+        match *self {
+            ForeignItemKind::Static(box StaticItem { ident, .. })
+            | ForeignItemKind::Fn(box Fn { ident, .. })
+            | ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => Some(ident),
+
+            ForeignItemKind::MacCall(_) => None,
+        }
+    }
+}
+
 impl From<ForeignItemKind> for ItemKind {
     fn from(foreign_item_kind: ForeignItemKind) -> ItemKind {
         match foreign_item_kind {
@@ -3790,21 +3841,21 @@ mod size_asserts {
 
     use super::*;
     // tidy-alphabetical-start
-    static_assert_size!(AssocItem, 88);
+    static_assert_size!(AssocItem, 80);
     static_assert_size!(AssocItemKind, 16);
     static_assert_size!(Attribute, 32);
     static_assert_size!(Block, 32);
     static_assert_size!(Expr, 72);
     static_assert_size!(ExprKind, 40);
-    static_assert_size!(Fn, 176);
-    static_assert_size!(ForeignItem, 88);
+    static_assert_size!(Fn, 184);
+    static_assert_size!(ForeignItem, 80);
     static_assert_size!(ForeignItemKind, 16);
     static_assert_size!(GenericArg, 24);
     static_assert_size!(GenericBound, 88);
     static_assert_size!(Generics, 40);
     static_assert_size!(Impl, 136);
-    static_assert_size!(Item, 136);
-    static_assert_size!(ItemKind, 64);
+    static_assert_size!(Item, 144);
+    static_assert_size!(ItemKind, 80);
     static_assert_size!(LitKind, 24);
     static_assert_size!(Local, 80);
     static_assert_size!(MetaItemLit, 40);
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 274fe312f7fad..30af6d910bfa2 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -41,7 +41,6 @@ pub trait WalkItemKind {
         &mut self,
         span: Span,
         id: NodeId,
-        ident: &mut Ident,
         visibility: &mut Visibility,
         ctxt: Self::Ctxt,
         visitor: &mut impl MutVisitor,
@@ -963,10 +962,10 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
     match kind {
         FnKind::Fn(
             _ctxt,
-            _ident,
             _vis,
             Fn {
                 defaultness,
+                ident,
                 generics,
                 contract,
                 body,
@@ -974,8 +973,9 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
                 define_opaque,
             },
         ) => {
-            // Identifier and visibility are visited as a part of the item.
+            // Visibility is visited as a part of the item.
             visit_defaultness(vis, defaultness);
+            vis.visit_ident(ident);
             vis.visit_fn_header(header);
             vis.visit_generics(generics);
             vis.visit_fn_decl(decl);
@@ -1233,12 +1233,11 @@ pub fn walk_item_kind<K: WalkItemKind>(
     kind: &mut K,
     span: Span,
     id: NodeId,
-    ident: &mut Ident,
     visibility: &mut Visibility,
     ctxt: K::Ctxt,
     vis: &mut impl MutVisitor,
 ) {
-    kind.walk(span, id, ident, visibility, ctxt, vis)
+    kind.walk(span, id, visibility, ctxt, vis)
 }
 
 impl WalkItemKind for ItemKind {
@@ -1247,21 +1246,22 @@ impl WalkItemKind for ItemKind {
         &mut self,
         span: Span,
         id: NodeId,
-        ident: &mut Ident,
         visibility: &mut Visibility,
         _ctxt: Self::Ctxt,
         vis: &mut impl MutVisitor,
     ) {
         match self {
-            ItemKind::ExternCrate(_orig_name) => {}
+            ItemKind::ExternCrate(_orig_name, ident) => vis.visit_ident(ident),
             ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
             ItemKind::Static(box StaticItem {
+                ident,
                 ty,
                 safety: _,
                 mutability: _,
                 expr,
                 define_opaque,
             }) => {
+                vis.visit_ident(ident);
                 vis.visit_ty(ty);
                 visit_opt(expr, |expr| vis.visit_expr(expr));
                 walk_define_opaques(vis, define_opaque);
@@ -1270,10 +1270,11 @@ impl WalkItemKind for ItemKind {
                 walk_const_item(vis, item);
             }
             ItemKind::Fn(func) => {
-                vis.visit_fn(FnKind::Fn(FnCtxt::Free, ident, visibility, &mut *func), span, id);
+                vis.visit_fn(FnKind::Fn(FnCtxt::Free, visibility, &mut *func), span, id);
             }
-            ItemKind::Mod(safety, mod_kind) => {
+            ItemKind::Mod(safety, ident, mod_kind) => {
                 visit_safety(vis, safety);
+                vis.visit_ident(ident);
                 match mod_kind {
                     ModKind::Loaded(
                         items,
@@ -1290,18 +1291,29 @@ impl WalkItemKind 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 }) => {
+            ItemKind::TyAlias(box TyAlias {
+                defaultness,
+                ident,
+                generics,
+                where_clauses,
+                bounds,
+                ty,
+            }) => {
                 visit_defaultness(vis, defaultness);
+                vis.visit_ident(ident);
                 vis.visit_generics(generics);
                 visit_bounds(vis, bounds, BoundKind::Bound);
                 visit_opt(ty, |ty| vis.visit_ty(ty));
                 walk_ty_alias_where_clauses(vis, where_clauses);
             }
-            ItemKind::Enum(EnumDef { variants }, generics) => {
+            ItemKind::Enum(ident, EnumDef { variants }, generics) => {
+                vis.visit_ident(ident);
                 vis.visit_generics(generics);
                 variants.flat_map_in_place(|variant| vis.flat_map_variant(variant));
             }
-            ItemKind::Struct(variant_data, generics) | ItemKind::Union(variant_data, generics) => {
+            ItemKind::Struct(ident, variant_data, generics)
+            | ItemKind::Union(ident, variant_data, generics) => {
+                vis.visit_ident(ident);
                 vis.visit_generics(generics);
                 vis.visit_variant_data(variant_data);
             }
@@ -1326,22 +1338,28 @@ impl WalkItemKind for ItemKind {
                     vis.flat_map_assoc_item(item, AssocCtxt::Impl { of_trait: of_trait.is_some() })
                 });
             }
-            ItemKind::Trait(box Trait { safety, is_auto: _, generics, bounds, items }) => {
+            ItemKind::Trait(box Trait { safety, is_auto: _, ident, generics, bounds, items }) => {
                 visit_safety(vis, safety);
+                vis.visit_ident(ident);
                 vis.visit_generics(generics);
                 visit_bounds(vis, bounds, BoundKind::Bound);
                 items.flat_map_in_place(|item| vis.flat_map_assoc_item(item, AssocCtxt::Trait));
             }
-            ItemKind::TraitAlias(generics, bounds) => {
+            ItemKind::TraitAlias(ident, generics, bounds) => {
+                vis.visit_ident(ident);
                 vis.visit_generics(generics);
                 visit_bounds(vis, bounds, BoundKind::Bound);
             }
             ItemKind::MacCall(m) => vis.visit_mac_call(m),
-            ItemKind::MacroDef(def) => vis.visit_macro_def(def),
+            ItemKind::MacroDef(ident, def) => {
+                vis.visit_ident(ident);
+                vis.visit_macro_def(def)
+            }
             ItemKind::Delegation(box Delegation {
                 id,
                 qself,
                 path,
+                ident,
                 rename,
                 body,
                 from_glob: _,
@@ -1349,6 +1367,7 @@ impl WalkItemKind for ItemKind {
                 vis.visit_id(id);
                 vis.visit_qself(qself);
                 vis.visit_path(path);
+                vis.visit_ident(ident);
                 if let Some(rename) = rename {
                     vis.visit_ident(rename);
                 }
@@ -1381,7 +1400,6 @@ impl WalkItemKind for AssocItemKind {
         &mut self,
         span: Span,
         id: NodeId,
-        ident: &mut Ident,
         visibility: &mut Visibility,
         ctxt: Self::Ctxt,
         visitor: &mut impl MutVisitor,
@@ -1391,20 +1409,18 @@ impl WalkItemKind for AssocItemKind {
                 walk_const_item(visitor, item);
             }
             AssocItemKind::Fn(func) => {
-                visitor.visit_fn(
-                    FnKind::Fn(FnCtxt::Assoc(ctxt), ident, visibility, &mut *func),
-                    span,
-                    id,
-                );
+                visitor.visit_fn(FnKind::Fn(FnCtxt::Assoc(ctxt), visibility, &mut *func), span, id);
             }
             AssocItemKind::Type(box TyAlias {
                 defaultness,
+                ident,
                 generics,
                 where_clauses,
                 bounds,
                 ty,
             }) => {
                 visit_defaultness(visitor, defaultness);
+                visitor.visit_ident(ident);
                 visitor.visit_generics(generics);
                 visit_bounds(visitor, bounds, BoundKind::Bound);
                 visit_opt(ty, |ty| visitor.visit_ty(ty));
@@ -1415,6 +1431,7 @@ impl WalkItemKind for AssocItemKind {
                 id,
                 qself,
                 path,
+                ident,
                 rename,
                 body,
                 from_glob: _,
@@ -1422,6 +1439,7 @@ impl WalkItemKind for AssocItemKind {
                 visitor.visit_id(id);
                 visitor.visit_qself(qself);
                 visitor.visit_path(path);
+                visitor.visit_ident(ident);
                 if let Some(rename) = rename {
                     visitor.visit_ident(rename);
                 }
@@ -1449,8 +1467,9 @@ impl WalkItemKind for AssocItemKind {
 }
 
 fn walk_const_item<T: MutVisitor>(vis: &mut T, item: &mut ConstItem) {
-    let ConstItem { defaultness, generics, ty, expr, define_opaque } = item;
+    let ConstItem { defaultness, ident, generics, ty, expr, define_opaque } = item;
     visit_defaultness(vis, defaultness);
+    vis.visit_ident(ident);
     vis.visit_generics(generics);
     vis.visit_ty(ty);
     visit_opt(expr, |expr| vis.visit_expr(expr));
@@ -1487,12 +1506,11 @@ fn walk_item_ctxt<K: WalkItemKind>(
     item: &mut P<Item<K>>,
     ctxt: K::Ctxt,
 ) {
-    let Item { ident, attrs, id, kind, vis, span, tokens } = item.deref_mut();
+    let Item { attrs, id, kind, vis, span, tokens } = item.deref_mut();
     visitor.visit_id(id);
     visit_attrs(visitor, attrs);
     visitor.visit_vis(vis);
-    visitor.visit_ident(ident);
-    kind.walk(*span, *id, ident, vis, ctxt, visitor);
+    kind.walk(*span, *id, vis, ctxt, visitor);
     visit_lazy_tts(visitor, tokens);
     visitor.visit_span(span);
 }
@@ -1525,38 +1543,37 @@ impl WalkItemKind for ForeignItemKind {
         &mut self,
         span: Span,
         id: NodeId,
-        ident: &mut Ident,
         visibility: &mut Visibility,
         _ctxt: Self::Ctxt,
         visitor: &mut impl MutVisitor,
     ) {
         match self {
             ForeignItemKind::Static(box StaticItem {
+                ident,
                 ty,
                 mutability: _,
                 expr,
                 safety: _,
                 define_opaque,
             }) => {
+                visitor.visit_ident(ident);
                 visitor.visit_ty(ty);
                 visit_opt(expr, |expr| visitor.visit_expr(expr));
                 walk_define_opaques(visitor, define_opaque);
             }
             ForeignItemKind::Fn(func) => {
-                visitor.visit_fn(
-                    FnKind::Fn(FnCtxt::Foreign, ident, visibility, &mut *func),
-                    span,
-                    id,
-                );
+                visitor.visit_fn(FnKind::Fn(FnCtxt::Foreign, visibility, &mut *func), span, id);
             }
             ForeignItemKind::TyAlias(box TyAlias {
                 defaultness,
+                ident,
                 generics,
                 where_clauses,
                 bounds,
                 ty,
             }) => {
                 visit_defaultness(visitor, defaultness);
+                visitor.visit_ident(ident);
                 visitor.visit_generics(generics);
                 visit_bounds(visitor, bounds, BoundKind::Bound);
                 visit_opt(ty, |ty| visitor.visit_ty(ty));
@@ -1984,8 +2001,7 @@ impl DummyAstNode for Item {
                 span: Default::default(),
                 tokens: Default::default(),
             },
-            ident: Ident::dummy(),
-            kind: ItemKind::ExternCrate(None),
+            kind: ItemKind::ExternCrate(None, Ident::dummy()),
             tokens: Default::default(),
         }
     }
@@ -2052,7 +2068,7 @@ impl<N: DummyAstNode, T: DummyAstNode> DummyAstNode for crate::ast_traits::AstNo
 #[derive(Debug)]
 pub enum FnKind<'a> {
     /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
-    Fn(FnCtxt, &'a mut Ident, &'a mut Visibility, &'a mut Fn),
+    Fn(FnCtxt, &'a mut Visibility, &'a mut Fn),
 
     /// E.g., `|x, y| body`.
     Closure(
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 2716601ca4f9d..1ef92ff8898ef 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -66,7 +66,7 @@ impl BoundKind {
 #[derive(Copy, Clone, Debug)]
 pub enum FnKind<'a> {
     /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
-    Fn(FnCtxt, &'a Ident, &'a Visibility, &'a Fn),
+    Fn(FnCtxt, &'a Visibility, &'a Fn),
 
     /// E.g., `|x, y| body`.
     Closure(&'a ClosureBinder, &'a Option<CoroutineKind>, &'a FnDecl, &'a Expr),
@@ -75,21 +75,21 @@ pub enum FnKind<'a> {
 impl<'a> FnKind<'a> {
     pub fn header(&self) -> Option<&'a FnHeader> {
         match *self {
-            FnKind::Fn(_, _, _, Fn { sig, .. }) => Some(&sig.header),
+            FnKind::Fn(_, _, Fn { sig, .. }) => Some(&sig.header),
             FnKind::Closure(..) => None,
         }
     }
 
     pub fn ident(&self) -> Option<&Ident> {
         match self {
-            FnKind::Fn(_, ident, ..) => Some(ident),
+            FnKind::Fn(_, _, Fn { ident, .. }) => Some(ident),
             _ => None,
         }
     }
 
     pub fn decl(&self) -> &'a FnDecl {
         match self {
-            FnKind::Fn(_, _, _, Fn { sig, .. }) => &sig.decl,
+            FnKind::Fn(_, _, Fn { sig, .. }) => &sig.decl,
             FnKind::Closure(_, _, decl, _) => decl,
         }
     }
@@ -118,7 +118,6 @@ pub trait WalkItemKind {
         &'a self,
         span: Span,
         id: NodeId,
-        ident: &'a Ident,
         visibility: &'a Visibility,
         ctxt: Self::Ctxt,
         visitor: &mut V,
@@ -364,63 +363,72 @@ impl WalkItemKind for ItemKind {
         &'a self,
         span: Span,
         id: NodeId,
-        ident: &'a Ident,
         vis: &'a Visibility,
         _ctxt: Self::Ctxt,
         visitor: &mut V,
     ) -> V::Result {
         match self {
-            ItemKind::ExternCrate(_rename) => {}
+            ItemKind::ExternCrate(_rename, ident) => try_visit!(visitor.visit_ident(ident)),
             ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)),
             ItemKind::Static(box StaticItem {
+                ident,
                 ty,
                 safety: _,
                 mutability: _,
                 expr,
                 define_opaque,
             }) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_ty(ty));
                 visit_opt!(visitor, visit_expr, expr);
                 try_visit!(walk_define_opaques(visitor, define_opaque));
             }
             ItemKind::Const(box ConstItem {
                 defaultness: _,
+                ident,
                 generics,
                 ty,
                 expr,
                 define_opaque,
             }) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_generics(generics));
                 try_visit!(visitor.visit_ty(ty));
                 visit_opt!(visitor, visit_expr, expr);
                 try_visit!(walk_define_opaques(visitor, define_opaque));
             }
             ItemKind::Fn(func) => {
-                let kind = FnKind::Fn(FnCtxt::Free, ident, vis, &*func);
+                let kind = FnKind::Fn(FnCtxt::Free, vis, &*func);
                 try_visit!(visitor.visit_fn(kind, span, id));
             }
-            ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
-                ModKind::Loaded(items, _inline, _inner_span, _) => {
-                    walk_list!(visitor, visit_item, items);
+            ItemKind::Mod(_unsafety, ident, mod_kind) => {
+                try_visit!(visitor.visit_ident(ident));
+                match mod_kind {
+                    ModKind::Loaded(items, _inline, _inner_span, _) => {
+                        walk_list!(visitor, visit_item, items);
+                    }
+                    ModKind::Unloaded => {}
                 }
-                ModKind::Unloaded => {}
-            },
+            }
             ItemKind::ForeignMod(ForeignMod { extern_span: _, safety: _, abi: _, items }) => {
                 walk_list!(visitor, visit_foreign_item, items);
             }
             ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)),
             ItemKind::TyAlias(box TyAlias {
                 generics,
+                ident,
                 bounds,
                 ty,
                 defaultness: _,
                 where_clauses: _,
             }) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_generics(generics));
                 walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
                 visit_opt!(visitor, visit_ty, ty);
             }
-            ItemKind::Enum(enum_definition, generics) => {
+            ItemKind::Enum(ident, enum_definition, generics) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_generics(generics));
                 try_visit!(visitor.visit_enum_def(enum_definition));
             }
@@ -444,32 +452,47 @@ impl WalkItemKind for ItemKind {
                     AssocCtxt::Impl { of_trait: of_trait.is_some() }
                 );
             }
-            ItemKind::Struct(struct_definition, generics)
-            | ItemKind::Union(struct_definition, generics) => {
+            ItemKind::Struct(ident, struct_definition, generics)
+            | ItemKind::Union(ident, struct_definition, generics) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_generics(generics));
                 try_visit!(visitor.visit_variant_data(struct_definition));
             }
-            ItemKind::Trait(box Trait { safety: _, is_auto: _, generics, bounds, items }) => {
+            ItemKind::Trait(box Trait {
+                safety: _,
+                is_auto: _,
+                ident,
+                generics,
+                bounds,
+                items,
+            }) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_generics(generics));
                 walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits);
                 walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
             }
-            ItemKind::TraitAlias(generics, bounds) => {
+            ItemKind::TraitAlias(ident, generics, bounds) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_generics(generics));
                 walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
             }
             ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
-            ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, id)),
+            ItemKind::MacroDef(ident, ts) => {
+                try_visit!(visitor.visit_ident(ident));
+                try_visit!(visitor.visit_mac_def(ts, id))
+            }
             ItemKind::Delegation(box Delegation {
                 id,
                 qself,
                 path,
+                ident,
                 rename,
                 body,
                 from_glob: _,
             }) => {
                 try_visit!(visitor.visit_qself(qself));
                 try_visit!(visitor.visit_path(path, *id));
+                try_visit!(visitor.visit_ident(ident));
                 visit_opt!(visitor, visit_ident, rename);
                 visit_opt!(visitor, visit_block, body);
             }
@@ -743,34 +766,37 @@ impl WalkItemKind for ForeignItemKind {
         &'a self,
         span: Span,
         id: NodeId,
-        ident: &'a Ident,
         vis: &'a Visibility,
         _ctxt: Self::Ctxt,
         visitor: &mut V,
     ) -> V::Result {
         match self {
             ForeignItemKind::Static(box StaticItem {
+                ident,
                 ty,
                 mutability: _,
                 expr,
                 safety: _,
                 define_opaque,
             }) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_ty(ty));
                 visit_opt!(visitor, visit_expr, expr);
                 try_visit!(walk_define_opaques(visitor, define_opaque));
             }
             ForeignItemKind::Fn(func) => {
-                let kind = FnKind::Fn(FnCtxt::Foreign, ident, vis, &*func);
+                let kind = FnKind::Fn(FnCtxt::Foreign, vis, &*func);
                 try_visit!(visitor.visit_fn(kind, span, id));
             }
             ForeignItemKind::TyAlias(box TyAlias {
                 generics,
+                ident,
                 bounds,
                 ty,
                 defaultness: _,
                 where_clauses: _,
             }) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_generics(generics));
                 walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
                 visit_opt!(visitor, visit_ty, ty);
@@ -917,10 +943,10 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
     match kind {
         FnKind::Fn(
             _ctxt,
-            _ident,
             _vis,
             Fn {
                 defaultness: _,
+                ident,
                 sig: FnSig { header, decl, span: _ },
                 generics,
                 contract,
@@ -928,7 +954,8 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
                 define_opaque,
             },
         ) => {
-            // Identifier and visibility are visited as a part of the item.
+            // Visibility is visited as a part of the item.
+            try_visit!(visitor.visit_ident(ident));
             try_visit!(visitor.visit_fn_header(header));
             try_visit!(visitor.visit_generics(generics));
             try_visit!(visitor.visit_fn_decl(decl));
@@ -952,7 +979,6 @@ impl WalkItemKind for AssocItemKind {
         &'a self,
         span: Span,
         id: NodeId,
-        ident: &'a Ident,
         vis: &'a Visibility,
         ctxt: Self::Ctxt,
         visitor: &mut V,
@@ -960,28 +986,32 @@ impl WalkItemKind for AssocItemKind {
         match self {
             AssocItemKind::Const(box ConstItem {
                 defaultness: _,
+                ident,
                 generics,
                 ty,
                 expr,
                 define_opaque,
             }) => {
+                try_visit!(visitor.visit_ident(ident));
                 try_visit!(visitor.visit_generics(generics));
                 try_visit!(visitor.visit_ty(ty));
                 visit_opt!(visitor, visit_expr, expr);
                 try_visit!(walk_define_opaques(visitor, define_opaque));
             }
             AssocItemKind::Fn(func) => {
-                let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, vis, &*func);
+                let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), vis, &*func);
                 try_visit!(visitor.visit_fn(kind, span, id));
             }
             AssocItemKind::Type(box TyAlias {
                 generics,
+                ident,
                 bounds,
                 ty,
                 defaultness: _,
                 where_clauses: _,
             }) => {
                 try_visit!(visitor.visit_generics(generics));
+                try_visit!(visitor.visit_ident(ident));
                 walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
                 visit_opt!(visitor, visit_ty, ty);
             }
@@ -992,12 +1022,14 @@ impl WalkItemKind for AssocItemKind {
                 id,
                 qself,
                 path,
+                ident,
                 rename,
                 body,
                 from_glob: _,
             }) => {
                 try_visit!(visitor.visit_qself(qself));
                 try_visit!(visitor.visit_path(path, *id));
+                try_visit!(visitor.visit_ident(ident));
                 visit_opt!(visitor, visit_ident, rename);
                 visit_opt!(visitor, visit_block, body);
             }
@@ -1039,11 +1071,10 @@ fn walk_item_ctxt<'a, V: Visitor<'a>, K: WalkItemKind>(
     item: &'a Item<K>,
     ctxt: K::Ctxt,
 ) -> V::Result {
-    let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item;
+    let Item { id, span, vis, attrs, kind, tokens: _ } = item;
     walk_list!(visitor, visit_attribute, attrs);
     try_visit!(visitor.visit_vis(vis));
-    try_visit!(visitor.visit_ident(ident));
-    try_visit!(kind.walk(*span, *id, ident, vis, ctxt, visitor));
+    try_visit!(kind.walk(*span, *id, vis, ctxt, visitor));
     V::Result::output()
 }
 
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index f7640c602d6fd..9899ee03a513a 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -56,6 +56,7 @@ use crate::{AllowReturnTypeNotation, ImplTraitPosition, ResolverAstLoweringExt};
 pub(crate) struct DelegationResults<'hir> {
     pub body_id: hir::BodyId,
     pub sig: hir::FnSig<'hir>,
+    pub ident: Ident,
     pub generics: &'hir hir::Generics<'hir>,
 }
 
@@ -104,9 +105,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 let decl = self.lower_delegation_decl(sig_id, param_count, c_variadic, span);
                 let sig = self.lower_delegation_sig(sig_id, decl, span);
                 let body_id = self.lower_delegation_body(delegation, param_count, span);
-
+                let ident = self.lower_ident(delegation.ident);
                 let generics = self.lower_delegation_generics(span);
-                DelegationResults { body_id, sig, generics }
+                DelegationResults { body_id, sig, ident, generics }
             }
             Err(err) => self.generate_delegation_error(err, span),
         }
@@ -405,8 +406,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let header = self.generate_header_error();
         let sig = hir::FnSig { decl, header, span };
 
+        let ident = Ident::dummy();
         let body_id = self.lower_body(|this| (&[], this.mk_expr(hir::ExprKind::Err(err), span)));
-        DelegationResults { generics, body_id, sig }
+        DelegationResults { ident, generics, body_id, sig }
     }
 
     fn generate_header_error(&self) -> hir::FnHeader {
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 43bf951eddc6c..28f596ac0926d 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -107,7 +107,6 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
     }
 
     fn lower_foreign_item(&mut self, item: &ForeignItem) {
-        debug_assert_ne!(item.ident.name, kw::Empty);
         self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item)))
     }
 }
@@ -151,7 +150,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let vis_span = self.lower_span(i.vis.span);
         let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
         let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
-        let kind = self.lower_item_kind(i.span, i.id, hir_id, i.ident, attrs, vis_span, &i.kind);
+        let kind = self.lower_item_kind(i.span, i.id, hir_id, attrs, vis_span, &i.kind);
         let item = hir::Item {
             owner_id: hir_id.expect_owner(),
             kind,
@@ -166,41 +165,44 @@ impl<'hir> LoweringContext<'_, 'hir> {
         span: Span,
         id: NodeId,
         hir_id: hir::HirId,
-        ident: Ident,
         attrs: &'hir [hir::Attribute],
         vis_span: Span,
         i: &ItemKind,
     ) -> hir::ItemKind<'hir> {
         match i {
-            ItemKind::ExternCrate(orig_name) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::ExternCrate(orig_name, ident) => {
+                let ident = self.lower_ident(*ident);
                 hir::ItemKind::ExternCrate(*orig_name, ident)
             }
             ItemKind::Use(use_tree) => {
-                debug_assert_eq!(ident.name, kw::Empty);
                 // Start with an empty prefix.
                 let prefix = Path { segments: ThinVec::new(), span: use_tree.span, tokens: None };
 
                 self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs)
             }
             ItemKind::Static(box ast::StaticItem {
+                ident,
                 ty: t,
                 safety: _,
                 mutability: m,
                 expr: e,
                 define_opaque,
             }) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+                let ident = self.lower_ident(*ident);
                 let (ty, body_id) =
                     self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
                 self.lower_define_opaque(hir_id, define_opaque);
                 hir::ItemKind::Static(ident, ty, *m, body_id)
             }
-            ItemKind::Const(box ast::ConstItem { generics, ty, expr, define_opaque, .. }) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::Const(box ast::ConstItem {
+                ident,
+                generics,
+                ty,
+                expr,
+                define_opaque,
+                ..
+            }) => {
+                let ident = self.lower_ident(*ident);
                 let (generics, (ty, body_id)) = self.lower_generics(
                     generics,
                     id,
@@ -214,13 +216,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
             ItemKind::Fn(box Fn {
                 sig: FnSig { decl, header, span: fn_sig_span },
+                ident,
                 generics,
                 body,
                 contract,
                 define_opaque,
                 ..
             }) => {
-                debug_assert_ne!(ident.name, kw::Empty);
                 self.with_new_scopes(*fn_sig_span, |this| {
                     // Note: we don't need to change the return type from `T` to
                     // `impl Future<Output = T>` here because lower_body
@@ -248,7 +250,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         span: this.lower_span(*fn_sig_span),
                     };
                     this.lower_define_opaque(hir_id, define_opaque);
-                    let ident = this.lower_ident(ident);
+                    let ident = this.lower_ident(*ident);
                     hir::ItemKind::Fn {
                         ident,
                         sig,
@@ -258,9 +260,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     }
                 })
             }
-            ItemKind::Mod(_, mod_kind) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::Mod(_, ident, mod_kind) => {
+                let ident = self.lower_ident(*ident);
                 match mod_kind {
                     ModKind::Loaded(items, _, spans, _) => {
                         hir::ItemKind::Mod(ident, self.lower_mod(items, spans))
@@ -268,24 +269,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     ModKind::Unloaded => panic!("`mod` items should have been loaded by now"),
                 }
             }
-            ItemKind::ForeignMod(fm) => {
-                debug_assert_eq!(ident.name, kw::Empty);
-                hir::ItemKind::ForeignMod {
-                    abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)),
-                    items: self
-                        .arena
-                        .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
-                }
-            }
+            ItemKind::ForeignMod(fm) => hir::ItemKind::ForeignMod {
+                abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)),
+                items: self
+                    .arena
+                    .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
+            },
             ItemKind::GlobalAsm(asm) => {
-                debug_assert_eq!(ident.name, kw::Empty);
                 let asm = self.lower_inline_asm(span, asm);
                 let fake_body =
                     self.lower_body(|this| (&[], this.expr(span, hir::ExprKind::InlineAsm(asm))));
                 hir::ItemKind::GlobalAsm { asm, fake_body }
             }
-            ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
-                debug_assert_ne!(ident.name, kw::Empty);
+            ItemKind::TyAlias(box TyAlias { ident, generics, where_clauses, ty, .. }) => {
                 // We lower
                 //
                 // type Foo = impl Trait
@@ -294,7 +290,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 //
                 // type Foo = Foo1
                 // opaque type Foo1: Trait
-                let ident = self.lower_ident(ident);
+                let ident = self.lower_ident(*ident);
                 let mut generics = generics.clone();
                 add_ty_alias_where_clause(&mut generics, *where_clauses, true);
                 let (generics, ty) = self.lower_generics(
@@ -322,9 +318,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 hir::ItemKind::TyAlias(ident, ty, generics)
             }
-            ItemKind::Enum(enum_definition, generics) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::Enum(ident, enum_definition, generics) => {
+                let ident = self.lower_ident(*ident);
                 let (generics, variants) = self.lower_generics(
                     generics,
                     id,
@@ -337,9 +332,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 hir::ItemKind::Enum(ident, hir::EnumDef { variants }, generics)
             }
-            ItemKind::Struct(struct_def, generics) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::Struct(ident, struct_def, generics) => {
+                let ident = self.lower_ident(*ident);
                 let (generics, struct_def) = self.lower_generics(
                     generics,
                     id,
@@ -348,9 +342,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 hir::ItemKind::Struct(ident, struct_def, generics)
             }
-            ItemKind::Union(vdata, generics) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::Union(ident, vdata, generics) => {
+                let ident = self.lower_ident(*ident);
                 let (generics, vdata) = self.lower_generics(
                     generics,
                     id,
@@ -369,7 +362,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 self_ty: ty,
                 items: impl_items,
             }) => {
-                debug_assert_eq!(ident.name, kw::Empty);
                 // Lower the "impl header" first. This ordering is important
                 // for in-band lifetimes! Consider `'a` here:
                 //
@@ -435,9 +427,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     items: new_impl_items,
                 }))
             }
-            ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::Trait(box Trait { is_auto, safety, ident, generics, bounds, items }) => {
+                let ident = self.lower_ident(*ident);
                 let (generics, (safety, items, bounds)) = self.lower_generics(
                     generics,
                     id,
@@ -456,9 +447,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 hir::ItemKind::Trait(*is_auto, safety, ident, generics, bounds, items)
             }
-            ItemKind::TraitAlias(generics, bounds) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::TraitAlias(ident, generics, bounds) => {
+                let ident = self.lower_ident(*ident);
                 let (generics, bounds) = self.lower_generics(
                     generics,
                     id,
@@ -472,9 +462,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 hir::ItemKind::TraitAlias(ident, generics, bounds)
             }
-            ItemKind::MacroDef(MacroDef { body, macro_rules }) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
+            ItemKind::MacroDef(ident, MacroDef { body, macro_rules }) => {
+                let ident = self.lower_ident(*ident);
                 let body = P(self.lower_delim_args(body));
                 let def_id = self.local_def_id(id);
                 let def_kind = self.tcx.def_kind(def_id);
@@ -488,11 +477,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 hir::ItemKind::Macro(ident, macro_def, macro_kind)
             }
             ItemKind::Delegation(box delegation) => {
-                debug_assert_ne!(ident.name, kw::Empty);
-                let ident = self.lower_ident(ident);
                 let delegation_results = self.lower_delegation(delegation, id, false);
                 hir::ItemKind::Fn {
-                    ident,
+                    ident: delegation_results.ident,
                     sig: delegation_results.sig,
                     generics: delegation_results.generics,
                     body: delegation_results.body_id,
@@ -649,61 +636,64 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
         let owner_id = hir_id.expect_owner();
         let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
-        let item = hir::ForeignItem {
-            owner_id,
-            ident: self.lower_ident(i.ident),
-            kind: match &i.kind {
-                ForeignItemKind::Fn(box Fn { sig, generics, define_opaque, .. }) => {
-                    let fdec = &sig.decl;
-                    let itctx = ImplTraitContext::Universal;
-                    let (generics, (decl, fn_args)) =
-                        self.lower_generics(generics, i.id, itctx, |this| {
-                            (
-                                // Disallow `impl Trait` in foreign items.
-                                this.lower_fn_decl(
-                                    fdec,
-                                    i.id,
-                                    sig.span,
-                                    FnDeclKind::ExternFn,
-                                    None,
-                                ),
-                                this.lower_fn_params_to_names(fdec),
-                            )
-                        });
+        let (ident, kind) = match &i.kind {
+            ForeignItemKind::Fn(box Fn { sig, ident, generics, define_opaque, .. }) => {
+                let fdec = &sig.decl;
+                let itctx = ImplTraitContext::Universal;
+                let (generics, (decl, fn_args)) =
+                    self.lower_generics(generics, i.id, itctx, |this| {
+                        (
+                            // Disallow `impl Trait` in foreign items.
+                            this.lower_fn_decl(fdec, i.id, sig.span, FnDeclKind::ExternFn, None),
+                            this.lower_fn_params_to_names(fdec),
+                        )
+                    });
 
-                    // Unmarked safety in unsafe block defaults to unsafe.
-                    let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs);
+                // Unmarked safety in unsafe block defaults to unsafe.
+                let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs);
 
-                    if define_opaque.is_some() {
-                        self.dcx().span_err(i.span, "foreign functions cannot define opaque types");
-                    }
+                if define_opaque.is_some() {
+                    self.dcx().span_err(i.span, "foreign functions cannot define opaque types");
+                }
 
+                (
+                    ident,
                     hir::ForeignItemKind::Fn(
                         hir::FnSig { header, decl, span: self.lower_span(sig.span) },
                         fn_args,
                         generics,
-                    )
-                }
-                ForeignItemKind::Static(box StaticItem {
-                    ty,
-                    mutability,
-                    expr: _,
-                    safety,
-                    define_opaque,
-                }) => {
-                    let ty = self
-                        .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
-                    let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
-
-                    if define_opaque.is_some() {
-                        self.dcx().span_err(i.span, "foreign statics cannot define opaque types");
-                    }
+                    ),
+                )
+            }
+            ForeignItemKind::Static(box StaticItem {
+                ident,
+                ty,
+                mutability,
+                expr: _,
+                safety,
+                define_opaque,
+            }) => {
+                let ty =
+                    self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
+                let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
 
-                    hir::ForeignItemKind::Static(ty, *mutability, safety)
+                // njn: where for this?
+                if define_opaque.is_some() {
+                    self.dcx().span_err(i.span, "foreign statics cannot define opaque types");
                 }
-                ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
-                ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
-            },
+
+                (ident, hir::ForeignItemKind::Static(ty, *mutability, safety))
+            }
+            ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => {
+                (ident, hir::ForeignItemKind::Type)
+            }
+            ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
+        };
+
+        let item = hir::ForeignItem {
+            owner_id,
+            ident: self.lower_ident(*ident),
+            kind,
             vis_span: self.lower_span(i.vis.span),
             span: self.lower_span(i.span),
         };
@@ -713,7 +703,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef {
         hir::ForeignItemRef {
             id: hir::ForeignItemId { owner_id: self.owner_id(i.id) },
-            ident: self.lower_ident(i.ident),
+            // `unwrap` is safe because `ForeignItemKind::MacCall` is the only foreign item kind
+            // without an identifier and it cannot reach here.
+            ident: self.lower_ident(i.kind.ident().unwrap()),
             span: self.lower_span(i.span),
         }
     }
@@ -800,13 +792,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
-        debug_assert_ne!(i.ident.name, kw::Empty);
         let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
         let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
         let trait_item_def_id = hir_id.expect_owner();
 
-        let (generics, kind, has_default) = match &i.kind {
-            AssocItemKind::Const(box ConstItem { generics, ty, expr, define_opaque, .. }) => {
+        let (ident, generics, kind, has_default) = match &i.kind {
+            AssocItemKind::Const(box ConstItem {
+                ident,
+                generics,
+                ty,
+                expr,
+                define_opaque,
+                ..
+            }) => {
                 let (generics, kind) = self.lower_generics(
                     generics,
                     i.id,
@@ -831,9 +829,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     }
                 }
 
-                (generics, kind, expr.is_some())
+                (*ident, generics, kind, expr.is_some())
             }
-            AssocItemKind::Fn(box Fn { sig, generics, body: None, define_opaque, .. }) => {
+            AssocItemKind::Fn(box Fn {
+                sig, ident, generics, body: None, define_opaque, ..
+            }) => {
                 // FIXME(contracts): Deny contract here since it won't apply to
                 // any impl method or callees.
                 let names = self.lower_fn_params_to_names(&sig.decl);
@@ -851,10 +851,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         "only trait methods with default bodies can define opaque types",
                     );
                 }
-                (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
+                (
+                    *ident,
+                    generics,
+                    hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)),
+                    false,
+                )
             }
             AssocItemKind::Fn(box Fn {
                 sig,
+                ident,
                 generics,
                 body: Some(body),
                 contract,
@@ -880,9 +886,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     attrs,
                 );
                 self.lower_define_opaque(hir_id, &define_opaque);
-                (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
+                (
+                    *ident,
+                    generics,
+                    hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)),
+                    true,
+                )
             }
-            AssocItemKind::Type(box TyAlias { generics, where_clauses, bounds, ty, .. }) => {
+            AssocItemKind::Type(box TyAlias {
+                ident, generics, where_clauses, bounds, ty, ..
+            }) => {
                 let mut generics = generics.clone();
                 add_ty_alias_where_clause(&mut generics, *where_clauses, false);
                 let (generics, kind) = self.lower_generics(
@@ -905,7 +918,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         )
                     },
                 );
-                (generics, kind, ty.is_some())
+                (*ident, generics, kind, ty.is_some())
             }
             AssocItemKind::Delegation(box delegation) => {
                 let delegation_results = self.lower_delegation(delegation, i.id, false);
@@ -913,7 +926,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     delegation_results.sig,
                     hir::TraitFn::Provided(delegation_results.body_id),
                 );
-                (delegation_results.generics, item_kind, true)
+                (delegation.ident, delegation_results.generics, item_kind, true)
             }
             AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
                 panic!("macros should have been expanded by now")
@@ -922,7 +935,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         let item = hir::TraitItem {
             owner_id: trait_item_def_id,
-            ident: self.lower_ident(i.ident),
+            ident: self.lower_ident(ident),
             generics,
             kind,
             span: self.lower_span(i.span),
@@ -932,15 +945,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
-        let kind = match &i.kind {
-            AssocItemKind::Const(..) => hir::AssocItemKind::Const,
-            AssocItemKind::Type(..) => hir::AssocItemKind::Type,
-            AssocItemKind::Fn(box Fn { sig, .. }) => {
-                hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
+        let (ident, kind) = match &i.kind {
+            AssocItemKind::Const(box ConstItem { ident, .. }) => {
+                (*ident, hir::AssocItemKind::Const)
             }
-            AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
-                has_self: self.delegatee_is_method(i.id, delegation.id, i.span, false),
-            },
+            AssocItemKind::Type(box TyAlias { ident, .. }) => (*ident, hir::AssocItemKind::Type),
+            AssocItemKind::Fn(box Fn { ident, sig, .. }) => {
+                (*ident, hir::AssocItemKind::Fn { has_self: sig.decl.has_self() })
+            }
+            AssocItemKind::Delegation(box delegation) => (
+                delegation.ident,
+                hir::AssocItemKind::Fn {
+                    has_self: self.delegatee_is_method(i.id, delegation.id, i.span, false),
+                },
+            ),
             AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
                 panic!("macros should have been expanded by now")
             }
@@ -948,7 +966,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let id = hir::TraitItemId { owner_id: self.owner_id(i.id) };
         hir::TraitItemRef {
             id,
-            ident: self.lower_ident(i.ident),
+            ident: self.lower_ident(ident),
             span: self.lower_span(i.span),
             kind,
         }
@@ -964,16 +982,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
         i: &AssocItem,
         is_in_trait_impl: bool,
     ) -> &'hir hir::ImplItem<'hir> {
-        debug_assert_ne!(i.ident.name, kw::Empty);
         // Since `default impl` is not yet implemented, this is always true in impls.
         let has_value = true;
         let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
         let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
         let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
 
-        let (generics, kind) = match &i.kind {
-            AssocItemKind::Const(box ConstItem { generics, ty, expr, define_opaque, .. }) => self
-                .lower_generics(
+        let (ident, (generics, kind)) = match &i.kind {
+            AssocItemKind::Const(box ConstItem {
+                ident,
+                generics,
+                ty,
+                expr,
+                define_opaque,
+                ..
+            }) => (
+                *ident,
+                self.lower_generics(
                     generics,
                     i.id,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
@@ -982,11 +1007,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
                             .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
                         let body = this.lower_const_body(i.span, expr.as_deref());
                         this.lower_define_opaque(hir_id, &define_opaque);
-
                         hir::ImplItemKind::Const(ty, body)
                     },
                 ),
-            AssocItemKind::Fn(box Fn { sig, generics, body, contract, define_opaque, .. }) => {
+            ),
+            AssocItemKind::Fn(box Fn {
+                sig,
+                ident,
+                generics,
+                body,
+                contract,
+                define_opaque,
+                ..
+            }) => {
                 let body_id = self.lower_maybe_coroutine_body(
                     sig.span,
                     i.span,
@@ -1007,44 +1040,50 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 self.lower_define_opaque(hir_id, &define_opaque);
 
-                (generics, hir::ImplItemKind::Fn(sig, body_id))
+                (*ident, (generics, hir::ImplItemKind::Fn(sig, body_id)))
             }
-            AssocItemKind::Type(box TyAlias { generics, where_clauses, ty, .. }) => {
+            AssocItemKind::Type(box TyAlias { ident, generics, where_clauses, ty, .. }) => {
                 let mut generics = generics.clone();
                 add_ty_alias_where_clause(&mut generics, *where_clauses, false);
-                self.lower_generics(
-                    &generics,
-                    i.id,
-                    ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
-                    |this| match ty {
-                        None => {
-                            let guar = this.dcx().span_delayed_bug(
-                                i.span,
-                                "expected to lower associated type, but it was missing",
-                            );
-                            let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar)));
-                            hir::ImplItemKind::Type(ty)
-                        }
-                        Some(ty) => {
-                            let ty = this.lower_ty(
-                                ty,
-                                ImplTraitContext::OpaqueTy {
-                                    origin: hir::OpaqueTyOrigin::TyAlias {
-                                        parent: this.local_def_id(i.id),
-                                        in_assoc_ty: true,
+                (
+                    *ident,
+                    self.lower_generics(
+                        &generics,
+                        i.id,
+                        ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
+                        |this| match ty {
+                            None => {
+                                let guar = this.dcx().span_delayed_bug(
+                                    i.span,
+                                    "expected to lower associated type, but it was missing",
+                                );
+                                let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar)));
+                                hir::ImplItemKind::Type(ty)
+                            }
+                            Some(ty) => {
+                                let ty = this.lower_ty(
+                                    ty,
+                                    ImplTraitContext::OpaqueTy {
+                                        origin: hir::OpaqueTyOrigin::TyAlias {
+                                            parent: this.local_def_id(i.id),
+                                            in_assoc_ty: true,
+                                        },
                                     },
-                                },
-                            );
-                            hir::ImplItemKind::Type(ty)
-                        }
-                    },
+                                );
+                                hir::ImplItemKind::Type(ty)
+                            }
+                        },
+                    ),
                 )
             }
             AssocItemKind::Delegation(box delegation) => {
                 let delegation_results = self.lower_delegation(delegation, i.id, is_in_trait_impl);
                 (
-                    delegation_results.generics,
-                    hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
+                    delegation.ident,
+                    (
+                        delegation_results.generics,
+                        hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
+                    ),
                 )
             }
             AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
@@ -1054,7 +1093,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         let item = hir::ImplItem {
             owner_id: hir_id.expect_owner(),
-            ident: self.lower_ident(i.ident),
+            ident: self.lower_ident(ident),
             generics,
             kind,
             vis_span: self.lower_span(i.vis.span),
@@ -1067,7 +1106,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_impl_item_ref(&mut self, i: &AssocItem, is_in_trait_impl: bool) -> hir::ImplItemRef {
         hir::ImplItemRef {
             id: hir::ImplItemId { owner_id: self.owner_id(i.id) },
-            ident: self.lower_ident(i.ident),
+            // `unwrap` is safe because `AssocItemKind::{MacCall,DelegationMac}` are the only
+            // assoc item kinds without an identifier and they cannot reach here.
+            ident: self.lower_ident(i.kind.ident().unwrap()),
             span: self.lower_span(i.span),
             kind: match &i.kind {
                 AssocItemKind::Const(..) => hir::AssocItemKind::Const,
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index da739b0e4532b..839d5d3bb954d 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -607,7 +607,7 @@ impl<'a> AstValidator<'a> {
 
     fn deny_items(&self, trait_items: &[P<AssocItem>], ident: Span) {
         if !trait_items.is_empty() {
-            let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect();
+            let spans: Vec<_> = trait_items.iter().map(|i| i.kind.ident().unwrap().span).collect();
             let total = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span);
             self.dcx().emit_err(errors::AutoTraitItems { spans, total, ident });
         }
@@ -817,8 +817,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             self.has_proc_macro_decls = true;
         }
 
-        if attr::contains_name(&item.attrs, sym::no_mangle) {
-            self.check_nomangle_item_asciionly(item.ident, item.span);
+        if let Some(ident) = item.kind.ident()
+            && attr::contains_name(&item.attrs, sym::no_mangle)
+        {
+            self.check_nomangle_item_asciionly(ident, item.span);
         }
 
         match &item.kind {
@@ -852,7 +854,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     }
 
                     this.visit_vis(&item.vis);
-                    this.visit_ident(&item.ident);
                     let disallowed = matches!(constness, Const::No)
                         .then(|| TildeConstReason::TraitImpl { span: item.span });
                     this.with_tilde_const(disallowed, |this| this.visit_generics(generics));
@@ -906,7 +907,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     }
 
                     this.visit_vis(&item.vis);
-                    this.visit_ident(&item.ident);
                     this.with_tilde_const(
                         Some(TildeConstReason::Impl { span: item.span }),
                         |this| this.visit_generics(generics),
@@ -918,8 +918,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 return; // Avoid visiting again.
             }
             ItemKind::Fn(
-                func
-                @ box Fn { defaultness, generics: _, sig, contract: _, body, define_opaque: _ },
+                func @ box Fn {
+                    defaultness,
+                    ident,
+                    generics: _,
+                    sig,
+                    contract: _,
+                    body,
+                    define_opaque: _,
+                },
             ) => {
                 self.check_defaultness(item.span, *defaultness);
 
@@ -949,8 +956,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 }
 
                 self.visit_vis(&item.vis);
-                self.visit_ident(&item.ident);
-                let kind = FnKind::Fn(FnCtxt::Free, &item.ident, &item.vis, &*func);
+                self.visit_ident(ident);
+                let kind = FnKind::Fn(FnCtxt::Free, &item.vis, &*func);
                 self.visit_fn(kind, item.span, item.id);
                 walk_list!(self, visit_attribute, &item.attrs);
                 return; // Avoid visiting again.
@@ -986,7 +993,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 });
                 return; // Avoid visiting again.
             }
-            ItemKind::Enum(def, _) => {
+            ItemKind::Enum(_, def, _) => {
                 for variant in &def.variants {
                     self.visibility_not_permitted(
                         &variant.vis,
@@ -1000,22 +1007,22 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     }
                 }
             }
-            ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => {
+            ItemKind::Trait(box Trait { is_auto, generics, ident, bounds, items, .. }) => {
                 let is_const_trait =
                     attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span);
                 self.with_in_trait(item.span, is_const_trait, |this| {
                     if *is_auto == IsAuto::Yes {
                         // Auto traits cannot have generics, super traits nor contain items.
-                        this.deny_generic_params(generics, item.ident.span);
-                        this.deny_super_traits(bounds, item.ident.span);
-                        this.deny_where_clause(&generics.where_clause, item.ident.span);
-                        this.deny_items(items, item.ident.span);
+                        this.deny_generic_params(generics, ident.span);
+                        this.deny_super_traits(bounds, ident.span);
+                        this.deny_where_clause(&generics.where_clause, ident.span);
+                        this.deny_items(items, ident.span);
                     }
 
                     // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
                     // context for the supertraits.
                     this.visit_vis(&item.vis);
-                    this.visit_ident(&item.ident);
+                    this.visit_ident(ident);
                     let disallowed = is_const_trait
                         .is_none()
                         .then(|| TildeConstReason::Trait { span: item.span });
@@ -1028,7 +1035,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 walk_list!(self, visit_attribute, &item.attrs);
                 return; // Avoid visiting again
             }
-            ItemKind::Mod(safety, mod_kind) => {
+            ItemKind::Mod(safety, ident, mod_kind) => {
                 if let &Safety::Unsafe(span) = safety {
                     self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" });
                 }
@@ -1036,13 +1043,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _))
                     && !attr::contains_name(&item.attrs, sym::path)
                 {
-                    self.check_mod_file_item_asciionly(item.ident);
+                    self.check_mod_file_item_asciionly(*ident);
                 }
             }
-            ItemKind::Struct(vdata, generics) => match vdata {
+            ItemKind::Struct(ident, vdata, generics) => match vdata {
                 VariantData::Struct { fields, .. } => {
                     self.visit_vis(&item.vis);
-                    self.visit_ident(&item.ident);
+                    self.visit_ident(ident);
                     self.visit_generics(generics);
                     // Permit `Anon{Struct,Union}` as field type.
                     walk_list!(self, visit_struct_field_def, fields);
@@ -1051,14 +1058,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 }
                 _ => {}
             },
-            ItemKind::Union(vdata, generics) => {
+            ItemKind::Union(ident, vdata, generics) => {
                 if vdata.fields().is_empty() {
                     self.dcx().emit_err(errors::FieldlessUnion { span: item.span });
                 }
                 match vdata {
                     VariantData::Struct { fields, .. } => {
                         self.visit_vis(&item.vis);
-                        self.visit_ident(&item.ident);
+                        self.visit_ident(ident);
                         self.visit_generics(generics);
                         // Permit `Anon{Struct,Union}` as field type.
                         walk_list!(self, visit_struct_field_def, fields);
@@ -1121,14 +1128,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
 
     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
         match &fi.kind {
-            ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => {
+            ForeignItemKind::Fn(box Fn { defaultness, ident, sig, body, .. }) => {
                 self.check_defaultness(fi.span, *defaultness);
-                self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
+                self.check_foreign_fn_bodyless(*ident, body.as_deref());
                 self.check_foreign_fn_headerless(sig.header);
-                self.check_foreign_item_ascii_only(fi.ident);
+                self.check_foreign_item_ascii_only(*ident);
             }
             ForeignItemKind::TyAlias(box TyAlias {
                 defaultness,
+                ident,
                 generics,
                 where_clauses,
                 bounds,
@@ -1136,15 +1144,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 ..
             }) => {
                 self.check_defaultness(fi.span, *defaultness);
-                self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span));
+                self.check_foreign_kind_bodyless(*ident, "type", ty.as_ref().map(|b| b.span));
                 self.check_type_no_bounds(bounds, "`extern` blocks");
                 self.check_foreign_ty_genericless(generics, where_clauses);
-                self.check_foreign_item_ascii_only(fi.ident);
+                self.check_foreign_item_ascii_only(*ident);
             }
-            ForeignItemKind::Static(box StaticItem { expr, safety, .. }) => {
+            ForeignItemKind::Static(box StaticItem { ident, safety, expr, .. }) => {
                 self.check_item_safety(fi.span, *safety);
-                self.check_foreign_kind_bodyless(fi.ident, "static", expr.as_ref().map(|b| b.span));
-                self.check_foreign_item_ascii_only(fi.ident);
+                self.check_foreign_kind_bodyless(*ident, "static", expr.as_ref().map(|b| b.span));
+                self.check_foreign_item_ascii_only(*ident);
             }
             ForeignItemKind::MacCall(..) => {}
         }
@@ -1351,7 +1359,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         }
 
         if let FnKind::Fn(
-            _,
             _,
             _,
             Fn {
@@ -1364,7 +1371,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         }
 
         // Functions without bodies cannot have patterns.
-        if let FnKind::Fn(ctxt, _, _, Fn { body: None, sig, .. }) = fk {
+        if let FnKind::Fn(ctxt, _, Fn { body: None, sig, .. }) = fk {
             Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
                 if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) {
                     if let Some(ident) = ident {
@@ -1398,15 +1405,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         .is_some();
 
         let disallowed = (!tilde_const_allowed).then(|| match fk {
-            FnKind::Fn(_, ident, _, _) => TildeConstReason::Function { ident: ident.span },
+            FnKind::Fn(_, _, f) => TildeConstReason::Function { ident: f.ident.span },
             FnKind::Closure(..) => TildeConstReason::Closure,
         });
         self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
     }
 
     fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
-        if attr::contains_name(&item.attrs, sym::no_mangle) {
-            self.check_nomangle_item_asciionly(item.ident, item.span);
+        if let Some(ident) = item.kind.ident()
+            && attr::contains_name(&item.attrs, sym::no_mangle)
+        {
+            self.check_nomangle_item_asciionly(ident, item.span);
         }
 
         if ctxt == AssocCtxt::Trait || self.outer_trait_or_trait_impl.is_none() {
@@ -1466,8 +1475,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             }
         }
 
-        if let AssocItemKind::Const(..) = item.kind {
-            self.check_item_named(item.ident, "const");
+        if let AssocItemKind::Const(ci) = &item.kind {
+            self.check_item_named(ci.ident, "const");
         }
 
         let parent_is_const =
@@ -1480,8 +1489,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     || matches!(func.sig.header.constness, Const::Yes(_)) =>
             {
                 self.visit_vis(&item.vis);
-                self.visit_ident(&item.ident);
-                let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), &item.ident, &item.vis, &*func);
+                self.visit_ident(&func.ident);
+                let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), &item.vis, &*func);
                 walk_list!(self, visit_attribute, &item.attrs);
                 self.visit_fn(kind, item.span, item.id);
             }
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index a3fcc110a1666..2fac881f4c42f 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -236,7 +236,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 gate!(&self, trait_alias, i.span, "trait aliases are experimental");
             }
 
-            ast::ItemKind::MacroDef(ast::MacroDef { macro_rules: false, .. }) => {
+            ast::ItemKind::MacroDef(_, ast::MacroDef { macro_rules: false, .. }) => {
                 let msg = "`macro` is experimental";
                 gate!(&self, decl_macro, i.span, msg);
             }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index d406a56c05da0..653bd77cc4dd8 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -28,23 +28,24 @@ impl<'a> State<'a> {
     }
 
     fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
-        let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
+        let ast::Item { id, span, ref attrs, ref kind, ref vis, tokens: _ } = *item;
         self.ann.pre(self, AnnNode::SubItem(id));
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(span.lo());
         self.print_outer_attributes(attrs);
         match kind {
             ast::ForeignItemKind::Fn(func) => {
-                self.print_fn_full(ident, vis, attrs, &*func);
+                self.print_fn_full(vis, attrs, &*func);
             }
             ast::ForeignItemKind::Static(box ast::StaticItem {
+                ident,
                 ty,
                 mutability,
                 expr,
                 safety,
                 define_opaque,
             }) => self.print_item_const(
-                ident,
+                *ident,
                 Some(*mutability),
                 &ast::Generics::default(),
                 ty,
@@ -56,13 +57,14 @@ impl<'a> State<'a> {
             ),
             ast::ForeignItemKind::TyAlias(box ast::TyAlias {
                 defaultness,
+                ident,
                 generics,
                 where_clauses,
                 bounds,
                 ty,
             }) => {
                 self.print_associated_type(
-                    ident,
+                    *ident,
                     generics,
                     *where_clauses,
                     bounds,
@@ -162,7 +164,7 @@ impl<'a> State<'a> {
         self.print_outer_attributes(&item.attrs);
         self.ann.pre(self, AnnNode::Item(item));
         match &item.kind {
-            ast::ItemKind::ExternCrate(orig_name) => {
+            ast::ItemKind::ExternCrate(orig_name, ident) => {
                 self.head(visibility_qualified(&item.vis, "extern crate"));
                 if let &Some(orig_name) = orig_name {
                     self.print_name(orig_name);
@@ -170,7 +172,7 @@ impl<'a> State<'a> {
                     self.word("as");
                     self.space();
                 }
-                self.print_ident(item.ident);
+                self.print_ident(*ident);
                 self.word(";");
                 self.end(); // end inner head-block
                 self.end(); // end outer head-block
@@ -182,6 +184,7 @@ impl<'a> State<'a> {
                 self.word(";");
             }
             ast::ItemKind::Static(box StaticItem {
+                ident,
                 ty,
                 safety,
                 mutability: mutbl,
@@ -190,7 +193,7 @@ impl<'a> State<'a> {
             }) => {
                 self.print_safety(*safety);
                 self.print_item_const(
-                    item.ident,
+                    *ident,
                     Some(*mutbl),
                     &ast::Generics::default(),
                     ty,
@@ -203,13 +206,14 @@ impl<'a> State<'a> {
             }
             ast::ItemKind::Const(box ast::ConstItem {
                 defaultness,
+                ident,
                 generics,
                 ty,
                 expr,
                 define_opaque,
             }) => {
                 self.print_item_const(
-                    item.ident,
+                    *ident,
                     None,
                     generics,
                     ty,
@@ -221,15 +225,15 @@ impl<'a> State<'a> {
                 );
             }
             ast::ItemKind::Fn(func) => {
-                self.print_fn_full(item.ident, &item.vis, &item.attrs, &*func);
+                self.print_fn_full(&item.vis, &item.attrs, &*func);
             }
-            ast::ItemKind::Mod(safety, mod_kind) => {
+            ast::ItemKind::Mod(safety, ident, mod_kind) => {
                 self.head(Self::to_string(|s| {
                     s.print_visibility(&item.vis);
                     s.print_safety(*safety);
                     s.word("mod");
                 }));
-                self.print_ident(item.ident);
+                self.print_ident(*ident);
 
                 match mod_kind {
                     ModKind::Loaded(items, ..) => {
@@ -273,13 +277,14 @@ impl<'a> State<'a> {
             }
             ast::ItemKind::TyAlias(box ast::TyAlias {
                 defaultness,
+                ident,
                 generics,
                 where_clauses,
                 bounds,
                 ty,
             }) => {
                 self.print_associated_type(
-                    item.ident,
+                    *ident,
                     generics,
                     *where_clauses,
                     bounds,
@@ -288,16 +293,16 @@ impl<'a> State<'a> {
                     *defaultness,
                 );
             }
-            ast::ItemKind::Enum(enum_definition, params) => {
-                self.print_enum_def(enum_definition, params, item.ident, item.span, &item.vis);
+            ast::ItemKind::Enum(ident, enum_definition, params) => {
+                self.print_enum_def(enum_definition, params, *ident, item.span, &item.vis);
             }
-            ast::ItemKind::Struct(struct_def, generics) => {
+            ast::ItemKind::Struct(ident, struct_def, generics) => {
                 self.head(visibility_qualified(&item.vis, "struct"));
-                self.print_struct(struct_def, generics, item.ident, item.span, true);
+                self.print_struct(struct_def, generics, *ident, item.span, true);
             }
-            ast::ItemKind::Union(struct_def, generics) => {
+            ast::ItemKind::Union(ident, struct_def, generics) => {
                 self.head(visibility_qualified(&item.vis, "union"));
-                self.print_struct(struct_def, generics, item.ident, item.span, true);
+                self.print_struct(struct_def, generics, *ident, item.span, true);
             }
             ast::ItemKind::Impl(box ast::Impl {
                 safety,
@@ -347,19 +352,19 @@ impl<'a> State<'a> {
                 self.bclose(item.span, empty);
             }
             ast::ItemKind::Trait(box ast::Trait {
-                is_auto,
                 safety,
+                is_auto,
+                ident,
                 generics,
                 bounds,
                 items,
-                ..
             }) => {
                 self.head("");
                 self.print_visibility(&item.vis);
                 self.print_safety(*safety);
                 self.print_is_auto(*is_auto);
                 self.word_nbsp("trait");
-                self.print_ident(item.ident);
+                self.print_ident(*ident);
                 self.print_generic_params(&generics.params);
                 if !bounds.is_empty() {
                     self.word_nbsp(":");
@@ -375,9 +380,9 @@ impl<'a> State<'a> {
                 let empty = item.attrs.is_empty() && items.is_empty();
                 self.bclose(item.span, empty);
             }
-            ast::ItemKind::TraitAlias(generics, bounds) => {
+            ast::ItemKind::TraitAlias(ident, generics, bounds) => {
                 self.head(visibility_qualified(&item.vis, "trait"));
-                self.print_ident(item.ident);
+                self.print_ident(*ident);
                 self.print_generic_params(&generics.params);
                 self.nbsp();
                 if !bounds.is_empty() {
@@ -395,8 +400,8 @@ impl<'a> State<'a> {
                     self.word(";");
                 }
             }
-            ast::ItemKind::MacroDef(macro_def) => {
-                self.print_mac_def(macro_def, &item.ident, item.span, |state| {
+            ast::ItemKind::MacroDef(ident, macro_def) => {
+                self.print_mac_def(macro_def, &ident, item.span, |state| {
                     state.print_visibility(&item.vis)
                 });
             }
@@ -549,24 +554,25 @@ impl<'a> State<'a> {
     }
 
     fn print_assoc_item(&mut self, item: &ast::AssocItem) {
-        let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
+        let ast::Item { id, span, ref attrs, ref kind, ref vis, tokens: _ } = *item;
         self.ann.pre(self, AnnNode::SubItem(id));
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(span.lo());
         self.print_outer_attributes(attrs);
         match kind {
             ast::AssocItemKind::Fn(func) => {
-                self.print_fn_full(ident, vis, attrs, &*func);
+                self.print_fn_full(vis, attrs, &*func);
             }
             ast::AssocItemKind::Const(box ast::ConstItem {
                 defaultness,
+                ident,
                 generics,
                 ty,
                 expr,
                 define_opaque,
             }) => {
                 self.print_item_const(
-                    ident,
+                    *ident,
                     None,
                     generics,
                     ty,
@@ -579,13 +585,14 @@ impl<'a> State<'a> {
             }
             ast::AssocItemKind::Type(box ast::TyAlias {
                 defaultness,
+                ident,
                 generics,
                 where_clauses,
                 bounds,
                 ty,
             }) => {
                 self.print_associated_type(
-                    ident,
+                    *ident,
                     generics,
                     *where_clauses,
                     bounds,
@@ -671,14 +678,8 @@ impl<'a> State<'a> {
         }
     }
 
-    fn print_fn_full(
-        &mut self,
-        name: Ident,
-        vis: &ast::Visibility,
-        attrs: &[ast::Attribute],
-        func: &ast::Fn,
-    ) {
-        let ast::Fn { defaultness, generics, sig, contract, body, define_opaque } = func;
+    fn print_fn_full(&mut self, vis: &ast::Visibility, attrs: &[ast::Attribute], func: &ast::Fn) {
+        let ast::Fn { defaultness, ident, generics, sig, contract, body, define_opaque } = func;
 
         self.print_define_opaques(define_opaque.as_deref());
 
@@ -687,7 +688,7 @@ impl<'a> State<'a> {
         }
         self.print_visibility(vis);
         self.print_defaultness(*defaultness);
-        self.print_fn(&sig.decl, sig.header, Some(name), generics);
+        self.print_fn(&sig.decl, sig.header, Some(*ident), generics);
         if let Some(contract) = &contract {
             self.nbsp();
             self.print_contract(contract);
@@ -734,13 +735,13 @@ impl<'a> State<'a> {
         &mut self,
         decl: &ast::FnDecl,
         header: ast::FnHeader,
-        name: Option<Ident>,
+        ident: Option<Ident>,
         generics: &ast::Generics,
     ) {
         self.print_fn_header_info(header);
-        if let Some(name) = name {
+        if let Some(ident) = ident {
             self.nbsp();
-            self.print_ident(name);
+            self.print_ident(ident);
         }
         self.print_generic_params(&generics.params);
         self.print_fn_params_and_ret(decl, false);
diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
index 1c1b2c88f76ee..ea406e706660d 100644
--- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
+++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
@@ -21,15 +21,15 @@ pub(crate) fn expand(
 
     // Allow using `#[alloc_error_handler]` on an item statement
     // FIXME - if we get deref patterns, use them to reduce duplication here
-    let (item, is_stmt, sig_span) = if let Annotatable::Item(item) = &item
+    let (item, ident, is_stmt, sig_span) = if let Annotatable::Item(item) = &item
         && let ItemKind::Fn(fn_kind) = &item.kind
     {
-        (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span))
+        (item, fn_kind.ident, false, ecx.with_def_site_ctxt(fn_kind.sig.span))
     } else if let Annotatable::Stmt(stmt) = &item
         && let StmtKind::Item(item) = &stmt.kind
         && let ItemKind::Fn(fn_kind) = &item.kind
     {
-        (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
+        (item, fn_kind.ident, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
     } else {
         ecx.dcx().emit_err(errors::AllocErrorMustBeFn { span: item.span() });
         return vec![orig_item];
@@ -39,7 +39,7 @@ pub(crate) fn expand(
     let span = ecx.with_def_site_ctxt(item.span);
 
     // Generate item statements for the allocator methods.
-    let stmts = thin_vec![generate_handler(ecx, item.ident, span, sig_span)];
+    let stmts = thin_vec![generate_handler(ecx, ident, span, sig_span)];
 
     // Generate anonymous constant serving as container for the allocator methods.
     let const_ty = ecx.ty(sig_span, TyKind::Tup(ThinVec::new()));
@@ -85,6 +85,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
     let kind = ItemKind::Fn(Box::new(Fn {
         defaultness: ast::Defaultness::Final,
         sig,
+        ident: Ident::from_str_and_span("__rg_oom", span),
         generics: Generics::default(),
         contract: None,
         body,
@@ -93,6 +94,6 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
 
     let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)];
 
-    let item = cx.item(span, Ident::from_str_and_span("__rg_oom", span), attrs, kind);
+    let item = cx.item(span, attrs, kind);
     cx.stmt_item(sig_span, item)
 }
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index eb5b345e49ecd..3e8ddb8abd43f 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -10,7 +10,7 @@ use rustc_index::bit_set::GrowableBitSet;
 use rustc_parse::exp;
 use rustc_parse::parser::{ExpKeywordPair, Parser};
 use rustc_session::lint;
-use rustc_span::{ErrorGuaranteed, Ident, InnerSpan, Span, Symbol, kw};
+use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, kw};
 use rustc_target::asm::InlineAsmArch;
 use smallvec::smallvec;
 use {rustc_ast as ast, rustc_parse_format as parse};
@@ -888,7 +888,6 @@ pub(super) fn expand_global_asm<'cx>(
             };
             match mac {
                 Ok(inline_asm) => MacEager::items(smallvec![P(ast::Item {
-                    ident: Ident::empty(),
                     attrs: ast::AttrVec::new(),
                     id: ast::DUMMY_NODE_ID,
                     kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)),
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index a949ab94f3ad7..ea7248ca5393a 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -112,7 +112,6 @@ impl<'cx, 'a> Context<'cx, 'a> {
             self.span,
             self.cx.item(
                 self.span,
-                Ident::empty(),
                 thin_vec![self.cx.attr_nested_word(sym::allow, sym::unused_imports, self.span)],
                 ItemKind::Use(UseTree {
                     prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])),
diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs
index be11711757e4b..8937d35d53aed 100644
--- a/compiler/rustc_builtin_macros/src/autodiff.rs
+++ b/compiler/rustc_builtin_macros/src/autodiff.rs
@@ -146,26 +146,26 @@ mod llvm_enzyme {
         }
         let dcx = ecx.sess.dcx();
         // first get the annotable item:
-        let (sig, is_impl): (FnSig, bool) = match &item {
+        let (primal, sig, is_impl): (Ident, FnSig, bool) = match &item {
             Annotatable::Item(iitem) => {
-                let sig = match &iitem.kind {
-                    ItemKind::Fn(box ast::Fn { sig, .. }) => sig,
+                let (ident, sig) = match &iitem.kind {
+                    ItemKind::Fn(box ast::Fn { ident, sig, .. }) => (ident, sig),
                     _ => {
                         dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
                         return vec![item];
                     }
                 };
-                (sig.clone(), false)
+                (*ident, sig.clone(), false)
             }
             Annotatable::AssocItem(assoc_item, Impl { of_trait: false }) => {
-                let sig = match &assoc_item.kind {
-                    ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) => sig,
+                let (ident, sig) = match &assoc_item.kind {
+                    ast::AssocItemKind::Fn(box ast::Fn { ident, sig, .. }) => (ident, sig),
                     _ => {
                         dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
                         return vec![item];
                     }
                 };
-                (sig.clone(), true)
+                (*ident, sig.clone(), true)
             }
             _ => {
                 dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
@@ -184,11 +184,9 @@ mod llvm_enzyme {
         let has_ret = has_ret(&sig.decl.output);
         let sig_span = ecx.with_call_site_ctxt(sig.span);
 
-        let (vis, primal) = match &item {
-            Annotatable::Item(iitem) => (iitem.vis.clone(), iitem.ident.clone()),
-            Annotatable::AssocItem(assoc_item, _) => {
-                (assoc_item.vis.clone(), assoc_item.ident.clone())
-            }
+        let vis = match &item {
+            Annotatable::Item(iitem) => iitem.vis.clone(),
+            Annotatable::AssocItem(assoc_item, _) => assoc_item.vis.clone(),
             _ => {
                 dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
                 return vec![item];
@@ -237,12 +235,12 @@ mod llvm_enzyme {
         let d_body = gen_enzyme_body(
             ecx, &x, n_active, &sig, &d_sig, primal, &new_args, span, sig_span, idents, errored,
         );
-        let d_ident = first_ident(&meta_item_vec[0]);
 
         // The first element of it is the name of the function to be generated
         let asdf = Box::new(ast::Fn {
             defaultness: ast::Defaultness::Final,
             sig: d_sig,
+            ident: first_ident(&meta_item_vec[0]),
             generics: Generics::default(),
             contract: None,
             body: Some(d_body),
@@ -323,14 +321,12 @@ mod llvm_enzyme {
                 id: ast::DUMMY_NODE_ID,
                 span,
                 vis,
-                ident: d_ident,
                 kind: assoc_item,
                 tokens: None,
             });
             Annotatable::AssocItem(d_fn, Impl { of_trait: false })
         } else {
-            let mut d_fn =
-                ecx.item(span, d_ident, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf));
+            let mut d_fn = ecx.item(span, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf));
             d_fn.vis = vis;
             Annotatable::Item(d_fn)
         };
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index c3656e8244fe0..44cf215c66227 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -34,8 +34,8 @@ pub(crate) fn expand_deriving_clone(
     let is_simple;
     match item {
         Annotatable::Item(annitem) => match &annitem.kind {
-            ItemKind::Struct(_, Generics { params, .. })
-            | ItemKind::Enum(_, Generics { params, .. }) => {
+            ItemKind::Struct(_, _, Generics { params, .. })
+            | ItemKind::Enum(_, _, Generics { params, .. }) => {
                 let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
                 let has_derive_copy = cx.resolver.has_derive_copy(container_id);
                 if has_derive_copy
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
index 7958e037555d5..aa01da3151eb4 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
@@ -21,7 +21,7 @@ pub(crate) fn expand_deriving_partial_ord(
 
     // Order in which to perform matching
     let discr_then_data = if let Annotatable::Item(item) = item
-        && let ItemKind::Enum(def, _) = &item.kind
+        && let ItemKind::Enum(_, def, _) = &item.kind
     {
         let dataful: Vec<bool> = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect();
         match dataful.iter().filter(|&&b| b).count() {
diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
index 46b79e0978082..446d8afeedd7f 100644
--- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
@@ -30,7 +30,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
     item.visit_with(&mut DetectNonGenericPointeeAttr { cx });
 
     let (name_ident, generics) = if let Annotatable::Item(aitem) = item
-        && let ItemKind::Struct(struct_data, g) = &aitem.kind
+        && let ItemKind::Struct(ident, struct_data, g) = &aitem.kind
     {
         if !matches!(
             struct_data,
@@ -40,7 +40,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
             cx.dcx().emit_err(RequireOneField { span });
             return;
         }
-        (aitem.ident, g)
+        (*ident, g)
     } else {
         cx.dcx().emit_err(RequireTransparent { span });
         return;
@@ -108,7 +108,6 @@ pub(crate) fn expand_deriving_coerce_pointee(
         push(Annotatable::Item(
             cx.item(
                 span,
-                Ident::empty(),
                 attrs.clone(),
                 ast::ItemKind::Impl(Box::new(ast::Impl {
                     safety: ast::Safety::Default,
@@ -153,7 +152,6 @@ pub(crate) fn expand_deriving_coerce_pointee(
         let trait_ref = cx.trait_ref(trait_path);
         let item = cx.item(
             span,
-            Ident::empty(),
             attrs.clone(),
             ast::ItemKind::Impl(Box::new(ast::Impl {
                 safety: ast::Safety::Default,
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 03ee59de70e12..b9197be444266 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -487,28 +487,28 @@ impl<'a> TraitDef<'a> {
                 );
 
                 let newitem = match &item.kind {
-                    ast::ItemKind::Struct(struct_def, generics) => self.expand_struct_def(
+                    ast::ItemKind::Struct(ident, struct_def, generics) => self.expand_struct_def(
                         cx,
                         struct_def,
-                        item.ident,
+                        *ident,
                         generics,
                         from_scratch,
                         is_packed,
                     ),
-                    ast::ItemKind::Enum(enum_def, generics) => {
+                    ast::ItemKind::Enum(ident, enum_def, generics) => {
                         // We ignore `is_packed` here, because `repr(packed)`
                         // enums cause an error later on.
                         //
                         // This can only cause further compilation errors
                         // downstream in blatantly illegal code, so it is fine.
-                        self.expand_enum_def(cx, enum_def, item.ident, generics, from_scratch)
+                        self.expand_enum_def(cx, enum_def, *ident, generics, from_scratch)
                     }
-                    ast::ItemKind::Union(struct_def, generics) => {
+                    ast::ItemKind::Union(ident, struct_def, generics) => {
                         if self.supports_unions {
                             self.expand_struct_def(
                                 cx,
                                 struct_def,
-                                item.ident,
+                                *ident,
                                 generics,
                                 from_scratch,
                                 is_packed,
@@ -596,7 +596,6 @@ impl<'a> TraitDef<'a> {
             P(ast::AssocItem {
                 id: ast::DUMMY_NODE_ID,
                 span: self.span,
-                ident,
                 vis: ast::Visibility {
                     span: self.span.shrink_to_lo(),
                     kind: ast::VisibilityKind::Inherited,
@@ -605,6 +604,7 @@ impl<'a> TraitDef<'a> {
                 attrs: ast::AttrVec::new(),
                 kind: ast::AssocItemKind::Type(Box::new(ast::TyAlias {
                     defaultness: ast::Defaultness::Final,
+                    ident,
                     generics: Generics::default(),
                     where_clauses: ast::TyAliasWhereClauses::default(),
                     bounds: Vec::new(),
@@ -789,7 +789,6 @@ impl<'a> TraitDef<'a> {
 
         cx.item(
             self.span,
-            Ident::empty(),
             attrs,
             ast::ItemKind::Impl(Box::new(ast::Impl {
                 safety: ast::Safety::Default,
@@ -1033,10 +1032,10 @@ impl<'a> MethodDef<'a> {
                 kind: ast::VisibilityKind::Inherited,
                 tokens: None,
             },
-            ident: method_ident,
             kind: ast::AssocItemKind::Fn(Box::new(ast::Fn {
                 defaultness,
                 sig,
+                ident: method_ident,
                 generics: fn_generics,
                 contract: None,
                 body: Some(body_block),
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index 90d79235820f4..4b1958bce3223 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -25,15 +25,15 @@ pub(crate) fn expand(
 
     // Allow using `#[global_allocator]` on an item statement
     // FIXME - if we get deref patterns, use them to reduce duplication here
-    let (item, is_stmt, ty_span) = if let Annotatable::Item(item) = &item
-        && let ItemKind::Static(box ast::StaticItem { ty, .. }) = &item.kind
+    let (item, ident, is_stmt, ty_span) = if let Annotatable::Item(item) = &item
+        && let ItemKind::Static(box ast::StaticItem { ident, ty, .. }) = &item.kind
     {
-        (item, false, ecx.with_def_site_ctxt(ty.span))
+        (item, *ident, false, ecx.with_def_site_ctxt(ty.span))
     } else if let Annotatable::Stmt(stmt) = &item
         && let StmtKind::Item(item) = &stmt.kind
-        && let ItemKind::Static(box ast::StaticItem { ty, .. }) = &item.kind
+        && let ItemKind::Static(box ast::StaticItem { ident, ty, .. }) = &item.kind
     {
-        (item, true, ecx.with_def_site_ctxt(ty.span))
+        (item, *ident, true, ecx.with_def_site_ctxt(ty.span))
     } else {
         ecx.dcx().emit_err(errors::AllocMustStatics { span: item.span() });
         return vec![orig_item];
@@ -41,7 +41,7 @@ pub(crate) fn expand(
 
     // Generate a bunch of new items using the AllocFnFactory
     let span = ecx.with_def_site_ctxt(item.span);
-    let f = AllocFnFactory { span, ty_span, global: item.ident, cx: ecx };
+    let f = AllocFnFactory { span, ty_span, global: ident, cx: ecx };
 
     // Generate item statements for the allocator methods.
     let stmts = ALLOCATOR_METHODS.iter().map(|method| f.allocator_fn(method)).collect();
@@ -80,17 +80,13 @@ impl AllocFnFactory<'_, '_> {
         let kind = ItemKind::Fn(Box::new(Fn {
             defaultness: ast::Defaultness::Final,
             sig,
+            ident: Ident::from_str_and_span(&global_fn_name(method.name), self.span),
             generics: Generics::default(),
             contract: None,
             body,
             define_opaque: None,
         }));
-        let item = self.cx.item(
-            self.span,
-            Ident::from_str_and_span(&global_fn_name(method.name), self.span),
-            self.attrs(),
-            kind,
-        );
+        let item = self.cx.item(self.span, self.attrs(), kind);
         self.cx.stmt_item(self.ty_span, item)
     }
 
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index ee6475c8b8e91..8862965c0532c 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -92,7 +92,12 @@ impl<'a> CollectProcMacros<'a> {
         }
     }
 
-    fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribute) {
+    fn collect_custom_derive(
+        &mut self,
+        item: &'a ast::Item,
+        function_name: Ident,
+        attr: &'a ast::Attribute,
+    ) {
         let Some((trait_name, proc_attrs)) =
             parse_macro_name_and_helper_attrs(self.dcx, attr, "derive")
         else {
@@ -104,7 +109,7 @@ impl<'a> CollectProcMacros<'a> {
                 id: item.id,
                 span: item.span,
                 trait_name,
-                function_name: item.ident,
+                function_name,
                 attrs: proc_attrs,
             }));
         } else {
@@ -118,12 +123,12 @@ impl<'a> CollectProcMacros<'a> {
         }
     }
 
-    fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) {
+    fn collect_attr_proc_macro(&mut self, item: &'a ast::Item, function_name: Ident) {
         if self.in_root && item.vis.kind.is_pub() {
             self.macros.push(ProcMacro::Attr(ProcMacroDef {
                 id: item.id,
                 span: item.span,
-                function_name: item.ident,
+                function_name,
             }));
         } else {
             let msg = if !self.in_root {
@@ -136,12 +141,12 @@ impl<'a> CollectProcMacros<'a> {
         }
     }
 
-    fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) {
+    fn collect_bang_proc_macro(&mut self, item: &'a ast::Item, function_name: Ident) {
         if self.in_root && item.vis.kind.is_pub() {
             self.macros.push(ProcMacro::Bang(ProcMacroDef {
                 id: item.id,
                 span: item.span,
-                function_name: item.ident,
+                function_name,
             }));
         } else {
             let msg = if !self.in_root {
@@ -165,12 +170,6 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
             }
         }
 
-        // First up, make sure we're checking a bare function. If we're not then
-        // we're just not interested in this item.
-        //
-        // If we find one, try to locate a `#[proc_macro_derive]` attribute on it.
-        let is_fn = matches!(item.kind, ast::ItemKind::Fn(..));
-
         let mut found_attr: Option<&'a ast::Attribute> = None;
 
         for attr in &item.attrs {
@@ -214,7 +213,11 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
             return;
         };
 
-        if !is_fn {
+        // Make sure we're checking a bare function. If we're not then we're
+        // just not interested any further in this item.
+        let fn_ident = if let ast::ItemKind::Fn(fn_) = &item.kind {
+            fn_.ident
+        } else {
             self.dcx
                 .create_err(errors::AttributeOnlyBeUsedOnBareFunctions {
                     span: attr.span,
@@ -222,7 +225,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
                 })
                 .emit();
             return;
-        }
+        };
 
         if self.is_test_crate {
             return;
@@ -238,12 +241,13 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
             return;
         }
 
+        // Try to locate a `#[proc_macro_derive]` attribute.
         if attr.has_name(sym::proc_macro_derive) {
-            self.collect_custom_derive(item, attr);
+            self.collect_custom_derive(item, fn_ident, attr);
         } else if attr.has_name(sym::proc_macro_attribute) {
-            self.collect_attr_proc_macro(item);
+            self.collect_attr_proc_macro(item, fn_ident);
         } else if attr.has_name(sym::proc_macro) {
-            self.collect_bang_proc_macro(item);
+            self.collect_bang_proc_macro(item, fn_ident);
         };
 
         let prev_in_root = mem::replace(&mut self.in_root, false);
@@ -278,7 +282,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
     let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());
 
     let proc_macro = Ident::new(sym::proc_macro, span);
-    let krate = cx.item(span, proc_macro, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None));
+    let krate = cx.item(span, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, proc_macro));
 
     let bridge = Ident::new(sym::bridge, span);
     let client = Ident::new(sym::client, span);
diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
index ba63b185e0967..a1ee53b7ca21f 100644
--- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs
+++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
@@ -43,9 +43,8 @@ pub fn inject(
 
     let item = cx.item(
         span,
-        Ident::new(name, ident_span),
         thin_vec![cx.attr_word(sym::macro_use, span)],
-        ast::ItemKind::ExternCrate(None),
+        ast::ItemKind::ExternCrate(None, Ident::new(name, ident_span)),
     );
 
     krate.items.insert(0, item);
@@ -68,7 +67,6 @@ pub fn inject(
     // Inject the relevant crate's prelude.
     let use_item = cx.item(
         span,
-        Ident::empty(),
         thin_vec![cx.attr_word(sym::prelude_import, span)],
         ast::ItemKind::Use(ast::UseTree {
             prefix: cx.path(span, import_path),
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index 239f8657284d5..1cef4f9514cd7 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -51,21 +51,28 @@ pub(crate) fn expand_test_case(
             return vec![];
         }
     };
-    item = item.map(|mut item| {
-        let test_path_symbol = Symbol::intern(&item_path(
-            // skip the name of the root module
-            &ecx.current_expansion.module.mod_path[1..],
-            &item.ident,
-        ));
-        item.vis = ast::Visibility {
-            span: item.vis.span,
-            kind: ast::VisibilityKind::Public,
-            tokens: None,
-        };
-        item.ident.span = item.ident.span.with_ctxt(sp.ctxt());
-        item.attrs.push(ecx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, sp));
-        item
-    });
+
+    // `#[test_case]` is valid on functions, consts, and statics. Only modify
+    // the item in those cases.
+    match &mut item.kind {
+        ast::ItemKind::Fn(box ast::Fn { ident, .. })
+        | ast::ItemKind::Const(box ast::ConstItem { ident, .. })
+        | ast::ItemKind::Static(box ast::StaticItem { ident, .. }) => {
+            ident.span = ident.span.with_ctxt(sp.ctxt());
+            let test_path_symbol = Symbol::intern(&item_path(
+                // skip the name of the root module
+                &ecx.current_expansion.module.mod_path[1..],
+                ident,
+            ));
+            item.vis = ast::Visibility {
+                span: item.vis.span,
+                kind: ast::VisibilityKind::Public,
+                tokens: None,
+            };
+            item.attrs.push(ecx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, sp));
+        }
+        _ => {}
+    }
 
     let ret = if is_stmt {
         Annotatable::Stmt(P(ecx.stmt_item(item.span, item)))
@@ -162,17 +169,17 @@ pub(crate) fn expand_test_or_bench(
     let ret_ty_sp = cx.with_def_site_ctxt(fn_.sig.decl.output.span());
     let attr_sp = cx.with_def_site_ctxt(attr_sp);
 
-    let test_id = Ident::new(sym::test, attr_sp);
+    let test_ident = Ident::new(sym::test, attr_sp);
 
     // creates test::$name
-    let test_path = |name| cx.path(ret_ty_sp, vec![test_id, Ident::from_str_and_span(name, sp)]);
+    let test_path = |name| cx.path(ret_ty_sp, vec![test_ident, Ident::from_str_and_span(name, sp)]);
 
     // creates test::ShouldPanic::$name
     let should_panic_path = |name| {
         cx.path(
             sp,
             vec![
-                test_id,
+                test_ident,
                 Ident::from_str_and_span("ShouldPanic", sp),
                 Ident::from_str_and_span(name, sp),
             ],
@@ -184,7 +191,7 @@ pub(crate) fn expand_test_or_bench(
         cx.path(
             sp,
             vec![
-                test_id,
+                test_ident,
                 Ident::from_str_and_span("TestType", sp),
                 Ident::from_str_and_span(name, sp),
             ],
@@ -223,7 +230,7 @@ pub(crate) fn expand_test_or_bench(
                             // super::$test_fn(b)
                             cx.expr_call(
                                 ret_ty_sp,
-                                cx.expr_path(cx.path(sp, vec![item.ident])),
+                                cx.expr_path(cx.path(sp, vec![fn_.ident])),
                                 thin_vec![cx.expr_ident(sp, b)],
                             ),
                         ],
@@ -249,7 +256,7 @@ pub(crate) fn expand_test_or_bench(
                             // $test_fn()
                             cx.expr_call(
                                 ret_ty_sp,
-                                cx.expr_path(cx.path(sp, vec![item.ident])),
+                                cx.expr_path(cx.path(sp, vec![fn_.ident])),
                                 ThinVec::new(),
                             ), // )
                         ],
@@ -262,15 +269,14 @@ pub(crate) fn expand_test_or_bench(
     let test_path_symbol = Symbol::intern(&item_path(
         // skip the name of the root module
         &cx.current_expansion.module.mod_path[1..],
-        &item.ident,
+        &fn_.ident,
     ));
 
-    let location_info = get_location_info(cx, &item);
+    let location_info = get_location_info(cx, &fn_);
 
     let mut test_const =
         cx.item(
             sp,
-            Ident::new(item.ident.name, sp),
             thin_vec![
                 // #[cfg(test)]
                 cx.attr_nested_word(sym::cfg, sym::test, attr_sp),
@@ -283,6 +289,7 @@ pub(crate) fn expand_test_or_bench(
             ast::ItemKind::Const(
                 ast::ConstItem {
                     defaultness: ast::Defaultness::Final,
+                    ident: Ident::new(fn_.ident.name, sp),
                     generics: ast::Generics::default(),
                     ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
                     define_opaque: None,
@@ -380,7 +387,8 @@ pub(crate) fn expand_test_or_bench(
     });
 
     // extern crate test
-    let test_extern = cx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None));
+    let test_extern =
+        cx.item(sp, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, test_ident));
 
     debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
 
@@ -434,8 +442,8 @@ fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>)
         .emit();
 }
 
-fn get_location_info(cx: &ExtCtxt<'_>, item: &ast::Item) -> (Symbol, usize, usize, usize, usize) {
-    let span = item.ident.span;
+fn get_location_info(cx: &ExtCtxt<'_>, fn_: &ast::Fn) -> (Symbol, usize, usize, usize, usize) {
+    let span = fn_.ident.span;
     let (source_file, lo_line, lo_col, hi_line, hi_col) =
         cx.sess.source_map().span_to_location_info(span);
 
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 768b459ec5e30..56a67b0534d98 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -134,27 +134,21 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
         if let Some(name) = get_test_name(&item) {
             debug!("this is a test item");
 
-            let test = Test { span: item.span, ident: item.ident, name };
+            // `unwrap` is ok because only functions, consts, and static should reach here.
+            let test = Test { span: item.span, ident: item.kind.ident().unwrap(), name };
             self.tests.push(test);
         }
 
         // We don't want to recurse into anything other than mods, since
         // mods or tests inside of functions will break things
         if let ast::ItemKind::Mod(
+            _,
             _,
             ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. }, _),
         ) = item.kind
         {
             let prev_tests = mem::take(&mut self.tests);
-            walk_item_kind(
-                &mut item.kind,
-                item.span,
-                item.id,
-                &mut item.ident,
-                &mut item.vis,
-                (),
-                self,
-            );
+            walk_item_kind(&mut item.kind, item.span, item.id, &mut item.vis, (), 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.
@@ -181,9 +175,9 @@ impl<'a> Visitor<'a> for InnerItemLinter<'_> {
 }
 
 fn entry_point_type(item: &ast::Item, at_root: bool) -> EntryPointType {
-    match item.kind {
-        ast::ItemKind::Fn(..) => {
-            rustc_ast::entry::entry_point_type(&item.attrs, at_root, Some(item.ident.name))
+    match &item.kind {
+        ast::ItemKind::Fn(fn_) => {
+            rustc_ast::entry::entry_point_type(&item.attrs, at_root, Some(fn_.ident.name))
         }
         _ => EntryPointType::None,
     }
@@ -295,7 +289,7 @@ fn generate_test_harness(
 fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
     let sp = cx.def_site;
     let ecx = &cx.ext_cx;
-    let test_id = Ident::new(sym::test, sp);
+    let test_ident = Ident::new(sym::test, sp);
 
     let runner_name = match cx.panic_strategy {
         PanicStrategy::Unwind => "test_main_static",
@@ -303,10 +297,9 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
     };
 
     // test::test_main_static(...)
-    let mut test_runner = cx
-        .test_runner
-        .clone()
-        .unwrap_or_else(|| ecx.path(sp, vec![test_id, Ident::from_str_and_span(runner_name, sp)]));
+    let mut test_runner = cx.test_runner.clone().unwrap_or_else(|| {
+        ecx.path(sp, vec![test_ident, Ident::from_str_and_span(runner_name, sp)])
+    });
 
     test_runner.span = sp;
 
@@ -317,7 +310,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
     // extern crate test
     let test_extern_stmt = ecx.stmt_item(
         sp,
-        ecx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)),
+        ecx.item(sp, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, test_ident)),
     );
 
     // #[rustc_main]
@@ -340,23 +333,24 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
     let decl = ecx.fn_decl(ThinVec::new(), ast::FnRetTy::Ty(main_ret_ty));
     let sig = ast::FnSig { decl, header: ast::FnHeader::default(), span: sp };
     let defaultness = ast::Defaultness::Final;
+
+    // Honor the reexport_test_harness_main attribute
+    let main_ident = match cx.reexport_test_harness_main {
+        Some(sym) => Ident::new(sym, sp.with_ctxt(SyntaxContext::root())),
+        None => Ident::new(sym::main, sp),
+    };
+
     let main = ast::ItemKind::Fn(Box::new(ast::Fn {
         defaultness,
         sig,
+        ident: main_ident,
         generics: ast::Generics::default(),
         contract: None,
         body: Some(main_body),
         define_opaque: None,
     }));
 
-    // Honor the reexport_test_harness_main attribute
-    let main_id = match cx.reexport_test_harness_main {
-        Some(sym) => Ident::new(sym, sp.with_ctxt(SyntaxContext::root())),
-        None => Ident::new(sym::main, sp),
-    };
-
     let main = P(ast::Item {
-        ident: main_id,
         attrs: thin_vec![main_attr, coverage_attr, doc_hidden_attr],
         id: ast::DUMMY_NODE_ID,
         kind: main,
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 990d0f2e028aa..d14e476ba3223 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1424,12 +1424,11 @@ pub fn parse_macro_name_and_helper_attrs(
 /// See #73345 and #83125 for more details.
 /// FIXME(#73933): Remove this eventually.
 fn pretty_printing_compatibility_hack(item: &Item, psess: &ParseSess) {
-    let name = item.ident.name;
-    if name == sym::ProceduralMasqueradeDummyType
-        && let ast::ItemKind::Enum(enum_def, _) = &item.kind
+    if let ast::ItemKind::Enum(ident, enum_def, _) = &item.kind
+        && ident.name == sym::ProceduralMasqueradeDummyType
         && let [variant] = &*enum_def.variants
         && variant.ident.name == sym::Input
-        && let FileName::Real(real) = psess.source_map().span_to_filename(item.ident.span)
+        && let FileName::Real(real) = psess.source_map().span_to_filename(ident.span)
         && let Some(c) = real
             .local_path()
             .unwrap_or(Path::new(""))
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 89a750bb39f0c..f68172c1f67c0 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -662,15 +662,8 @@ impl<'a> ExtCtxt<'a> {
         P(ast::FnDecl { inputs, output })
     }
 
-    pub fn item(
-        &self,
-        span: Span,
-        name: Ident,
-        attrs: ast::AttrVec,
-        kind: ast::ItemKind,
-    ) -> P<ast::Item> {
+    pub fn item(&self, span: Span, attrs: ast::AttrVec, kind: ast::ItemKind) -> P<ast::Item> {
         P(ast::Item {
-            ident: name,
             attrs,
             id: ast::DUMMY_NODE_ID,
             kind,
@@ -687,17 +680,17 @@ impl<'a> ExtCtxt<'a> {
     pub fn item_static(
         &self,
         span: Span,
-        name: Ident,
+        ident: Ident,
         ty: P<ast::Ty>,
         mutability: ast::Mutability,
         expr: P<ast::Expr>,
     ) -> P<ast::Item> {
         self.item(
             span,
-            name,
             AttrVec::new(),
             ast::ItemKind::Static(
                 ast::StaticItem {
+                    ident,
                     ty,
                     safety: ast::Safety::Default,
                     mutability,
@@ -712,18 +705,18 @@ impl<'a> ExtCtxt<'a> {
     pub fn item_const(
         &self,
         span: Span,
-        name: Ident,
+        ident: Ident,
         ty: P<ast::Ty>,
         expr: P<ast::Expr>,
     ) -> P<ast::Item> {
         let defaultness = ast::Defaultness::Final;
         self.item(
             span,
-            name,
             AttrVec::new(),
             ast::ItemKind::Const(
                 ast::ConstItem {
                     defaultness,
+                    ident,
                     // FIXME(generic_const_items): Pass the generics as a parameter.
                     generics: ast::Generics::default(),
                     ty,
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 22da1179feb98..bca846d2ec423 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -743,6 +743,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                                 && matches!(
                                     item_inner.kind,
                                     ItemKind::Mod(
+                                        _,
                                         _,
                                         ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _, _),
                                     )
@@ -911,7 +912,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
             fn visit_item(&mut self, item: &'ast ast::Item) {
                 match &item.kind {
-                    ItemKind::Mod(_, mod_kind)
+                    ItemKind::Mod(_, _, mod_kind)
                         if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _)) =>
                     {
                         feature_err(
@@ -1221,9 +1222,8 @@ impl InvocationCollectorNode for P<ast::Item> {
         }
 
         // Work around borrow checker not seeing through `P`'s deref.
-        let (ident, span, mut attrs) = (node.ident, node.span, mem::take(&mut node.attrs));
-        let ItemKind::Mod(_, mod_kind) = &mut node.kind else { unreachable!() };
-
+        let (span, mut attrs) = (node.span, mem::take(&mut node.attrs));
+        let ItemKind::Mod(_, ident, ref mut mod_kind) = node.kind else { unreachable!() };
         let ecx = &mut collector.cx;
         let (file_path, dir_path, dir_ownership) = match mod_kind {
             ModKind::Loaded(_, inline, _, _) => {
@@ -1305,6 +1305,7 @@ impl InvocationCollectorNode for P<ast::Item> {
         collector.cx.current_expansion.module = orig_module;
         res
     }
+
     fn declared_names(&self) -> Vec<Ident> {
         if let ItemKind::Use(ut) = &self.kind {
             fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec<Ident>) {
@@ -1324,7 +1325,7 @@ impl InvocationCollectorNode for P<ast::Item> {
             return idents;
         }
 
-        vec![self.ident]
+        if let Some(ident) = self.kind.ident() { vec![ident] } else { vec![] }
     }
 }
 
@@ -1844,11 +1845,11 @@ fn build_single_delegations<'a, Node: InvocationCollectorNode>(
             id: ast::DUMMY_NODE_ID,
             span: if from_glob { item_span } else { ident.span },
             vis: item.vis.clone(),
-            ident: rename.unwrap_or(ident),
             kind: Node::delegation_item_kind(Box::new(ast::Delegation {
                 id: ast::DUMMY_NODE_ID,
                 qself: deleg.qself.clone(),
                 path,
+                ident: rename.unwrap_or(ident),
                 rename,
                 body: deleg.body.clone(),
                 from_glob,
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index a60a87244cc6e..0136292decbcf 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -26,7 +26,7 @@ pub(crate) fn placeholder(
         })
     }
 
-    let ident = Ident::empty();
+    let ident = Ident::dummy();
     let attrs = ast::AttrVec::new();
     let vis = vis.unwrap_or(ast::Visibility {
         span: DUMMY_SP,
@@ -62,7 +62,6 @@ pub(crate) fn placeholder(
         AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
             id,
             span,
-            ident,
             vis,
             attrs,
             kind: ast::ItemKind::MacCall(mac_placeholder()),
@@ -71,7 +70,6 @@ pub(crate) fn placeholder(
         AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![P(ast::AssocItem {
             id,
             span,
-            ident,
             vis,
             attrs,
             kind: ast::AssocItemKind::MacCall(mac_placeholder()),
@@ -80,7 +78,6 @@ pub(crate) fn placeholder(
         AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem {
             id,
             span,
-            ident,
             vis,
             attrs,
             kind: ast::AssocItemKind::MacCall(mac_placeholder()),
@@ -90,7 +87,6 @@ pub(crate) fn placeholder(
             AstFragment::TraitImplItems(smallvec![P(ast::AssocItem {
                 id,
                 span,
-                ident,
                 vis,
                 attrs,
                 kind: ast::AssocItemKind::MacCall(mac_placeholder()),
@@ -101,7 +97,6 @@ pub(crate) fn placeholder(
             AstFragment::ForeignItems(smallvec![P(ast::ForeignItem {
                 id,
                 span,
-                ident,
                 vis,
                 attrs,
                 kind: ast::ForeignItemKind::MacCall(mac_placeholder()),
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 9dccd4a0552c3..c56dbc2e1c401 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -330,7 +330,6 @@ impl EarlyLintPass for UnsafeCode {
         if let FnKind::Fn(
             ctxt,
             _,
-            _,
             ast::Fn {
                 sig: ast::FnSig { header: ast::FnHeader { safety: ast::Safety::Unsafe(_), .. }, .. },
                 body,
@@ -3116,6 +3115,7 @@ impl EarlyLintPass for SpecialModuleName {
         for item in &krate.items {
             if let ast::ItemKind::Mod(
                 _,
+                ident,
                 ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _, _),
             ) = item.kind
             {
@@ -3123,7 +3123,7 @@ impl EarlyLintPass for SpecialModuleName {
                     continue;
                 }
 
-                match item.ident.name.as_str() {
+                match ident.name.as_str() {
                     "lib" => cx.emit_span_lint(
                         SPECIAL_MODULE_NAME,
                         item.span,
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 752636ccaf061..df567e80e5568 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -172,20 +172,22 @@ impl EarlyLintPass for NonCamelCaseTypes {
         }
 
         match &it.kind {
-            ast::ItemKind::TyAlias(..)
-            | ast::ItemKind::Enum(..)
-            | ast::ItemKind::Struct(..)
-            | ast::ItemKind::Union(..) => self.check_case(cx, "type", &it.ident),
-            ast::ItemKind::Trait(..) => self.check_case(cx, "trait", &it.ident),
-            ast::ItemKind::TraitAlias(..) => self.check_case(cx, "trait alias", &it.ident),
+            ast::ItemKind::TyAlias(box ast::TyAlias { ident, .. })
+            | ast::ItemKind::Enum(ident, ..)
+            | ast::ItemKind::Struct(ident, ..)
+            | ast::ItemKind::Union(ident, ..) => self.check_case(cx, "type", ident),
+            ast::ItemKind::Trait(box ast::Trait { ident, .. }) => {
+                self.check_case(cx, "trait", ident)
+            }
+            ast::ItemKind::TraitAlias(ident, _, _) => self.check_case(cx, "trait alias", ident),
 
             // N.B. This check is only for inherent associated types, so that we don't lint against
             // trait impls where we should have warned for the trait definition already.
             ast::ItemKind::Impl(box ast::Impl { of_trait: None, items, .. }) => {
                 for it in items {
                     // FIXME: this doesn't respect `#[allow(..)]` on the item itself.
-                    if let ast::AssocItemKind::Type(..) = it.kind {
-                        self.check_case(cx, "associated type", &it.ident);
+                    if let ast::AssocItemKind::Type(alias) = &it.kind {
+                        self.check_case(cx, "associated type", &alias.ident);
                     }
                 }
             }
@@ -194,8 +196,8 @@ impl EarlyLintPass for NonCamelCaseTypes {
     }
 
     fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
-        if let ast::AssocItemKind::Type(..) = it.kind {
-            self.check_case(cx, "associated type", &it.ident);
+        if let ast::AssocItemKind::Type(alias) = &it.kind {
+            self.check_case(cx, "associated type", &alias.ident);
         }
     }
 
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index b7f13e0afdcde..16f87ab79bee5 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -1032,14 +1032,19 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
     }
 
     fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
-        self.cstore.has_global_allocator = match &*global_allocator_spans(krate) {
-            [span1, span2, ..] => {
-                self.dcx().emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
-                true
-            }
-            spans => !spans.is_empty(),
-        };
-        self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(krate) {
+        self.cstore.has_global_allocator =
+            match &*fn_spans(krate, Symbol::intern(&global_fn_name(sym::alloc))) {
+                [span1, span2, ..] => {
+                    self.dcx()
+                        .emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
+                    true
+                }
+                spans => !spans.is_empty(),
+            };
+        self.cstore.has_alloc_error_handler = match &*fn_spans(
+            krate,
+            Symbol::intern(alloc_error_handler_name(AllocatorKind::Global)),
+        ) {
             [span1, span2, ..] => {
                 self.dcx()
                     .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 });
@@ -1310,17 +1315,14 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
         definitions: &Definitions,
     ) -> Option<CrateNum> {
         match item.kind {
-            ast::ItemKind::ExternCrate(orig_name) => {
-                debug!(
-                    "resolving extern crate stmt. ident: {} orig_name: {:?}",
-                    item.ident, orig_name
-                );
+            ast::ItemKind::ExternCrate(orig_name, ident) => {
+                debug!("resolving extern crate stmt. ident: {} orig_name: {:?}", ident, orig_name);
                 let name = match orig_name {
                     Some(orig_name) => {
                         validate_crate_name(self.sess, orig_name, Some(item.span));
                         orig_name
                     }
-                    None => item.ident.name,
+                    None => ident.name,
                 };
                 let dep_kind = if attr::contains_name(&item.attrs, sym::no_link) {
                     CrateDepKind::MacrosOnly
@@ -1368,36 +1370,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
     }
 }
 
-fn global_allocator_spans(krate: &ast::Crate) -> Vec<Span> {
-    struct Finder {
-        name: Symbol,
-        spans: Vec<Span>,
-    }
-    impl<'ast> visit::Visitor<'ast> for Finder {
-        fn visit_item(&mut self, item: &'ast ast::Item) {
-            if item.ident.name == self.name
-                && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol)
-            {
-                self.spans.push(item.span);
-            }
-            visit::walk_item(self, item)
-        }
-    }
-
-    let name = Symbol::intern(&global_fn_name(sym::alloc));
-    let mut f = Finder { name, spans: Vec::new() };
-    visit::walk_crate(&mut f, krate);
-    f.spans
-}
-
-fn alloc_error_handler_spans(krate: &ast::Crate) -> Vec<Span> {
+fn fn_spans(krate: &ast::Crate, name: Symbol) -> Vec<Span> {
     struct Finder {
         name: Symbol,
         spans: Vec<Span>,
     }
     impl<'ast> visit::Visitor<'ast> for Finder {
         fn visit_item(&mut self, item: &'ast ast::Item) {
-            if item.ident.name == self.name
+            if let Some(ident) = item.kind.ident()
+                && ident.name == self.name
                 && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol)
             {
                 self.spans.push(item.span);
@@ -1406,7 +1387,6 @@ fn alloc_error_handler_spans(krate: &ast::Crate) -> Vec<Span> {
         }
     }
 
-    let name = Symbol::intern(alloc_error_handler_name(AllocatorKind::Global));
     let mut f = Finder { name, spans: Vec::new() };
     visit::walk_crate(&mut f, krate);
     f.spans
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index aad1857837554..e93fb2473fbfb 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -34,10 +34,10 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
-    fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemInfo> {
+    fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemKind> {
         let safety = self.parse_safety(Case::Sensitive);
         self.expect_keyword(exp!(Mod))?;
-        let id = self.parse_ident()?;
+        let ident = self.parse_ident()?;
         let mod_kind = if self.eat(exp!(Semi)) {
             ModKind::Unloaded
         } else {
@@ -46,7 +46,7 @@ impl<'a> Parser<'a> {
             attrs.extend(inner_attrs);
             ModKind::Loaded(items, Inline::Yes, inner_span, Ok(()))
         };
-        Ok((id, ItemKind::Mod(safety, mod_kind)))
+        Ok(ItemKind::Mod(safety, ident, mod_kind))
     }
 
     /// Parses the contents of a module (inner attributes followed by module items).
@@ -115,8 +115,6 @@ impl<'a> Parser<'a> {
     }
 }
 
-pub(super) type ItemInfo = (Ident, ItemKind);
-
 impl<'a> Parser<'a> {
     pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<P<Item>>> {
         let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
@@ -163,11 +161,11 @@ impl<'a> Parser<'a> {
                 fn_parse_mode,
                 Case::Sensitive,
             )?;
-            if let Some((ident, kind)) = kind {
+            if let Some(kind) = kind {
                 this.error_on_unconsumed_default(def, &kind);
                 let span = lo.to(this.prev_token.span);
                 let id = DUMMY_NODE_ID;
-                let item = Item { ident, attrs, id, kind, vis, span, tokens: None };
+                let item = Item { attrs, id, kind, vis, span, tokens: None };
                 return Ok((Some(item), Trailing::No, UsePreAttrPos::No));
             }
 
@@ -208,7 +206,7 @@ impl<'a> Parser<'a> {
         def: &mut Defaultness,
         fn_parse_mode: FnParseMode,
         case: Case,
-    ) -> PResult<'a, Option<ItemInfo>> {
+    ) -> PResult<'a, Option<ItemKind>> {
         let check_pub = def == &Defaultness::Final;
         let mut def_ = || mem::replace(def, Defaultness::Final);
 
@@ -218,17 +216,15 @@ impl<'a> Parser<'a> {
             // FUNCTION ITEM
             let (ident, sig, generics, contract, body) =
                 self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
-            (
+            ItemKind::Fn(Box::new(Fn {
+                defaultness: def_(),
                 ident,
-                ItemKind::Fn(Box::new(Fn {
-                    defaultness: def_(),
-                    sig,
-                    generics,
-                    contract,
-                    body,
-                    define_opaque: None,
-                })),
-            )
+                sig,
+                generics,
+                contract,
+                body,
+                define_opaque: None,
+            }))
         } else if self.eat_keyword(exp!(Extern)) {
             if self.eat_keyword(exp!(Crate)) {
                 // EXTERN CRATE
@@ -247,8 +243,7 @@ impl<'a> Parser<'a> {
             // STATIC ITEM
             self.bump(); // `static`
             let mutability = self.parse_mutability();
-            let (ident, item) = self.parse_static_item(safety, mutability)?;
-            (ident, ItemKind::Static(Box::new(item)))
+            self.parse_static_item(safety, mutability)?
         } else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) {
             // CONST ITEM
             if self.token.is_keyword(kw::Impl) {
@@ -258,16 +253,14 @@ impl<'a> Parser<'a> {
                 self.recover_const_mut(const_span);
                 self.recover_missing_kw_before_item()?;
                 let (ident, generics, ty, expr) = self.parse_const_item()?;
-                (
+                ItemKind::Const(Box::new(ConstItem {
+                    defaultness: def_(),
                     ident,
-                    ItemKind::Const(Box::new(ConstItem {
-                        defaultness: def_(),
-                        generics,
-                        ty,
-                        expr,
-                        define_opaque: None,
-                    })),
-                )
+                    generics,
+                    ty,
+                    expr,
+                    define_opaque: None,
+                }))
             }
         } else if self.check_keyword(exp!(Trait)) || self.check_auto_or_unsafe_trait_item() {
             // TRAIT ITEM
@@ -334,14 +327,14 @@ impl<'a> Parser<'a> {
                 self.recover_missing_kw_before_item()?;
             }
             // MACRO INVOCATION ITEM
-            (Ident::empty(), ItemKind::MacCall(P(self.parse_item_macro(vis)?)))
+            ItemKind::MacCall(P(self.parse_item_macro(vis)?))
         } else {
             return Ok(None);
         };
         Ok(Some(info))
     }
 
-    fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemInfo>> {
+    fn recover_import_as_use(&mut self) -> PResult<'a, Option<ItemKind>> {
         let span = self.token.span;
         let token_name = super::token_descr(&self.token);
         let snapshot = self.create_snapshot_for_diagnostic();
@@ -359,7 +352,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn parse_use_item(&mut self) -> PResult<'a, ItemInfo> {
+    fn parse_use_item(&mut self) -> PResult<'a, ItemKind> {
         let tree = self.parse_use_tree()?;
         if let Err(mut e) = self.expect_semi() {
             match tree.kind {
@@ -373,7 +366,7 @@ impl<'a> Parser<'a> {
             }
             return Err(e);
         }
-        Ok((Ident::empty(), ItemKind::Use(tree)))
+        Ok(ItemKind::Use(tree))
     }
 
     /// When parsing a statement, would the start of a path be an item?
@@ -483,7 +476,7 @@ impl<'a> Parser<'a> {
         if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) }
     }
 
-    fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemInfo>> {
+    fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemKind>> {
         // To be expanded
         Ok(None)
     }
@@ -577,7 +570,7 @@ impl<'a> Parser<'a> {
         &mut self,
         attrs: &mut AttrVec,
         defaultness: Defaultness,
-    ) -> PResult<'a, ItemInfo> {
+    ) -> PResult<'a, ItemKind> {
         let safety = self.parse_safety(Case::Sensitive);
         self.expect_keyword(exp!(Impl))?;
 
@@ -687,7 +680,7 @@ impl<'a> Parser<'a> {
             }
             None => (None, ty_first), // impl Type
         };
-        let item_kind = ItemKind::Impl(Box::new(Impl {
+        Ok(ItemKind::Impl(Box::new(Impl {
             safety,
             polarity,
             defaultness,
@@ -696,12 +689,10 @@ impl<'a> Parser<'a> {
             of_trait,
             self_ty,
             items: impl_items,
-        }));
-
-        Ok((Ident::empty(), item_kind))
+        })))
     }
 
-    fn parse_item_delegation(&mut self) -> PResult<'a, ItemInfo> {
+    fn parse_item_delegation(&mut self) -> PResult<'a, ItemKind> {
         let span = self.token.span;
         self.expect_keyword(exp!(Reuse))?;
 
@@ -724,7 +715,7 @@ impl<'a> Parser<'a> {
             })
         };
 
-        let (ident, item_kind) = if self.eat_path_sep() {
+        let item_kind = if self.eat_path_sep() {
             let suffixes = if self.eat(exp!(Star)) {
                 None
             } else {
@@ -732,7 +723,7 @@ impl<'a> Parser<'a> {
                 Some(self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), parse_suffix)?.0)
             };
             let deleg = DelegationMac { qself, prefix: path, suffixes, body: body(self)? };
-            (Ident::empty(), ItemKind::DelegationMac(Box::new(deleg)))
+            ItemKind::DelegationMac(Box::new(deleg))
         } else {
             let rename = rename(self)?;
             let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident);
@@ -740,17 +731,18 @@ impl<'a> Parser<'a> {
                 id: DUMMY_NODE_ID,
                 qself,
                 path,
+                ident,
                 rename,
                 body: body(self)?,
                 from_glob: false,
             };
-            (ident, ItemKind::Delegation(Box::new(deleg)))
+            ItemKind::Delegation(Box::new(deleg))
         };
 
         let span = span.to(self.prev_token.span);
         self.psess.gated_spans.gate(sym::fn_delegation, span);
 
-        Ok((ident, item_kind))
+        Ok(item_kind)
     }
 
     fn parse_item_list<T>(
@@ -900,7 +892,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses `unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`.
-    fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemInfo> {
+    fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> {
         let safety = self.parse_safety(Case::Sensitive);
         // Parse optional `auto` prefix.
         let is_auto = if self.eat_keyword(exp!(Auto)) {
@@ -941,15 +933,12 @@ impl<'a> Parser<'a> {
 
             self.psess.gated_spans.gate(sym::trait_alias, whole_span);
 
-            Ok((ident, ItemKind::TraitAlias(generics, bounds)))
+            Ok(ItemKind::TraitAlias(ident, generics, bounds))
         } else {
             // It's a normal trait.
             generics.where_clause = self.parse_where_clause()?;
             let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
-            Ok((
-                ident,
-                ItemKind::Trait(Box::new(Trait { is_auto, safety, generics, bounds, items })),
-            ))
+            Ok(ItemKind::Trait(Box::new(Trait { is_auto, safety, ident, generics, bounds, items })))
         }
     }
 
@@ -977,11 +966,12 @@ impl<'a> Parser<'a> {
         force_collect: ForceCollect,
     ) -> PResult<'a, Option<Option<P<AssocItem>>>> {
         Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
-            |Item { attrs, id, span, vis, ident, kind, tokens }| {
+            |Item { attrs, id, span, vis, kind, tokens }| {
                 let kind = match AssocItemKind::try_from(kind) {
                     Ok(kind) => kind,
                     Err(kind) => match kind {
                         ItemKind::Static(box StaticItem {
+                            ident,
                             ty,
                             safety: _,
                             mutability: _,
@@ -991,6 +981,7 @@ impl<'a> Parser<'a> {
                             self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
                             AssocItemKind::Const(Box::new(ConstItem {
                                 defaultness: Defaultness::Final,
+                                ident,
                                 generics: Generics::default(),
                                 ty,
                                 expr,
@@ -1000,7 +991,7 @@ impl<'a> Parser<'a> {
                         _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
                     },
                 };
-                Some(P(Item { attrs, id, span, vis, ident, kind, tokens }))
+                Some(P(Item { attrs, id, span, vis, kind, tokens }))
             },
         ))
     }
@@ -1010,7 +1001,7 @@ impl<'a> Parser<'a> {
     /// TypeAlias = "type" Ident Generics (":" GenericBounds)? WhereClause ("=" Ty)? WhereClause ";" ;
     /// ```
     /// The `"type"` has already been eaten.
-    fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemInfo> {
+    fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemKind> {
         let ident = self.parse_ident()?;
         let mut generics = self.parse_generics()?;
 
@@ -1045,16 +1036,14 @@ impl<'a> Parser<'a> {
 
         self.expect_semi()?;
 
-        Ok((
+        Ok(ItemKind::TyAlias(Box::new(TyAlias {
+            defaultness,
             ident,
-            ItemKind::TyAlias(Box::new(TyAlias {
-                defaultness,
-                generics,
-                where_clauses,
-                bounds,
-                ty,
-            })),
-        ))
+            generics,
+            where_clauses,
+            bounds,
+            ty,
+        })))
     }
 
     /// Parses a `UseTree`.
@@ -1158,16 +1147,16 @@ impl<'a> Parser<'a> {
     /// extern crate foo;
     /// extern crate bar as foo;
     /// ```
-    fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemInfo> {
+    fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> {
         // Accept `extern crate name-like-this` for better diagnostics
-        let orig_name = self.parse_crate_name_with_dashes()?;
-        let (item_name, orig_name) = if let Some(rename) = self.parse_rename()? {
-            (rename, Some(orig_name.name))
+        let orig_ident = self.parse_crate_name_with_dashes()?;
+        let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? {
+            (Some(orig_ident.name), rename)
         } else {
-            (orig_name, None)
+            (None, orig_ident)
         };
         self.expect_semi()?;
-        Ok((item_name, ItemKind::ExternCrate(orig_name)))
+        Ok(ItemKind::ExternCrate(orig_name, item_ident))
     }
 
     fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
@@ -1218,7 +1207,7 @@ impl<'a> Parser<'a> {
         &mut self,
         attrs: &mut AttrVec,
         mut safety: Safety,
-    ) -> PResult<'a, ItemInfo> {
+    ) -> PResult<'a, ItemKind> {
         let extern_span = self.prev_token.uninterpolated_span();
         let abi = self.parse_abi(); // ABI?
         // FIXME: This recovery should be tested better.
@@ -1230,13 +1219,12 @@ impl<'a> Parser<'a> {
             safety = Safety::Unsafe(self.token.span);
             let _ = self.eat_keyword(exp!(Unsafe));
         }
-        let module = ast::ForeignMod {
+        Ok(ItemKind::ForeignMod(ast::ForeignMod {
             extern_span,
             safety,
             abi,
             items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
-        };
-        Ok((Ident::empty(), ItemKind::ForeignMod(module)))
+        }))
     }
 
     /// Parses a foreign item (one in an `extern { ... }` block).
@@ -1246,11 +1234,11 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, Option<Option<P<ForeignItem>>>> {
         let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: false };
         Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
-            |Item { attrs, id, span, vis, ident, kind, tokens }| {
+            |Item { attrs, id, span, vis, kind, tokens }| {
                 let kind = match ForeignItemKind::try_from(kind) {
                     Ok(kind) => kind,
                     Err(kind) => match kind {
-                        ItemKind::Const(box ConstItem { ty, expr, .. }) => {
+                        ItemKind::Const(box ConstItem { ident, ty, expr, .. }) => {
                             let const_span = Some(span.with_hi(ident.span.lo()))
                                 .filter(|span| span.can_be_used_for_suggestions());
                             self.dcx().emit_err(errors::ExternItemCannotBeConst {
@@ -1258,6 +1246,7 @@ impl<'a> Parser<'a> {
                                 const_span,
                             });
                             ForeignItemKind::Static(Box::new(StaticItem {
+                                ident,
                                 ty,
                                 mutability: Mutability::Not,
                                 expr,
@@ -1268,7 +1257,7 @@ impl<'a> Parser<'a> {
                         _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
                     },
                 };
-                Some(P(Item { attrs, id, span, vis, ident, kind, tokens }))
+                Some(P(Item { attrs, id, span, vis, kind, tokens }))
             },
         ))
     }
@@ -1343,13 +1332,13 @@ impl<'a> Parser<'a> {
         const_span: Span,
         attrs: &mut AttrVec,
         defaultness: Defaultness,
-    ) -> PResult<'a, ItemInfo> {
+    ) -> PResult<'a, ItemKind> {
         let impl_span = self.token.span;
         let err = self.expected_ident_found_err();
 
         // Only try to recover if this is implementing a trait for a type
-        let mut impl_info = match self.parse_item_impl(attrs, defaultness) {
-            Ok(impl_info) => impl_info,
+        let mut item_kind = match self.parse_item_impl(attrs, defaultness) {
+            Ok(item_kind) => item_kind,
             Err(recovery_error) => {
                 // Recovery failed, raise the "expected identifier" error
                 recovery_error.cancel();
@@ -1357,7 +1346,7 @@ impl<'a> Parser<'a> {
             }
         };
 
-        match &mut impl_info.1 {
+        match &mut item_kind {
             ItemKind::Impl(box Impl { of_trait: Some(trai), constness, .. }) => {
                 *constness = Const::Yes(const_span);
 
@@ -1374,10 +1363,11 @@ impl<'a> Parser<'a> {
             _ => unreachable!(),
         }
 
-        Ok(impl_info)
+        Ok(item_kind)
     }
 
-    /// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in `mutability`.
+    /// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in
+    /// `mutability`.
     ///
     /// ```ebnf
     /// Static = "static" "mut"? $ident ":" $ty (= $expr)? ";" ;
@@ -1386,7 +1376,7 @@ impl<'a> Parser<'a> {
         &mut self,
         safety: Safety,
         mutability: Mutability,
-    ) -> PResult<'a, (Ident, StaticItem)> {
+    ) -> PResult<'a, ItemKind> {
         let ident = self.parse_ident()?;
 
         if self.token == TokenKind::Lt && self.may_recover() {
@@ -1398,7 +1388,8 @@ impl<'a> Parser<'a> {
         // FIXME: This could maybe benefit from `.may_recover()`?
         let ty = match (self.eat(exp!(Colon)), self.check(exp!(Eq)) | self.check(exp!(Semi))) {
             (true, false) => self.parse_ty()?,
-            // If there wasn't a `:` or the colon was followed by a `=` or `;`, recover a missing type.
+            // If there wasn't a `:` or the colon was followed by a `=` or `;`, recover a missing
+            // type.
             (colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)),
         };
 
@@ -1406,7 +1397,8 @@ impl<'a> Parser<'a> {
 
         self.expect_semi()?;
 
-        Ok((ident, StaticItem { ty, safety, mutability, expr, define_opaque: None }))
+        let item = StaticItem { ident, ty, safety, mutability, expr, define_opaque: None };
+        Ok(ItemKind::Static(Box::new(item)))
     }
 
     /// Parse a constant item with the prefix `"const"` already parsed.
@@ -1531,7 +1523,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses an enum declaration.
-    fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
+    fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> {
         if self.token.is_keyword(kw::Struct) {
             let span = self.prev_token.span.to(self.token.span);
             let err = errors::EnumStructMutuallyExclusive { span };
@@ -1544,7 +1536,7 @@ impl<'a> Parser<'a> {
         }
 
         let prev_span = self.prev_token.span;
-        let id = self.parse_ident()?;
+        let ident = self.parse_ident()?;
         let mut generics = self.parse_generics()?;
         generics.where_clause = self.parse_where_clause()?;
 
@@ -1555,10 +1547,10 @@ impl<'a> Parser<'a> {
             (thin_vec![], Trailing::No)
         } else {
             self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), |p| {
-                p.parse_enum_variant(id.span)
+                p.parse_enum_variant(ident.span)
             })
             .map_err(|mut err| {
-                err.span_label(id.span, "while parsing this enum");
+                err.span_label(ident.span, "while parsing this enum");
                 if self.token == token::Colon {
                     let snapshot = self.create_snapshot_for_diagnostic();
                     self.bump();
@@ -1584,7 +1576,7 @@ impl<'a> Parser<'a> {
         };
 
         let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
-        Ok((id, ItemKind::Enum(enum_definition, generics)))
+        Ok(ItemKind::Enum(ident, enum_definition, generics))
     }
 
     fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
@@ -1676,8 +1668,8 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses `struct Foo { ... }`.
-    fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
-        let class_name = self.parse_ident()?;
+    fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> {
+        let ident = self.parse_ident()?;
 
         let mut generics = self.parse_generics()?;
 
@@ -1698,7 +1690,7 @@ impl<'a> Parser<'a> {
         let vdata = if self.token.is_keyword(kw::Where) {
             let tuple_struct_body;
             (generics.where_clause, tuple_struct_body) =
-                self.parse_struct_where_clause(class_name, generics.span)?;
+                self.parse_struct_where_clause(ident, generics.span)?;
 
             if let Some(body) = tuple_struct_body {
                 // If we see a misplaced tuple struct body: `struct Foo<T> where T: Copy, (T);`
@@ -1712,7 +1704,7 @@ impl<'a> Parser<'a> {
                 // If we see: `struct Foo<T> where T: Copy { ... }`
                 let (fields, recovered) = self.parse_record_struct_body(
                     "struct",
-                    class_name.span,
+                    ident.span,
                     generics.where_clause.has_where_token,
                 )?;
                 VariantData::Struct { fields, recovered }
@@ -1724,7 +1716,7 @@ impl<'a> Parser<'a> {
         } else if self.token == token::OpenDelim(Delimiter::Brace) {
             let (fields, recovered) = self.parse_record_struct_body(
                 "struct",
-                class_name.span,
+                ident.span,
                 generics.where_clause.has_where_token,
             )?;
             VariantData::Struct { fields, recovered }
@@ -1740,12 +1732,12 @@ impl<'a> Parser<'a> {
             return Err(self.dcx().create_err(err));
         };
 
-        Ok((class_name, ItemKind::Struct(vdata, generics)))
+        Ok(ItemKind::Struct(ident, vdata, generics))
     }
 
     /// Parses `union Foo { ... }`.
-    fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> {
-        let class_name = self.parse_ident()?;
+    fn parse_item_union(&mut self) -> PResult<'a, ItemKind> {
+        let ident = self.parse_ident()?;
 
         let mut generics = self.parse_generics()?;
 
@@ -1753,14 +1745,14 @@ impl<'a> Parser<'a> {
             generics.where_clause = self.parse_where_clause()?;
             let (fields, recovered) = self.parse_record_struct_body(
                 "union",
-                class_name.span,
+                ident.span,
                 generics.where_clause.has_where_token,
             )?;
             VariantData::Struct { fields, recovered }
         } else if self.token == token::OpenDelim(Delimiter::Brace) {
             let (fields, recovered) = self.parse_record_struct_body(
                 "union",
-                class_name.span,
+                ident.span,
                 generics.where_clause.has_where_token,
             )?;
             VariantData::Struct { fields, recovered }
@@ -1772,7 +1764,7 @@ impl<'a> Parser<'a> {
             return Err(err);
         };
 
-        Ok((class_name, ItemKind::Union(vdata, generics)))
+        Ok(ItemKind::Union(ident, vdata, generics))
     }
 
     /// This function parses the fields of record structs:
@@ -2124,15 +2116,17 @@ impl<'a> Parser<'a> {
                 }
             } else if self.eat_keyword(exp!(Struct)) {
                 match self.parse_item_struct() {
-                    Ok((ident, _)) => self
-                        .dcx()
-                        .struct_span_err(
-                            lo.with_hi(ident.span.hi()),
-                            format!("structs are not allowed in {adt_ty} definitions"),
-                        )
-                        .with_help(
-                            "consider creating a new `struct` definition instead of nesting",
-                        ),
+                    Ok(item) => {
+                        let ItemKind::Struct(ident, ..) = item else { unreachable!() };
+                        self.dcx()
+                            .struct_span_err(
+                                lo.with_hi(ident.span.hi()),
+                                format!("structs are not allowed in {adt_ty} definitions"),
+                            )
+                            .with_help(
+                                "consider creating a new `struct` definition instead of nesting",
+                            )
+                    }
                     Err(err) => {
                         err.cancel();
                         self.restore_snapshot(snapshot);
@@ -2177,7 +2171,7 @@ impl<'a> Parser<'a> {
     /// MacParams = "(" TOKEN_STREAM ")" ;
     /// DeclMac = "macro" Ident MacParams? MacBody ;
     /// ```
-    fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemInfo> {
+    fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> {
         let ident = self.parse_ident()?;
         let body = if self.check(exp!(OpenBrace)) {
             self.parse_delim_args()? // `MacBody`
@@ -2199,7 +2193,7 @@ impl<'a> Parser<'a> {
         };
 
         self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
-        Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: false })))
+        Ok(ItemKind::MacroDef(ident, ast::MacroDef { body, macro_rules: false }))
     }
 
     /// Is this a possibly malformed start of a `macro_rules! foo` item definition?
@@ -2228,7 +2222,7 @@ impl<'a> Parser<'a> {
         &mut self,
         vis: &Visibility,
         has_bang: bool,
-    ) -> PResult<'a, ItemInfo> {
+    ) -> PResult<'a, ItemKind> {
         self.expect_keyword(exp!(MacroRules))?; // `macro_rules`
 
         if has_bang {
@@ -2246,7 +2240,7 @@ impl<'a> Parser<'a> {
         self.eat_semi_for_macro_if_needed(&body);
         self.complain_if_pub_macro(vis, true);
 
-        Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: true })))
+        Ok(ItemKind::MacroDef(ident, ast::MacroDef { body, macro_rules: true }))
     }
 
     /// Item macro invocations or `macro_rules!` definitions need inherited visibility.
diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs
index 471966d086d5f..49ae6cb9b7264 100644
--- a/compiler/rustc_parse/src/parser/tests.rs
+++ b/compiler/rustc_parse/src/parser/tests.rs
@@ -2922,7 +2922,7 @@ fn out_of_line_mod() {
         .unwrap()
         .unwrap();
 
-        let ast::ItemKind::Mod(_, mod_kind) = &item.kind else { panic!() };
+        let ast::ItemKind::Mod(_, _, mod_kind) = &item.kind else { panic!() };
         assert_matches!(mod_kind, ast::ModKind::Loaded(items, ..) if items.len() == 2);
     });
 }
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 9d4b46cd30660..664bd4ad0a252 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -268,22 +268,22 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
 impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
     fn visit_item(&mut self, i: &'ast ast::Item) {
         let target = match &i.kind {
-            ast::ItemKind::ExternCrate(_) => Target::ExternCrate,
+            ast::ItemKind::ExternCrate(..) => Target::ExternCrate,
             ast::ItemKind::Use(_) => Target::Use,
             ast::ItemKind::Static(_) => Target::Static,
             ast::ItemKind::Const(_) => Target::Const,
             ast::ItemKind::Fn(_) | ast::ItemKind::Delegation(..) => Target::Fn,
-            ast::ItemKind::Mod(_, _) => Target::Mod,
+            ast::ItemKind::Mod(..) => Target::Mod,
             ast::ItemKind::ForeignMod(_) => Target::ForeignFn,
             ast::ItemKind::GlobalAsm(_) => Target::GlobalAsm,
             ast::ItemKind::TyAlias(_) => Target::TyAlias,
-            ast::ItemKind::Enum(_, _) => Target::Enum,
-            ast::ItemKind::Struct(_, _) => Target::Struct,
-            ast::ItemKind::Union(_, _) => Target::Union,
+            ast::ItemKind::Enum(..) => Target::Enum,
+            ast::ItemKind::Struct(..) => Target::Struct,
+            ast::ItemKind::Union(..) => Target::Union,
             ast::ItemKind::Trait(_) => Target::Trait,
-            ast::ItemKind::TraitAlias(_, _) => Target::TraitAlias,
+            ast::ItemKind::TraitAlias(..) => Target::TraitAlias,
             ast::ItemKind::Impl(_) => Target::Impl,
-            ast::ItemKind::MacroDef(_) => Target::MacroDef,
+            ast::ItemKind::MacroDef(..) => Target::MacroDef,
             ast::ItemKind::MacCall(_) | ast::ItemKind::DelegationMac(_) => {
                 unreachable!("macros should have been expanded")
             }
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 97fbf7e378acf..4368f7882ff46 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -10,8 +10,8 @@ use std::sync::Arc;
 
 use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind};
 use rustc_ast::{
-    self as ast, AssocItem, AssocItemKind, Block, ForeignItem, ForeignItemKind, Impl, Item,
-    ItemKind, MetaItemKind, NodeId, StmtKind,
+    self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, Fn, ForeignItem,
+    ForeignItemKind, Impl, Item, ItemKind, MetaItemKind, NodeId, StaticItem, StmtKind, TyAlias,
 };
 use rustc_attr_parsing as attr;
 use rustc_expand::base::ResolverExpand;
@@ -735,7 +735,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         let parent_scope = &self.parent_scope;
         let parent = parent_scope.module;
         let expansion = parent_scope.expansion;
-        let ident = item.ident;
         let sp = item.span;
         let vis = self.resolve_visibility(&item.vis);
         let feed = self.r.feed(item.id);
@@ -762,17 +761,18 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 );
             }
 
-            ItemKind::ExternCrate(orig_name) => {
+            ItemKind::ExternCrate(orig_name, ident) => {
                 self.build_reduced_graph_for_extern_crate(
                     orig_name,
                     item,
+                    ident,
                     local_def_id,
                     vis,
                     parent,
                 );
             }
 
-            ItemKind::Mod(.., ref mod_kind) => {
+            ItemKind::Mod(_, ident, ref mod_kind) => {
                 let module = self.r.new_module(
                     Some(parent),
                     ModuleKind::Def(def_kind, def_id, Some(ident.name)),
@@ -792,10 +792,12 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             }
 
             // These items live in the value namespace.
-            ItemKind::Const(..) | ItemKind::Delegation(..) | ItemKind::Static(..) => {
+            ItemKind::Const(box ConstItem { ident, .. })
+            | ItemKind::Delegation(box Delegation { ident, .. })
+            | ItemKind::Static(box StaticItem { ident, .. }) => {
                 self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
             }
-            ItemKind::Fn(..) => {
+            ItemKind::Fn(box Fn { ident, .. }) => {
                 self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
 
                 // Functions introducing procedural macros reserve a slot
@@ -804,11 +806,11 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             }
 
             // These items live in the type namespace.
-            ItemKind::TyAlias(..) | ItemKind::TraitAlias(..) => {
+            ItemKind::TyAlias(box TyAlias { ident, .. }) | ItemKind::TraitAlias(ident, ..) => {
                 self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
             }
 
-            ItemKind::Enum(_, _) | ItemKind::Trait(..) => {
+            ItemKind::Enum(ident, _, _) | ItemKind::Trait(box ast::Trait { ident, .. }) => {
                 let module = self.r.new_module(
                     Some(parent),
                     ModuleKind::Def(def_kind, def_id, Some(ident.name)),
@@ -821,7 +823,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             }
 
             // These items live in both the type and value namespaces.
-            ItemKind::Struct(ref vdata, _) => {
+            ItemKind::Struct(ident, ref vdata, _) => {
                 self.build_reduced_graph_for_struct_variant(
                     vdata.fields(),
                     ident,
@@ -872,7 +874,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 }
             }
 
-            ItemKind::Union(ref vdata, _) => {
+            ItemKind::Union(ident, ref vdata, _) => {
                 self.build_reduced_graph_for_struct_variant(
                     vdata.fields(),
                     ident,
@@ -899,11 +901,11 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         &mut self,
         orig_name: Option<Symbol>,
         item: &Item,
+        ident: Ident,
         local_def_id: LocalDefId,
         vis: ty::Visibility,
         parent: Module<'ra>,
     ) {
-        let ident = item.ident;
         let sp = item.span;
         let parent_scope = self.parent_scope;
         let expansion = parent_scope.expansion;
@@ -987,7 +989,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
     }
 
     /// Constructs the reduced graph for one foreign item.
-    fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) {
+    fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, ident: Ident) {
         let feed = self.r.feed(item.id);
         let local_def_id = feed.key();
         let def_id = local_def_id.to_def_id();
@@ -1000,7 +1002,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         let parent = self.parent_scope.module;
         let expansion = self.parent_scope.expansion;
         let vis = self.resolve_visibility(&item.vis);
-        self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion));
+        self.r.define(parent, ident, ns, (self.res(def_id), vis, item.span, expansion));
         self.r.feed_visibility(feed, vis);
     }
 
@@ -1043,7 +1045,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                         span: item.span,
                     });
                 }
-                if let ItemKind::ExternCrate(Some(orig_name)) = item.kind
+                if let ItemKind::ExternCrate(Some(orig_name), _) = item.kind
                     && orig_name == kw::SelfLower
                 {
                     self.r.dcx().emit_err(errors::MacroUseExternCrateSelf { span: attr.span });
@@ -1177,11 +1179,15 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Invocation(invoc_id))
     }
 
-    fn proc_macro_stub(&self, item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {
+    fn proc_macro_stub(
+        &self,
+        item: &ast::Item,
+        fn_ident: Ident,
+    ) -> Option<(MacroKind, Ident, Span)> {
         if ast::attr::contains_name(&item.attrs, sym::proc_macro) {
-            return Some((MacroKind::Bang, item.ident, item.span));
+            return Some((MacroKind::Bang, fn_ident, item.span));
         } else if ast::attr::contains_name(&item.attrs, sym::proc_macro_attribute) {
-            return Some((MacroKind::Attr, item.ident, item.span));
+            return Some((MacroKind::Attr, fn_ident, item.span));
         } else if let Some(attr) = ast::attr::find_by_name(&item.attrs, sym::proc_macro_derive)
             && let Some(meta_item_inner) =
                 attr.meta_item_list().and_then(|list| list.get(0).cloned())
@@ -1214,17 +1220,21 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         let feed = self.r.feed(item.id);
         let def_id = feed.key();
         let (res, ident, span, macro_rules) = match &item.kind {
-            ItemKind::MacroDef(def) => (self.res(def_id), item.ident, item.span, def.macro_rules),
-            ItemKind::Fn(..) => match self.proc_macro_stub(item) {
-                Some((macro_kind, ident, span)) => {
-                    let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id());
-                    let macro_data = MacroData::new(self.r.dummy_ext(macro_kind));
-                    self.r.macro_map.insert(def_id.to_def_id(), macro_data);
-                    self.r.proc_macro_stubs.insert(def_id);
-                    (res, ident, span, false)
+            ItemKind::MacroDef(ident, def) => {
+                (self.res(def_id), *ident, item.span, def.macro_rules)
+            }
+            ItemKind::Fn(box ast::Fn { ident: fn_ident, .. }) => {
+                match self.proc_macro_stub(item, *fn_ident) {
+                    Some((macro_kind, ident, span)) => {
+                        let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id());
+                        let macro_data = MacroData::new(self.r.dummy_ext(macro_kind));
+                        self.r.macro_map.insert(def_id.to_def_id(), macro_data);
+                        self.r.proc_macro_stubs.insert(def_id);
+                        (res, ident, span, false)
+                    }
+                    None => return parent_scope.macro_rules,
                 }
-                None => return parent_scope.macro_rules,
-            },
+            }
             _ => unreachable!(),
         };
 
@@ -1327,8 +1337,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                         // Visit attributes after items for backward compatibility.
                         // This way they can use `macro_rules` defined later.
                         self.visit_vis(&item.vis);
-                        self.visit_ident(&item.ident);
-                        item.kind.walk(item.span, item.id, &item.ident, &item.vis, (), self);
+                        item.kind.walk(item.span, item.id, &item.vis, (), self);
                         visit::walk_list!(self, visit_attribute, &item.attrs);
                     }
                     _ => visit::walk_item(self, item),
@@ -1353,12 +1362,17 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
-        if let ForeignItemKind::MacCall(_) = foreign_item.kind {
-            self.visit_invoc_in_module(foreign_item.id);
-            return;
-        }
+        let ident = match foreign_item.kind {
+            ForeignItemKind::Static(box StaticItem { ident, .. })
+            | ForeignItemKind::Fn(box Fn { ident, .. })
+            | ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => ident,
+            ForeignItemKind::MacCall(_) => {
+                self.visit_invoc_in_module(foreign_item.id);
+                return;
+            }
+        };
 
-        self.build_reduced_graph_for_foreign_item(foreign_item);
+        self.build_reduced_graph_for_foreign_item(foreign_item, ident);
         visit::walk_item(self, foreign_item);
     }
 
@@ -1372,26 +1386,35 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
     }
 
     fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
-        if let AssocItemKind::MacCall(_) = item.kind {
-            match ctxt {
-                AssocCtxt::Trait => {
-                    self.visit_invoc_in_module(item.id);
-                }
-                AssocCtxt::Impl { .. } => {
-                    let invoc_id = item.id.placeholder_to_expn_id();
-                    if !self.r.glob_delegation_invoc_ids.contains(&invoc_id) {
-                        self.r
-                            .impl_unexpanded_invocations
-                            .entry(self.r.invocation_parent(invoc_id))
-                            .or_default()
-                            .insert(invoc_id);
+        let (ident, ns) = match item.kind {
+            AssocItemKind::Const(box ConstItem { ident, .. })
+            | AssocItemKind::Fn(box Fn { ident, .. })
+            | AssocItemKind::Delegation(box Delegation { ident, .. }) => (ident, ValueNS),
+
+            AssocItemKind::Type(box TyAlias { ident, .. }) => (ident, TypeNS),
+
+            AssocItemKind::MacCall(_) => {
+                match ctxt {
+                    AssocCtxt::Trait => {
+                        self.visit_invoc_in_module(item.id);
+                    }
+                    AssocCtxt::Impl { .. } => {
+                        let invoc_id = item.id.placeholder_to_expn_id();
+                        if !self.r.glob_delegation_invoc_ids.contains(&invoc_id) {
+                            self.r
+                                .impl_unexpanded_invocations
+                                .entry(self.r.invocation_parent(invoc_id))
+                                .or_default()
+                                .insert(invoc_id);
+                        }
+                        self.visit_invoc(item.id);
                     }
-                    self.visit_invoc(item.id);
                 }
+                return;
             }
-            return;
-        }
 
+            AssocItemKind::DelegationMac(..) => bug!(),
+        };
         let vis = self.resolve_visibility(&item.vis);
         let feed = self.r.feed(item.id);
         let local_def_id = feed.key();
@@ -1406,20 +1429,13 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             self.r.feed_visibility(feed, vis);
         }
 
-        let ns = match item.kind {
-            AssocItemKind::Const(..) | AssocItemKind::Delegation(..) | AssocItemKind::Fn(..) => {
-                ValueNS
-            }
-            AssocItemKind::Type(..) => TypeNS,
-            AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => bug!(), // handled above
-        };
         if ctxt == AssocCtxt::Trait {
             let parent = self.parent_scope.module;
             let expansion = self.parent_scope.expansion;
-            self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion));
+            self.r.define(parent, ident, ns, (self.res(def_id), vis, item.span, expansion));
         } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) {
             let impl_def_id = self.r.tcx.local_parent(local_def_id);
-            let key = BindingKey::new(item.ident.normalize_to_macros_2_0(), ns);
+            let key = BindingKey::new(ident.normalize_to_macros_2_0(), ns);
             self.r.impl_binding_keys.entry(impl_def_id).or_default().insert(key);
         }
 
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 51ff4aa834baa..e97233e97ce55 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -219,14 +219,14 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'ra, 'tcx> {
             // because this means that they were generated in some fashion by the
             // compiler and we don't need to consider them.
             ast::ItemKind::Use(..) if item.span.is_dummy() => return,
-            ast::ItemKind::ExternCrate(orig_name) => {
+            ast::ItemKind::ExternCrate(orig_name, ident) => {
                 self.extern_crate_items.push(ExternCrateToLint {
                     id: item.id,
                     span: item.span,
                     vis_span: item.vis.span,
                     span_with_attributes: item.span_with_attributes(),
                     has_attrs: !item.attrs.is_empty(),
-                    ident: item.ident,
+                    ident,
                     renames: orig_name.is_some(),
                 });
             }
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 6f48a75d61742..13dfb59f27fc0 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -122,7 +122,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
             },
             ItemKind::Const(..) => DefKind::Const,
             ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
-            ItemKind::MacroDef(def) => {
+            ItemKind::MacroDef(ident, def) => {
                 let edition = i.span.edition();
 
                 // FIXME(jdonszelmann) make one of these in the resolver?
@@ -141,7 +141,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
                 );
 
                 let macro_data =
-                    self.resolver.compile_macro(def, i.ident, &attrs, i.span, i.id, edition);
+                    self.resolver.compile_macro(def, *ident, &attrs, i.span, i.id, edition);
                 let macro_kind = macro_data.ext.macro_kind();
                 opt_macro_data = Some(macro_data);
                 DefKind::Macro(macro_kind)
@@ -152,7 +152,8 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
                 return self.visit_macro_invoc(i.id);
             }
         };
-        let def_id = self.create_def(i.id, Some(i.ident.name), def_kind, i.span);
+        let def_id =
+            self.create_def(i.id, i.kind.ident().map(|ident| ident.name), def_kind, i.span);
 
         if let Some(macro_data) = opt_macro_data {
             self.resolver.macro_map.insert(def_id.to_def_id(), macro_data);
@@ -161,7 +162,8 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
         self.with_parent(def_id, |this| {
             this.with_impl_trait(ImplTraitContext::Existential, |this| {
                 match i.kind {
-                    ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
+                    ItemKind::Struct(_, ref struct_def, _)
+                    | ItemKind::Union(_, ref struct_def, _) => {
                         // If this is a unit or tuple-like struct, register the constructor.
                         if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(struct_def) {
                             this.create_def(
@@ -183,10 +185,12 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
         match fn_kind {
             FnKind::Fn(
                 _ctxt,
-                _ident,
                 _vis,
-                Fn { sig: FnSig { header, decl, span: _ }, generics, contract, body, .. },
+                Fn {
+                    sig: FnSig { header, decl, span: _ }, ident, generics, contract, body, ..
+                },
             ) if let Some(coroutine_kind) = header.coroutine_kind => {
+                self.visit_ident(ident);
                 self.visit_fn_header(header);
                 self.visit_generics(generics);
                 if let Some(contract) = contract {
@@ -234,8 +238,9 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
     }
 
     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
-        let def_kind = match fi.kind {
+        let (ident, def_kind) = match fi.kind {
             ForeignItemKind::Static(box StaticItem {
+                ident,
                 ty: _,
                 mutability,
                 expr: _,
@@ -247,14 +252,14 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
                     ast::Safety::Safe(_) => hir::Safety::Safe,
                 };
 
-                DefKind::Static { safety, mutability, nested: false }
+                (ident, DefKind::Static { safety, mutability, nested: false })
             }
-            ForeignItemKind::Fn(_) => DefKind::Fn,
-            ForeignItemKind::TyAlias(_) => DefKind::ForeignTy,
+            ForeignItemKind::Fn(box Fn { ident, .. }) => (ident, DefKind::Fn),
+            ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => (ident, DefKind::ForeignTy),
             ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id),
         };
 
-        let def = self.create_def(fi.id, Some(fi.ident.name), def_kind, fi.span);
+        let def = self.create_def(fi.id, Some(ident.name), def_kind, fi.span);
 
         self.with_parent(def, |this| visit::walk_item(this, fi));
     }
@@ -318,16 +323,17 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
     }
 
     fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
-        let def_kind = match &i.kind {
-            AssocItemKind::Fn(..) | AssocItemKind::Delegation(..) => DefKind::AssocFn,
-            AssocItemKind::Const(..) => DefKind::AssocConst,
-            AssocItemKind::Type(..) => DefKind::AssocTy,
+        let (ident, def_kind) = match &i.kind {
+            AssocItemKind::Fn(box Fn { ident, .. })
+            | AssocItemKind::Delegation(box Delegation { ident, .. }) => (*ident, DefKind::AssocFn),
+            AssocItemKind::Const(box ConstItem { ident, .. }) => (*ident, DefKind::AssocConst),
+            AssocItemKind::Type(box TyAlias { ident, .. }) => (*ident, DefKind::AssocTy),
             AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
                 return self.visit_macro_invoc(i.id);
             }
         };
 
-        let def = self.create_def(i.id, Some(i.ident.name), def_kind, i.span);
+        let def = self.create_def(i.id, Some(ident.name), def_kind, i.span);
         self.with_parent(def, |this| visit::walk_assoc_item(this, i, ctxt));
     }
 
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 63ea8c4ced13c..7d6af12909c71 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -3063,7 +3063,7 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder {
 
     fn visit_item(&mut self, item: &'tcx ast::Item) {
         if self.target_module == item.id {
-            if let ItemKind::Mod(_, ModKind::Loaded(items, _inline, mod_spans, _)) = &item.kind {
+            if let ItemKind::Mod(_, _, ModKind::Loaded(items, _inline, mod_spans, _)) = &item.kind {
                 let inject = mod_spans.inject_use_span;
                 if is_span_suitable_for_use_injection(inject) {
                     self.first_legal_span = Some(inject);
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 6ef4aa407253d..a5ca4565d7b42 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -252,7 +252,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx>
                 self.current_private_vis = prev_private_vis;
             }
 
-            ast::ItemKind::Enum(EnumDef { ref variants }, _) => {
+            ast::ItemKind::Enum(_, EnumDef { ref variants }, _) => {
                 self.set_bindings_effective_visibilities(def_id);
                 for variant in variants {
                     let variant_def_id = self.r.local_def_id(variant.id);
@@ -262,7 +262,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx>
                 }
             }
 
-            ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => {
+            ast::ItemKind::Struct(_, ref def, _) | ast::ItemKind::Union(_, ref def, _) => {
                 for field in def.fields() {
                     self.update_field(self.r.local_def_id(field.id), def_id);
                 }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 0d23ae501f04b..20e19caf9096b 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1025,9 +1025,10 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
         match fn_kind {
             // Bail if the function is foreign, and thus cannot validly have
             // a body, or if there's no body for some other reason.
-            FnKind::Fn(FnCtxt::Foreign, _, _, Fn { sig, generics, .. })
-            | FnKind::Fn(_, _, _, Fn { sig, generics, body: None, .. }) => {
+            FnKind::Fn(FnCtxt::Foreign, _, Fn { sig, ident, generics, .. })
+            | FnKind::Fn(_, _, Fn { sig, ident, generics, body: None, .. }) => {
                 self.visit_fn_header(&sig.header);
+                self.visit_ident(ident);
                 self.visit_generics(generics);
                 self.with_lifetime_rib(
                     LifetimeRibKind::AnonymousCreateParameter {
@@ -1058,7 +1059,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
             // Create a label rib for the function.
             this.with_label_rib(RibKind::FnOrCoroutine, |this| {
                 match fn_kind {
-                    FnKind::Fn(_, _, _, Fn { sig, generics, contract, body, .. }) => {
+                    FnKind::Fn(_, _, Fn { sig, generics, contract, body, .. }) => {
                         this.visit_generics(generics);
 
                         let declaration = &sig.decl;
@@ -2632,8 +2633,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
         }
 
-        let name = item.ident.name;
-        debug!("(resolving item) resolving {} ({:?})", name, item.kind);
+        debug!("(resolving item) resolving {:?} ({:?})", item.kind.ident(), item.kind);
 
         let def_kind = self.r.local_def_kind(item.id);
         match item.kind {
@@ -2664,9 +2664,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 self.resolve_define_opaques(define_opaque);
             }
 
-            ItemKind::Enum(_, ref generics)
-            | ItemKind::Struct(_, ref generics)
-            | ItemKind::Union(_, ref generics) => {
+            ItemKind::Enum(_, _, ref generics)
+            | ItemKind::Struct(_, _, ref generics)
+            | ItemKind::Union(_, _, ref generics) => {
                 self.resolve_adt(item, generics);
             }
 
@@ -2710,7 +2710,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 );
             }
 
-            ItemKind::TraitAlias(ref generics, ref bounds) => {
+            ItemKind::TraitAlias(_, ref generics, ref bounds) => {
                 // Create a new rib for the trait-wide type parameters.
                 self.with_generic_param_rib(
                     &generics.params,
@@ -2748,7 +2748,11 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             }
 
             ItemKind::Static(box ast::StaticItem {
-                ref ty, ref expr, ref define_opaque, ..
+                ident,
+                ref ty,
+                ref expr,
+                ref define_opaque,
+                ..
             }) => {
                 self.with_static_rib(def_kind, |this| {
                     this.with_lifetime_rib(
@@ -2762,13 +2766,14 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                     if let Some(expr) = expr {
                         // We already forbid generic params because of the above item rib,
                         // so it doesn't matter whether this is a trivial constant.
-                        this.resolve_const_body(expr, Some((item.ident, ConstantItemKind::Static)));
+                        this.resolve_const_body(expr, Some((ident, ConstantItemKind::Static)));
                     }
                 });
                 self.resolve_define_opaques(define_opaque);
             }
 
             ItemKind::Const(box ast::ConstItem {
+                ident,
                 ref generics,
                 ref ty,
                 ref expr,
@@ -2801,10 +2806,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                         );
 
                         if let Some(expr) = expr {
-                            this.resolve_const_body(
-                                expr,
-                                Some((item.ident, ConstantItemKind::Const)),
-                            );
+                            this.resolve_const_body(expr, Some((ident, ConstantItemKind::Const)));
                         }
                     },
                 );
@@ -2821,7 +2823,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 self.future_proof_import(use_tree);
             }
 
-            ItemKind::MacroDef(ref macro_def) => {
+            ItemKind::MacroDef(_, ref macro_def) => {
                 // Maintain macro_rules scopes in the same way as during early resolution
                 // for diagnostics and doc links.
                 if macro_def.macro_rules {
@@ -3319,7 +3321,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis)));
         match &item.kind {
             AssocItemKind::Const(box ast::ConstItem {
-                generics, ty, expr, define_opaque, ..
+                ident,
+                generics,
+                ty,
+                expr,
+                define_opaque,
+                ..
             }) => {
                 debug!("resolve_implementation AssocItemKind::Const");
                 self.with_generic_param_rib(
@@ -3350,7 +3357,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                                         // exists in trait
                                         this.check_trait_item(
                                             item.id,
-                                            item.ident,
+                                            *ident,
                                             &item.kind,
                                             ValueNS,
                                             item.span,
@@ -3376,7 +3383,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 );
                 self.resolve_define_opaques(define_opaque);
             }
-            AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
+            AssocItemKind::Fn(box Fn { ident, generics, define_opaque, .. }) => {
                 debug!("resolve_implementation AssocItemKind::Fn");
                 // We also need a new scope for the impl item type parameters.
                 self.with_generic_param_rib(
@@ -3392,7 +3399,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                         // exists in trait
                         this.check_trait_item(
                             item.id,
-                            item.ident,
+                            *ident,
                             &item.kind,
                             ValueNS,
                             item.span,
@@ -3406,7 +3413,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
 
                 self.resolve_define_opaques(define_opaque);
             }
-            AssocItemKind::Type(box TyAlias { generics, .. }) => {
+            AssocItemKind::Type(box TyAlias { ident, generics, .. }) => {
                 self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty());
                 debug!("resolve_implementation AssocItemKind::Type");
                 // We also need a new scope for the impl item type parameters.
@@ -3424,7 +3431,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                             // exists in trait
                             this.check_trait_item(
                                 item.id,
-                                item.ident,
+                                *ident,
                                 &item.kind,
                                 TypeNS,
                                 item.span,
@@ -3451,7 +3458,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                     |this| {
                         this.check_trait_item(
                             item.id,
-                            item.ident,
+                            delegation.ident,
                             &item.kind,
                             ValueNS,
                             item.span,
@@ -4337,7 +4344,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 if let Some(items) = self.diag_metadata.current_trait_assoc_items
                     && let [Segment { ident, .. }] = path
                     && items.iter().any(|item| {
-                        item.ident == *ident && matches!(item.kind, AssocItemKind::Type(_))
+                        if let AssocItemKind::Type(alias) = &item.kind
+                            && alias.ident == *ident
+                        {
+                            true
+                        } else {
+                            false
+                        }
                     })
                 {
                     let mut diag = self.r.tcx.dcx().struct_allow("");
@@ -5159,12 +5172,12 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
             ItemKind::TyAlias(box TyAlias { generics, .. })
             | ItemKind::Const(box ConstItem { generics, .. })
             | ItemKind::Fn(box Fn { generics, .. })
-            | ItemKind::Enum(_, generics)
-            | ItemKind::Struct(_, generics)
-            | ItemKind::Union(_, generics)
+            | ItemKind::Enum(_, _, generics)
+            | ItemKind::Struct(_, _, generics)
+            | ItemKind::Union(_, _, generics)
             | ItemKind::Impl(box Impl { generics, .. })
             | ItemKind::Trait(box Trait { generics, .. })
-            | ItemKind::TraitAlias(generics, _) => {
+            | ItemKind::TraitAlias(_, generics, _) => {
                 if let ItemKind::Fn(box Fn { sig, .. }) = &item.kind {
                     self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs);
                 }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index e40f84e7e598e..b62bc6c45e0c5 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -224,12 +224,13 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 let suggestion = if self.current_trait_ref.is_none()
                     && let Some((fn_kind, _)) = self.diag_metadata.current_function
                     && let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt()
-                    && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = fn_kind
+                    && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = fn_kind
                     && let Some(items) = self.diag_metadata.current_impl_items
                     && let Some(item) = items.iter().find(|i| {
-                        i.ident.name == item_str.name
+                        i.kind.ident().is_some_and(|ident| {
                             // Don't suggest if the item is in Fn signature arguments (#112590).
-                            && !sig.span.contains(item_span)
+                            ident.name == item_str.name && !sig.span.contains(item_span)
+                        })
                     }) {
                     let sp = item_span.shrink_to_lo();
 
@@ -268,14 +269,14 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                             // you can't call `fn foo(&self)` from `fn bar()` (#115992).
                             // We also want to mention that the method exists.
                             span_label = Some((
-                                item.ident.span,
+                                fn_.ident.span,
                                 "a method by that name is available on `Self` here",
                             ));
                             None
                         }
                         AssocItemKind::Fn(fn_) if !fn_.sig.decl.has_self() && !is_call => {
                             span_label = Some((
-                                item.ident.span,
+                                fn_.ident.span,
                                 "an associated function by that name is available on `Self` here",
                             ));
                             None
@@ -604,7 +605,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 Applicability::MaybeIncorrect,
             );
             if !self.self_value_is_available(path[0].ident.span) {
-                if let Some((FnKind::Fn(_, _, _, ast::Fn { sig, .. }), fn_span)) =
+                if let Some((FnKind::Fn(_, _, ast::Fn { sig, .. }), fn_span)) =
                     &self.diag_metadata.current_function
                 {
                     let (span, sugg) = if let Some(param) = sig.decl.inputs.get(0) {
@@ -1064,15 +1065,11 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         }
         err.code(E0411);
         err.span_label(span, "`Self` is only available in impls, traits, and type definitions");
-        if let Some(item_kind) = self.diag_metadata.current_item {
-            if !item_kind.ident.span.is_dummy() {
+        if let Some(item) = self.diag_metadata.current_item {
+            if let Some(ident) = item.kind.ident() {
                 err.span_label(
-                    item_kind.ident.span,
-                    format!(
-                        "`Self` not allowed in {} {}",
-                        item_kind.kind.article(),
-                        item_kind.kind.descr()
-                    ),
+                    ident.span,
+                    format!("`Self` not allowed in {} {}", item.kind.article(), item.kind.descr()),
                 );
             }
         }
@@ -1150,17 +1147,14 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                     );
                 }
             }
-        } else if let Some(item_kind) = self.diag_metadata.current_item {
-            if matches!(item_kind.kind, ItemKind::Delegation(..)) {
-                err.span_label(item_kind.span, format!("delegation supports {self_from_macro}"));
+        } else if let Some(item) = self.diag_metadata.current_item {
+            if matches!(item.kind, ItemKind::Delegation(..)) {
+                err.span_label(item.span, format!("delegation supports {self_from_macro}"));
             } else {
+                let span = if let Some(ident) = item.kind.ident() { ident.span } else { item.span };
                 err.span_label(
-                    item_kind.ident.span,
-                    format!(
-                        "`self` not allowed in {} {}",
-                        item_kind.kind.article(),
-                        item_kind.kind.descr()
-                    ),
+                    span,
+                    format!("`self` not allowed in {} {}", item.kind.article(), item.kind.descr()),
                 );
             }
         }
@@ -2196,7 +2190,9 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
 
         if let Some(items) = self.diag_metadata.current_trait_assoc_items {
             for assoc_item in items {
-                if assoc_item.ident == ident {
+                if let Some(assoc_ident) = assoc_item.kind.ident()
+                    && assoc_ident == ident
+                {
                     return Some(match &assoc_item.kind {
                         ast::AssocItemKind::Const(..) => AssocSuggestion::AssocConst,
                         ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) if sig.decl.has_self() => {
@@ -2735,7 +2731,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             return None;
         }
         match (self.diag_metadata.current_item, single_uppercase_char, self.diag_metadata.currently_processing_generic_args) {
-            (Some(Item { kind: ItemKind::Fn(..), ident, .. }), _, _) if ident.name == sym::main => {
+            (Some(Item { kind: ItemKind::Fn(fn_), .. }), _, _) if fn_.ident.name == sym::main => {
                 // Ignore `fn main()` as we don't want to suggest `fn main<T>()`
             }
             (
@@ -3400,7 +3396,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                     {
                         let pre = if lt.kind == MissingLifetimeKind::Ampersand
                             && let Some((kind, _span)) = self.diag_metadata.current_function
-                            && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind
+                            && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind
                             && !sig.decl.inputs.is_empty()
                             && let sugg = sig
                                 .decl
@@ -3441,7 +3437,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                         } else if (lt.kind == MissingLifetimeKind::Ampersand
                             || lt.kind == MissingLifetimeKind::Underscore)
                             && let Some((kind, _span)) = self.diag_metadata.current_function
-                            && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind
+                            && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind
                             && let ast::FnRetTy::Ty(ret_ty) = &sig.decl.output
                             && !sig.decl.inputs.is_empty()
                             && let arg_refs = sig
@@ -3501,7 +3497,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                         let mut owned_sugg = lt.kind == MissingLifetimeKind::Ampersand;
                         let mut sugg = vec![(lt.span, String::new())];
                         if let Some((kind, _span)) = self.diag_metadata.current_function
-                            && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind
+                            && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind
                             && let ast::FnRetTy::Ty(ty) = &sig.decl.output
                         {
                             let mut lt_finder =
diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs
index 56b1e76ae8cfd..4edd5433de6cd 100644
--- a/src/librustdoc/doctest/make.rs
+++ b/src/librustdoc/doctest/make.rs
@@ -350,21 +350,21 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn
             info.has_global_allocator = true;
         }
         match item.kind {
-            ast::ItemKind::Fn(_) if !info.has_main_fn => {
+            ast::ItemKind::Fn(ref fn_item) if !info.has_main_fn => {
                 // We only push if it's the top item because otherwise, we would duplicate
                 // its content since the top-level item was already added.
-                if item.ident.name == sym::main {
+                if fn_item.ident.name == sym::main {
                     info.has_main_fn = true;
                 }
             }
-            ast::ItemKind::ExternCrate(original) => {
+            ast::ItemKind::ExternCrate(original, ident) => {
                 is_extern_crate = true;
                 if !info.already_has_extern_crate
                     && let Some(crate_name) = crate_name
                 {
                     info.already_has_extern_crate = match original {
                         Some(name) => name.as_str() == *crate_name,
-                        None => item.ident.as_str() == *crate_name,
+                        None => ident.as_str() == *crate_name,
                     };
                 }
             }
diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
index 7d86bd3e540a1..c2aac7ca090bb 100644
--- a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
+++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
@@ -53,7 +53,7 @@ declare_lint_pass!(CrateInMacroDef => [CRATE_IN_MACRO_DEF]);
 
 impl EarlyLintPass for CrateInMacroDef {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        if let ItemKind::MacroDef(macro_def) = &item.kind
+        if let ItemKind::MacroDef(_, macro_def) = &item.kind
             && item.attrs.iter().any(is_macro_export)
             && let Some(span) = contains_unhygienic_crate_reference(&macro_def.body.tokens)
         {
diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
index 3008082c2329d..f6c10da1596b2 100644
--- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
@@ -13,16 +13,16 @@ use rustc_parse::parser::ForceCollect;
 use rustc_session::parse::ParseSess;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::{FilePathMapping, SourceMap};
-use rustc_span::{FileName, Pos, sym};
+use rustc_span::{FileName, Ident, Pos, sym};
 
 use super::Fragments;
 
-fn get_test_spans(item: &Item, test_attr_spans: &mut Vec<Range<usize>>) {
+fn get_test_spans(item: &Item, ident: Ident, test_attr_spans: &mut Vec<Range<usize>>) {
     test_attr_spans.extend(
         item.attrs
             .iter()
             .find(|attr| attr.has_name(sym::test))
-            .map(|attr| attr.span.lo().to_usize()..item.ident.span.hi().to_usize()),
+            .map(|attr| attr.span.lo().to_usize()..ident.span.hi().to_usize()),
     );
 }
 
@@ -64,10 +64,10 @@ pub fn check(
                     match parser.parse_item(ForceCollect::No) {
                         Ok(Some(item)) => match &item.kind {
                             ItemKind::Fn(box Fn {
-                                sig, body: Some(block), ..
-                            }) if item.ident.name == sym::main => {
+                                ident, sig, body: Some(block), ..
+                            }) if ident.name == sym::main => {
                                 if !ignore {
-                                    get_test_spans(&item, &mut test_attr_spans);
+                                    get_test_spans(&item, *ident, &mut test_attr_spans);
                                 }
                                 let is_async = matches!(sig.header.coroutine_kind, Some(CoroutineKind::Async { .. }));
                                 let returns_nothing = match &sig.decl.output {
@@ -85,10 +85,10 @@ pub fn check(
                                 }
                             },
                             // Another function was found; this case is ignored for needless_doctest_main
-                            ItemKind::Fn(box Fn { .. }) => {
+                            ItemKind::Fn(fn_) => {
                                 eligible = false;
                                 if !ignore {
-                                    get_test_spans(&item, &mut test_attr_spans);
+                                    get_test_spans(&item, fn_.ident, &mut test_attr_spans);
                                 }
                             },
                             // Tests with one of these items are ignored
diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
index 1dac7b971f957..243c99a19ce1b 100644
--- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
+++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
@@ -63,7 +63,7 @@ impl_lint_pass!(DuplicateMod => [DUPLICATE_MOD]);
 
 impl EarlyLintPass for DuplicateMod {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind
+        if let ItemKind::Mod(_, _, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind
             && let FileName::Real(real) = cx.sess().source_map().span_to_filename(mod_spans.inner_span)
             && let Some(local_path) = real.into_local_path()
             && let Ok(absolute_path) = local_path.canonicalize()
diff --git a/src/tools/clippy/clippy_lints/src/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/empty_line_after.rs
index 80c2b03c41cf4..c67dcd3c82b50 100644
--- a/src/tools/clippy/clippy_lints/src/empty_line_after.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_line_after.rs
@@ -8,8 +8,7 @@ use rustc_errors::{Applicability, Diag, SuggestionStyle};
 use rustc_lexer::TokenKind;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_session::impl_lint_pass;
-use rustc_span::symbol::kw;
-use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol};
+use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol, kw};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -375,21 +374,23 @@ impl EmptyLineAfter {
         &mut self,
         cx: &EarlyContext<'_>,
         kind: &ItemKind,
-        ident: &Ident,
+        ident: Option<Ident>,
         span: Span,
         attrs: &[Attribute],
         id: NodeId,
     ) {
         self.items.push(ItemInfo {
             kind: kind.descr(),
-            name: ident.name,
-            span: if span.contains(ident.span) {
+            // FIXME: this `sym::empty` can be leaked, see
+            // https://github.com/rust-lang/rust/pull/138740#discussion_r2021979899
+            name: if let Some(ident) = ident { ident.name } else { kw::Empty },
+            span: if let Some(ident) = ident {
                 span.with_hi(ident.span.hi())
             } else {
                 span.with_hi(span.lo())
             },
             mod_items: match kind {
-                ItemKind::Mod(_, ModKind::Loaded(items, _, _, _)) => items
+                ItemKind::Mod(_, _, ModKind::Loaded(items, _, _, _)) => items
                     .iter()
                     .filter(|i| !matches!(i.span.ctxt().outer_expn_data().kind, ExpnKind::AstPass(_)))
                     .map(|i| i.id)
@@ -471,7 +472,7 @@ impl EarlyLintPass for EmptyLineAfter {
         self.check_item_kind(
             cx,
             &item.kind.clone().into(),
-            &item.ident,
+            item.kind.ident(),
             item.span,
             &item.attrs,
             item.id,
@@ -482,7 +483,7 @@ impl EarlyLintPass for EmptyLineAfter {
         self.check_item_kind(
             cx,
             &item.kind.clone().into(),
-            &item.ident,
+            item.kind.ident(),
             item.span,
             &item.attrs,
             item.id,
@@ -490,6 +491,6 @@ impl EarlyLintPass for EmptyLineAfter {
     }
 
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        self.check_item_kind(cx, &item.kind, &item.ident, item.span, &item.attrs, item.id);
+        self.check_item_kind(cx, &item.kind, item.kind.ident(), item.span, &item.attrs, item.id);
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
index 743ec5b9ea7fb..7d87f04fef9d8 100644
--- a/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
@@ -74,10 +74,9 @@ declare_lint_pass!(EmptyWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS, EMPTY_ENUM
 
 impl EarlyLintPass for EmptyWithBrackets {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        let span_after_ident = item.span.with_lo(item.ident.span.hi());
-
-        if let ItemKind::Struct(var_data, _) = &item.kind
+        if let ItemKind::Struct(ident, var_data, _) = &item.kind
             && has_brackets(var_data)
+            && let span_after_ident = item.span.with_lo(ident.span.hi())
             && has_no_fields(cx, var_data, span_after_ident)
         {
             span_lint_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
index ba2b37fbf11a3..aae8291905d37 100644
--- a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
+++ b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
@@ -51,7 +51,7 @@ declare_lint_pass!(FieldScopedVisibilityModifiers => [FIELD_SCOPED_VISIBILITY_MO
 
 impl EarlyLintPass for FieldScopedVisibilityModifiers {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        let ItemKind::Struct(ref st, _) = item.kind else {
+        let ItemKind::Struct(_, ref st, _) = item.kind else {
             return;
         };
         for field in st.fields() {
diff --git a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs
index 0e1980a6acb61..4b32ba83b325e 100644
--- a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs
+++ b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs
@@ -39,7 +39,7 @@ declare_lint_pass!(MultipleBoundLocations => [MULTIPLE_BOUND_LOCATIONS]);
 
 impl EarlyLintPass for MultipleBoundLocations {
     fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, _: Span, _: NodeId) {
-        if let FnKind::Fn(_, _, _, Fn { generics, .. }) = kind
+        if let FnKind::Fn(_, _, Fn { generics, .. }) = kind
             && !generics.params.is_empty()
             && !generics.where_clause.predicates.is_empty()
         {
diff --git a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
index 267e2067e101a..cda752d003fa0 100644
--- a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
+++ b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
@@ -41,7 +41,7 @@ declare_lint_pass!(PartialPubFields => [PARTIAL_PUB_FIELDS]);
 
 impl EarlyLintPass for PartialPubFields {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        let ItemKind::Struct(ref st, _) = item.kind else {
+        let ItemKind::Struct(_, ref st, _) = item.kind else {
             return;
         };
 
diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
index fa08245350429..35f80b2acda68 100644
--- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
@@ -174,11 +174,11 @@ impl SingleComponentPathImports {
         }
 
         match &item.kind {
-            ItemKind::Mod(_, ModKind::Loaded(items, ..)) => {
+            ItemKind::Mod(_, _, ModKind::Loaded(items, ..)) => {
                 self.check_mod(items);
             },
-            ItemKind::MacroDef(MacroDef { macro_rules: true, .. }) => {
-                macros.push(item.ident.name);
+            ItemKind::MacroDef(ident, MacroDef { macro_rules: true, .. }) => {
+                macros.push(ident.name);
             },
             ItemKind::Use(use_tree) => {
                 let segments = &use_tree.prefix.segments;
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
index 6023ae9cc7b16..eba576392ebce 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -321,17 +321,18 @@ pub fn eq_local_kind(l: &LocalKind, r: &LocalKind) -> bool {
 }
 
 pub fn eq_item<K>(l: &Item<K>, r: &Item<K>, mut eq_kind: impl FnMut(&K, &K) -> bool) -> bool {
-    eq_id(l.ident, r.ident) && over(&l.attrs, &r.attrs, eq_attr) && eq_vis(&l.vis, &r.vis) && eq_kind(&l.kind, &r.kind)
+    over(&l.attrs, &r.attrs, eq_attr) && eq_vis(&l.vis, &r.vis) && eq_kind(&l.kind, &r.kind)
 }
 
 #[expect(clippy::similar_names, clippy::too_many_lines)] // Just a big match statement
 pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
     use ItemKind::*;
     match (l, r) {
-        (ExternCrate(l), ExternCrate(r)) => l == r,
+        (ExternCrate(ls, li), ExternCrate(rs, ri)) => ls == rs && eq_id(*li, *ri),
         (Use(l), Use(r)) => eq_use_tree(l, r),
         (
             Static(box StaticItem {
+                ident: li,
                 ty: lt,
                 mutability: lm,
                 expr: le,
@@ -339,16 +340,22 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
                 define_opaque: _,
             }),
             Static(box StaticItem {
+                ident: ri,
                 ty: rt,
                 mutability: rm,
                 expr: re,
                 safety: rs,
                 define_opaque: _,
             }),
-        ) => lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
+        ) => eq_id(*li, *ri)
+                && lm == rm
+                && ls == rs
+                && eq_ty(lt, rt)
+                && eq_expr_opt(le.as_ref(), re.as_ref()),
         (
             Const(box ConstItem {
                 defaultness: ld,
+                ident: li,
                 generics: lg,
                 ty: lt,
                 expr: le,
@@ -356,16 +363,22 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
             }),
             Const(box ConstItem {
                 defaultness: rd,
+                ident: ri,
                 generics: rg,
                 ty: rt,
                 expr: re,
                 define_opaque: _,
             }),
-        ) => eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
+        ) => eq_defaultness(*ld, *rd)
+                && eq_id(*li, *ri)
+                && eq_generics(lg, rg)
+                && eq_ty(lt, rt)
+                && eq_expr_opt(le.as_ref(), re.as_ref()),
         (
             Fn(box ast::Fn {
                 defaultness: ld,
                 sig: lf,
+                ident: li,
                 generics: lg,
                 contract: lc,
                 body: lb,
@@ -374,6 +387,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
             Fn(box ast::Fn {
                 defaultness: rd,
                 sig: rf,
+                ident: ri,
                 generics: rg,
                 contract: rc,
                 body: rb,
@@ -382,12 +396,14 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         ) => {
             eq_defaultness(*ld, *rd)
                 && eq_fn_sig(lf, rf)
+                && eq_id(*li, *ri)
                 && eq_generics(lg, rg)
                 && eq_opt_fn_contract(lc, rc)
                 && both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r))
         },
-        (Mod(lu, lmk), Mod(ru, rmk)) => {
-            lu == ru
+        (Mod(ls, li, lmk), Mod(rs, ri, rmk)) => {
+            ls == rs
+                && eq_id(*li, *ri)
                 && match (lmk, rmk) {
                     (ModKind::Loaded(litems, linline, _, _), ModKind::Loaded(ritems, rinline, _, _)) => {
                         linline == rinline && over(litems, ritems, |l, r| eq_item(l, r, eq_item_kind))
@@ -421,33 +437,40 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
                 && over(lb, rb, eq_generic_bound)
                 && both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r))
         },
-        (Enum(le, lg), Enum(re, rg)) => over(&le.variants, &re.variants, eq_variant) && eq_generics(lg, rg),
-        (Struct(lv, lg), Struct(rv, rg)) | (Union(lv, lg), Union(rv, rg)) => {
-            eq_variant_data(lv, rv) && eq_generics(lg, rg)
+        (Enum(li, le, lg), Enum(ri, re, rg)) => {
+            eq_id(*li, *ri) && over(&le.variants, &re.variants, eq_variant) && eq_generics(lg, rg)
+        }
+        (Struct(li, lv, lg), Struct(ri, rv, rg)) | (Union(li, lv, lg), Union(ri, rv, rg)) => {
+            eq_id(*li, *ri) && eq_variant_data(lv, rv) && eq_generics(lg, rg)
         },
         (
             Trait(box ast::Trait {
                 is_auto: la,
                 safety: lu,
+                ident: li,
                 generics: lg,
                 bounds: lb,
-                items: li,
+                items: lis,
             }),
             Trait(box ast::Trait {
                 is_auto: ra,
                 safety: ru,
+                ident: ri,
                 generics: rg,
                 bounds: rb,
-                items: ri,
+                items: ris,
             }),
         ) => {
             la == ra
                 && matches!(lu, Safety::Default) == matches!(ru, Safety::Default)
+                && eq_id(*li, *ri)
                 && eq_generics(lg, rg)
                 && over(lb, rb, eq_generic_bound)
-                && over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind))
+                && over(lis, ris, |l, r| eq_item(l, r, eq_assoc_item_kind))
         },
-        (TraitAlias(lg, lb), TraitAlias(rg, rb)) => eq_generics(lg, rg) && over(lb, rb, eq_generic_bound),
+        (TraitAlias(li, lg, lb), TraitAlias(ri, rg, rb)) => {
+            eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound)
+        }
         (
             Impl(box ast::Impl {
                 safety: lu,
@@ -480,7 +503,9 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
                 && over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind))
         },
         (MacCall(l), MacCall(r)) => eq_mac_call(l, r),
-        (MacroDef(l), MacroDef(r)) => l.macro_rules == r.macro_rules && eq_delim_args(&l.body, &r.body),
+        (MacroDef(li, ld), MacroDef(ri, rd)) => {
+            eq_id(*li, *ri) && ld.macro_rules == rd.macro_rules && eq_delim_args(&ld.body, &rd.body)
+        }
         _ => false,
     }
 }
@@ -490,6 +515,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
     match (l, r) {
         (
             Static(box StaticItem {
+                ident: li,
                 ty: lt,
                 mutability: lm,
                 expr: le,
@@ -497,17 +523,25 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
                 define_opaque: _,
             }),
             Static(box StaticItem {
+                ident: ri,
                 ty: rt,
                 mutability: rm,
                 expr: re,
                 safety: rs,
                 define_opaque: _,
             }),
-        ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()) && ls == rs,
+        ) => {
+            eq_id(*li, *ri)
+                && eq_ty(lt, rt)
+                && lm == rm
+                && eq_expr_opt(le.as_ref(), re.as_ref())
+                && ls == rs
+        }
         (
             Fn(box ast::Fn {
                 defaultness: ld,
                 sig: lf,
+                ident: li,
                 generics: lg,
                 contract: lc,
                 body: lb,
@@ -516,6 +550,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
             Fn(box ast::Fn {
                 defaultness: rd,
                 sig: rf,
+                ident: ri,
                 generics: rg,
                 contract: rc,
                 body: rb,
@@ -524,6 +559,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
         ) => {
             eq_defaultness(*ld, *rd)
                 && eq_fn_sig(lf, rf)
+                && eq_id(*li, *ri)
                 && eq_generics(lg, rg)
                 && eq_opt_fn_contract(lc, rc)
                 && both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r))
@@ -531,20 +567,23 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
         (
             TyAlias(box ast::TyAlias {
                 defaultness: ld,
+                ident: li,
                 generics: lg,
+                where_clauses: _,
                 bounds: lb,
                 ty: lt,
-                ..
             }),
             TyAlias(box ast::TyAlias {
                 defaultness: rd,
+                ident: ri,
                 generics: rg,
+                where_clauses: _,
                 bounds: rb,
                 ty: rt,
-                ..
             }),
         ) => {
             eq_defaultness(*ld, *rd)
+                && eq_id(*li, *ri)
                 && eq_generics(lg, rg)
                 && over(lb, rb, eq_generic_bound)
                 && both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r))
@@ -560,6 +599,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
         (
             Const(box ConstItem {
                 defaultness: ld,
+                ident: li,
                 generics: lg,
                 ty: lt,
                 expr: le,
@@ -567,16 +607,24 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
             }),
             Const(box ConstItem {
                 defaultness: rd,
+                ident: ri,
                 generics: rg,
                 ty: rt,
                 expr: re,
                 define_opaque: _,
             }),
-        ) => eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
+        ) => {
+            eq_defaultness(*ld, *rd)
+                && eq_id(*li, *ri)
+                && eq_generics(lg, rg)
+                && eq_ty(lt, rt)
+                && eq_expr_opt(le.as_ref(), re.as_ref())
+        }
         (
             Fn(box ast::Fn {
                 defaultness: ld,
                 sig: lf,
+                ident: li,
                 generics: lg,
                 contract: lc,
                 body: lb,
@@ -585,6 +633,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
             Fn(box ast::Fn {
                 defaultness: rd,
                 sig: rf,
+                ident: ri,
                 generics: rg,
                 contract: rc,
                 body: rb,
@@ -593,6 +642,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
         ) => {
             eq_defaultness(*ld, *rd)
                 && eq_fn_sig(lf, rf)
+                && eq_id(*li, *ri)
                 && eq_generics(lg, rg)
                 && eq_opt_fn_contract(lc, rc)
                 && both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r))
@@ -600,20 +650,23 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
         (
             Type(box TyAlias {
                 defaultness: ld,
+                ident: li,
                 generics: lg,
+                where_clauses: _,
                 bounds: lb,
                 ty: lt,
-                ..
             }),
             Type(box TyAlias {
                 defaultness: rd,
+                ident: ri,
                 generics: rg,
+                where_clauses: _,
                 bounds: rb,
                 ty: rt,
-                ..
             }),
         ) => {
             eq_defaultness(*ld, *rd)
+                && eq_id(*li, *ri)
                 && eq_generics(lg, rg)
                 && over(lb, rb, eq_generic_bound)
                 && both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r))
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index e866f13efc73e..65120770edd61 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -246,7 +246,7 @@ pub(crate) fn format_expr(
         | ast::ExprKind::Await(_, _)
         | ast::ExprKind::Yield(ast::YieldKind::Postfix(_)) => rewrite_chain(expr, context, shape),
         ast::ExprKind::MacCall(ref mac) => {
-            rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|_| {
+            rewrite_macro(mac, context, shape, MacroPosition::Expression).or_else(|_| {
                 wrap_str(
                     context.snippet(expr.span).to_owned(),
                     context.config.max_width(),
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index 3fb3284e3d7fd..322af97d9dc47 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -6,7 +6,7 @@ use std::cmp::{Ordering, max, min};
 use regex::Regex;
 use rustc_ast::visit;
 use rustc_ast::{ast, ptr};
-use rustc_span::{BytePos, DUMMY_SP, Span, symbol};
+use rustc_span::{BytePos, DUMMY_SP, Ident, Span, symbol};
 use tracing::debug;
 
 use crate::attr::filter_inline_attrs;
@@ -333,12 +333,12 @@ impl<'a> FnSig<'a> {
         defaultness: ast::Defaultness,
     ) -> FnSig<'a> {
         match *fn_kind {
-            visit::FnKind::Fn(visit::FnCtxt::Assoc(..), _, vis, ast::Fn { sig, generics, .. }) => {
+            visit::FnKind::Fn(visit::FnCtxt::Assoc(..), vis, ast::Fn { sig, generics, .. }) => {
                 let mut fn_sig = FnSig::from_method_sig(sig, generics, vis);
                 fn_sig.defaultness = defaultness;
                 fn_sig
             }
-            visit::FnKind::Fn(_, _, vis, ast::Fn { sig, generics, .. }) => FnSig {
+            visit::FnKind::Fn(_, vis, ast::Fn { sig, generics, .. }) => FnSig {
                 decl,
                 generics,
                 ext: sig.header.ext,
@@ -750,11 +750,10 @@ impl<'a> FmtVisitor<'a> {
                 (Type(lty), Type(rty))
                     if both_type(&lty.ty, &rty.ty) || both_opaque(&lty.ty, &rty.ty) =>
                 {
-                    a.ident.as_str().cmp(b.ident.as_str())
-                }
-                (Const(..), Const(..)) | (MacCall(..), MacCall(..)) => {
-                    a.ident.as_str().cmp(b.ident.as_str())
+                    lty.ident.as_str().cmp(rty.ident.as_str())
                 }
+                (Const(ca), Const(cb)) => ca.ident.as_str().cmp(cb.ident.as_str()),
+                (MacCall(..), MacCall(..)) => Ordering::Equal,
                 (Fn(..), Fn(..)) | (Delegation(..), Delegation(..)) => {
                     a.span.lo().cmp(&b.span.lo())
                 }
@@ -1105,14 +1104,16 @@ impl<'a> StructParts<'a> {
     }
 
     pub(crate) fn from_item(item: &'a ast::Item) -> Self {
-        let (prefix, def, generics) = match item.kind {
-            ast::ItemKind::Struct(ref def, ref generics) => ("struct ", def, generics),
-            ast::ItemKind::Union(ref def, ref generics) => ("union ", def, generics),
+        let (prefix, def, ident, generics) = match item.kind {
+            ast::ItemKind::Struct(ident, ref def, ref generics) => {
+                ("struct ", def, ident, generics)
+            }
+            ast::ItemKind::Union(ident, ref def, ref generics) => ("union ", def, ident, generics),
             _ => unreachable!(),
         };
         StructParts {
             prefix,
-            ident: item.ident,
+            ident,
             vis: &item.vis,
             def,
             generics: Some(generics),
@@ -1168,6 +1169,7 @@ pub(crate) fn format_trait(
     let ast::Trait {
         is_auto,
         safety,
+        ident,
         ref generics,
         ref bounds,
         ref items,
@@ -1186,13 +1188,13 @@ pub(crate) fn format_trait(
 
     let shape = Shape::indented(offset, context.config).offset_left(result.len())?;
     let generics_str =
-        rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape).ok()?;
+        rewrite_generics(context, rewrite_ident(context, ident), generics, shape).ok()?;
     result.push_str(&generics_str);
 
     // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
     if !bounds.is_empty() {
         // Retrieve *unnormalized* ident (See #6069)
-        let source_ident = context.snippet(item.ident.span);
+        let source_ident = context.snippet(ident.span);
         let ident_hi = context.snippet_provider.span_after(item.span, source_ident);
         let bound_hi = bounds.last().unwrap().span().hi();
         let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
@@ -1679,11 +1681,12 @@ fn format_tuple_struct(
     Some(result)
 }
 
-pub(crate) enum ItemVisitorKind<'a> {
-    Item(&'a ast::Item),
-    AssocTraitItem(&'a ast::AssocItem),
-    AssocImplItem(&'a ast::AssocItem),
-    ForeignItem(&'a ast::ForeignItem),
+#[derive(Clone, Copy)]
+pub(crate) enum ItemVisitorKind {
+    Item,
+    AssocTraitItem,
+    AssocImplItem,
+    ForeignItem,
 }
 
 struct TyAliasRewriteInfo<'c, 'g>(
@@ -1695,17 +1698,19 @@ struct TyAliasRewriteInfo<'c, 'g>(
     Span,
 );
 
-pub(crate) fn rewrite_type_alias<'a, 'b>(
+pub(crate) fn rewrite_type_alias<'a>(
     ty_alias_kind: &ast::TyAlias,
+    vis: &ast::Visibility,
     context: &RewriteContext<'a>,
     indent: Indent,
-    visitor_kind: &ItemVisitorKind<'b>,
+    visitor_kind: ItemVisitorKind,
     span: Span,
 ) -> RewriteResult {
     use ItemVisitorKind::*;
 
     let ast::TyAlias {
         defaultness,
+        ident,
         ref generics,
         ref bounds,
         ref ty,
@@ -1715,11 +1720,6 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
     let rhs_hi = ty
         .as_ref()
         .map_or(where_clauses.before.span.hi(), |ty| ty.span.hi());
-    let (ident, vis) = match visitor_kind {
-        Item(i) => (i.ident, &i.vis),
-        AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis),
-        ForeignItem(i) => (i.ident, &i.vis),
-    };
     let rw_info = &TyAliasRewriteInfo(context, indent, generics, where_clauses, ident, span);
     let op_ty = opaque_ty(ty);
     // Type Aliases are formatted slightly differently depending on the context
@@ -1727,14 +1727,14 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
     // https://rustc-dev-guide.rust-lang.org/opaque-types-type-alias-impl-trait.html
     // https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/items.md#type-aliases
     match (visitor_kind, &op_ty) {
-        (Item(_) | AssocTraitItem(_) | ForeignItem(_), Some(op_bounds)) => {
+        (Item | AssocTraitItem | ForeignItem, Some(op_bounds)) => {
             let op = OpaqueType { bounds: op_bounds };
             rewrite_ty(rw_info, Some(bounds), Some(&op), rhs_hi, vis)
         }
-        (Item(_) | AssocTraitItem(_) | ForeignItem(_), None) => {
+        (Item | AssocTraitItem | ForeignItem, None) => {
             rewrite_ty(rw_info, Some(bounds), ty_opt, rhs_hi, vis)
         }
-        (AssocImplItem(_), _) => {
+        (AssocImplItem, _) => {
             let result = if let Some(op_bounds) = op_ty {
                 let op = OpaqueType { bounds: op_bounds };
                 rewrite_ty(
@@ -2024,14 +2024,23 @@ pub(crate) struct StaticParts<'a> {
 
 impl<'a> StaticParts<'a> {
     pub(crate) fn from_item(item: &'a ast::Item) -> Self {
-        let (defaultness, prefix, safety, ty, mutability, expr, generics) = match &item.kind {
-            ast::ItemKind::Static(s) => {
-                (None, "static", s.safety, &s.ty, s.mutability, &s.expr, None)
-            }
+        let (defaultness, prefix, safety, ident, ty, mutability, expr, generics) = match &item.kind
+        {
+            ast::ItemKind::Static(s) => (
+                None,
+                "static",
+                s.safety,
+                s.ident,
+                &s.ty,
+                s.mutability,
+                &s.expr,
+                None,
+            ),
             ast::ItemKind::Const(c) => (
                 Some(c.defaultness),
                 "const",
                 ast::Safety::Default,
+                c.ident,
                 &c.ty,
                 ast::Mutability::Not,
                 &c.expr,
@@ -2043,7 +2052,7 @@ impl<'a> StaticParts<'a> {
             prefix,
             safety,
             vis: &item.vis,
-            ident: item.ident,
+            ident,
             generics,
             ty,
             mutability,
@@ -2053,7 +2062,7 @@ impl<'a> StaticParts<'a> {
         }
     }
 
-    pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self {
+    pub(crate) fn from_trait_item(ti: &'a ast::AssocItem, ident: Ident) -> Self {
         let (defaultness, ty, expr_opt, generics) = match &ti.kind {
             ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr, Some(&c.generics)),
             _ => unreachable!(),
@@ -2062,7 +2071,7 @@ impl<'a> StaticParts<'a> {
             prefix: "const",
             safety: ast::Safety::Default,
             vis: &ti.vis,
-            ident: ti.ident,
+            ident,
             generics,
             ty,
             mutability: ast::Mutability::Not,
@@ -2072,7 +2081,7 @@ impl<'a> StaticParts<'a> {
         }
     }
 
-    pub(crate) fn from_impl_item(ii: &'a ast::AssocItem) -> Self {
+    pub(crate) fn from_impl_item(ii: &'a ast::AssocItem, ident: Ident) -> Self {
         let (defaultness, ty, expr, generics) = match &ii.kind {
             ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr, Some(&c.generics)),
             _ => unreachable!(),
@@ -2081,7 +2090,7 @@ impl<'a> StaticParts<'a> {
             prefix: "const",
             safety: ast::Safety::Default,
             vis: &ii.vis,
-            ident: ii.ident,
+            ident,
             generics,
             ty,
             mutability: ast::Mutability::Not,
@@ -3442,6 +3451,7 @@ impl Rewrite for ast::ForeignItem {
                 let ast::Fn {
                     defaultness,
                     ref sig,
+                    ident,
                     ref generics,
                     ref body,
                     ..
@@ -3453,7 +3463,8 @@ impl Rewrite for ast::ForeignItem {
                     let inner_attrs = inner_attributes(&self.attrs);
                     let fn_ctxt = visit::FnCtxt::Foreign;
                     visitor.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, &self.ident, &self.vis, fn_kind),
+                        ident,
+                        visit::FnKind::Fn(fn_ctxt, &self.vis, fn_kind),
                         &sig.decl,
                         self.span,
                         defaultness,
@@ -3464,7 +3475,7 @@ impl Rewrite for ast::ForeignItem {
                     rewrite_fn_base(
                         context,
                         shape.indent,
-                        self.ident,
+                        ident,
                         &FnSig::from_method_sig(sig, generics, &self.vis),
                         span,
                         FnBraceStyle::None,
@@ -3483,7 +3494,7 @@ impl Rewrite for ast::ForeignItem {
                     vis,
                     safety,
                     mut_str,
-                    rewrite_ident(context, self.ident)
+                    rewrite_ident(context, static_foreign_item.ident)
                 );
                 // 1 = ;
                 rewrite_assign_rhs(
@@ -3498,11 +3509,11 @@ impl Rewrite for ast::ForeignItem {
                 .map(|s| s + ";")
             }
             ast::ForeignItemKind::TyAlias(ref ty_alias) => {
-                let (kind, span) = (&ItemVisitorKind::ForeignItem(self), self.span);
-                rewrite_type_alias(ty_alias, context, shape.indent, kind, span)
+                let kind = ItemVisitorKind::ForeignItem;
+                rewrite_type_alias(ty_alias, &self.vis, context, shape.indent, kind, self.span)
             }
             ast::ForeignItemKind::MacCall(ref mac) => {
-                rewrite_macro(mac, None, context, shape, MacroPosition::Item)
+                rewrite_macro(mac, context, shape, MacroPosition::Item)
             }
         }?;
 
@@ -3562,12 +3573,13 @@ fn rewrite_attrs(
 pub(crate) fn rewrite_mod(
     context: &RewriteContext<'_>,
     item: &ast::Item,
+    ident: Ident,
     attrs_shape: Shape,
 ) -> Option<String> {
     let mut result = String::with_capacity(32);
     result.push_str(&*format_visibility(context, &item.vis));
     result.push_str("mod ");
-    result.push_str(rewrite_ident(context, item.ident));
+    result.push_str(rewrite_ident(context, ident));
     result.push(';');
     rewrite_attrs(context, item, &result, attrs_shape)
 }
@@ -3594,7 +3606,7 @@ pub(crate) fn rewrite_extern_crate(
 pub(crate) fn is_mod_decl(item: &ast::Item) -> bool {
     !matches!(
         item.kind,
-        ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _))
+        ast::ItemKind::Mod(_, _, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _))
     )
 }
 
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index e239ff47c043e..ddf3d2ce96af6 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -16,10 +16,7 @@ use rustc_ast::token::{Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::{TokenStream, TokenStreamIter, TokenTree};
 use rustc_ast::{ast, ptr};
 use rustc_ast_pretty::pprust;
-use rustc_span::{
-    BytePos, DUMMY_SP, Span, Symbol,
-    symbol::{self, kw},
-};
+use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol};
 use tracing::debug;
 
 use crate::comment::{
@@ -60,7 +57,7 @@ pub(crate) enum MacroArg {
     Ty(ptr::P<ast::Ty>),
     Pat(ptr::P<ast::Pat>),
     Item(ptr::P<ast::Item>),
-    Keyword(symbol::Ident, Span),
+    Keyword(Ident, Span),
 }
 
 impl MacroArg {
@@ -103,20 +100,12 @@ impl Rewrite for MacroArg {
 }
 
 /// Rewrite macro name without using pretty-printer if possible.
-fn rewrite_macro_name(
-    context: &RewriteContext<'_>,
-    path: &ast::Path,
-    extra_ident: Option<symbol::Ident>,
-) -> String {
-    let name = if path.segments.len() == 1 {
+fn rewrite_macro_name(context: &RewriteContext<'_>, path: &ast::Path) -> String {
+    if path.segments.len() == 1 {
         // Avoid using pretty-printer in the common case.
         format!("{}!", rewrite_ident(context, path.segments[0].ident))
     } else {
         format!("{}!", pprust::path_to_string(path))
-    };
-    match extra_ident {
-        Some(ident) if ident.name != kw::Empty => format!("{name} {ident}"),
-        _ => name,
     }
 }
 
@@ -165,7 +154,6 @@ fn return_macro_parse_failure_fallback(
 
 pub(crate) fn rewrite_macro(
     mac: &ast::MacCall,
-    extra_ident: Option<symbol::Ident>,
     context: &RewriteContext<'_>,
     shape: Shape,
     position: MacroPosition,
@@ -179,14 +167,7 @@ pub(crate) fn rewrite_macro(
     } else {
         let guard = context.enter_macro();
         let result = catch_unwind(AssertUnwindSafe(|| {
-            rewrite_macro_inner(
-                mac,
-                extra_ident,
-                context,
-                shape,
-                position,
-                guard.is_nested(),
-            )
+            rewrite_macro_inner(mac, context, shape, position, guard.is_nested())
         }));
         match result {
             Err(..) => {
@@ -207,7 +188,6 @@ pub(crate) fn rewrite_macro(
 
 fn rewrite_macro_inner(
     mac: &ast::MacCall,
-    extra_ident: Option<symbol::Ident>,
     context: &RewriteContext<'_>,
     shape: Shape,
     position: MacroPosition,
@@ -222,7 +202,7 @@ fn rewrite_macro_inner(
 
     let original_style = macro_style(mac, context);
 
-    let macro_name = rewrite_macro_name(context, &mac.path, extra_ident);
+    let macro_name = rewrite_macro_name(context, &mac.path);
     let is_forced_bracket = FORCED_BRACKET_MACROS.contains(&&macro_name[..]);
 
     let style = if is_forced_bracket && !is_nested_macro {
@@ -432,7 +412,7 @@ pub(crate) fn rewrite_macro_def(
     shape: Shape,
     indent: Indent,
     def: &ast::MacroDef,
-    ident: symbol::Ident,
+    ident: Ident,
     vis: &ast::Visibility,
     span: Span,
 ) -> RewriteResult {
diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs
index a40ee7f66a978..bc5a6d3e70402 100644
--- a/src/tools/rustfmt/src/modules.rs
+++ b/src/tools/rustfmt/src/modules.rs
@@ -152,7 +152,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
         let mut visitor = visitor::CfgIfVisitor::new(self.psess);
         visitor.visit_item(&item);
         for module_item in visitor.mods() {
-            if let ast::ItemKind::Mod(_, ref sub_mod_kind) = module_item.item.kind {
+            if let ast::ItemKind::Mod(_, _, ref sub_mod_kind) = module_item.item.kind {
                 self.visit_sub_mod(
                     &module_item.item,
                     Module::new(
@@ -178,7 +178,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
                 continue;
             }
 
-            if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind {
+            if let ast::ItemKind::Mod(_, _, ref sub_mod_kind) = item.kind {
                 let span = item.span;
                 self.visit_sub_mod(
                     &item,
@@ -204,7 +204,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
                 self.visit_cfg_if(Cow::Borrowed(item))?;
             }
 
-            if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind {
+            if let ast::ItemKind::Mod(_, _, ref sub_mod_kind) = item.kind {
                 let span = item.span;
                 self.visit_sub_mod(
                     item,
@@ -248,7 +248,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
         if is_mod_decl(item) {
             // mod foo;
             // Look for an extern file.
-            self.find_external_module(item.ident, &item.attrs, sub_mod)
+            self.find_external_module(item.kind.ident().unwrap(), &item.attrs, sub_mod)
         } else {
             // An internal module (`mod foo { /* ... */ }`);
             Ok(Some(SubModKind::Internal(item)))
@@ -291,7 +291,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
                 self.visit_sub_mod_after_directory_update(sub_mod, Some(directory))
             }
             SubModKind::Internal(item) => {
-                self.push_inline_mod_directory(item.ident, &item.attrs);
+                self.push_inline_mod_directory(item.kind.ident().unwrap(), &item.attrs);
                 self.visit_sub_mod_after_directory_update(sub_mod, None)
             }
             SubModKind::MultiExternal(mods) => {
diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs
index bafed41e39f42..8dc9457450326 100644
--- a/src/tools/rustfmt/src/patterns.rs
+++ b/src/tools/rustfmt/src/patterns.rs
@@ -307,9 +307,7 @@ impl Rewrite for Pat {
                 context,
                 shape,
             ),
-            PatKind::MacCall(ref mac) => {
-                rewrite_macro(mac, None, context, shape, MacroPosition::Pat)
-            }
+            PatKind::MacCall(ref mac) => rewrite_macro(mac, context, shape, MacroPosition::Pat),
             PatKind::Paren(ref pat) => pat
                 .rewrite_result(
                     context,
diff --git a/src/tools/rustfmt/src/reorder.rs b/src/tools/rustfmt/src/reorder.rs
index 8a31e0ac816e3..2460b61698ccf 100644
--- a/src/tools/rustfmt/src/reorder.rs
+++ b/src/tools/rustfmt/src/reorder.rs
@@ -25,14 +25,17 @@ use crate::visitor::FmtVisitor;
 /// Choose the ordering between the given two items.
 fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering {
     match (&a.kind, &b.kind) {
-        (&ast::ItemKind::Mod(..), &ast::ItemKind::Mod(..)) => {
-            a.ident.as_str().cmp(b.ident.as_str())
+        (&ast::ItemKind::Mod(_, a_ident, _), &ast::ItemKind::Mod(_, b_ident, _)) => {
+            a_ident.as_str().cmp(b_ident.as_str())
         }
-        (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => {
+        (
+            &ast::ItemKind::ExternCrate(ref a_name, a_ident),
+            &ast::ItemKind::ExternCrate(ref b_name, b_ident),
+        ) => {
             // `extern crate foo as bar;`
             //               ^^^ Comparing this.
-            let a_orig_name = a_name.unwrap_or(a.ident.name);
-            let b_orig_name = b_name.unwrap_or(b.ident.name);
+            let a_orig_name = a_name.unwrap_or(a_ident.name);
+            let b_orig_name = b_name.unwrap_or(b_ident.name);
             let result = a_orig_name.as_str().cmp(b_orig_name.as_str());
             if result != Ordering::Equal {
                 return result;
@@ -44,7 +47,7 @@ fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering {
                 (Some(..), None) => Ordering::Greater,
                 (None, Some(..)) => Ordering::Less,
                 (None, None) => Ordering::Equal,
-                (Some(..), Some(..)) => a.ident.as_str().cmp(b.ident.as_str()),
+                (Some(..), Some(..)) => a_ident.as_str().cmp(b_ident.as_str()),
             }
         }
         _ => unreachable!(),
@@ -69,7 +72,7 @@ fn rewrite_reorderable_item(
 ) -> Option<String> {
     match item.kind {
         ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item, shape),
-        ast::ItemKind::Mod(..) => rewrite_mod(context, item, shape),
+        ast::ItemKind::Mod(_, ident, _) => rewrite_mod(context, item, ident, shape),
         _ => None,
     }
 }
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 06a67334086c5..75a5a8532b84f 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -1018,7 +1018,7 @@ impl Rewrite for ast::Ty {
             ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape),
             ast::TyKind::Never => Ok(String::from("!")),
             ast::TyKind::MacCall(ref mac) => {
-                rewrite_macro(mac, None, context, shape, MacroPosition::Expression)
+                rewrite_macro(mac, context, shape, MacroPosition::Expression)
             }
             ast::TyKind::ImplicitSelf => Ok(String::from("")),
             ast::TyKind::ImplTrait(_, ref it) => {
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index 5749d8c63faf4..16d1f5105d5f9 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -3,7 +3,7 @@ use std::rc::Rc;
 use std::sync::Arc;
 
 use rustc_ast::{ast, token::Delimiter, visit};
-use rustc_span::{BytePos, Pos, Span, symbol};
+use rustc_span::{BytePos, Ident, Pos, Span, symbol};
 use tracing::debug;
 
 use crate::attr::*;
@@ -172,7 +172,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                         get_span_without_attrs(stmt.as_ast_node()),
                     );
                 } else {
-                    self.visit_mac(&mac_stmt.mac, None, MacroPosition::Statement);
+                    self.visit_mac(&mac_stmt.mac, MacroPosition::Statement);
                 }
                 self.format_missing(stmt.span().hi());
             }
@@ -377,6 +377,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
     // on traits do not get handled here.
     pub(crate) fn visit_fn(
         &mut self,
+        ident: Ident,
         fk: visit::FnKind<'_>,
         fd: &ast::FnDecl,
         s: Span,
@@ -388,7 +389,6 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         let rewrite = match fk {
             visit::FnKind::Fn(
                 _,
-                ident,
                 _,
                 ast::Fn {
                     body: Some(ref b), ..
@@ -397,7 +397,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                 block = b;
                 self.rewrite_fn_before_block(
                     indent,
-                    *ident,
+                    ident,
                     &FnSig::from_fn_kind(&fk, fd, defaultness),
                     mk_sp(s.lo(), b.span.lo()),
                 )
@@ -444,7 +444,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
 
         let should_visit_node_again = match item.kind {
             // For use/extern crate items, skip rewriting attributes but check for a skip attribute.
-            ast::ItemKind::Use(..) | ast::ItemKind::ExternCrate(_) => {
+            ast::ItemKind::Use(..) | ast::ItemKind::ExternCrate(..) => {
                 if contains_skip(attrs) {
                     self.push_skipped_with_span(attrs.as_slice(), item.span(), item.span());
                     false
@@ -497,11 +497,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     let rw = self.with_context(|ctx| format_trait(ctx, item, block_indent));
                     self.push_rewrite(item.span, rw);
                 }
-                ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => {
+                ast::ItemKind::TraitAlias(ident, ref generics, ref generic_bounds) => {
                     let shape = Shape::indented(self.block_indent, self.config);
                     let rw = format_trait_alias(
                         &self.get_context(),
-                        item.ident,
+                        ident,
                         &item.vis,
                         generics,
                         generic_bounds,
@@ -509,7 +509,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     );
                     self.push_rewrite(item.span, rw);
                 }
-                ast::ItemKind::ExternCrate(_) => {
+                ast::ItemKind::ExternCrate(..) => {
                     let rw = rewrite_extern_crate(&self.get_context(), item, self.shape());
                     let span = if attrs.is_empty() {
                         item.span
@@ -521,17 +521,17 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                 ast::ItemKind::Struct(..) | ast::ItemKind::Union(..) => {
                     self.visit_struct(&StructParts::from_item(item));
                 }
-                ast::ItemKind::Enum(ref def, ref generics) => {
+                ast::ItemKind::Enum(ident, ref def, ref generics) => {
                     self.format_missing_with_indent(source!(self, item.span).lo());
-                    self.visit_enum(item.ident, &item.vis, def, generics, item.span);
+                    self.visit_enum(ident, &item.vis, def, generics, item.span);
                     self.last_pos = source!(self, item.span).hi();
                 }
-                ast::ItemKind::Mod(safety, ref mod_kind) => {
+                ast::ItemKind::Mod(safety, ident, ref mod_kind) => {
                     self.format_missing_with_indent(source!(self, item.span).lo());
-                    self.format_mod(mod_kind, safety, &item.vis, item.span, item.ident, attrs);
+                    self.format_mod(mod_kind, safety, &item.vis, item.span, ident, attrs);
                 }
                 ast::ItemKind::MacCall(ref mac) => {
-                    self.visit_mac(mac, Some(item.ident), MacroPosition::Item);
+                    self.visit_mac(mac, MacroPosition::Item);
                 }
                 ast::ItemKind::ForeignMod(ref foreign_mod) => {
                     self.format_missing_with_indent(source!(self, item.span).lo());
@@ -544,6 +544,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     let ast::Fn {
                         defaultness,
                         ref sig,
+                        ident,
                         ref generics,
                         ref body,
                         ..
@@ -555,7 +556,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                             _ => visit::FnCtxt::Foreign,
                         };
                         self.visit_fn(
-                            visit::FnKind::Fn(fn_ctxt, &item.ident, &item.vis, fn_kind),
+                            ident,
+                            visit::FnKind::Fn(fn_ctxt, &item.vis, fn_kind),
                             &sig.decl,
                             item.span,
                             defaultness,
@@ -564,28 +566,26 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     } else {
                         let indent = self.block_indent;
                         let rewrite = self
-                            .rewrite_required_fn(
-                                indent, item.ident, sig, &item.vis, generics, item.span,
-                            )
+                            .rewrite_required_fn(indent, ident, sig, &item.vis, generics, item.span)
                             .ok();
                         self.push_rewrite(item.span, rewrite);
                     }
                 }
                 ast::ItemKind::TyAlias(ref ty_alias) => {
                     use ItemVisitorKind::Item;
-                    self.visit_ty_alias_kind(ty_alias, &Item(item), item.span);
+                    self.visit_ty_alias_kind(ty_alias, &item.vis, Item, item.span);
                 }
                 ast::ItemKind::GlobalAsm(..) => {
                     let snippet = Some(self.snippet(item.span).to_owned());
                     self.push_rewrite(item.span, snippet);
                 }
-                ast::ItemKind::MacroDef(ref def) => {
+                ast::ItemKind::MacroDef(ident, ref def) => {
                     let rewrite = rewrite_macro_def(
                         &self.get_context(),
                         self.shape(),
                         self.block_indent,
                         def,
-                        item.ident,
+                        ident,
                         &item.vis,
                         item.span,
                     )
@@ -605,11 +605,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
     fn visit_ty_alias_kind(
         &mut self,
         ty_kind: &ast::TyAlias,
-        visitor_kind: &ItemVisitorKind<'_>,
+        vis: &ast::Visibility,
+        visitor_kind: ItemVisitorKind,
         span: Span,
     ) {
         let rewrite = rewrite_type_alias(
             ty_kind,
+            vis,
             &self.get_context(),
             self.block_indent,
             visitor_kind,
@@ -619,15 +621,16 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         self.push_rewrite(span, rewrite);
     }
 
-    fn visit_assoc_item(&mut self, visitor_kind: &ItemVisitorKind<'_>) {
+    fn visit_assoc_item(&mut self, ai: &ast::AssocItem, visitor_kind: ItemVisitorKind) {
         use ItemVisitorKind::*;
-        // TODO(calebcartwright): Not sure the skip spans are correct
-        let (ai, skip_span, assoc_ctxt) = match visitor_kind {
-            AssocTraitItem(ai) => (*ai, ai.span(), visit::AssocCtxt::Trait),
+        let assoc_ctxt = match visitor_kind {
+            AssocTraitItem => visit::AssocCtxt::Trait,
             // There is no difference between trait and inherent assoc item formatting
-            AssocImplItem(ai) => (*ai, ai.span, visit::AssocCtxt::Impl { of_trait: false }),
+            AssocImplItem => visit::AssocCtxt::Impl { of_trait: false },
             _ => unreachable!(),
         };
+        // TODO(calebcartwright): Not sure the skip spans are correct
+        let skip_span = ai.span;
         skip_out_of_file_lines_range_visitor!(self, ai.span);
 
         if self.visit_attrs(&ai.attrs, ast::AttrStyle::Outer) {
@@ -637,16 +640,17 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
 
         // TODO(calebcartwright): consider enabling box_patterns feature gate
         match (&ai.kind, visitor_kind) {
-            (ast::AssocItemKind::Const(..), AssocTraitItem(_)) => {
-                self.visit_static(&StaticParts::from_trait_item(ai))
+            (ast::AssocItemKind::Const(c), AssocTraitItem) => {
+                self.visit_static(&StaticParts::from_trait_item(ai, c.ident))
             }
-            (ast::AssocItemKind::Const(..), AssocImplItem(_)) => {
-                self.visit_static(&StaticParts::from_impl_item(ai))
+            (ast::AssocItemKind::Const(c), AssocImplItem) => {
+                self.visit_static(&StaticParts::from_impl_item(ai, c.ident))
             }
             (ast::AssocItemKind::Fn(ref fn_kind), _) => {
                 let ast::Fn {
                     defaultness,
                     ref sig,
+                    ident,
                     ref generics,
                     ref body,
                     ..
@@ -655,7 +659,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     let inner_attrs = inner_attributes(&ai.attrs);
                     let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt);
                     self.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, &ai.ident, &ai.vis, fn_kind),
+                        ident,
+                        visit::FnKind::Fn(fn_ctxt, &ai.vis, fn_kind),
                         &sig.decl,
                         ai.span,
                         defaultness,
@@ -664,35 +669,35 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                 } else {
                     let indent = self.block_indent;
                     let rewrite = self
-                        .rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span)
+                        .rewrite_required_fn(indent, fn_kind.ident, sig, &ai.vis, generics, ai.span)
                         .ok();
                     self.push_rewrite(ai.span, rewrite);
                 }
             }
             (ast::AssocItemKind::Type(ref ty_alias), _) => {
-                self.visit_ty_alias_kind(ty_alias, visitor_kind, ai.span);
+                self.visit_ty_alias_kind(ty_alias, &ai.vis, visitor_kind, ai.span);
             }
             (ast::AssocItemKind::MacCall(ref mac), _) => {
-                self.visit_mac(mac, Some(ai.ident), MacroPosition::Item);
+                self.visit_mac(mac, MacroPosition::Item);
             }
             _ => unreachable!(),
         }
     }
 
     pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) {
-        self.visit_assoc_item(&ItemVisitorKind::AssocTraitItem(ti));
+        self.visit_assoc_item(ti, ItemVisitorKind::AssocTraitItem);
     }
 
     pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) {
-        self.visit_assoc_item(&ItemVisitorKind::AssocImplItem(ii));
+        self.visit_assoc_item(ii, ItemVisitorKind::AssocImplItem);
     }
 
-    fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option<symbol::Ident>, pos: MacroPosition) {
+    fn visit_mac(&mut self, mac: &ast::MacCall, pos: MacroPosition) {
         skip_out_of_file_lines_range_visitor!(self, mac.span());
 
         // 1 = ;
         let shape = self.shape().saturating_sub_width(1);
-        let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos).ok());
+        let rewrite = self.with_context(|ctx| rewrite_macro(mac, ctx, shape, pos).ok());
         // As of v638 of the rustc-ap-* crates, the associated span no longer includes
         // the trailing semicolon. This determines the correct span to ensure scenarios
         // with whitespace between the delimiters and trailing semi (i.e. `foo!(abc)     ;`)
diff --git a/tests/ui/custom_test_frameworks/full.rs b/tests/ui/custom_test_frameworks/full.rs
index 289767b1f698a..57b55e9437bf3 100644
--- a/tests/ui/custom_test_frameworks/full.rs
+++ b/tests/ui/custom_test_frameworks/full.rs
@@ -25,4 +25,17 @@ impl example_runner::Testable for IsFoo {
 const TEST_1: IsFoo = IsFoo("hello");
 
 #[test_case]
-const TEST_2: IsFoo = IsFoo("foo");
+static TEST_2: IsFoo = IsFoo("foo");
+
+// FIXME: `test_case` is currently ignored on anything other than
+// fn/const/static. This should be an error. Compare this with `#[test]` and
+// #[bench] whose expanders emit "error: expected a non-associated function,
+// found […]" if applied to invalid items.
+#[test_case]
+struct _S;
+
+// FIXME: as above.
+#[test_case]
+impl _S {
+    fn _f() {}
+}
diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr
index 191daff2137d8..24e3894864787 100644
--- a/tests/ui/stats/input-stats.stderr
+++ b/tests/ui/stats/input-stats.stderr
@@ -10,9 +10,9 @@ ast-stats-1 - DocComment                32 ( 0.5%)             1
 ast-stats-1 - Normal                    32 ( 0.5%)             1
 ast-stats-1 WherePredicate            72 ( 1.1%)             1            72
 ast-stats-1 - BoundPredicate            72 ( 1.1%)             1
+ast-stats-1 ForeignItem               80 ( 1.2%)             1            80
+ast-stats-1 - Fn                        80 ( 1.2%)             1
 ast-stats-1 Local                     80 ( 1.2%)             1            80
-ast-stats-1 ForeignItem               88 ( 1.3%)             1            88
-ast-stats-1 - Fn                        88 ( 1.3%)             1
 ast-stats-1 Arm                       96 ( 1.4%)             2            48
 ast-stats-1 FnDecl                   120 ( 1.8%)             5            24
 ast-stats-1 Param                    160 ( 2.4%)             4            40
@@ -23,37 +23,37 @@ ast-stats-1 - Expr                      96 ( 1.4%)             3
 ast-stats-1 Block                    192 ( 2.9%)             6            32
 ast-stats-1 FieldDef                 208 ( 3.1%)             2           104
 ast-stats-1 Variant                  208 ( 3.1%)             2           104
-ast-stats-1 AssocItem                352 ( 5.3%)             4            88
-ast-stats-1 - Fn                       176 ( 2.6%)             2
-ast-stats-1 - Type                     176 ( 2.6%)             2
-ast-stats-1 GenericBound             352 ( 5.3%)             4            88
-ast-stats-1 - Trait                    352 ( 5.3%)             4
-ast-stats-1 GenericParam             480 ( 7.2%)             5            96
+ast-stats-1 AssocItem                320 ( 4.8%)             4            80
+ast-stats-1 - Fn                       160 ( 2.4%)             2
+ast-stats-1 - Type                     160 ( 2.4%)             2
+ast-stats-1 GenericBound             352 ( 5.2%)             4            88
+ast-stats-1 - Trait                    352 ( 5.2%)             4
+ast-stats-1 GenericParam             480 ( 7.1%)             5            96
 ast-stats-1 Pat                      504 ( 7.5%)             7            72
 ast-stats-1 - Struct                    72 ( 1.1%)             1
 ast-stats-1 - Wild                      72 ( 1.1%)             1
-ast-stats-1 - Ident                    360 ( 5.4%)             5
+ast-stats-1 - Ident                    360 ( 5.3%)             5
 ast-stats-1 Expr                     576 ( 8.6%)             8            72
 ast-stats-1 - Match                     72 ( 1.1%)             1
 ast-stats-1 - Path                      72 ( 1.1%)             1
 ast-stats-1 - Struct                    72 ( 1.1%)             1
 ast-stats-1 - Lit                      144 ( 2.1%)             2
 ast-stats-1 - Block                    216 ( 3.2%)             3
-ast-stats-1 PathSegment              744 (11.1%)            31            24
-ast-stats-1 Ty                       896 (13.4%)            14            64
+ast-stats-1 PathSegment              744 (11.0%)            31            24
+ast-stats-1 Ty                       896 (13.3%)            14            64
 ast-stats-1 - Ptr                       64 ( 1.0%)             1
 ast-stats-1 - Ref                       64 ( 1.0%)             1
 ast-stats-1 - ImplicitSelf             128 ( 1.9%)             2
 ast-stats-1 - Path                     640 ( 9.5%)            10
-ast-stats-1 Item                   1_224 (18.3%)             9           136
-ast-stats-1 - Enum                     136 ( 2.0%)             1
-ast-stats-1 - ForeignMod               136 ( 2.0%)             1
-ast-stats-1 - Impl                     136 ( 2.0%)             1
-ast-stats-1 - Trait                    136 ( 2.0%)             1
-ast-stats-1 - Fn                       272 ( 4.1%)             2
-ast-stats-1 - Use                      408 ( 6.1%)             3
+ast-stats-1 Item                   1_296 (19.2%)             9           144
+ast-stats-1 - Enum                     144 ( 2.1%)             1
+ast-stats-1 - ForeignMod               144 ( 2.1%)             1
+ast-stats-1 - Impl                     144 ( 2.1%)             1
+ast-stats-1 - Trait                    144 ( 2.1%)             1
+ast-stats-1 - Fn                       288 ( 4.3%)             2
+ast-stats-1 - Use                      432 ( 6.4%)             3
 ast-stats-1 ----------------------------------------------------------------
-ast-stats-1 Total                  6_704                   116
+ast-stats-1 Total                  6_736                   116
 ast-stats-1
 ast-stats-2 POST EXPANSION AST STATS
 ast-stats-2 Name                Accumulated Size         Count     Item Size
@@ -61,12 +61,12 @@ ast-stats-2 ----------------------------------------------------------------
 ast-stats-2 Crate                     40 ( 0.5%)             1            40
 ast-stats-2 GenericArgs               40 ( 0.5%)             1            40
 ast-stats-2 - AngleBracketed            40 ( 0.5%)             1
-ast-stats-2 ExprField                 48 ( 0.7%)             1            48
+ast-stats-2 ExprField                 48 ( 0.6%)             1            48
 ast-stats-2 WherePredicate            72 ( 1.0%)             1            72
 ast-stats-2 - BoundPredicate            72 ( 1.0%)             1
+ast-stats-2 ForeignItem               80 ( 1.1%)             1            80
+ast-stats-2 - Fn                        80 ( 1.1%)             1
 ast-stats-2 Local                     80 ( 1.1%)             1            80
-ast-stats-2 ForeignItem               88 ( 1.2%)             1            88
-ast-stats-2 - Fn                        88 ( 1.2%)             1
 ast-stats-2 Arm                       96 ( 1.3%)             2            48
 ast-stats-2 FnDecl                   120 ( 1.6%)             5            24
 ast-stats-2 InlineAsm                120 ( 1.6%)             1           120
@@ -81,13 +81,13 @@ ast-stats-2 - Expr                      96 ( 1.3%)             3
 ast-stats-2 Block                    192 ( 2.6%)             6            32
 ast-stats-2 FieldDef                 208 ( 2.8%)             2           104
 ast-stats-2 Variant                  208 ( 2.8%)             2           104
-ast-stats-2 AssocItem                352 ( 4.8%)             4            88
-ast-stats-2 - Fn                       176 ( 2.4%)             2
-ast-stats-2 - Type                     176 ( 2.4%)             2
+ast-stats-2 AssocItem                320 ( 4.3%)             4            80
+ast-stats-2 - Fn                       160 ( 2.2%)             2
+ast-stats-2 - Type                     160 ( 2.2%)             2
 ast-stats-2 GenericBound             352 ( 4.8%)             4            88
 ast-stats-2 - Trait                    352 ( 4.8%)             4
 ast-stats-2 GenericParam             480 ( 6.5%)             5            96
-ast-stats-2 Pat                      504 ( 6.9%)             7            72
+ast-stats-2 Pat                      504 ( 6.8%)             7            72
 ast-stats-2 - Struct                    72 ( 1.0%)             1
 ast-stats-2 - Wild                      72 ( 1.0%)             1
 ast-stats-2 - Ident                    360 ( 4.9%)             5
@@ -96,24 +96,24 @@ ast-stats-2 - InlineAsm                 72 ( 1.0%)             1
 ast-stats-2 - Match                     72 ( 1.0%)             1
 ast-stats-2 - Path                      72 ( 1.0%)             1
 ast-stats-2 - Struct                    72 ( 1.0%)             1
-ast-stats-2 - Lit                      144 ( 2.0%)             2
+ast-stats-2 - Lit                      144 ( 1.9%)             2
 ast-stats-2 - Block                    216 ( 2.9%)             3
-ast-stats-2 PathSegment              864 (11.8%)            36            24
-ast-stats-2 Ty                       896 (12.2%)            14            64
+ast-stats-2 PathSegment              864 (11.7%)            36            24
+ast-stats-2 Ty                       896 (12.1%)            14            64
 ast-stats-2 - Ptr                       64 ( 0.9%)             1
 ast-stats-2 - Ref                       64 ( 0.9%)             1
 ast-stats-2 - ImplicitSelf             128 ( 1.7%)             2
-ast-stats-2 - Path                     640 ( 8.7%)            10
-ast-stats-2 Item                   1_496 (20.3%)            11           136
-ast-stats-2 - Enum                     136 ( 1.8%)             1
-ast-stats-2 - ExternCrate              136 ( 1.8%)             1
-ast-stats-2 - ForeignMod               136 ( 1.8%)             1
-ast-stats-2 - Impl                     136 ( 1.8%)             1
-ast-stats-2 - Trait                    136 ( 1.8%)             1
-ast-stats-2 - Fn                       272 ( 3.7%)             2
-ast-stats-2 - Use                      544 ( 7.4%)             4
+ast-stats-2 - Path                     640 ( 8.6%)            10
+ast-stats-2 Item                   1_584 (21.4%)            11           144
+ast-stats-2 - Enum                     144 ( 1.9%)             1
+ast-stats-2 - ExternCrate              144 ( 1.9%)             1
+ast-stats-2 - ForeignMod               144 ( 1.9%)             1
+ast-stats-2 - Impl                     144 ( 1.9%)             1
+ast-stats-2 - Trait                    144 ( 1.9%)             1
+ast-stats-2 - Fn                       288 ( 3.9%)             2
+ast-stats-2 - Use                      576 ( 7.8%)             4
 ast-stats-2 ----------------------------------------------------------------
-ast-stats-2 Total                  7_352                   127
+ast-stats-2 Total                  7_400                   127
 ast-stats-2
 hir-stats HIR STATS
 hir-stats Name                Accumulated Size         Count     Item Size