about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs130
-rw-r--r--compiler/rustc_ast/src/visit.rs376
-rw-r--r--compiler/rustc_ast_lowering/src/delegation.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs59
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_lint/src/early.rs37
-rw-r--r--compiler/rustc_llvm/build.rs4
-rw-r--r--compiler/rustc_middle/src/query/mod.rs3
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs16
-rw-r--r--compiler/rustc_passes/src/check_attr.rs4
-rw-r--r--compiler/rustc_resolve/src/check_unused.rs10
-rw-r--r--compiler/rustc_resolve/src/late.rs8
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs2
14 files changed, 325 insertions, 335 deletions
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index f1b183e25b5..08726ee6b41 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -12,7 +12,6 @@ use std::panic;
 
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
 use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_span::source_map::Spanned;
 use rustc_span::{Ident, Span};
 use smallvec::{Array, SmallVec, smallvec};
 use thin_vec::ThinVec;
@@ -499,58 +498,6 @@ fn walk_assoc_item_constraint<T: MutVisitor>(
     vis.visit_span(span);
 }
 
-pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut Ty) {
-    let Ty { id, kind, span, tokens: _ } = ty;
-    vis.visit_id(id);
-    match kind {
-        TyKind::Err(_guar) => {}
-        TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Never | TyKind::CVarArgs => {
-        }
-        TyKind::Slice(ty) => vis.visit_ty(ty),
-        TyKind::Ptr(MutTy { ty, mutbl: _ }) => vis.visit_ty(ty),
-        TyKind::Ref(lt, MutTy { ty, mutbl: _ }) | TyKind::PinnedRef(lt, MutTy { ty, mutbl: _ }) => {
-            visit_opt(lt, |lt| vis.visit_lifetime(lt));
-            vis.visit_ty(ty);
-        }
-        TyKind::BareFn(bft) => {
-            let BareFnTy { safety, ext: _, generic_params, decl, decl_span } = bft.deref_mut();
-            visit_safety(vis, safety);
-            generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
-            vis.visit_fn_decl(decl);
-            vis.visit_span(decl_span);
-        }
-        TyKind::UnsafeBinder(binder) => {
-            let UnsafeBinderTy { generic_params, inner_ty } = binder.deref_mut();
-            generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
-            vis.visit_ty(inner_ty);
-        }
-        TyKind::Tup(tys) => visit_thin_vec(tys, |ty| vis.visit_ty(ty)),
-        TyKind::Paren(ty) => vis.visit_ty(ty),
-        TyKind::Pat(ty, pat) => {
-            vis.visit_ty(ty);
-            vis.visit_ty_pat(pat);
-        }
-        TyKind::Path(qself, path) => {
-            vis.visit_qself(qself);
-            vis.visit_path(path);
-        }
-        TyKind::Array(ty, length) => {
-            vis.visit_ty(ty);
-            vis.visit_anon_const(length);
-        }
-        TyKind::Typeof(expr) => vis.visit_anon_const(expr),
-        TyKind::TraitObject(bounds, _syntax) => {
-            visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::TraitObject))
-        }
-        TyKind::ImplTrait(id, bounds) => {
-            vis.visit_id(id);
-            visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Impl));
-        }
-        TyKind::MacCall(mac) => vis.visit_mac_call(mac),
-    }
-    vis.visit_span(span);
-}
-
 pub fn walk_ty_pat<T: MutVisitor>(vis: &mut T, ty: &mut TyPat) {
     let TyPat { id, kind, span, tokens: _ } = ty;
     vis.visit_id(id);
@@ -588,13 +535,6 @@ fn walk_ident<T: MutVisitor>(vis: &mut T, Ident { name: _, span }: &mut Ident) {
     vis.visit_span(span);
 }
 
-fn walk_path_segment<T: MutVisitor>(vis: &mut T, segment: &mut PathSegment) {
-    let PathSegment { ident, id, args } = segment;
-    vis.visit_id(id);
-    vis.visit_ident(ident);
-    visit_opt(args, |args| vis.visit_generic_args(args));
-}
-
 fn walk_path<T: MutVisitor>(vis: &mut T, Path { segments, span, tokens: _ }: &mut Path) {
     for segment in segments {
         vis.visit_path_segment(segment);
@@ -729,18 +669,6 @@ fn walk_closure_binder<T: MutVisitor>(vis: &mut T, binder: &mut ClosureBinder) {
     }
 }
 
-fn walk_coroutine_kind<T: MutVisitor>(vis: &mut T, coroutine_kind: &mut CoroutineKind) {
-    match coroutine_kind {
-        CoroutineKind::Async { span, closure_id, return_impl_trait_id }
-        | CoroutineKind::Gen { span, closure_id, return_impl_trait_id }
-        | CoroutineKind::AsyncGen { span, closure_id, return_impl_trait_id } => {
-            vis.visit_id(closure_id);
-            vis.visit_id(return_impl_trait_id);
-            vis.visit_span(span);
-        }
-    }
-}
-
 fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
     match kind {
         FnKind::Fn(
@@ -991,13 +919,6 @@ pub fn walk_flat_map_expr_field<T: MutVisitor>(
     smallvec![f]
 }
 
-pub fn walk_block<T: MutVisitor>(vis: &mut T, block: &mut Block) {
-    let Block { id, stmts, rules: _, span, tokens: _ } = block;
-    vis.visit_id(id);
-    stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt));
-    vis.visit_span(span);
-}
-
 pub fn walk_item_kind<K: WalkItemKind>(
     kind: &mut K,
     span: Span,
@@ -1041,57 +962,6 @@ pub fn walk_flat_map_assoc_item(
     smallvec![item]
 }
 
-pub fn walk_pat<T: MutVisitor>(vis: &mut T, pat: &mut Pat) {
-    let Pat { id, kind, span, tokens: _ } = pat;
-    vis.visit_id(id);
-    match kind {
-        PatKind::Err(_guar) => {}
-        PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {}
-        PatKind::Ident(_binding_mode, ident, sub) => {
-            vis.visit_ident(ident);
-            visit_opt(sub, |sub| vis.visit_pat(sub));
-        }
-        PatKind::Expr(e) => vis.visit_expr(e),
-        PatKind::TupleStruct(qself, path, elems) => {
-            vis.visit_qself(qself);
-            vis.visit_path(path);
-            visit_thin_vec(elems, |elem| vis.visit_pat(elem));
-        }
-        PatKind::Path(qself, path) => {
-            vis.visit_qself(qself);
-            vis.visit_path(path);
-        }
-        PatKind::Struct(qself, path, fields, _etc) => {
-            vis.visit_qself(qself);
-            vis.visit_path(path);
-            fields.flat_map_in_place(|field| vis.flat_map_pat_field(field));
-        }
-        PatKind::Box(inner) => vis.visit_pat(inner),
-        PatKind::Deref(inner) => vis.visit_pat(inner),
-        PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner),
-        PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => {
-            visit_opt(e1, |e| vis.visit_expr(e));
-            visit_opt(e2, |e| vis.visit_expr(e));
-            vis.visit_span(span);
-        }
-        PatKind::Guard(p, e) => {
-            vis.visit_pat(p);
-            vis.visit_expr(e);
-        }
-        PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
-            visit_thin_vec(elems, |elem| vis.visit_pat(elem))
-        }
-        PatKind::Paren(inner) => vis.visit_pat(inner),
-        PatKind::MacCall(mac) => vis.visit_mac_call(mac),
-    }
-    vis.visit_span(span);
-}
-
-fn walk_anon_const<T: MutVisitor>(vis: &mut T, AnonConst { id, value }: &mut AnonConst) {
-    vis.visit_id(id);
-    vis.visit_expr(value);
-}
-
 fn walk_inline_asm<T: MutVisitor>(vis: &mut T, asm: &mut InlineAsm) {
     // FIXME: Visit spans inside all this currently ignored stuff.
     let InlineAsm {
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index e1c2dd05324..908d9fd4bda 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -210,7 +210,7 @@ pub trait Visitor<'ast>: Sized {
         walk_poly_trait_ref(self, t)
     }
     fn visit_variant_data(&mut self, s: &'ast VariantData) -> Self::Result {
-        walk_struct_def(self, s)
+        walk_variant_data(self, s)
     }
     fn visit_field_def(&mut self, s: &'ast FieldDef) -> Self::Result {
         walk_field_def(self, s)
@@ -233,10 +233,13 @@ pub trait Visitor<'ast>: Sized {
     fn visit_mac_call(&mut self, mac: &'ast MacCall) -> Self::Result {
         walk_mac(self, mac)
     }
-    fn visit_macro_def(&mut self, _mac: &'ast MacroDef, _id: NodeId) -> Self::Result {
+    fn visit_id(&mut self, _id: NodeId) -> Self::Result {
         Self::Result::output()
     }
-    fn visit_path(&mut self, path: &'ast Path, _id: NodeId) -> Self::Result {
+    fn visit_macro_def(&mut self, _mac: &'ast MacroDef) -> Self::Result {
+        Self::Result::output()
+    }
+    fn visit_path(&mut self, path: &'ast Path) -> Self::Result {
         walk_path(self, path)
     }
     fn visit_use_tree(
@@ -295,8 +298,8 @@ pub trait Visitor<'ast>: Sized {
     fn visit_capture_by(&mut self, _capture_by: &'ast CaptureBy) -> Self::Result {
         Self::Result::output()
     }
-    fn visit_coroutine_kind(&mut self, _coroutine_kind: &'ast CoroutineKind) -> Self::Result {
-        Self::Result::output()
+    fn visit_coroutine_kind(&mut self, coroutine_kind: &'ast CoroutineKind) -> Self::Result {
+        walk_coroutine_kind(self, coroutine_kind)
     }
     fn visit_fn_decl(&mut self, fn_decl: &'ast FnDecl) -> Self::Result {
         walk_fn_decl(self, fn_decl)
@@ -334,17 +337,14 @@ macro_rules! common_visitor_and_walkers {
             $(${ignore($lt)}V::Result::output())?
         }
 
-        // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier
+        /// helper since `Visitor` wants `NodeId` but `MutVisitor` wants `&mut NodeId`
         $(${ignore($lt)}
-            #[expect(unused, rustc::pass_by_value)]
-            #[inline]
+            #[expect(rustc::pass_by_value)]
         )?
+        #[inline]
         fn visit_id<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, id: &$($lt)? $($mut)? NodeId) $(-> <V as Visitor<$lt>>::Result)? {
-            $(
-                ${ignore($mut)}
-                visitor.visit_id(id);
-            )?
-            $(${ignore($lt)}V::Result::output())?
+            // deref `&NodeId` into `NodeId` only for `Visitor`
+            visitor.visit_id( $(${ignore($lt)} * )? id)
         }
 
         // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier
@@ -577,8 +577,7 @@ macro_rules! common_visitor_and_walkers {
                     ItemKind::MacCall(m) => vis.visit_mac_call(m),
                     ItemKind::MacroDef(ident, def) => {
                         try_visit!(vis.visit_ident(ident));
-                        // FIXME(fee1-dead) assymetry
-                        vis.visit_macro_def(def$(${ignore($lt)}, id)?)
+                        vis.visit_macro_def(def)
                     }
                     ItemKind::Delegation(box Delegation {
                         id,
@@ -591,7 +590,7 @@ macro_rules! common_visitor_and_walkers {
                     }) => {
                         try_visit!(visit_id(vis, id));
                         try_visit!(vis.visit_qself(qself));
-                        try_visit!(vis.visit_path(path$(${ignore($lt)}, *id)?));
+                        try_visit!(vis.visit_path(path));
                         try_visit!(vis.visit_ident(ident));
                         visit_opt!(vis, visit_ident, rename);
                         visit_opt!(vis, visit_block, body);
@@ -599,7 +598,7 @@ macro_rules! common_visitor_and_walkers {
                     }
                     ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
                         try_visit!(vis.visit_qself(qself));
-                        try_visit!(vis.visit_path(prefix$(${ignore($lt)}, id)?));
+                        try_visit!(vis.visit_path(prefix));
                         if let Some(suffixes) = suffixes {
                             for (ident, rename) in suffixes {
                                 try_visit!(vis.visit_ident(ident));
@@ -642,8 +641,7 @@ macro_rules! common_visitor_and_walkers {
             if let Some(define_opaque) = define_opaque {
                 for (id, path) in define_opaque {
                     try_visit!(visit_id(visitor, id));
-                    // FIXME(fee1-dead): look into this weird assymetry
-                    try_visit!(visitor.visit_path(path$(${ignore($lt)}, *id)?));
+                    try_visit!(visitor.visit_path(path));
                 }
             }
             $(<V as Visitor<$lt>>::Result::output())?
@@ -699,7 +697,7 @@ macro_rules! common_visitor_and_walkers {
                     }) => {
                         try_visit!(visit_id(vis, id));
                         try_visit!(vis.visit_qself(qself));
-                        try_visit!(vis.visit_path(path $(${ignore($lt)}, *id)?));
+                        try_visit!(vis.visit_path(path));
                         try_visit!(vis.visit_ident(ident));
                         visit_opt!(vis, visit_ident, rename);
                         visit_opt!(vis, visit_block, body);
@@ -707,7 +705,7 @@ macro_rules! common_visitor_and_walkers {
                     }
                     AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
                         try_visit!(vis.visit_qself(qself));
-                        try_visit!(vis.visit_path(prefix$(${ignore($lt)}, id)?));
+                        try_visit!(vis.visit_path(prefix));
                         if let Some(suffixes) = suffixes {
                             for (ident, rename) in suffixes {
                                 try_visit!(vis.visit_ident(ident));
@@ -773,6 +771,190 @@ macro_rules! common_visitor_and_walkers {
                 }
             }
         }
+
+        fn walk_coroutine_kind<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            coroutine_kind: &$($lt)? $($mut)? CoroutineKind,
+        ) $(-> <V as Visitor<$lt>>::Result)? {
+            match coroutine_kind {
+                CoroutineKind::Async { span, closure_id, return_impl_trait_id }
+                | CoroutineKind::Gen { span, closure_id, return_impl_trait_id }
+                | CoroutineKind::AsyncGen { span, closure_id, return_impl_trait_id } => {
+                    try_visit!(visit_id(vis, closure_id));
+                    try_visit!(visit_id(vis, return_impl_trait_id));
+                    visit_span(vis, span)
+                }
+            }
+        }
+
+        pub fn walk_pat<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            pattern: &$($lt)? $($mut)? Pat
+        ) $(-> <V as Visitor<$lt>>::Result)? {
+            let Pat { id, kind, span, tokens: _ } = pattern;
+            try_visit!(visit_id(vis, id));
+            match kind {
+                PatKind::Err(_guar) => {}
+                PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {}
+                PatKind::Ident(_bmode, ident, optional_subpattern) => {
+                    try_visit!(vis.visit_ident(ident));
+                    visit_opt!(vis, visit_pat, optional_subpattern);
+                }
+                PatKind::Expr(expression) => try_visit!(vis.visit_expr(expression)),
+                PatKind::TupleStruct(opt_qself, path, elems) => {
+                    try_visit!(vis.visit_qself(opt_qself));
+                    try_visit!(vis.visit_path(path));
+                    walk_list!(vis, visit_pat, elems);
+                }
+                PatKind::Path(opt_qself, path) => {
+                    try_visit!(vis.visit_qself(opt_qself));
+                    try_visit!(vis.visit_path(path))
+                }
+                PatKind::Struct(opt_qself, path, fields, _rest) => {
+                    try_visit!(vis.visit_qself(opt_qself));
+                    try_visit!(vis.visit_path(path));
+
+                    $(
+                        ${ignore($lt)}
+                        walk_list!(vis, visit_pat_field, fields);
+                    )?
+                    $(
+                        ${ignore($mut)}
+                        fields.flat_map_in_place(|field| vis.flat_map_pat_field(field));
+                    )?
+                }
+                PatKind::Box(subpattern) | PatKind::Deref(subpattern) | PatKind::Paren(subpattern) => {
+                    try_visit!(vis.visit_pat(subpattern));
+                }
+                PatKind::Ref(subpattern, _ /*mutbl*/) => {
+                    try_visit!(vis.visit_pat(subpattern));
+                }
+                PatKind::Range(lower_bound, upper_bound, _end) => {
+                    visit_opt!(vis, visit_expr, lower_bound);
+                    visit_opt!(vis, visit_expr, upper_bound);
+                    try_visit!(visit_span(vis, span));
+                }
+                PatKind::Guard(subpattern, guard_condition) => {
+                    try_visit!(vis.visit_pat(subpattern));
+                    try_visit!(vis.visit_expr(guard_condition));
+                }
+                PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
+                    walk_list!(vis, visit_pat, elems);
+                }
+                PatKind::MacCall(mac) => try_visit!(vis.visit_mac_call(mac)),
+            }
+            visit_span(vis, span)
+        }
+
+        pub fn walk_anon_const<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            constant: &$($lt)? $($mut)? AnonConst,
+        ) $(-> <V as Visitor<$lt>>::Result)? {
+            let AnonConst { id, value } = constant;
+            try_visit!(visit_id(vis, id));
+            vis.visit_expr(value)
+        }
+
+        pub fn walk_path_segment<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            segment: &$($lt)? $($mut)? PathSegment,
+        ) $(-> <V as Visitor<$lt>>::Result)? {
+            let PathSegment { ident, id, args } = segment;
+            try_visit!(visit_id(vis, id));
+            try_visit!(vis.visit_ident(ident));
+            visit_opt!(vis, visit_generic_args, args);
+            $(<V as Visitor<$lt>>::Result::output())?
+        }
+
+        pub fn walk_block<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            block: &$($lt)? $($mut)? Block
+        ) $(-> <V as Visitor<$lt>>::Result)? {
+            let Block { stmts, id, rules: _, span, tokens: _ } = block;
+            try_visit!(visit_id(vis, id));
+            $(
+                ${ignore($lt)}
+                walk_list!(vis, visit_stmt, stmts);
+            )?
+            $(
+                ${ignore($mut)}
+                stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt));
+            )?
+            visit_span(vis, span)
+        }
+
+
+        pub fn walk_ty<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V, ty: &$($lt)? $($mut)? Ty
+        ) $(-> <V as Visitor<$lt>>::Result)? {
+            let Ty { id, kind, span, tokens: _ } = ty;
+            try_visit!(visit_id(vis, id));
+            match kind {
+                TyKind::Err(_guar) => {}
+                TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Never | TyKind::CVarArgs => {}
+                TyKind::Slice(ty) | TyKind::Paren(ty) => try_visit!(vis.visit_ty(ty)),
+                TyKind::Ptr(MutTy { ty, mutbl: _ }) => try_visit!(vis.visit_ty(ty)),
+                TyKind::Ref(opt_lifetime, MutTy { ty, mutbl: _ })
+                | TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl: _ }) => {
+                    // FIXME(fee1-dead) asymmetry
+                    visit_opt!(vis, visit_lifetime, opt_lifetime$(${ignore($lt)}, LifetimeCtxt::Ref)?);
+                    try_visit!(vis.visit_ty(ty));
+                }
+                TyKind::Tup(tuple_element_types) => {
+                    walk_list!(vis, visit_ty, tuple_element_types);
+                }
+                TyKind::BareFn(function_declaration) => {
+                    let BareFnTy { safety, ext: _, generic_params, decl, decl_span } =
+                        &$($mut)? **function_declaration;
+                    visit_safety(vis, safety);
+                    $(
+                        ${ignore($lt)}
+                        walk_list!(vis, visit_generic_param, generic_params);
+                    )?
+                    $(
+                        ${ignore($mut)}
+                        generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
+                    )?
+
+                    try_visit!(vis.visit_fn_decl(decl));
+                    try_visit!(visit_span(vis, decl_span));
+                }
+                TyKind::UnsafeBinder(binder) => {
+                    $(
+                        ${ignore($lt)}
+                        walk_list!(vis, visit_generic_param, &binder.generic_params);
+                    )?
+                    $(
+                        ${ignore($mut)}
+                        binder.generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
+                    )?
+                    try_visit!(vis.visit_ty(&$($mut)?binder.inner_ty));
+                }
+                TyKind::Path(maybe_qself, path) => {
+                    try_visit!(vis.visit_qself(maybe_qself));
+                    try_visit!(vis.visit_path(path));
+                }
+                TyKind::Pat(ty, pat) => {
+                    try_visit!(vis.visit_ty(ty));
+                    try_visit!(vis.visit_ty_pat(pat));
+                }
+                TyKind::Array(ty, length) => {
+                    try_visit!(vis.visit_ty(ty));
+                    try_visit!(vis.visit_anon_const(length));
+                }
+                TyKind::TraitObject(bounds, _syntax) => {
+                    walk_list!(vis, visit_param_bound, bounds, BoundKind::TraitObject);
+                }
+                TyKind::ImplTrait(id, bounds) => {
+                    try_visit!(visit_id(vis, id));
+                    walk_list!(vis, visit_param_bound, bounds, BoundKind::Impl);
+                }
+                TyKind::Typeof(expression) => try_visit!(vis.visit_anon_const(expression)),
+
+                TyKind::MacCall(mac) => try_visit!(vis.visit_mac_call(mac)),
+            }
+            visit_span(vis, span)
+        }
     };
 }
 
@@ -808,7 +990,8 @@ where
 
 pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitRef) -> V::Result {
     let TraitRef { path, ref_id } = trait_ref;
-    visitor.visit_path(path, *ref_id)
+    try_visit!(visitor.visit_path(path));
+    visitor.visit_id(*ref_id)
 }
 
 pub fn walk_enum_def<'a, V: Visitor<'a>>(
@@ -848,56 +1031,6 @@ pub fn walk_pat_field<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a PatField) ->
     V::Result::output()
 }
 
-pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
-    let Ty { id, kind, span: _, tokens: _ } = typ;
-    match kind {
-        TyKind::Slice(ty) | TyKind::Paren(ty) => try_visit!(visitor.visit_ty(ty)),
-        TyKind::Ptr(MutTy { ty, mutbl: _ }) => try_visit!(visitor.visit_ty(ty)),
-        TyKind::Ref(opt_lifetime, MutTy { ty, mutbl: _ })
-        | TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl: _ }) => {
-            visit_opt!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref);
-            try_visit!(visitor.visit_ty(ty));
-        }
-        TyKind::Tup(tuple_element_types) => {
-            walk_list!(visitor, visit_ty, tuple_element_types);
-        }
-        TyKind::BareFn(function_declaration) => {
-            let BareFnTy { safety: _, ext: _, generic_params, decl, decl_span: _ } =
-                &**function_declaration;
-            walk_list!(visitor, visit_generic_param, generic_params);
-            try_visit!(visitor.visit_fn_decl(decl));
-        }
-        TyKind::UnsafeBinder(binder) => {
-            walk_list!(visitor, visit_generic_param, &binder.generic_params);
-            try_visit!(visitor.visit_ty(&binder.inner_ty));
-        }
-        TyKind::Path(maybe_qself, path) => {
-            try_visit!(visitor.visit_qself(maybe_qself));
-            try_visit!(visitor.visit_path(path, *id));
-        }
-        TyKind::Pat(ty, pat) => {
-            try_visit!(visitor.visit_ty(ty));
-            try_visit!(visitor.visit_ty_pat(pat));
-        }
-        TyKind::Array(ty, length) => {
-            try_visit!(visitor.visit_ty(ty));
-            try_visit!(visitor.visit_anon_const(length));
-        }
-        TyKind::TraitObject(bounds, _syntax) => {
-            walk_list!(visitor, visit_param_bound, bounds, BoundKind::TraitObject);
-        }
-        TyKind::ImplTrait(_id, bounds) => {
-            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl);
-        }
-        TyKind::Typeof(expression) => try_visit!(visitor.visit_anon_const(expression)),
-        TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy => {}
-        TyKind::Err(_guar) => {}
-        TyKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
-        TyKind::Never | TyKind::CVarArgs => {}
-    }
-    V::Result::output()
-}
-
 pub fn walk_ty_pat<'a, V: Visitor<'a>>(visitor: &mut V, tp: &'a TyPat) -> V::Result {
     let TyPat { id: _, kind, span: _, tokens: _ } = tp;
     match kind {
@@ -931,7 +1064,8 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
     id: NodeId,
 ) -> V::Result {
     let UseTree { prefix, kind, span: _ } = use_tree;
-    try_visit!(visitor.visit_path(prefix, id));
+    try_visit!(visitor.visit_id(id));
+    try_visit!(visitor.visit_path(prefix));
     match kind {
         UseTreeKind::Simple(rename) => {
             // The extra IDs are handled during AST lowering.
@@ -947,16 +1081,6 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
     V::Result::output()
 }
 
-pub fn walk_path_segment<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    segment: &'a PathSegment,
-) -> V::Result {
-    let PathSegment { ident, id: _, args } = segment;
-    try_visit!(visitor.visit_ident(ident));
-    visit_opt!(visitor, visit_generic_args, args);
-    V::Result::output()
-}
-
 pub fn walk_generic_args<'a, V>(visitor: &mut V, generic_args: &'a GenericArgs) -> V::Result
 where
     V: Visitor<'a>,
@@ -1012,52 +1136,6 @@ pub fn walk_assoc_item_constraint<'a, V: Visitor<'a>>(
     V::Result::output()
 }
 
-pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Result {
-    let Pat { id, kind, span: _, tokens: _ } = pattern;
-    match kind {
-        PatKind::TupleStruct(opt_qself, path, elems) => {
-            try_visit!(visitor.visit_qself(opt_qself));
-            try_visit!(visitor.visit_path(path, *id));
-            walk_list!(visitor, visit_pat, elems);
-        }
-        PatKind::Path(opt_qself, path) => {
-            try_visit!(visitor.visit_qself(opt_qself));
-            try_visit!(visitor.visit_path(path, *id))
-        }
-        PatKind::Struct(opt_qself, path, fields, _rest) => {
-            try_visit!(visitor.visit_qself(opt_qself));
-            try_visit!(visitor.visit_path(path, *id));
-            walk_list!(visitor, visit_pat_field, fields);
-        }
-        PatKind::Box(subpattern) | PatKind::Deref(subpattern) | PatKind::Paren(subpattern) => {
-            try_visit!(visitor.visit_pat(subpattern));
-        }
-        PatKind::Ref(subpattern, _ /*mutbl*/) => {
-            try_visit!(visitor.visit_pat(subpattern));
-        }
-        PatKind::Ident(_bmode, ident, optional_subpattern) => {
-            try_visit!(visitor.visit_ident(ident));
-            visit_opt!(visitor, visit_pat, optional_subpattern);
-        }
-        PatKind::Expr(expression) => try_visit!(visitor.visit_expr(expression)),
-        PatKind::Range(lower_bound, upper_bound, _end) => {
-            visit_opt!(visitor, visit_expr, lower_bound);
-            visit_opt!(visitor, visit_expr, upper_bound);
-        }
-        PatKind::Guard(subpattern, guard_condition) => {
-            try_visit!(visitor.visit_pat(subpattern));
-            try_visit!(visitor.visit_expr(guard_condition));
-        }
-        PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {}
-        PatKind::Err(_guar) => {}
-        PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
-            walk_list!(visitor, visit_pat, elems);
-        }
-        PatKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
-    }
-    V::Result::output()
-}
-
 pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) -> V::Result {
     match bound {
         GenericBound::Trait(trait_ref) => visitor.visit_poly_trait_ref(trait_ref),
@@ -1075,7 +1153,10 @@ pub fn walk_precise_capturing_arg<'a, V: Visitor<'a>>(
 ) -> V::Result {
     match arg {
         PreciseCapturingArg::Lifetime(lt) => visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg),
-        PreciseCapturingArg::Arg(path, id) => visitor.visit_path(path, *id),
+        PreciseCapturingArg::Arg(path, id) => {
+            try_visit!(visitor.visit_id(*id));
+            visitor.visit_path(path)
+        }
     }
 }
 
@@ -1216,11 +1297,9 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
     V::Result::output()
 }
 
-pub fn walk_struct_def<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    struct_definition: &'a VariantData,
-) -> V::Result {
-    walk_list!(visitor, visit_field_def, struct_definition.fields());
+pub fn walk_variant_data<'a, V: Visitor<'a>>(visitor: &mut V, data: &'a VariantData) -> V::Result {
+    visit_opt!(visitor, visit_id, data.ctor_node_id());
+    walk_list!(visitor, visit_field_def, data.fields());
     V::Result::output()
 }
 
@@ -1235,12 +1314,6 @@ pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef)
     V::Result::output()
 }
 
-pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) -> V::Result {
-    let Block { stmts, id: _, rules: _, span: _, tokens: _ } = block;
-    walk_list!(visitor, visit_stmt, stmts);
-    V::Result::output()
-}
-
 pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result {
     let Stmt { id: _, kind, span: _ } = statement;
     match kind {
@@ -1259,12 +1332,7 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V:
 
 pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) -> V::Result {
     let MacCall { path, args: _ } = mac;
-    visitor.visit_path(path, DUMMY_NODE_ID)
-}
-
-pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) -> V::Result {
-    let AnonConst { id: _, value } = constant;
-    visitor.visit_expr(value)
+    visitor.visit_path(path)
 }
 
 pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) -> V::Result {
@@ -1304,7 +1372,8 @@ pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(
     InlineAsmSym { id, qself, path }: &'a InlineAsmSym,
 ) -> V::Result {
     try_visit!(visitor.visit_qself(qself));
-    visitor.visit_path(path, *id)
+    try_visit!(visitor.visit_id(*id));
+    visitor.visit_path(path)
 }
 
 pub fn walk_format_args<'a, V: Visitor<'a>>(visitor: &mut V, fmt: &'a FormatArgs) -> V::Result {
@@ -1336,7 +1405,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
         ExprKind::Struct(se) => {
             let StructExpr { qself, path, fields, rest } = &**se;
             try_visit!(visitor.visit_qself(qself));
-            try_visit!(visitor.visit_path(path, *id));
+            try_visit!(visitor.visit_id(*id));
+            try_visit!(visitor.visit_path(path));
             walk_list!(visitor, visit_expr_field, fields);
             match rest {
                 StructRest::Base(expr) => try_visit!(visitor.visit_expr(expr)),
@@ -1446,7 +1516,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
         ExprKind::Underscore => {}
         ExprKind::Path(maybe_qself, path) => {
             try_visit!(visitor.visit_qself(maybe_qself));
-            try_visit!(visitor.visit_path(path, *id));
+            try_visit!(visitor.visit_id(*id));
+            try_visit!(visitor.visit_path(path));
         }
         ExprKind::Break(opt_label, opt_expr) => {
             visit_opt!(visitor, visit_label, opt_label);
@@ -1509,7 +1580,8 @@ pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) -> V::
     let Visibility { kind, span: _, tokens: _ } = vis;
     match kind {
         VisibilityKind::Restricted { path, id, shorthand: _ } => {
-            try_visit!(visitor.visit_path(path, *id));
+            try_visit!(visitor.visit_id(*id));
+            try_visit!(visitor.visit_path(path));
         }
         VisibilityKind::Public | VisibilityKind::Inherited => {}
     }
@@ -1522,7 +1594,7 @@ pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute)
         AttrKind::Normal(normal) => {
             let NormalAttr { item, tokens: _ } = &**normal;
             let AttrItem { unsafety: _, path, args, tokens: _ } = item;
-            try_visit!(visitor.visit_path(path, DUMMY_NODE_ID));
+            try_visit!(visitor.visit_path(path));
             try_visit!(walk_attr_args(visitor, args));
         }
         AttrKind::DocComment(_kind, _sym) => {}
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index 93c627f64c9..42d25b512f5 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -446,13 +446,7 @@ impl<'a> SelfResolver<'a> {
 }
 
 impl<'ast, 'a> Visitor<'ast> for SelfResolver<'a> {
-    fn visit_path(&mut self, path: &'ast Path, id: NodeId) {
+    fn visit_id(&mut self, id: NodeId) {
         self.try_replace_id(id);
-        visit::walk_path(self, path);
-    }
-
-    fn visit_path_segment(&mut self, seg: &'ast PathSegment) {
-        self.try_replace_id(seg.id);
-        visit::walk_path_segment(self, seg);
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 58fa3c392ca..1a39a0c3fda 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -3,7 +3,7 @@ mod raw_dylib;
 use std::collections::BTreeSet;
 use std::ffi::OsString;
 use std::fs::{File, OpenOptions, read};
-use std::io::{BufWriter, Write};
+use std::io::{BufReader, BufWriter, Write};
 use std::ops::{ControlFlow, Deref};
 use std::path::{Path, PathBuf};
 use std::process::{Output, Stdio};
@@ -184,6 +184,12 @@ pub fn link_binary(
                 );
             }
 
+            if sess.target.binary_format == BinaryFormat::Elf {
+                if let Err(err) = warn_if_linked_with_gold(sess, &out_filename) {
+                    info!(?err, "Error while checking if gold was the linker");
+                }
+            }
+
             if output.is_stdout() {
                 if output.is_tty() {
                     sess.dcx().emit_err(errors::BinaryOutputToTty {
@@ -3375,3 +3381,54 @@ fn add_lld_args(
         }
     }
 }
+
+// gold has been deprecated with binutils 2.44
+// and is known to behave incorrectly around Rust programs.
+// There have been reports of being unable to bootstrap with gold:
+// https://github.com/rust-lang/rust/issues/139425
+// Additionally, gold miscompiles SHF_GNU_RETAIN sections, which are
+// emitted with `#[used(linker)]`.
+fn warn_if_linked_with_gold(sess: &Session, path: &Path) -> Result<(), Box<dyn std::error::Error>> {
+    use object::read::elf::{FileHeader, SectionHeader};
+    use object::read::{ReadCache, ReadRef, Result};
+    use object::{Endianness, elf};
+
+    fn elf_has_gold_version_note<'a>(
+        elf: &impl FileHeader,
+        data: impl ReadRef<'a>,
+    ) -> Result<bool> {
+        let endian = elf.endian()?;
+
+        let section =
+            elf.sections(endian, data)?.section_by_name(endian, b".note.gnu.gold-version");
+        if let Some((_, section)) = section {
+            if let Some(mut notes) = section.notes(endian, data)? {
+                return Ok(notes.any(|note| {
+                    note.is_ok_and(|note| note.n_type(endian) == elf::NT_GNU_GOLD_VERSION)
+                }));
+            }
+        }
+
+        Ok(false)
+    }
+
+    let data = ReadCache::new(BufReader::new(File::open(path)?));
+
+    let was_linked_with_gold = if sess.target.pointer_width == 64 {
+        let elf = elf::FileHeader64::<Endianness>::parse(&data)?;
+        elf_has_gold_version_note(elf, &data)?
+    } else if sess.target.pointer_width == 32 {
+        let elf = elf::FileHeader32::<Endianness>::parse(&data)?;
+        elf_has_gold_version_note(elf, &data)?
+    } else {
+        return Ok(());
+    };
+
+    if was_linked_with_gold {
+        let mut warn =
+            sess.dcx().struct_warn("the gold linker is deprecated and has known bugs with Rust");
+        warn.help("consider using LLD or ld from GNU binutils instead");
+        warn.emit();
+    }
+    Ok(())
+}
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 068d96c860f..558f13a832c 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -715,6 +715,7 @@ fn test_unstable_options_tracking_hash() {
     untracked!(no_analysis, true);
     untracked!(no_leak_check, true);
     untracked!(no_parallel_backend, true);
+    untracked!(no_steal_thir, true);
     untracked!(parse_crate_root_only, true);
     // `pre_link_arg` is omitted because it just forwards to `pre_link_args`.
     untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]);
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 0c62c14af63..4978f293ab7 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -74,8 +74,8 @@ impl<'ecx, 'tcx, T: EarlyLintPass> EarlyContextAndPass<'ecx, 'tcx, T> {
 impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
     for EarlyContextAndPass<'ecx, 'tcx, T>
 {
-    fn visit_coroutine_kind(&mut self, coroutine_kind: &'ast ast::CoroutineKind) -> Self::Result {
-        self.check_id(coroutine_kind.closure_id());
+    fn visit_id(&mut self, id: rustc_ast::NodeId) {
+        self.check_id(id);
     }
 
     fn visit_param(&mut self, param: &'ast ast::Param) {
@@ -101,7 +101,6 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
 
     fn visit_pat(&mut self, p: &'ast ast::Pat) {
         lint_callback!(self, check_pat, p);
-        self.check_id(p.id);
         ast_visit::walk_pat(self, p);
         lint_callback!(self, check_pat_post, p);
     }
@@ -112,11 +111,6 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
         });
     }
 
-    fn visit_anon_const(&mut self, c: &'ast ast::AnonConst) {
-        self.check_id(c.id);
-        ast_visit::walk_anon_const(self, c);
-    }
-
     fn visit_expr(&mut self, e: &'ast ast::Expr) {
         self.with_lint_attrs(e.id, &e.attrs, |cx| {
             lint_callback!(cx, check_expr, e);
@@ -157,13 +151,6 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
         ast_visit::walk_fn(self, fk);
     }
 
-    fn visit_variant_data(&mut self, s: &'ast ast::VariantData) {
-        if let Some(ctor_node_id) = s.ctor_node_id() {
-            self.check_id(ctor_node_id);
-        }
-        ast_visit::walk_struct_def(self, s);
-    }
-
     fn visit_field_def(&mut self, s: &'ast ast::FieldDef) {
         self.with_lint_attrs(s.id, &s.attrs, |cx| {
             ast_visit::walk_field_def(cx, s);
@@ -179,7 +166,6 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
 
     fn visit_ty(&mut self, t: &'ast ast::Ty) {
         lint_callback!(self, check_ty, t);
-        self.check_id(t.id);
         ast_visit::walk_ty(self, t);
     }
 
@@ -196,7 +182,6 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
 
     fn visit_block(&mut self, b: &'ast ast::Block) {
         lint_callback!(self, check_block, b);
-        self.check_id(b.id);
         ast_visit::walk_block(self, b);
     }
 
@@ -257,29 +242,13 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
         });
     }
 
-    fn visit_lifetime(&mut self, lt: &'ast ast::Lifetime, _: ast_visit::LifetimeCtxt) {
-        self.check_id(lt.id);
-        ast_visit::walk_lifetime(self, lt);
-    }
-
-    fn visit_path(&mut self, p: &'ast ast::Path, id: ast::NodeId) {
-        self.check_id(id);
-        ast_visit::walk_path(self, p);
-    }
-
-    fn visit_path_segment(&mut self, s: &'ast ast::PathSegment) {
-        self.check_id(s.id);
-        ast_visit::walk_path_segment(self, s);
-    }
-
     fn visit_attribute(&mut self, attr: &'ast ast::Attribute) {
         lint_callback!(self, check_attribute, attr);
         ast_visit::walk_attribute(self, attr);
     }
 
-    fn visit_macro_def(&mut self, mac: &'ast ast::MacroDef, id: ast::NodeId) {
+    fn visit_macro_def(&mut self, mac: &'ast ast::MacroDef) {
         lint_callback!(self, check_mac_def, mac);
-        self.check_id(id);
     }
 
     fn visit_mac_call(&mut self, mac: &'ast ast::MacCall) {
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index a662694ac38..9a6549379d3 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -228,10 +228,10 @@ fn main() {
     let mut cmd = Command::new(&llvm_config);
     cmd.arg(llvm_link_arg).arg("--libs");
 
-    // Don't link system libs if cross-compiling unless targeting Windows.
+    // Don't link system libs if cross-compiling unless targeting Windows from Windows host.
     // On Windows system DLLs aren't linked directly, instead import libraries are used.
     // These import libraries are independent of the host.
-    if !is_crossed || target.contains("windows") {
+    if !is_crossed || target.contains("windows") && host.contains("windows") {
         cmd.arg("--system-libs");
     }
 
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 279033ee072..542653efd30 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -535,7 +535,8 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    /// Fetch the THIR for a given body.
+    /// Fetch the THIR for a given body. The THIR body gets stolen by unsafety checking unless
+    /// `-Zno-steal-thir` is on.
     query thir_body(key: LocalDefId) -> Result<(&'tcx Steal<thir::Thir<'tcx>>, thir::ExprId), ErrorGuaranteed> {
         // Perf tests revealed that hashing THIR is inefficient (see #85729).
         no_hash
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 9d0681b19b9..d5061b71699 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -201,9 +201,14 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
     /// Handle closures/coroutines/inline-consts, which is unsafecked with their parent body.
     fn visit_inner_body(&mut self, def: LocalDefId) {
         if let Ok((inner_thir, expr)) = self.tcx.thir_body(def) {
-            // Runs all other queries that depend on THIR.
+            // Run all other queries that depend on THIR.
             self.tcx.ensure_done().mir_built(def);
-            let inner_thir = &inner_thir.steal();
+            let inner_thir = if self.tcx.sess.opts.unstable_opts.no_steal_thir {
+                &inner_thir.borrow()
+            } else {
+                // We don't have other use for the THIR. Steal it to reduce memory usage.
+                &inner_thir.steal()
+            };
             let hir_context = self.tcx.local_def_id_to_hir_id(def);
             let safety_context = mem::replace(&mut self.safety_context, SafetyContext::Safe);
             let mut inner_visitor = UnsafetyVisitor {
@@ -1157,7 +1162,12 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
     let Ok((thir, expr)) = tcx.thir_body(def) else { return };
     // Runs all other queries that depend on THIR.
     tcx.ensure_done().mir_built(def);
-    let thir = &thir.steal();
+    let thir = if tcx.sess.opts.unstable_opts.no_steal_thir {
+        &thir.borrow()
+    } else {
+        // We don't have other use for the THIR. Steal it to reduce memory usage.
+        &thir.steal()
+    };
 
     let hir_id = tcx.local_def_id_to_hir_id(def);
     let safety_context = tcx.hir_fn_sig_by_hir_id(hir_id).map_or(SafetyContext::Safe, |fn_sig| {
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 0777d442b59..5b7d45bb152 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -2312,7 +2312,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
     }
 
     fn check_macro_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
-        let name = attr.name().unwrap();
+        let Some(name) = attr.name() else {
+            return;
+        };
         match target {
             Target::ExternCrate | Target::Mod => {}
             _ => {
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 0579e91c0d6..e0b2adb3fc9 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -193,6 +193,16 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> {
                 continue;
             }
 
+            let module = self
+                .r
+                .get_nearest_non_block_module(self.r.local_def_id(extern_crate.id).to_def_id());
+            if module.no_implicit_prelude {
+                // If the module has `no_implicit_prelude`, then we don't suggest
+                // replacing the extern crate with a use, as it would not be
+                // inserted into the prelude. User writes `extern` style deliberately.
+                continue;
+            }
+
             let vis_span = extern_crate
                 .vis_span
                 .find_ancestor_inside(extern_crate.span)
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 744e99c86e1..473e9e22549 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -874,7 +874,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
                             kind: LifetimeBinderKind::PolyTrait,
                             span,
                         },
-                        |this| this.visit_path(path, ty.id),
+                        |this| this.visit_path(path),
                     );
                 } else {
                     visit::walk_ty(self, ty)
@@ -1265,7 +1265,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
                             AnonConstKind::ConstArg(IsRepeatExpr::No),
                             |this| {
                                 this.smart_resolve_path(ty.id, &None, path, PathSource::Expr(None));
-                                this.visit_path(path, ty.id);
+                                this.visit_path(path);
                             },
                         );
 
@@ -3640,7 +3640,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         if let Some(qself) = &delegation.qself {
             self.visit_ty(&qself.ty);
         }
-        self.visit_path(&delegation.path, delegation.id);
+        self.visit_path(&delegation.path);
         let Some(body) = &delegation.body else { return };
         self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
             let span = delegation.path.segments.last().unwrap().ident.span;
@@ -4867,7 +4867,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 if let Some(qself) = &se.qself {
                     self.visit_ty(&qself.ty);
                 }
-                self.visit_path(&se.path, expr.id);
+                self.visit_path(&se.path);
                 walk_list!(self, resolve_expr_field, &se.fields, expr);
                 match &se.rest {
                     StructRest::Base(expr) => self.visit_expr(expr),
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 5b4068740a1..12fa05118ca 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -2366,6 +2366,8 @@ options! {
         "run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"),
     no_profiler_runtime: bool = (false, parse_no_value, [TRACKED],
         "prevent automatic injection of the profiler_builtins crate"),
+    no_steal_thir: bool = (false, parse_bool, [UNTRACKED],
+        "don't steal the THIR when we're done with it; useful for rustc drivers (default: no)"),
     no_trait_vptr: bool = (false, parse_no_value, [TRACKED],
         "disable generation of trait vptr in vtable for upcasting"),
     no_unique_section_names: bool = (false, parse_bool, [TRACKED],
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 970faf2997c..4e842a8f93a 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -937,8 +937,10 @@ symbols! {
         external_doc,
         f,
         f128,
+        f128_epsilon,
         f128_nan,
         f16,
+        f16_epsilon,
         f16_nan,
         f16c_target_feature,
         f32,