Rollup merge of #141921 - ehuss:arm-min-max, r=tgross35

Disable f64 minimum/maximum tests for arm 32

This disables the f64 minimum/maximum tests for the arm-unknown-linux-gnueabihf job. The next release will be supporting cross-compiled doctests, and these tests fail on that platform.

It looks like this was just fixed via https://github.com/llvm/llvm-project/pull/142170, but I assume that will not trickle down to our copy of llvm in the next couple of weeks. Assuming that does get fixed when llvm is updated, then these can be removed.

cc https://github.com/rust-lang/rust/issues/141087
diff --git a/.mailmap b/.mailmap
index c3ce111..3b57f88 100644
--- a/.mailmap
+++ b/.mailmap
@@ -653,7 +653,7 @@
 Trevor Gross <tmgross@umich.edu> <t.gross35@gmail.com>
 Trevor Gross <tmgross@umich.edu> <tgross@intrepidcs.com>
 Trevor Spiteri <tspiteri@ieee.org> <trevor.spiteri@um.edu.mt>
-Tshepang Mbambo <tshepang@gmail.com>
+Tshepang Mbambo <hopsi@tuta.io> <tshepang@gmail.com>
 Ty Overby <ty@pre-alpha.com>
 Tyler Mandry <tmandry@gmail.com> <tmandry@google.com>
 Tyler Ruckinger <t.ruckinger@gmail.com>
diff --git a/Cargo.lock b/Cargo.lock
index e486f61..43f5f40 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -179,24 +179,11 @@
 
 [[package]]
 name = "askama"
-version = "0.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d4744ed2eef2645831b441d8f5459689ade2ab27c854488fbab1fbe94fce1a7"
-dependencies = [
- "askama_derive 0.13.1",
- "itoa",
- "percent-encoding",
- "serde",
- "serde_json",
-]
-
-[[package]]
-name = "askama"
 version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4"
 dependencies = [
- "askama_derive 0.14.0",
+ "askama_derive",
  "itoa",
  "percent-encoding",
  "serde",
@@ -205,28 +192,11 @@
 
 [[package]]
 name = "askama_derive"
-version = "0.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d661e0f57be36a5c14c48f78d09011e67e0cb618f269cca9f2fd8d15b68c46ac"
-dependencies = [
- "askama_parser 0.13.0",
- "basic-toml",
- "memchr",
- "proc-macro2",
- "quote",
- "rustc-hash 2.1.1",
- "serde",
- "serde_derive",
- "syn 2.0.101",
-]
-
-[[package]]
-name = "askama_derive"
 version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f"
 dependencies = [
- "askama_parser 0.14.0",
+ "askama_parser",
  "basic-toml",
  "memchr",
  "proc-macro2",
@@ -239,18 +209,6 @@
 
 [[package]]
 name = "askama_parser"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf315ce6524c857bb129ff794935cf6d42c82a6cff60526fe2a63593de4d0d4f"
-dependencies = [
- "memchr",
- "serde",
- "serde_derive",
- "winnow 0.7.10",
-]
-
-[[package]]
-name = "askama_parser"
 version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358"
@@ -582,7 +540,7 @@
 version = "0.1.89"
 dependencies = [
  "anstream",
- "askama 0.13.1",
+ "askama",
  "cargo_metadata 0.18.1",
  "clippy_config",
  "clippy_lints",
@@ -1432,7 +1390,7 @@
 version = "0.1.0"
 dependencies = [
  "anyhow",
- "askama 0.14.0",
+ "askama",
  "cargo_metadata 0.18.1",
  "serde",
  "serde_json",
@@ -4676,7 +4634,7 @@
 version = "0.0.0"
 dependencies = [
  "arrayvec",
- "askama 0.14.0",
+ "askama",
  "base64",
  "expect-test",
  "indexmap",
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index f1b183e..08726ee 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -12,7 +12,6 @@
 
 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 e1c2dd0..908d9fd 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -210,7 +210,7 @@ fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) -> Self::Result {
         walk_poly_trait_ref(self, t)
     }
     fn visit_variant_data(&mut self, s: &'ast VariantData) -> Self::Result {
-        walk_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 @@ fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) -> Self:
     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 @@ fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) -> Self::Result {
     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 @@ fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, span: &$($lt)? $($
             $(${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 @@ fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
                     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 @@ fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
                     }) => {
                         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 @@ fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
                     }
                     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 @@ fn walk_define_opaques<$($lt,)? V: $Visitor$(<$lt>)?>(
             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 @@ fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
                     }) => {
                         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 @@ fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
                     }
                     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 @@ fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
                 }
             }
         }
+
+        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 @@ pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V, trait_ref: &'a PolyTraitRef)
 
 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 93c627f..42d25b5 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -446,13 +446,7 @@ fn try_replace_id(&mut self, id: NodeId) {
 }
 
 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 58fa3c3..1a39a0c 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -3,7 +3,7 @@
 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 068d96c..558f13a 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -715,6 +715,7 @@ macro_rules! untracked {
     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 0c62c14..4978f29 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -74,8 +74,8 @@ fn with_lint_attrs<F>(&mut self, id: ast::NodeId, attrs: &'_ [ast::Attribute], f
 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 @@ fn visit_foreign_item(&mut self, it: &'ast ast::ForeignItem) {
 
     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 @@ fn visit_pat_field(&mut self, field: &'ast ast::PatField) {
         });
     }
 
-    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 @@ fn visit_fn(&mut self, fk: ast_visit::FnKind<'ast>, span: Span, id: ast::NodeId)
         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 @@ fn visit_variant(&mut self, v: &'ast ast::Variant) {
 
     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 @@ fn visit_local(&mut self, l: &'ast ast::Local) {
 
     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 @@ fn visit_assoc_item(&mut self, item: &'ast ast::AssocItem, ctxt: ast_visit::Asso
         });
     }
 
-    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 a662694..9a65493 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 279033e..542653e 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -535,7 +535,8 @@
         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 9d0681b..d5061b7 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -201,9 +201,14 @@ fn unsafe_op_in_unsafe_fn_allowed(&self) -> bool {
     /// 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 0777d44..5b7d45b 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -2312,7 +2312,9 @@ fn check_deprecated(&self, hir_id: HirId, attr: &Attribute, _span: Span, target:
     }
 
     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 0579e91..e0b2adb 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -193,6 +193,16 @@ fn report_unused_extern_crate_items(
                 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 744e99c..473e9e2 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -874,7 +874,7 @@ fn visit_ty(&mut self, ty: &'ast Ty) {
                             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 @@ fn visit_generic_arg(&mut self, arg: &'ast GenericArg) {
                             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 @@ fn resolve_delegation(&mut self, delegation: &'ast Delegation) {
         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 @@ fn resolve_expr(&mut self, expr: &'ast Expr, parent: Option<&'ast Expr>) {
                 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 5b40687..12fa051 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -2366,6 +2366,8 @@ pub(crate) fn parse_align(slot: &mut Option<Align>, v: Option<&str>) -> bool {
         "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 970faf2..4e842a8 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -937,8 +937,10 @@
         external_doc,
         f,
         f128,
+        f128_epsilon,
         f128_nan,
         f16,
+        f16_epsilon,
         f16_nan,
         f16c_target_feature,
         f32,
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 700fb0f..9991b76 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -200,7 +200,7 @@ pub trait Unsize<T: ?Sized> {
 ///
 /// Constants are only allowed as patterns if (a) their type implements
 /// `PartialEq`, and (b) interpreting the value of the constant as a pattern
-/// is equialent to calling `PartialEq`. This ensures that constants used as
+/// is equivalent to calling `PartialEq`. This ensures that constants used as
 /// patterns cannot expose implementation details in an unexpected way or
 /// cause semver hazards.
 ///
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 6b9b2ba..58de62a 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -171,6 +171,7 @@ impl f128 {
     /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
     /// [`MANTISSA_DIGITS`]: f128::MANTISSA_DIGITS
     #[unstable(feature = "f128", issue = "116909")]
+    #[rustc_diagnostic_item = "f128_epsilon"]
     pub const EPSILON: f128 = 1.92592994438723585305597794258492732e-34_f128;
 
     /// Smallest finite `f128` value.
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index eb7af99..45f402d 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -168,6 +168,7 @@ impl f16 {
     /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
     /// [`MANTISSA_DIGITS`]: f16::MANTISSA_DIGITS
     #[unstable(feature = "f16", issue = "116909")]
+    #[rustc_diagnostic_item = "f16_epsilon"]
     pub const EPSILON: f16 = 9.7656e-4_f16;
 
     /// Smallest finite `f16` value.
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index 08a2881..1ef3e07 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -54,13 +54,15 @@
 		src/etc/test-float-parse \
 		$(BOOTSTRAP_ARGS)
 	# Run standard library tests in Miri.
-	$(Q)$(BOOTSTRAP) miri --stage 2 \
+	$(Q)MIRIFLAGS="-Zmiri-strict-provenance" \
+		$(BOOTSTRAP) miri --stage 2 \
 		library/coretests \
 		library/alloctests \
 		library/alloc \
 		$(BOOTSTRAP_ARGS) \
 		--no-doc
-	# Some doctests use file system operations to demonstrate dealing with `Result`.
+	# Some doctests use file system operations to demonstrate dealing with `Result`,
+	# so we have to run them with isolation disabled.
 	$(Q)MIRIFLAGS="-Zmiri-disable-isolation" \
 		$(BOOTSTRAP) miri --stage 2 \
 		library/coretests \
@@ -70,22 +72,19 @@
 		--doc
 	# In `std` we cannot test everything, so we skip some modules.
 	$(Q)MIRIFLAGS="-Zmiri-disable-isolation" \
-		$(BOOTSTRAP) miri --stage 2 library/std \
+		$(BOOTSTRAP) miri --stage 2 \
+		library/std \
 		$(BOOTSTRAP_ARGS) \
-		--no-doc -- \
-		--skip fs:: --skip net:: --skip process:: --skip sys::fd:: --skip sys::pal::
-	$(Q)MIRIFLAGS="-Zmiri-disable-isolation" \
-		$(BOOTSTRAP) miri --stage 2 library/std \
-		$(BOOTSTRAP_ARGS) \
-		--doc -- \
+		-- \
 		--skip fs:: --skip net:: --skip process:: --skip sys::fd:: --skip sys::pal::
 	# Also test some very target-specific modules on other targets
 	# (making sure to cover an i686 target as well).
 	$(Q)MIRIFLAGS="-Zmiri-disable-isolation" BOOTSTRAP_SKIP_TARGET_SANITY=1 \
-		$(BOOTSTRAP) miri --stage 2 library/std \
-		$(BOOTSTRAP_ARGS) \
+		$(BOOTSTRAP) miri --stage 2 \
+		library/std \
 		--target aarch64-apple-darwin,i686-pc-windows-msvc \
-		--no-doc -- \
+		$(BOOTSTRAP_ARGS) \
+		-- \
 		time:: sync:: thread:: env::
 dist:
 	$(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS)
diff --git a/src/ci/citool/tests/jobs.rs b/src/ci/citool/tests/jobs.rs
index a61d0fe..fcdca89 100644
--- a/src/ci/citool/tests/jobs.rs
+++ b/src/ci/citool/tests/jobs.rs
@@ -51,6 +51,8 @@ fn get_matrix(event_name: &str, commit_msg: &str, branch_ref: &str) -> String {
         .env("GITHUB_EVENT_NAME", event_name)
         .env("COMMIT_MESSAGE", commit_msg)
         .env("GITHUB_REF", branch_ref)
+        .env("GITHUB_RUN_ID", "123")
+        .env("GITHUB_RUN_ATTEMPT", "1")
         .stdout(Stdio::piped())
         .output()
         .expect("Failed to execute command");
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 6585906..b44915f 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -127,7 +127,7 @@
     env:
       IMAGE: aarch64-gnu-llvm-19
       DOCKER_SCRIPT: stage_2_test_set1.sh
-    <<: *job-aarch64-linux-8c
+    <<: *job-aarch64-linux
   - name: aarch64-gnu-llvm-19-2
     env:
       IMAGE: aarch64-gnu-llvm-19
diff --git a/src/doc/rustc-dev-guide/.mailmap b/src/doc/rustc-dev-guide/.mailmap
index 1a1f6ff..907495e 100644
--- a/src/doc/rustc-dev-guide/.mailmap
+++ b/src/doc/rustc-dev-guide/.mailmap
@@ -3,3 +3,4 @@
 Jynn Nelson <github@jyn.dev> <jyn.nelson@redjack.com>
 Jynn Nelson <github@jyn.dev> <jnelson@cloudflare.com>
 Jynn Nelson <github@jyn.dev>
+Tshepang Mbambo <hopsi@tuta.io> <tshepang@gmail.com>
diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version
index 0d889a5..b1e9eec 100644
--- a/src/doc/rustc-dev-guide/rust-version
+++ b/src/doc/rustc-dev-guide/rust-version
@@ -1 +1 @@
-e42bbfe1f7c26f8760a99c4b1f27d33aba1040bb
+99e7c15e81385b38a8186b51edc4577d5d7b5bdd
diff --git a/src/doc/rustc-dev-guide/src/appendix/compiler-lecture.md b/src/doc/rustc-dev-guide/src/appendix/compiler-lecture.md
index dabd2f0..90c4097 100644
--- a/src/doc/rustc-dev-guide/src/appendix/compiler-lecture.md
+++ b/src/doc/rustc-dev-guide/src/appendix/compiler-lecture.md
@@ -46,3 +46,4 @@
 
 ## Code Generation
 - [January 2019: Cranelift](https://www.youtube.com/watch?v=9OIA7DTFQWU)
+- [December 2024: LLVM Developers' Meeting - Rust ❤️ LLVM](https://www.youtube.com/watch?v=Kqz-umsAnk8)
\ No newline at end of file
diff --git a/src/doc/rustc-dev-guide/src/borrow_check/two_phase_borrows.md b/src/doc/rustc-dev-guide/src/borrow_check/two_phase_borrows.md
index bcd4878..b77ae09 100644
--- a/src/doc/rustc-dev-guide/src/borrow_check/two_phase_borrows.md
+++ b/src/doc/rustc-dev-guide/src/borrow_check/two_phase_borrows.md
@@ -76,7 +76,7 @@
 [`AutoBorrow`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/adjustment/enum.AutoBorrow.html
 [converted]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_build/thir/cx/expr/trait.ToBorrowKind.html#method.to_borrow_kind
 [`BorrowKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.BorrowKind.html
-[`GatherBorrows`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/visit/trait.Visitor.html#method.visit_local
+[`GatherBorrows`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/borrow_set/struct.GatherBorrows.html
 [`BorrowData`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/borrow_set/struct.BorrowData.html
 
 ## Checking two-phase borrows
diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md
index 333554c..76c3960 100644
--- a/src/doc/rustc-dev-guide/src/building/suggested.md
+++ b/src/doc/rustc-dev-guide/src/building/suggested.md
@@ -91,7 +91,7 @@
   additional rebuilds in some cases.
 
 To avoid these problems:
-- Add `--build-dir=build-rust-analyzer` to all of the custom `x` commands in
+- Add `--build-dir=build/rust-analyzer` to all of the custom `x` commands in
   your editor's rust-analyzer configuration.
   (Feel free to choose a different directory name if desired.)
 - Modify the `rust-analyzer.rustfmt.overrideCommand` setting so that it points
@@ -100,10 +100,7 @@
   copy of `rust-analyzer-proc-macro-srv` in that other build directory.
 
 Using separate build directories for command-line builds and rust-analyzer
-requires extra disk space, and also means that running `./x clean` on the
-command-line will not clean out the separate build directory. To clean the
-separate build directory, run `./x clean --build-dir=build-rust-analyzer`
-instead.
+requires extra disk space.
 
 ### Visual Studio Code
 
@@ -137,7 +134,7 @@
 
 ### Neovim
 
-For Neovim users there are several options for configuring for rustc. The
+For Neovim users, there are a few options. The
 easiest way is by using [neoconf.nvim](https://github.com/folke/neoconf.nvim/),
 which allows for project-local configuration files with the native LSP. The
 steps for how to use it are below. Note that they require rust-analyzer to
diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md
index 2f8f4b0..01e59c9 100644
--- a/src/doc/rustc-dev-guide/src/diagnostics.md
+++ b/src/doc/rustc-dev-guide/src/diagnostics.md
@@ -866,19 +866,17 @@
 (and sub-structs) for the JSON serialization. Don't confuse this with
 [`errors::Diag`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html)!
 
-## `#[rustc_on_unimplemented(...)]`
+## `#[rustc_on_unimplemented]`
 
-The `#[rustc_on_unimplemented]` attribute allows trait definitions to add specialized
-notes to error messages when an implementation was expected but not found.
-You can refer to the trait's generic arguments by name and to the resolved type using `Self`.
-
-For example:
+This attribute allows trait definitions to modify error messages when an implementation was
+expected but not found. The string literals in the attribute are format strings and can be
+formatted with named parameters. See the Formatting
+section below for what parameters are permitted.
 
 ```rust,ignore
-#![feature(rustc_attrs)]
-
-#[rustc_on_unimplemented="an iterator over elements of type `{A}` \
-    cannot be built from a collection of type `{Self}`"]
+#[rustc_on_unimplemented(message = "an iterator over \
+    elements of type `{A}` cannot be built from a \
+    collection of type `{Self}`")]
 trait MyIterator<A> {
     fn next(&mut self) -> A;
 }
@@ -895,32 +893,26 @@
 When the user compiles this, they will see the following;
 
 ```txt
-error[E0277]: the trait bound `&[{integer}]: MyIterator<char>` is not satisfied
-  --> <anon>:14:5
+error[E0277]: an iterator over elements of type `char` cannot be built from a collection of type `&[{integer}]`
+  --> src/main.rs:13:19
    |
-14 |     iterate_chars(&[1, 2, 3][..]);
-   |     ^^^^^^^^^^^^^ an iterator over elements of type `char` cannot be built from a collection of type `&[{integer}]`
+13 |     iterate_chars(&[1, 2, 3][..]);
+   |     ------------- ^^^^^^^^^^^^^^ the trait `MyIterator<char>` is not implemented for `&[{integer}]`
+   |     |
+   |     required by a bound introduced by this call
    |
-   = help: the trait `MyIterator<char>` is not implemented for `&[{integer}]`
-   = note: required by `iterate_chars`
+note: required by a bound in `iterate_chars`
 ```
 
-`rustc_on_unimplemented` also supports advanced filtering for better targeting
-of messages, as well as modifying specific parts of the error message. You
-target the text of:
-
+You can modify the contents of:
  - the main error message (`message`)
  - the label (`label`)
- - an extra note (`note`)
+ - the note(s) (`note`)
 
 For example, the following attribute
 
 ```rust,ignore
-#[rustc_on_unimplemented(
-    message="message",
-    label="label",
-    note="note"
-)]
+#[rustc_on_unimplemented(message = "message", label = "label", note = "note")]
 trait MyIterator<A> {
     fn next(&mut self) -> A;
 }
@@ -930,45 +922,61 @@
 
 ```text
 error[E0277]: message
-  --> <anon>:14:5
+  --> <file>:10:19
    |
-14 |     iterate_chars(&[1, 2, 3][..]);
-   |     ^^^^^^^^^^^^^ label
+10 |     iterate_chars(&[1, 2, 3][..]);
+   |     ------------- ^^^^^^^^^^^^^^ label
+   |     |
+   |     required by a bound introduced by this call
    |
-   = note: note
    = help: the trait `MyIterator<char>` is not implemented for `&[{integer}]`
-   = note: required by `iterate_chars`
+   = note: note
+note: required by a bound in `iterate_chars`
 ```
 
-To allow more targeted error messages, it is possible to filter the
-application of these fields based on a variety of attributes when using
-`on`:
+The functionality discussed so far is also available with
+[`#[diagnostic::on_unimplemented]`](https://doc.rust-lang.org/nightly/reference/attributes/diagnostics.html#the-diagnosticon_unimplemented-attribute).
+If you can, you should use that instead.
 
+### Filtering
+
+To allow more targeted error messages, it is possible to filter the
+application of these fields with `on`.
+
+You can filter on the following boolean flags:
  - `crate_local`: whether the code causing the trait bound to not be
    fulfilled is part of the user's crate. This is used to avoid suggesting
    code changes that would require modifying a dependency.
- - Any of the generic arguments that can be substituted in the text can be
-   referred by name as well for filtering, like `Rhs="i32"`, except for
-   `Self`.
- - `_Self`: to filter only on a particular calculated trait resolution, like
-   `Self="std::iter::Iterator<char>"`. This is needed because `Self` is a
-   keyword which cannot appear in attributes.
- - `direct`: user-specified rather than derived obligation.
- - `from_desugaring`: usable both as boolean (whether the flag is present)
-   or matching against a particular desugaring. The desugaring is identified
-   with its variant name in the `DesugaringKind` enum.
+ - `direct`: whether this is an user-specified rather than derived obligation.
+ - `from_desugaring`: whether we are in some kind of desugaring, like `?`
+   or a `try` block for example. This flag can also be matched on, see below.
 
-For example, the `Iterator` trait can be annotated in the following way:
+You can match on the following names and values, using `name = "value"`:
+ - `cause`: Match against one variant of the `ObligationCauseCode`
+   enum. Only `"MainFunctionType"` is supported.
+ - `from_desugaring`: Match against a particular variant of the `DesugaringKind`
+   enum. The desugaring is identified by its variant name, for example
+   `"QuestionMark"` for `?` desugaring or `"TryBlock"` for `try` blocks.
+ - `Self` and any generic arguments of the trait, like `Self = "alloc::string::String"`
+   or `Rhs="i32"`.
+   
+The compiler can provide several values to match on, for example:
+  - the self_ty, pretty printed with and without type arguments resolved.
+  - `"{integral}"`, if self_ty is an integral of which the type is known.
+  - `"[]"`, `"[{ty}]"`, `"[{ty}; _]"`, `"[{ty}; $N]"` when applicable.
+  - references to said slices and arrays.
+  - `"fn"`, `"unsafe fn"` or `"#[target_feature] fn"` when self is a function.
+  - `"{integer}"` and `"{float}"` if the type is a number but we haven't inferred it yet.
+  - combinations of the above, like `"[{integral}; _]"`.
+
+For example, the `Iterator` trait can be filtered in the following way:
 
 ```rust,ignore
 #[rustc_on_unimplemented(
-    on(
-        _Self="&str",
-        note="call `.chars()` or `.as_bytes()` on `{Self}`"
-    ),
-    message="`{Self}` is not an iterator",
-    label="`{Self}` is not an iterator",
-    note="maybe try calling `.iter()` or a similar method"
+    on(Self = "&str", note = "call `.chars()` or `.as_bytes()` on `{Self}`"),
+    message = "`{Self}` is not an iterator",
+    label = "`{Self}` is not an iterator",
+    note = "maybe try calling `.iter()` or a similar method"
 )]
 pub trait Iterator {}
 ```
@@ -997,15 +1005,47 @@
   = note: required by `std::iter::IntoIterator::into_iter`
 ```
 
-If you need to filter on multiple attributes, you can use `all`, `any` or
-`not` in the following way:
+The `on` filter accepts `all`, `any` and `not` predicates similar to the `cfg` attribute:
 
 ```rust,ignore
-#[rustc_on_unimplemented(
-    on(
-        all(_Self="&str", T="std::string::String"),
-        note="you can coerce a `{T}` into a `{Self}` by writing `&*variable`"
-    )
-)]
-pub trait From<T>: Sized { /* ... */ }
+#[rustc_on_unimplemented(on(
+    all(Self = "&str", T = "alloc::string::String"),
+    note = "you can coerce a `{T}` into a `{Self}` by writing `&*variable`"
+))]
+pub trait From<T>: Sized {
+    /* ... */
+}
+```
+
+### Formatting 
+
+The string literals are format strings that accept parameters wrapped in braces
+but positional and listed parameters and format specifiers are not accepted.
+The following parameter names are valid:
+- `Self` and all generic parameters of the trait.
+- `This`: the name of the trait the attribute is on, without generics.
+- `Trait`: the name of the "sugared" trait. See `TraitRefPrintSugared`.
+- `ItemContext`: the kind of `hir::Node` we're in, things like `"an async block"`,
+   `"a function"`, `"an async function"`, etc.
+
+Something like:
+
+```rust,ignore
+#![feature(rustc_attrs)]
+
+#[rustc_on_unimplemented(message = "Self = `{Self}`, \
+    T = `{T}`, this = `{This}`, trait = `{Trait}`, \
+    context = `{ItemContext}`")]
+pub trait From<T>: Sized {
+    fn from(x: T) -> Self;
+}
+
+fn main() {
+    let x: i8 = From::from(42_i32);
+}
+```
+
+Will format the message into 
+```text
+"Self = `i8`, T = `i32`, this = `From`, trait = `From<i32>`, context = `a function`"
 ```
diff --git a/src/doc/rustc-dev-guide/src/early_late_parameters.md b/src/doc/rustc-dev-guide/src/early_late_parameters.md
index 3b2a5e8..3f94b09 100644
--- a/src/doc/rustc-dev-guide/src/early_late_parameters.md
+++ b/src/doc/rustc-dev-guide/src/early_late_parameters.md
@@ -174,7 +174,8 @@
 - When naming a function (early)
 - When calling a function (late)
 
-There currently is no syntax for explicitly specifying generic arguments for late bound parameters as part of the call step, only specifying generic arguments when naming a function. The syntax `foo::<'static>();`, despite being part of a function call, behaves as `(foo::<'static>)();` and instantiates the early bound generic parameters on the function item type.
+There is currently no syntax for explicitly specifying generic arguments for late bound parameters during the call step; generic arguments can only be specified for early bound parameters when naming a function.
+The syntax `foo::<'static>();`, despite being part of a function call, behaves as `(foo::<'static>)();` and instantiates the early bound generic parameters on the function item type.
 
 See the following example:
 ```rust
diff --git a/src/doc/rustc-dev-guide/src/fuzzing.md b/src/doc/rustc-dev-guide/src/fuzzing.md
index b588ca1..3000537 100644
--- a/src/doc/rustc-dev-guide/src/fuzzing.md
+++ b/src/doc/rustc-dev-guide/src/fuzzing.md
@@ -73,21 +73,32 @@
 
 - The rustc/rust-analyzer/clippy test suites (or even source code) --- though avoid
   tests that are already known to cause failures, which often begin with comments
-  like `// failure-status: 101` or `// known-bug: #NNN`.
-- The already-fixed ICEs in [Glacier][glacier] --- though avoid the unfixed
-  ones in `ices/`!
+  like `//@ failure-status: 101` or `//@ known-bug: #NNN`.
+- The already-fixed ICEs in the archived [Glacier][glacier] repository --- though
+  avoid the unfixed ones in `ices/`!
+
+[glacier]: https://github.com/rust-lang/glacier
 
 ## Extra credit
 
 Here are a few things you can do to help the Rust project after filing an ICE.
 
-- [Bisect][bisect] the bug to figure out when it was introduced 
+- [Bisect][bisect] the bug to figure out when it was introduced.
+  If you find the regressing PR / commit, you can mark the issue with the label
+  `S-has-bisection`. If not, consider applying `E-needs-bisection` instead.
 - Fix "distractions": problems with the test case that don't contribute to
   triggering the ICE, such as syntax errors or borrow-checking errors
-- Minimize the test case (see below)
-- Add the minimal test case to [Glacier][glacier]
+- Minimize the test case (see below). If successful, you can label the
+  issue with `S-has-mcve`. Otherwise, you can apply `E-needs-mcve`.
+- Add the minimal test case to the rust-lang/rust repo as a [crashes test].
+  While you're at it, consider including other "untracked" crashes in your PR.
+  Please don't forget to mark your issue with `S-bug-has-test` afterwards.
+
+See also [applying and removing labels][labeling].
 
 [bisect]: https://rust-lang.github.io/cargo-bisect-rustc/
+[crashes test]: tests/compiletest.html#crashes-tests
+[labeling]: https://forge.rust-lang.org/release/issue-triaging.html#applying-and-removing-labels
 
 ## Minimization
 
@@ -143,7 +154,6 @@
 - [tree-splicer][tree-splicer] generates new source files by combining existing
   ones while maintaining correct syntax
 
-[glacier]: https://github.com/rust-lang/glacier
 [fuzz-rustc]: https://github.com/dwrensha/fuzz-rustc
 [icemaker]: https://github.com/matthiaskrgr/icemaker/
 [tree-splicer]: https://github.com/langston-barrett/tree-splicer/
diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md
index 0e5b32a..435202c 100644
--- a/src/doc/rustc-dev-guide/src/getting-started.md
+++ b/src/doc/rustc-dev-guide/src/getting-started.md
@@ -89,7 +89,7 @@
 Not all important or beginner work has issue labels.
 See below for how to find work that isn't labelled.
 
-[help-wanted-search]: https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Arust-lang+no%3Aassignee+label%3AE-easy%2C%22good+first+issue%22%2Cgood-first-issue%2CE-medium%2CEasy%2CE-help-wanted%2CE-mentor+-label%3AS-blocked+-linked:pr+
+[help-wanted-search]: https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Arust-lang+no%3Aassignee+label%3AE-easy%2C%22good+first+issue%22%2Cgood-first-issue%2CE-medium%2CEasy%2CE-help-wanted%2CE-mentor+-label%3AS-blocked+-linked%3Apr+
 [Triage]: ./contributing.md#issue-triage
 
 ### Recurring work
@@ -98,8 +98,6 @@
 issues" to co-ordinate the work between contributors. Here are some example tracking issues where
 it's easy to pick up work without a large time commitment:
 
-- [Rustdoc Askama Migration](https://github.com/rust-lang/rust/issues/108868)
-- [Diagnostic Translation](https://github.com/rust-lang/rust/issues/100717)
 - [Move UI tests to subdirectories](https://github.com/rust-lang/rust/issues/73494)
 
 If you find more recurring work, please feel free to add it here!
diff --git a/src/doc/rustc-dev-guide/src/normalization.md b/src/doc/rustc-dev-guide/src/normalization.md
index ef530cc..9705b1a 100644
--- a/src/doc/rustc-dev-guide/src/normalization.md
+++ b/src/doc/rustc-dev-guide/src/normalization.md
@@ -166,7 +166,10 @@
 
 When interfacing with the type system it will often be the case that it's necessary to request a type be normalized. There are a number of different entry points to the underlying normalization logic and each entry point should only be used in specific parts of the compiler.
 
-An additional complication is that the compiler is currently undergoing a transition from the old trait solver to the new trait solver. As part of this transition our approach to normalization in the compiler has changed somewhat significantly, resulting in some normalization entry points being "old solver only" slated for removal in the long-term once the new solver has stabilized.
+<!-- date-check: May 2025 -->
+An additional complication is that the compiler is currently undergoing a transition from the old trait solver to the new trait solver.
+As part of this transition our approach to normalization in the compiler has changed somewhat significantly, resulting in some normalization entry points being "old solver only" slated for removal in the long-term once the new solver has stabilized.
+The transition can be tracked via the [WG-trait-system-refactor](https://github.com/rust-lang/rust/labels/WG-trait-system-refactor) label in Github.
 
 Here is a rough overview of the different entry points to normalization in the compiler:
 - `infcx.at.structurally_normalize`
@@ -306,4 +309,4 @@
 
 [^5]: Const aliases certainly wouldn't be *less* sound than type aliases if we stopped doing this
 
-[const_evaluatable]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ClauseKind.html#variant.ConstEvaluatable
\ No newline at end of file
+[const_evaluatable]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ClauseKind.html#variant.ConstEvaluatable
diff --git a/src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md b/src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md
index bdf4e4c..42600ad 100644
--- a/src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md
+++ b/src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md
@@ -13,13 +13,16 @@
 To help explain how it works, let's consider an example.
 
 ```rust
+#![feature(type_alias_impl_trait)]
 mod m {
     pub type Seq<T> = impl IntoIterator<Item = T>;
 
+    #[define_opaque(Seq)]
     pub fn produce_singleton<T>(t: T) -> Seq<T> {
         vec![t]
     }
 
+    #[define_opaque(Seq)]
     pub fn produce_doubleton<T>(t: T, u: T) -> Seq<T> {
         vec![t, u]
     }
diff --git a/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md
index 5f35881..85cece2 100644
--- a/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md
+++ b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md
@@ -356,7 +356,7 @@
 
 Failing because a down-stream impl could theoretically provide an
 implementation for `RPITIT` without providing an implementation of
-`foo`:
+`bar`:
 
 ```text
 error[E0308]: mismatched types
diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals.md b/src/doc/rustc-dev-guide/src/rustdoc-internals.md
index 80421b8..bc91c62 100644
--- a/src/doc/rustc-dev-guide/src/rustdoc-internals.md
+++ b/src/doc/rustc-dev-guide/src/rustdoc-internals.md
@@ -281,10 +281,10 @@
 description of all the commands available to `rustdoc` tests (e.g. [`@has`] and
 [`@matches`]) is in [`htmldocck.py`].
 
-To use multiple crates in a `rustdoc` test, add `// aux-build:filename.rs`
+To use multiple crates in a `rustdoc` test, add `//@ aux-build:filename.rs`
 to the top of the test file. `filename.rs` should be placed in an `auxiliary`
 directory relative to the test file with the comment. If you need to build
-docs for the auxiliary file, use `// build-aux-docs`.
+docs for the auxiliary file, use `//@ build-aux-docs`.
 
 In addition, there are separate tests for the search index and `rustdoc`'s
 ability to query it. The files in `tests/rustdoc-js` each contain a
diff --git a/src/doc/rustc-dev-guide/src/rustdoc.md b/src/doc/rustc-dev-guide/src/rustdoc.md
index e36d6a3..de70ba6 100644
--- a/src/doc/rustc-dev-guide/src/rustdoc.md
+++ b/src/doc/rustc-dev-guide/src/rustdoc.md
@@ -93,13 +93,13 @@
   interactivity.  For information on how to write this form of test,
   see [`tests/rustdoc-gui/README.md`][rustdoc-gui-readme]
   as well as [the description of the `.goml` format][goml-script]
-* Additionally, JavaScript type annotations are written using [TypeScript-flavored JSDoc]
-  comments and an external d.ts file. The code itself is plain, valid JavaScript; we only
-  use tsc as a linter.
-* The tests on the structure of rustdoc HTML output are located in `tests/rustdoc`,
+* Tests on the structure of rustdoc HTML output are located in `tests/rustdoc`,
   where they're handled by the test runner of bootstrap and
   the supplementary script `src/etc/htmldocck.py`.
   [These tests have several extra directives available to them](./rustdoc-internals/rustdoc-test-suite.md).
+* Additionally, JavaScript type annotations are written using [TypeScript-flavored JSDoc]
+  comments and an external d.ts file. The code itself is plain, valid JavaScript; we only
+  use tsc as a linter.
 
 [TypeScript-flavored JSDoc]: https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html
 [rustdoc-gui-readme]: https://github.com/rust-lang/rust/blob/master/tests/rustdoc-gui/README.md
@@ -116,6 +116,28 @@
 Service Workers, don't work reliably. We can still use such features but we
 should make sure pages are still usable without them.
 
+Rustdoc [does not type-check function bodies][platform-specific docs].
+This works by [overriding the built-in queries for typeck][override queries],
+by [silencing name resolution errors], and by [not resolving opaque types].
+This comes with several caveats: in particular, rustdoc *cannot* run any parts of the compiler that
+require type-checking bodies; for example it cannot generate `.rlib` files or run most lints.
+We want to move away from this model eventually, but we need some alternative for
+[the people using it][async-std]; see [various][zulip stop accepting broken code]
+[previous][rustdoc meeting 2024-07-08] [zulip][compiler meeting 2023-01-26] [discussion][notriddle rfc].
+For examples of code that breaks if this hack is removed, see
+[`tests/rustdoc-ui/error-in-impl-trait`].
+
+[platform-specific docs]: https://doc.rust-lang.org/rustdoc/advanced-features.html#interactions-between-platform-specific-docs
+[override queries]: https://github.com/rust-lang/rust/blob/52bf0cf795dfecc8b929ebb1c1e2545c3f41d4c9/src/librustdoc/core.rs#L299-L323
+[silencing name resolution errors]: https://github.com/rust-lang/rust/blob/52bf0cf795dfecc8b929ebb1c1e2545c3f41d4c9/compiler/rustc_resolve/src/late.rs#L4517
+[not resolving opaque types]: https://github.com/rust-lang/rust/blob/52bf0cf795dfecc8b929ebb1c1e2545c3f41d4c9/compiler/rustc_hir_analysis/src/check/check.rs#L188-L194
+[async-std]: https://github.com/rust-lang/rust/issues/75100
+[rustdoc meeting 2024-07-08]: https://rust-lang.zulipchat.com/#narrow/channel/393423-t-rustdoc.2Fmeetings/topic/meeting.202024-07-08/near/449969836
+[compiler meeting 2023-01-26]: https://rust-lang.zulipchat.com/#narrow/channel/238009-t-compiler.2Fmeetings/topic/.5Bweekly.5D.202023-01-26/near/323755789
+[zulip stop accepting broken code]: https://rust-lang.zulipchat.com/#narrow/stream/266220-rustdoc/topic/stop.20accepting.20broken.20code
+[notriddle rfc]: https://rust-lang.zulipchat.com/#narrow/channel/266220-t-rustdoc/topic/Pre-RFC.3A.20stop.20accepting.20broken.20code
+[`tests/rustdoc-ui/error-in-impl-trait`]: https://github.com/rust-lang/rust/tree/163cb4ea3f0ae3bc7921cc259a08a7bf92e73ee6/tests/rustdoc-ui/error-in-impl-trait
+
 ## Multiple runs, same output directory
 
 Rustdoc can be run multiple times for varying inputs, with its output set to the
diff --git a/src/doc/rustc-dev-guide/src/solve/coinduction.md b/src/doc/rustc-dev-guide/src/solve/coinduction.md
index c682e00..9753f75 100644
--- a/src/doc/rustc-dev-guide/src/solve/coinduction.md
+++ b/src/doc/rustc-dev-guide/src/solve/coinduction.md
@@ -237,14 +237,14 @@
 Any cycles should result in infinite types, which aren't supported anyways and would only
 result in overflow when deeply normalizing for codegen.
 
-experimentation and examples: https://hackmd.io/-8p0AHnzSq2VAE6HE_wX-w?view
+experimentation and examples: <https://hackmd.io/-8p0AHnzSq2VAE6HE_wX-w?view>
 
 Another attempt at a summary.
 - in projection eq, we must make progress with constraining the rhs
 - a cycle is only ok if while equating we have a rigid ty on the lhs after norm at least once
 - cycles outside of the recursive `eq` call of `normalizes_to` are always fine
 
-[^1]: related: https://coq.inria.fr/refman/language/core/coinductive.html#top-level-definitions-of-corecursive-functions
+[^1]: related: <https://coq.inria.fr/refman/language/core/coinductive.html#top-level-definitions-of-corecursive-functions>
 
 [perfect derive]: https://smallcultfollowing.com/babysteps/blog/2022/04/12/implied-bounds-and-perfect-derive
 [ex1]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0a9c3830b93a2380e6978d6328df8f72
diff --git a/src/doc/rustc-dev-guide/src/solve/opaque-types.md b/src/doc/rustc-dev-guide/src/solve/opaque-types.md
index 509c34a..6898ef3 100644
--- a/src/doc/rustc-dev-guide/src/solve/opaque-types.md
+++ b/src/doc/rustc-dev-guide/src/solve/opaque-types.md
@@ -1,8 +1,10 @@
 # Opaque types in the new solver
 
-The way opaque types are handled in the new solver differs from the old implementation.
+The way [opaque types] are handled in the new solver differs from the old implementation.
 This should be a self-contained explanation of the behavior in the new solver.
 
+[opaque types]: ../opaque-types-type-alias-impl-trait.md
+
 ## opaques are alias types
 
 Opaque types are treated the same as other aliases, most notabily associated types,
diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md
index 8f259f2..ef3f4c7 100644
--- a/src/doc/rustc-dev-guide/src/tests/ci.md
+++ b/src/doc/rustc-dev-guide/src/tests/ci.md
@@ -100,8 +100,8 @@
 only a subset run the full suite of tests (see Rust's [platform tiers]).
 
 Auto jobs are defined in the `auto` section of [`jobs.yml`]. They are executed
-on the `auto` branch under the `rust-lang-ci/rust` repository[^rust-lang-ci] and
-their results can be seen [here](https://github.com/rust-lang-ci/rust/actions),
+on the `auto` branch under the `rust-lang/rust` repository and
+their results can be seen [here](https://github.com/rust-lang/rust/actions),
 although usually you will be notified of the result by a comment made by bors on
 the corresponding PR.
 
@@ -110,9 +110,6 @@
 
 [platform tiers]: https://forge.rust-lang.org/release/platform-support.html#rust-platform-support
 
-[^rust-lang-ci]: The `auto` and `try` jobs run under the `rust-lang-ci` fork for
-    historical reasons. This may change in the future.
-
 ### Try builds
 
 Sometimes we want to run a subset of the test suite on CI for a given PR, or
@@ -179,8 +176,8 @@
 > that are exercised this way.
 
 Try jobs are defined in the `try` section of [`jobs.yml`]. They are executed on
-the `try` branch under the `rust-lang-ci/rust` repository[^rust-lang-ci] and
-their results can be seen [here](https://github.com/rust-lang-ci/rust/actions),
+the `try` branch under the `rust-lang/rust` repository and
+their results can be seen [here](https://github.com/rust-lang/rust/actions),
 although usually you will be notified of the result by a comment made by bors on
 the corresponding PR.
 
@@ -355,7 +352,7 @@
 - Files copied into the Docker image in the Dockerfile
 - The architecture of the GitHub runner (x86 or ARM)
 
-[ghcr.io]: https://github.com/rust-lang-ci/rust/pkgs/container/rust-ci
+[ghcr.io]: https://github.com/rust-lang/rust/pkgs/container/rust-ci
 [Docker registry caching]: https://docs.docker.com/build/cache/backends/registry/
 
 ### LLVM caching with sccache
@@ -446,7 +443,7 @@
 this:
 
 1. Go to
-   <https://github.com/rust-lang-ci/rust/actions?query=branch%3Aauto+is%3Asuccess>
+   <https://github.com/rust-lang/rust/actions?query=branch%3Aauto+is%3Asuccess>
    to find the most recently successful build, and click on it.
 2. Choose the job you are interested in on the left-hand side.
 3. Click on the gear icon and choose "View raw logs"
@@ -458,7 +455,6 @@
 [`jobs.yml`]: https://github.com/rust-lang/rust/blob/master/src/ci/github-actions/jobs.yml
 [`.github/workflows/ci.yml`]: https://github.com/rust-lang/rust/blob/master/.github/workflows/ci.yml
 [`src/ci/citool`]: https://github.com/rust-lang/rust/blob/master/src/ci/citool
-[rust-lang-ci]: https://github.com/rust-lang-ci/rust/actions
 [bors]: https://github.com/bors
 [homu]: https://github.com/rust-lang/homu
 [merge queue]: https://bors.rust-lang.org/queue/rust
diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md
index 0ba078f..e1b2374 100644
--- a/src/doc/rustc-dev-guide/src/tests/compiletest.md
+++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md
@@ -546,10 +546,10 @@
 
 [`tests/crashes`] serve as a collection of tests that are expected to cause the
 compiler to ICE, panic or crash in some other way, so that accidental fixes are
-tracked. This was formally done at <https://github.com/rust-lang/glacier> but
+tracked. Formerly, this was done at <https://github.com/rust-lang/glacier> but
 doing it inside the rust-lang/rust testsuite is more convenient.
 
-It is imperative that a test in the suite causes rustc to ICE, panic or crash
+It is imperative that a test in the suite causes rustc to ICE, panic, or
 crash in some other way. A test will "pass" if rustc exits with an exit status
 other than 1 or 0.
 
@@ -560,9 +560,12 @@
 $ COMPILETEST_VERBOSE_CRASHES=1 ./x test tests/crashes/999999.rs --stage 1
 ```
 
-When adding crashes from <https://github.com/rust-lang/rust/issues>, the issue
-number should be noted in the file name (`12345.rs` should suffice) and also
-inside the file include a `//@ known-bug: #4321` directive.
+Anyone can add ["untracked" crashes] from the issue tracker. It's strongly
+recommended to include test cases from several issues in a single PR.
+When you do so, each issue number should be noted in the file name (`12345.rs`
+should suffice) and also inside the file by means of a `//@ known-bug: #12345`
+directive. Please [label][labeling] the relevant issues with `S-bug-has-test`
+afterwards.
 
 If you happen to fix one of the crashes, please move it to a fitting
 subdirectory in `tests/ui` and give it a meaningful name. Please add a doc
@@ -585,6 +588,8 @@
 known-bug` directive inside the test file.
 
 [`tests/crashes`]: https://github.com/rust-lang/rust/tree/master/tests/crashes
+["untracked" crashes]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+state%3Aopen+label%3AI-ICE%2CI-crash+label%3AT-compiler+label%3AS-has-mcve+-label%3AS-bug-has-test
+[labeling]: https://forge.rust-lang.org/release/issue-triaging.html#applying-and-removing-labels
 
 ## Building auxiliary crates
 
@@ -614,7 +619,7 @@
 `aux-crate` is very similar to `aux-build`. However, it uses the `--extern` flag
 to link to the extern crate to make the crate be available as an extern prelude.
 That allows you to specify the additional syntax of the `--extern` flag, such as
-renaming a dependency. For example, `// aux-crate:foo=bar.rs` will compile
+renaming a dependency. For example, `//@ aux-crate:foo=bar.rs` will compile
 `auxiliary/bar.rs` and make it available under then name `foo` within the test.
 This is similar to how Cargo does dependency renaming.
 
diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md
index dae659e..8a86241 100644
--- a/src/doc/rustc-dev-guide/src/tests/directives.md
+++ b/src/doc/rustc-dev-guide/src/tests/directives.md
@@ -59,7 +59,7 @@
 | `aux-crate`           | Like `aux-build` but makes available as extern prelude                                                | All except `run-make` | `<extern_prelude_name>=<path/to/aux/file.rs>` |
 | `aux-codegen-backend` | Similar to `aux-build` but pass the compiled dylib to `-Zcodegen-backend` when building the main file | `ui-fulldeps`         | Path to codegen backend file                  |
 | `proc-macro`          | Similar to `aux-build`, but for aux forces host and don't use `-Cprefer-dynamic`[^pm].                | All except `run-make` | Path to auxiliary proc-macro `.rs` file       |
-| `build_aux_docs`      | Build docs for auxiliaries as well                                                                    | All except `run-make` | N/A                                           |
+| `build-aux-docs`      | Build docs for auxiliaries as well                                                                    | All except `run-make` | N/A                                           |
 
 [^pm]: please see the Auxiliary proc-macro section in the
     [compiletest](./compiletest.md) chapter for specifics.
diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md
index 721d20b..3402838 100644
--- a/src/doc/rustc-dev-guide/src/tests/ui.md
+++ b/src/doc/rustc-dev-guide/src/tests/ui.md
@@ -192,7 +192,7 @@
 to write out the entire message, just make sure to include the important part of
 the message to make it self-documenting.
 
-The error annotation needs to match with the line of the diagnostic. There are
+Most error annotations need to match with the line of the diagnostic. There are
 several ways to match the message with the line (see the examples below):
 
 * `~`: Associates the error level and message with the *current* line
@@ -205,9 +205,6 @@
 * `~v`: Associates the error level and message with the *next* error
   annotation line. Each symbol (`v`) that you add adds a line to this, so `~vvv`
   is three lines below the error annotation line.
-* `~?`: Used to match error levels and messages with errors not having line
-  information. These can be placed on any line in the test file, but are
-  conventionally placed at the end.
 
 Example:
 
@@ -222,6 +219,10 @@
 negligible (i.e. there is no semantic difference between `//~ ERROR` and
 `//~ERROR` although the former is more common in the codebase).
 
+`~? <diagnostic kind>` (example being `~? ERROR`)
+is used to match diagnostics without line information.
+These can be placed on any line in the test file, but are conventionally placed at the end.
+
 ### Error annotation examples
 
 Here are examples of error annotations on different lines of UI test source.
diff --git a/src/doc/rustc-dev-guide/src/ty_module/binders.md b/src/doc/rustc-dev-guide/src/ty_module/binders.md
index 71157ec..7fd9eee 100644
--- a/src/doc/rustc-dev-guide/src/ty_module/binders.md
+++ b/src/doc/rustc-dev-guide/src/ty_module/binders.md
@@ -1,6 +1,6 @@
 # `Binder` and Higher ranked regions
 
-Sometimes we define generic parameters not on an item but as part of a type or a where clauses. As an example the type `for<'a> fn(&'a u32)` or the where clause `for<'a> T: Trait<'a>` both introduce a generic lifetime named `'a`. Currently there is no stable syntax for `for<T>` or `for<const N: usize>` but on nightly `feature(non_lifetime_binders)` feature can be used to write where clauses (but not types) using `for<T>`/`for<const N: usize>`.
+Sometimes we define generic parameters not on an item but as part of a type or a where clause. As an example the type `for<'a> fn(&'a u32)` or the where clause `for<'a> T: Trait<'a>` both introduce a generic lifetime named `'a`. Currently there is no stable syntax for `for<T>` or `for<const N: usize>` but on nightly `feature(non_lifetime_binders)` can be used to write where clauses (but not types) using `for<T>`/`for<const N: usize>`.
 
 The `for` is referred to as a "binder" because it brings new names into scope. In rustc we use the `Binder` type to track where these parameters are introduced and what the parameters are (i.e. how many and whether the parameter is a type/const/region). A type such as `for<'a> fn(&'a u32)` would be
 represented in rustc as:
@@ -13,8 +13,9 @@
 
 Usages of these parameters is represented by the `RegionKind::Bound` (or `TyKind::Bound`/`ConstKind::Bound` variants). These bound regions/types/consts are composed of two main pieces of data:
 - A [DebruijnIndex](../appendix/background.md#what-is-a-de-bruijn-index) to specify which binder we are referring to.
-- A [`BoundVar`] which specifies which of the parameters the `Binder` introduces we are referring to.
-- We also sometimes store some extra information for diagnostics reasons via the [`BoundTyKind`]/[`BoundRegionKind`] but this is not important for type equality or more generally the semantics of `Ty`. (omitted from the above example)
+- A [`BoundVar`] which specifies which of the parameters that the `Binder` introduces we are referring to.
+
+We also sometimes store some extra information for diagnostics reasons via the [`BoundTyKind`]/[`BoundRegionKind`] but this is not important for type equality or more generally the semantics of `Ty`. (omitted from the above example)
 
 In debug output (and also informally when talking to each other) we tend to write these bound variables in the format of `^DebruijnIndex_BoundVar`. The above example would instead be written as `Binder(fn(&'^0_0), &[BoundVariableKind::Region])`. Sometimes when the `DebruijnIndex` is `0` we just omit it and would write `^0`.
 
@@ -43,7 +44,7 @@
     &[BoundVariableKind::Region(...)],
 )
 ```
-This would cause all kinds of issues as the region `'^1_0` refers to a binder at a higher level than the outermost binder i.e. it is an escaping bound var. The `'^1` region (also writeable as `'^0_1`) is also ill formed as the binder it refers to does not introduce a second parameter. Modern day rustc will ICE when constructing this binder due to both of those regions, in the past we would have simply allowed this to work and then ran into issues in other parts of the codebase. 
+This would cause all kinds of issues as the region `'^1_0` refers to a binder at a higher level than the outermost binder i.e. it is an escaping bound var. The `'^1` region (also writeable as `'^0_1`) is also ill formed as the binder it refers to does not introduce a second parameter. Modern day rustc will ICE when constructing this binder due to both of those reasons, in the past we would have simply allowed this to work and then ran into issues in other parts of the codebase. 
 
 [`Binder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Binder.html
 [`BoundVar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.BoundVar.html
diff --git a/src/doc/rustc-dev-guide/src/ty_module/instantiating_binders.md b/src/doc/rustc-dev-guide/src/ty_module/instantiating_binders.md
index 04d56cc..e3f091c 100644
--- a/src/doc/rustc-dev-guide/src/ty_module/instantiating_binders.md
+++ b/src/doc/rustc-dev-guide/src/ty_module/instantiating_binders.md
@@ -105,7 +105,8 @@
 
 ## Instantiating with `ReLateParam`
 
-As discussed in a previous chapter, `RegionKind` has two variants for representing generic parameters, `ReLateParam` and `ReEarlyParam`. `ReLateParam` is conceptually a `Placeholder` that is always in the root universe (`U0`). It is used when instantiating late bound parameters of functions/closures while inside of them. Its actual representation is relatively different from both `ReEarlyParam` and `RePlaceholder`:
+As discussed in [the chapter about representing types][representing-types], `RegionKind` has two variants for representing generic parameters, `ReLateParam` and `ReEarlyParam`.
+`ReLateParam` is conceptually a `Placeholder` that is always in the root universe (`U0`). It is used when instantiating late bound parameters of functions/closures while inside of them. Its actual representation is relatively different from both `ReEarlyParam` and `RePlaceholder`:
 - A `DefId` for the item that introduced the late bound generic parameter
 - A [`BoundRegionKind`] which either specifies the `DefId` of the generic parameter and its name (via a `Symbol`), or that this placeholder is representing the anonymous lifetime of a `Fn`/`FnMut` closure's self borrow. There is also a variant for `BrAnon` but this is not used for `ReLateParam`.
 
@@ -133,6 +134,7 @@
 As a concrete example, accessing the signature of a function we are type checking will be represented as `EarlyBinder<Binder<FnSig>>`. As we are already "inside" of these binders, we would call `instantiate_identity` followed by `liberate_late_bound_regions`.
 
 [`liberate_late_bound_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.liberate_late_bound_regions
+[representing-types]: param_ty_const_regions.md
 [`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html
 [`enter_forall`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/struct.InferCtxt.html#method.enter_forall
 [ch_placeholders_universes]: ../borrow_check/region_inference/placeholders_and_universes.md
diff --git a/src/doc/rustc-dev-guide/src/ty_module/param_ty_const_regions.md b/src/doc/rustc-dev-guide/src/ty_module/param_ty_const_regions.md
index c52f0c0..493693c 100644
--- a/src/doc/rustc-dev-guide/src/ty_module/param_ty_const_regions.md
+++ b/src/doc/rustc-dev-guide/src/ty_module/param_ty_const_regions.md
@@ -11,15 +11,15 @@
 
 There are three separate ways we represent usages of generic parameters:
 - [`TyKind::Param`]/[`ConstKind::Param`]/[`RegionKind::EarlyParam`] for early bound generic parameters (note: all type and const parameters are considered early bound, see the [chapter on early vs late bound parameters][ch_early_late_bound] for more information)
-- [`TyKind::Bound`]/[`ConstKind::Bound`]/[`RegionKind::Bound`] for references to parameters introduced via higher ranked bounds or higher ranked types i.e. `for<'a> fn(&'a u32)` or `for<'a> T: Trait<'a>`. This will be discussed in the [chapter on `Binder`s][ch_binders].
-- [`RegionKind::LateParam`] for late bound lifetime parameters, `LateParam` will be discussed in the [chapter on instantiating `Binder`s][ch_instantiating_binders].
+- [`TyKind::Bound`]/[`ConstKind::Bound`]/[`RegionKind::Bound`] for references to parameters introduced via higher ranked bounds or higher ranked types i.e. `for<'a> fn(&'a u32)` or `for<'a> T: Trait<'a>`. This is discussed in the [chapter on `Binder`s][ch_binders].
+- [`RegionKind::LateParam`] for late bound lifetime parameters, `LateParam` is discussed in the [chapter on instantiating `Binder`s][ch_instantiating_binders].
 
-This chapter will only cover `TyKind::Param` `ConstKind::Param` and `RegionKind::EarlyParam`.
+This chapter only covers `TyKind::Param` `ConstKind::Param` and `RegionKind::EarlyParam`.
 
 ## Ty/Const Parameters
 
-As `TyKind::Param` and `ConstKind::Param` are implemented identically this section will only refer to `TyKind::Param` for simplicity. However
-you should keep in mind that everything here also is true of `ConstKind::Param`
+As `TyKind::Param` and `ConstKind::Param` are implemented identically this section only refers to `TyKind::Param` for simplicity.
+However you should keep in mind that everything here also is true of `ConstKind::Param`
 
 Each `TyKind::Param` contains two things: the name of the parameter and an index.
 
@@ -83,7 +83,7 @@
 }
 ```
 
-`RegionKind::LateParam` will be discussed more in the chapter on [instantiating binders][ch_instantiating_binders].
+`RegionKind::LateParam` is discussed more in the chapter on [instantiating binders][ch_instantiating_binders].
 
 [ch_early_late_bound]: ../early_late_parameters.md
 [ch_binders]: ./binders.md
diff --git a/src/doc/rustc-dev-guide/src/typing_parameter_envs.md b/src/doc/rustc-dev-guide/src/typing_parameter_envs.md
index 67eaf51..e21bc51 100644
--- a/src/doc/rustc-dev-guide/src/typing_parameter_envs.md
+++ b/src/doc/rustc-dev-guide/src/typing_parameter_envs.md
@@ -32,7 +32,7 @@
     <T as Trait>::Assoc: Clone,
 {}
 ```
-If we were conceptually inside of `foo` (for example, type-checking or linting it) we would use this `ParamEnv` everywhere that we interact with the type system. This would allow things such as normalization (TODO: write a chapter about normalization and link it), evaluating generic constants, and proving where clauses/goals, to rely on `T` being sized, implementing `Trait`, etc.
+If we were conceptually inside of `foo` (for example, type-checking or linting it) we would use this `ParamEnv` everywhere that we interact with the type system. This would allow things such as [normalization], evaluating generic constants, and proving where clauses/goals, to rely on `T` being sized, implementing `Trait`, etc.
 
 A more concrete example:
 ```rust
@@ -70,6 +70,7 @@
 [predicates_of]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/collect/predicates_of/fn.predicates_of.html
 [method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html
 [query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.param_env
+[normalization]: normalization.md
 
 ### Acquiring a `ParamEnv`
 
@@ -199,8 +200,8 @@
 
 Depending on what context we are performing type system operations in, different behaviour may be required. For example during coherence there are stronger requirements about when we can consider goals to not hold or when we can consider types to be unequal.
 
-Tracking which "phase" of the compiler type system operations are being performed in is done by the [`TypingMode`][tenv] enum. The documentation on the `TypingMode` enum is quite good so instead of repeating it here verbatim we would recommend reading the API documentation directly.
+Tracking which "phase" of the compiler type system operations are being performed in is done by the [`TypingMode`][tmode] enum. The documentation on the `TypingMode` enum is quite good so instead of repeating it here verbatim we would recommend reading the API documentation directly.
 
 [penv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html
-[tenv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/infer_ctxt/enum.TypingMode.html
+[tenv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypingEnv.html
 [tmode]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.TypingMode.html
diff --git a/src/doc/rustc-dev-guide/triagebot.toml b/src/doc/rustc-dev-guide/triagebot.toml
index 53fa724..978802e 100644
--- a/src/doc/rustc-dev-guide/triagebot.toml
+++ b/src/doc/rustc-dev-guide/triagebot.toml
@@ -1,18 +1,82 @@
-[assign]
+# This file's format is documented at
+# https://forge.rust-lang.org/triagebot/pr-assignment.html#configuration
+
+[autolabel."needs-triage"]
+new_issue = true
+exclude_labels = [
+    "A-diagnostics",
+    "C-tracking-issue",
+]
+
+[review-submitted]
+# This label is added when a "request changes" review is submitted.
+reviewed_label = "S-waiting-on-author"
+# These labels are removed when a "request changes" review is submitted.
+review_labels = ["S-waiting-on-review"]
+
+[review-requested]
+# Those labels are removed when PR author requests a review from an assignee
+remove_labels = ["S-waiting-on-author"]
+# Those labels are added when PR author requests a review from an assignee
+add_labels = ["S-waiting-on-review"]
+
+# Enable shortcuts like `@rustbot ready`
+# Documentation at: https://forge.rust-lang.org/triagebot/shortcuts.html
+[shortcut]
+
+[autolabel."S-waiting-on-review"]
+new_pr = true
+
+# Enable issue transfers within the org
+# Documentation at: https://forge.rust-lang.org/triagebot/transfer.html
+[transfer]
 
 [relabel]
 allow-unauthenticated = [
-    "waiting-on-review",
-    "waiting-on-author",
-    "blocked",
+    "-Z*",
+    "A-*",
+    "C-*",
+    "D-*",
+    "E-*",
+    "F-*",
+    "I-*",
+    "L-*",
+    "O-*",
+    "PG-*",
+    "S-*",
+    "T-*",
+    "WG-*",
+    "needs-triage",
 ]
 
+# Enable `@rustbot note` functionality
+# Documentation at: https://forge.rust-lang.org/triagebot/note.html
+[note]
+
+# Prevents mentions in commits to avoid users being spammed
+# Documentation at: https://forge.rust-lang.org/triagebot/no-mentions.html
 [no-mentions]
 
-[canonicalize-issue-links]
+# Canonicalize issue numbers to avoid closing the wrong issue
+# when commits are included in subtrees, as well as warning links in commits.
+# Documentation at: https://forge.rust-lang.org/triagebot/issue-links.html
+[issue-links]
 
 # Automatically close and reopen PRs made by bots to run CI on them
 [bot-pull-requests]
 
 [behind-upstream]
-days-threshold = 7
\ No newline at end of file
+days-threshold = 7
+
+# Enable triagebot (PR) assignment.
+# Documentation at: https://forge.rust-lang.org/triagebot/pr-assignment.html
+[assign]
+
+# Keep members alphanumerically sorted.
+[assign.adhoc_groups]
+rustc-dev-guide = [
+    "@BoxyUwU",
+    "@jieyouxu",
+    "@jyn514",
+    "@tshepang",
+]
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index a3b70e7..95e6afa 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -192,6 +192,8 @@
 crate, improving re-compile times. This takes a path to a directory where
 incremental files will be stored.
 
+Using incremental compilation inhibits certain optimizations (for example by increasing the amount of codegen units) and is therefore not recommend for release builds.
+
 ## inline-threshold
 
 This option is deprecated and does nothing.
@@ -213,6 +215,8 @@
 
 "Append" is significant; you can pass this flag multiple times to add multiple arguments.
 
+On Unix-like targets that use `cc` as the linker driver, use `-Clink-arg=-Wl,$ARG` to pass an argument to the actual linker.
+
 ## link-args
 
 This flag lets you append multiple extra arguments to the linker invocation. The
@@ -248,6 +252,10 @@
 be inferred based on the target. See also the [linker-flavor](#linker-flavor)
 flag for another way to specify the linker.
 
+Note that on Unix-like targets (for example, `*-unknown-linux-gnu` or `*-unknown-freebsd`)
+the C compiler (for example `cc` or `clang`) is used as the "linker" here, serving as a linker driver.
+It will invoke the actual linker with all the necessary flags to be able to link against the system libraries like libc.
+
 ## linker-flavor
 
 This flag controls the linker flavor used by `rustc`. If a linker is given with
@@ -301,6 +309,12 @@
 
 Pass `--help` to see a list of options.
 
+<div class="warning">
+
+Because this flag directly talks to LLVM, it is not subject to the usual stability guarantees of rustc's CLI interface.
+
+</div>
+
 ## lto
 
 This flag controls whether LLVM uses [link time
@@ -315,6 +329,7 @@
   LTO](http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html).
   This is similar to "fat", but takes substantially less time to run while
   still achieving performance gains similar to "fat".
+  For larger projects like the Rust compiler, ThinLTO can even result in better performance than fat LTO.
 
 If `-C lto` is not specified, then the compiler will attempt to perform "thin
 local LTO" which performs "thin" LTO on the local crate only across its
@@ -343,6 +358,8 @@
 This flag tells the pass manager to use an empty list of passes, instead of the
 usual pre-populated list of passes.
 
+When combined with `-O --emit llvm-ir`, it can be used to see the optimized LLVM IR emitted by rustc before any optimizations are applied by LLVM.
+
 ## no-redzone
 
 This flag allows you to disable [the
@@ -379,7 +396,7 @@
 * `2`: some optimizations.
 * `3`: all optimizations.
 * `s`: optimize for binary size.
-* `z`: optimize for binary size, but also turn off loop vectorization.
+* `z`: optimize for binary size, but more aggressively. Often results in larger binaries than `s`
 
 Note: The [`-O` flag][option-o-optimize] is an alias for `-C opt-level=3`.
 
@@ -407,6 +424,9 @@
 
 If not specified, the default depends on the target.
 
+If any crate in the crate graph uses `abort`, the final binary (`bin`, `dylib`, `cdylib`, `staticlib`) must also use `abort`.
+If `std` is used as a `dylib` with `unwind`, the final binary must also use `unwind`.
+
 ## passes
 
 This flag can be used to add extra [LLVM
@@ -416,6 +436,12 @@
 
 See also the [`no-prepopulate-passes`](#no-prepopulate-passes) flag.
 
+<div class="warning">
+
+Because this flag directly talks to LLVM, it not subject to the usual stability guarantees of rustc's CLI interface.
+
+</div>
+
 ## prefer-dynamic
 
 By default, `rustc` prefers to statically link dependencies. This option will
@@ -523,12 +549,30 @@
 
 ## rpath
 
-This flag controls whether [`rpath`](https://en.wikipedia.org/wiki/Rpath) is
-enabled. It takes one of the following values:
+This flag controls whether rustc sets an [`rpath`](https://en.wikipedia.org/wiki/Rpath) for the binary.
+It takes one of the following values:
 
 * `y`, `yes`, `on`, `true` or no value: enable rpath.
 * `n`, `no`, `off` or `false`: disable rpath (the default).
 
+This flag only does something on Unix-like platforms (Mach-O and ELF), it is ignored on other platforms.
+
+If enabled, rustc will add output-relative (using `@load_path` on Mach-O and `$ORIGIN` on ELF respectively) rpaths to all `dylib` dependencies.
+
+For example, for the following directory structure, with `libdep.so` being a `dylib` crate compiled with `-Cprefer-dynamic`:
+
+```text
+dep
+ |- libdep.so
+a.rs
+```
+
+`rustc a.rs --extern dep=dep/libdep.so -Crpath` will, on x86-64 Linux, result in approximately the following `DT_RUNPATH`: `$ORIGIN/dep:$ORIGIN/$RELATIVE_PATH_TO_SYSROOT/lib/rustlib/x86_64-unknown-linux-gnu/lib` (where `RELATIVE_PATH_TO_SYSROOT` depends on the build directory location).
+
+This is primarily useful for local development, to ensure that all the `dylib` dependencies can be found appropriately.
+
+To set the rpath to a different value (which can be useful for distribution), `-Clink-arg` with a platform-specific linker argument can be used to set the rpath directly.
+
 ## save-temps
 
 This flag controls whether temporary files generated during compilation are
@@ -545,6 +589,8 @@
 * `y`, `yes`, `on`, `true` or no value: use soft floats.
 * `n`, `no`, `off` or `false`: use hardware floats (the default).
 
+This flag only works on `*eabihf` targets and **is unsound and deprecated**.
+
 ## split-debuginfo
 
 This option controls the emission of "split debuginfo" for debug information
diff --git a/src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md b/src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md
index e52ad1c..42662fb 100644
--- a/src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md
+++ b/src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md
@@ -11,7 +11,7 @@
 
 [@jethrogb](https://github.com/jethrogb)
 [@raoulstrackx](https://github.com/raoulstrackx)
-[@mzohreva](https://github.com/mzohreva)
+[@aditijannu](https://github.com/aditijannu)
 
 Further contacts:
 
diff --git a/src/doc/unstable-book/src/compiler-flags/no-steal-thir.md b/src/doc/unstable-book/src/compiler-flags/no-steal-thir.md
new file mode 100644
index 0000000..d83677d
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/no-steal-thir.md
@@ -0,0 +1,7 @@
+# `no-steal-thir`
+
+By default, to save on memory, the THIR body (obtained from the `tcx.thir_body` query) is stolen
+once no longer used. This is inconvenient for authors of rustc drivers who want to access the THIR.
+
+This option disables the stealing. This has no observable effect on compiler behavior, only on
+memory usage.
diff --git a/src/etc/test-float-parse/src/lib.rs b/src/etc/test-float-parse/src/lib.rs
index 0bd4878..f590149 100644
--- a/src/etc/test-float-parse/src/lib.rs
+++ b/src/etc/test-float-parse/src/lib.rs
@@ -119,6 +119,7 @@ pub fn register_tests(cfg: &Config) -> Vec<TestInfo> {
 
     // Register normal generators for all floats.
 
+    #[cfg(not(bootstrap))]
     #[cfg(target_has_reliable_f16)]
     register_float::<f16>(&mut tests, cfg);
     register_float::<f32>(&mut tests, cfg);
diff --git a/src/etc/test-float-parse/src/traits.rs b/src/etc/test-float-parse/src/traits.rs
index 65a8721..16484f8 100644
--- a/src/etc/test-float-parse/src/traits.rs
+++ b/src/etc/test-float-parse/src/traits.rs
@@ -170,6 +170,7 @@ fn constants() -> &'static Constants {
 
 impl_float!(f32, u32; f64, u64);
 
+#[cfg(not(bootstrap))]
 #[cfg(target_has_reliable_f16)]
 impl_float!(f16, u16);
 
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index c091c95..f1c375b 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -388,7 +388,7 @@ pub enum AssocItemConstraintKind {
 /// Rustdoc makes no guarantees about the inner value of Id's. Applications
 /// should treat them as opaque keys to lookup items, and avoid attempting
 /// to parse them, or otherwise depend on any implementation details.
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
 // FIXME(aDotInTheVoid): Consider making this non-public in rustdoc-types.
 pub struct Id(pub u32);
 
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index f69e5be..3a76c61 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -42,7 +42,7 @@
 filetime = "0.2.9"
 itertools = "0.12"
 pulldown-cmark = { version = "0.11", default-features = false, features = ["html"] }
-askama = { version = "0.13", default-features = false, features = ["alloc", "config", "derive"] }
+askama = { version = "0.14", default-features = false, features = ["alloc", "config", "derive"] }
 
 # UI test dependencies
 if_chain = "1.0"
diff --git a/src/tools/clippy/book/src/development/trait_checking.md b/src/tools/clippy/book/src/development/trait_checking.md
index cc4eb96..6d01496 100644
--- a/src/tools/clippy/book/src/development/trait_checking.md
+++ b/src/tools/clippy/book/src/development/trait_checking.md
@@ -17,7 +17,7 @@
 the symbol of the trait in question:
 
 ```rust
-use clippy_utils::is_trait_method;
+use clippy_utils::ty::implements_trait;
 use rustc_hir::Expr;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_span::symbol::sym;
@@ -25,7 +25,7 @@
 impl LateLintPass<'_> for CheckIteratorTraitLint {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
 		let implements_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| {
-    		implements_trait(cx, cx.typeck_results().expr_ty(arg), id, &[])
+    		implements_trait(cx, cx.typeck_results().expr_ty(expr), id, &[])
 		});
 		if implements_iterator {
 			// [...]
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index 9809e32..7c850b4 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -1026,7 +1026,7 @@
 The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
 reference.
 
-**Default Value:** `target_pointer_width * 2`
+**Default Value:** `target_pointer_width`
 
 ---
 **Affected lints:**
diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs
index 4ce8d00..87158ce 100644
--- a/src/tools/clippy/clippy_config/src/conf.rs
+++ b/src/tools/clippy/clippy_config/src/conf.rs
@@ -828,7 +828,7 @@ fn span_from_toml_range(file: &SourceFile, span: Range<usize>) -> Span {
     trait_assoc_item_kinds_order: SourceItemOrderingTraitAssocItemKinds = DEFAULT_TRAIT_ASSOC_ITEM_KINDS_ORDER.into(),
     /// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
     /// reference.
-    #[default_text = "target_pointer_width * 2"]
+    #[default_text = "target_pointer_width"]
     #[lints(trivially_copy_pass_by_ref)]
     trivial_copy_size_limit: Option<u64> = None,
     /// The maximum complexity a type can have
diff --git a/src/tools/clippy/clippy_dev/src/fmt.rs b/src/tools/clippy/clippy_dev/src/fmt.rs
index 13d6b12..c1b6b37 100644
--- a/src/tools/clippy/clippy_dev/src/fmt.rs
+++ b/src/tools/clippy/clippy_dev/src/fmt.rs
@@ -1,5 +1,6 @@
 use crate::utils::{
-    ClippyInfo, ErrAction, FileUpdater, UpdateMode, UpdateStatus, panic_action, run_with_args_split, run_with_output,
+    ErrAction, FileUpdater, UpdateMode, UpdateStatus, expect_action, run_with_output, split_args_for_threads,
+    walk_dir_no_dot_or_target,
 };
 use itertools::Itertools;
 use rustc_lexer::{TokenKind, tokenize};
@@ -9,7 +10,6 @@
 use std::ops::ControlFlow;
 use std::path::PathBuf;
 use std::process::{self, Command, Stdio};
-use walkdir::WalkDir;
 
 pub enum Error {
     Io(io::Error),
@@ -260,7 +260,7 @@ fn fmt_syms(update_mode: UpdateMode) {
     );
 }
 
-fn run_rustfmt(clippy: &ClippyInfo, update_mode: UpdateMode) {
+fn run_rustfmt(update_mode: UpdateMode) {
     let mut rustfmt_path = String::from_utf8(run_with_output(
         "rustup which rustfmt",
         Command::new("rustup").args(["which", "rustfmt"]),
@@ -268,42 +268,19 @@ fn run_rustfmt(clippy: &ClippyInfo, update_mode: UpdateMode) {
     .expect("invalid rustfmt path");
     rustfmt_path.truncate(rustfmt_path.trim_end().len());
 
-    let mut cargo_path = String::from_utf8(run_with_output(
-        "rustup which cargo",
-        Command::new("rustup").args(["which", "cargo"]),
-    ))
-    .expect("invalid cargo path");
-    cargo_path.truncate(cargo_path.trim_end().len());
+    let args: Vec<_> = walk_dir_no_dot_or_target()
+        .filter_map(|e| {
+            let e = expect_action(e, ErrAction::Read, ".");
+            e.path()
+                .as_os_str()
+                .as_encoded_bytes()
+                .ends_with(b".rs")
+                .then(|| e.into_path().into_os_string())
+        })
+        .collect();
 
-    // Start all format jobs first before waiting on the results.
-    let mut children = Vec::with_capacity(16);
-    for &path in &[
-        ".",
-        "clippy_config",
-        "clippy_dev",
-        "clippy_lints",
-        "clippy_lints_internal",
-        "clippy_utils",
-        "rustc_tools_util",
-        "lintcheck",
-    ] {
-        let mut cmd = Command::new(&cargo_path);
-        cmd.current_dir(clippy.path.join(path))
-            .args(["fmt"])
-            .env("RUSTFMT", &rustfmt_path)
-            .stdout(Stdio::null())
-            .stdin(Stdio::null())
-            .stderr(Stdio::piped());
-        if update_mode.is_check() {
-            cmd.arg("--check");
-        }
-        match cmd.spawn() {
-            Ok(x) => children.push(("cargo fmt", x)),
-            Err(ref e) => panic_action(&e, ErrAction::Run, "cargo fmt".as_ref()),
-        }
-    }
-
-    run_with_args_split(
+    let mut children: Vec<_> = split_args_for_threads(
+        32,
         || {
             let mut cmd = Command::new(&rustfmt_path);
             if update_mode.is_check() {
@@ -312,66 +289,44 @@ fn run_rustfmt(clippy: &ClippyInfo, update_mode: UpdateMode) {
             cmd.stdout(Stdio::null())
                 .stdin(Stdio::null())
                 .stderr(Stdio::piped())
-                .args(["--config", "show_parse_errors=false"]);
+                .args(["--unstable-features", "--skip-children"]);
             cmd
         },
-        |cmd| match cmd.spawn() {
-            Ok(x) => children.push(("rustfmt", x)),
-            Err(ref e) => panic_action(&e, ErrAction::Run, "rustfmt".as_ref()),
-        },
-        WalkDir::new("tests")
-            .into_iter()
-            .filter_entry(|p| p.path().file_name().is_none_or(|x| x != "skip_rustfmt"))
-            .filter_map(|e| {
-                let e = e.expect("error reading `tests`");
-                e.path()
-                    .as_os_str()
-                    .as_encoded_bytes()
-                    .ends_with(b".rs")
-                    .then(|| e.into_path().into_os_string())
-            }),
-    );
+        args.iter(),
+    )
+    .map(|mut cmd| expect_action(cmd.spawn(), ErrAction::Run, "rustfmt"))
+    .collect();
 
-    for (name, child) in &mut children {
-        match child.wait() {
-            Ok(status) => match (update_mode, status.exit_ok()) {
-                (UpdateMode::Check | UpdateMode::Change, Ok(())) => {},
-                (UpdateMode::Check, Err(_)) => {
-                    let mut s = String::new();
-                    if let Some(mut stderr) = child.stderr.take()
-                        && stderr.read_to_string(&mut s).is_ok()
-                    {
-                        eprintln!("{s}");
-                    }
-                    eprintln!("Formatting check failed!\nRun `cargo dev fmt` to update.");
-                    process::exit(1);
-                },
-                (UpdateMode::Change, Err(e)) => {
-                    let mut s = String::new();
-                    if let Some(mut stderr) = child.stderr.take()
-                        && stderr.read_to_string(&mut s).is_ok()
-                    {
-                        eprintln!("{s}");
-                    }
-                    panic_action(&e, ErrAction::Run, name.as_ref());
-                },
+    for child in &mut children {
+        let status = expect_action(child.wait(), ErrAction::Run, "rustfmt");
+        match (update_mode, status.exit_ok()) {
+            (UpdateMode::Check | UpdateMode::Change, Ok(())) => {},
+            (UpdateMode::Check, Err(_)) => {
+                let mut s = String::new();
+                if let Some(mut stderr) = child.stderr.take()
+                    && stderr.read_to_string(&mut s).is_ok()
+                {
+                    eprintln!("{s}");
+                }
+                eprintln!("Formatting check failed!\nRun `cargo dev fmt` to update.");
+                process::exit(1);
             },
-            Err(ref e) => panic_action(e, ErrAction::Run, name.as_ref()),
+            (UpdateMode::Change, e) => {
+                let mut s = String::new();
+                if let Some(mut stderr) = child.stderr.take()
+                    && stderr.read_to_string(&mut s).is_ok()
+                {
+                    eprintln!("{s}");
+                }
+                expect_action(e, ErrAction::Run, "rustfmt");
+            },
         }
     }
 }
 
 // the "main" function of cargo dev fmt
-pub fn run(clippy: &ClippyInfo, update_mode: UpdateMode) {
-    if clippy.has_intellij_hook {
-        eprintln!(
-            "error: a local rustc repo is enabled as path dependency via `cargo dev setup intellij`.\n\
-            Not formatting because that would format the local repo as well!\n\
-            Please revert the changes to `Cargo.toml`s with `cargo dev remove intellij`."
-        );
-        return;
-    }
-    run_rustfmt(clippy, update_mode);
+pub fn run(update_mode: UpdateMode) {
+    run_rustfmt(update_mode);
     fmt_syms(update_mode);
     if let Err(e) = fmt_conf(update_mode.is_check()) {
         e.display();
diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs
index ebcd861..26aa269 100644
--- a/src/tools/clippy/clippy_dev/src/main.rs
+++ b/src/tools/clippy/clippy_dev/src/main.rs
@@ -26,7 +26,7 @@ fn main() {
             allow_staged,
             allow_no_vcs,
         } => dogfood::dogfood(fix, allow_dirty, allow_staged, allow_no_vcs),
-        DevCommand::Fmt { check } => fmt::run(&clippy, utils::UpdateMode::from_check(check)),
+        DevCommand::Fmt { check } => fmt::run(utils::UpdateMode::from_check(check)),
         DevCommand::UpdateLints { check } => update_lints::update(utils::UpdateMode::from_check(check)),
         DevCommand::NewLint {
             pass,
diff --git a/src/tools/clippy/clippy_dev/src/rename_lint.rs b/src/tools/clippy/clippy_dev/src/rename_lint.rs
index be8b27c..d625974 100644
--- a/src/tools/clippy/clippy_dev/src/rename_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/rename_lint.rs
@@ -1,13 +1,12 @@
 use crate::update_lints::{RenamedLint, find_lint_decls, generate_lint_files, read_deprecated_lints};
 use crate::utils::{
-    FileUpdater, RustSearcher, Token, UpdateMode, UpdateStatus, Version, delete_dir_if_exists, delete_file_if_exists,
-    try_rename_dir, try_rename_file,
+    ErrAction, FileUpdater, RustSearcher, Token, UpdateMode, UpdateStatus, Version, delete_dir_if_exists,
+    delete_file_if_exists, expect_action, try_rename_dir, try_rename_file, walk_dir_no_dot_or_target,
 };
 use rustc_lexer::TokenKind;
 use std::ffi::OsString;
 use std::fs;
 use std::path::Path;
-use walkdir::WalkDir;
 
 /// Runs the `rename_lint` command.
 ///
@@ -133,17 +132,10 @@ pub fn rename(clippy_version: Version, old_name: &str, new_name: &str, uplift: b
     }
 
     let mut update_fn = file_update_fn(old_name, new_name, mod_edit);
-    for file in WalkDir::new(".").into_iter().filter_entry(|e| {
-        // Skip traversing some of the larger directories.
-        e.path()
-            .as_os_str()
-            .as_encoded_bytes()
-            .get(2..)
-            .is_none_or(|x| x != "target".as_bytes() && x != ".git".as_bytes())
-    }) {
-        let file = file.expect("error reading clippy directory");
-        if file.path().as_os_str().as_encoded_bytes().ends_with(b".rs") {
-            updater.update_file(file.path(), &mut update_fn);
+    for e in walk_dir_no_dot_or_target() {
+        let e = expect_action(e, ErrAction::Read, ".");
+        if e.path().as_os_str().as_encoded_bytes().ends_with(b".rs") {
+            updater.update_file(e.path(), &mut update_fn);
         }
     }
     generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints);
diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs
index 25ba2c7..320462a 100644
--- a/src/tools/clippy/clippy_dev/src/update_lints.rs
+++ b/src/tools/clippy/clippy_dev/src/update_lints.rs
@@ -1,5 +1,5 @@
 use crate::utils::{
-    ErrAction, File, FileUpdater, RustSearcher, Token, UpdateMode, UpdateStatus, panic_action, update_text_region_fn,
+    ErrAction, File, FileUpdater, RustSearcher, Token, UpdateMode, UpdateStatus, expect_action, update_text_region_fn,
 };
 use itertools::Itertools;
 use std::collections::HashSet;
@@ -201,10 +201,7 @@ pub fn find_lint_decls() -> Vec<Lint> {
 /// Reads the source files from the given root directory
 fn read_src_with_module(src_root: &Path) -> impl use<'_> + Iterator<Item = (DirEntry, String)> {
     WalkDir::new(src_root).into_iter().filter_map(move |e| {
-        let e = match e {
-            Ok(e) => e,
-            Err(ref e) => panic_action(e, ErrAction::Read, src_root),
-        };
+        let e = expect_action(e, ErrAction::Read, src_root);
         let path = e.path().as_os_str().as_encoded_bytes();
         if let Some(path) = path.strip_suffix(b".rs")
             && let Some(path) = path.get("clippy_lints/src/".len()..)
diff --git a/src/tools/clippy/clippy_dev/src/utils.rs b/src/tools/clippy/clippy_dev/src/utils.rs
index 255e36a..c4808b7 100644
--- a/src/tools/clippy/clippy_dev/src/utils.rs
+++ b/src/tools/clippy/clippy_dev/src/utils.rs
@@ -1,14 +1,16 @@
 use core::fmt::{self, Display};
+use core::num::NonZero;
 use core::ops::Range;
 use core::slice;
 use core::str::FromStr;
 use rustc_lexer::{self as lexer, FrontmatterAllowed};
-use std::env;
 use std::ffi::OsStr;
 use std::fs::{self, OpenOptions};
 use std::io::{self, Read as _, Seek as _, SeekFrom, Write};
 use std::path::{Path, PathBuf};
 use std::process::{self, Command, ExitStatus, Stdio};
+use std::{env, thread};
+use walkdir::WalkDir;
 
 #[cfg(not(windows))]
 static CARGO_CLIPPY_EXE: &str = "cargo-clippy";
@@ -45,6 +47,14 @@ pub fn panic_action(err: &impl Display, action: ErrAction, path: &Path) -> ! {
     panic!("error {} `{}`: {}", action.as_str(), path.display(), *err)
 }
 
+#[track_caller]
+pub fn expect_action<T>(res: Result<T, impl Display>, action: ErrAction, path: impl AsRef<Path>) -> T {
+    match res {
+        Ok(x) => x,
+        Err(ref e) => panic_action(e, action, path.as_ref()),
+    }
+}
+
 /// Wrapper around `std::fs::File` which panics with a path on failure.
 pub struct File<'a> {
     pub inner: fs::File,
@@ -55,9 +65,9 @@ impl<'a> File<'a> {
     #[track_caller]
     pub fn open(path: &'a (impl AsRef<Path> + ?Sized), options: &mut OpenOptions) -> Self {
         let path = path.as_ref();
-        match options.open(path) {
-            Ok(inner) => Self { inner, path },
-            Err(e) => panic_action(&e, ErrAction::Open, path),
+        Self {
+            inner: expect_action(options.open(path), ErrAction::Open, path),
+            path,
         }
     }
 
@@ -84,10 +94,7 @@ pub fn open_read_to_cleared_string<'dst>(
     /// Read the entire contents of a file to the given buffer.
     #[track_caller]
     pub fn read_append_to_string<'dst>(&mut self, dst: &'dst mut String) -> &'dst mut String {
-        match self.inner.read_to_string(dst) {
-            Ok(_) => {},
-            Err(e) => panic_action(&e, ErrAction::Read, self.path),
-        }
+        expect_action(self.inner.read_to_string(dst), ErrAction::Read, self.path);
         dst
     }
 
@@ -107,9 +114,7 @@ pub fn replace_contents(&mut self, data: &[u8]) {
             },
             Err(e) => Err(e),
         };
-        if let Err(e) = res {
-            panic_action(&e, ErrAction::Write, self.path);
-        }
+        expect_action(res, ErrAction::Write, self.path);
     }
 }
 
@@ -660,47 +665,91 @@ pub fn try_rename_dir(old_name: &Path, new_name: &Path) -> bool {
 }
 
 pub fn write_file(path: &Path, contents: &str) {
-    fs::write(path, contents).unwrap_or_else(|e| panic_action(&e, ErrAction::Write, path));
+    expect_action(fs::write(path, contents), ErrAction::Write, path);
 }
 
 #[must_use]
 pub fn run_with_output(path: &(impl AsRef<Path> + ?Sized), cmd: &mut Command) -> Vec<u8> {
     fn f(path: &Path, cmd: &mut Command) -> Vec<u8> {
-        match cmd
-            .stdin(Stdio::null())
-            .stdout(Stdio::piped())
-            .stderr(Stdio::inherit())
-            .output()
-        {
-            Ok(x) => match x.status.exit_ok() {
-                Ok(()) => x.stdout,
-                Err(ref e) => panic_action(e, ErrAction::Run, path),
-            },
-            Err(ref e) => panic_action(e, ErrAction::Run, path),
-        }
+        let output = expect_action(
+            cmd.stdin(Stdio::null())
+                .stdout(Stdio::piped())
+                .stderr(Stdio::inherit())
+                .output(),
+            ErrAction::Run,
+            path,
+        );
+        expect_action(output.status.exit_ok(), ErrAction::Run, path);
+        output.stdout
     }
     f(path.as_ref(), cmd)
 }
 
-pub fn run_with_args_split(
-    mut make_cmd: impl FnMut() -> Command,
-    mut run_cmd: impl FnMut(&mut Command),
-    args: impl Iterator<Item: AsRef<OsStr>>,
-) {
-    let mut cmd = make_cmd();
-    let mut len = 0;
-    for arg in args {
-        len += arg.as_ref().len();
-        cmd.arg(arg);
-        // Very conservative limit
-        if len > 10000 {
-            run_cmd(&mut cmd);
-            cmd = make_cmd();
-            len = 0;
+/// Splits an argument list across multiple `Command` invocations.
+///
+/// The argument list will be split into a number of batches based on
+/// `thread::available_parallelism`, with `min_batch_size` setting a lower bound on the size of each
+/// batch.
+///
+/// If the size of the arguments would exceed the system limit additional batches will be created.
+pub fn split_args_for_threads(
+    min_batch_size: usize,
+    make_cmd: impl FnMut() -> Command,
+    args: impl ExactSizeIterator<Item: AsRef<OsStr>>,
+) -> impl Iterator<Item = Command> {
+    struct Iter<F, I> {
+        make_cmd: F,
+        args: I,
+        min_batch_size: usize,
+        batch_size: usize,
+        thread_count: usize,
+    }
+    impl<F, I> Iterator for Iter<F, I>
+    where
+        F: FnMut() -> Command,
+        I: ExactSizeIterator<Item: AsRef<OsStr>>,
+    {
+        type Item = Command;
+        fn next(&mut self) -> Option<Self::Item> {
+            if self.thread_count > 1 {
+                self.thread_count -= 1;
+            }
+            let mut cmd = (self.make_cmd)();
+            let mut cmd_len = 0usize;
+            for arg in self.args.by_ref().take(self.batch_size) {
+                cmd.arg(arg.as_ref());
+                // `+ 8` to account for the `argv` pointer on unix.
+                // Windows is complicated since the arguments are first converted to UTF-16ish,
+                // but this needs to account for the space between arguments and whatever additional
+                // is needed to escape within an argument.
+                cmd_len += arg.as_ref().len() + 8;
+                cmd_len += 8;
+
+                // Windows has a command length limit of 32767. For unix systems this is more
+                // complicated since the limit includes environment variables and room needs to be
+                // left to edit them once the program starts, but the total size comes from
+                // `getconf ARG_MAX`.
+                //
+                // For simplicity we use 30000 here under a few assumptions.
+                // * Individual arguments aren't super long (the final argument is still added)
+                // * `ARG_MAX` is set to a reasonable amount. Basically every system will be configured way above
+                //   what windows supports, but POSIX only requires `4096`.
+                if cmd_len > 30000 {
+                    self.batch_size = self.args.len().div_ceil(self.thread_count).max(self.min_batch_size);
+                    break;
+                }
+            }
+            (cmd_len != 0).then_some(cmd)
         }
     }
-    if len != 0 {
-        run_cmd(&mut cmd);
+    let thread_count = thread::available_parallelism().map_or(1, NonZero::get);
+    let batch_size = args.len().div_ceil(thread_count).max(min_batch_size);
+    Iter {
+        make_cmd,
+        args,
+        min_batch_size,
+        batch_size,
+        thread_count,
     }
 }
 
@@ -720,3 +769,12 @@ pub fn delete_dir_if_exists(path: &Path) {
         Err(ref e) => panic_action(e, ErrAction::Delete, path),
     }
 }
+
+/// Walks all items excluding top-level dot files/directories and any target directories.
+pub fn walk_dir_no_dot_or_target() -> impl Iterator<Item = ::walkdir::Result<::walkdir::DirEntry>> {
+    WalkDir::new(".").into_iter().filter_entry(|e| {
+        e.path()
+            .file_name()
+            .is_none_or(|x| x != "target" && x.as_encoded_bytes().first().copied() != Some(b'.'))
+    })
+}
diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
index 06376c5..152516b 100644
--- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs
+++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
@@ -5,7 +5,7 @@
 use clippy_utils::source::snippet_with_applicability;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, Node};
+use rustc_hir::{Closure, ClosureKind, CoroutineKind, Expr, ExprKind, LetStmt, LocalSource, Node, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::impl_lint_pass;
 use rustc_span::{Span, SyntaxContext, sym};
@@ -60,6 +60,8 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
         if cur_syntax_ctxt != self.prev_ctxt &&
             let Some(macro_call) = first_dbg_macro_in_expansion(cx, expr.span) &&
             !macro_call.span.in_external_macro(cx.sess().source_map()) &&
+            // avoids exprs generated by the desugaring of coroutines
+            !is_coroutine_desugar(expr) &&
             self.checked_dbg_call_site.insert(macro_call.span) &&
             // allows `dbg!` in test code if allow-dbg-in-test is set to true in clippy.toml
             !(self.allow_dbg_in_tests && is_in_test(cx.tcx, expr.hir_id))
@@ -73,50 +75,51 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
                 "the `dbg!` macro is intended as a debugging tool",
                 |diag| {
                     let mut applicability = Applicability::MachineApplicable;
-
-                    let (sugg_span, suggestion) = match expr.peel_drop_temps().kind {
-                        // dbg!()
-                        ExprKind::Block(..) => {
-                            // If the `dbg!` macro is a "free" statement and not contained within other expressions,
-                            // remove the whole statement.
-                            if let Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id)
-                                && let Some(semi_span) = cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span)
-                            {
-                                (macro_call.span.to(semi_span), String::new())
-                            } else {
-                                (macro_call.span, String::from("()"))
-                            }
-                        },
-                        // dbg!(1)
-                        ExprKind::Match(val, ..) => (
-                            macro_call.span,
-                            snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability)
-                                .to_string(),
-                        ),
-                        // dbg!(2, 3)
-                        ExprKind::Tup(
-                            [
-                                Expr {
-                                    kind: ExprKind::Match(first, ..),
-                                    ..
-                                },
-                                ..,
-                                Expr {
-                                    kind: ExprKind::Match(last, ..),
-                                    ..
-                                },
-                            ],
-                        ) => {
-                            let snippet = snippet_with_applicability(
-                                cx,
-                                first.span.source_callsite().to(last.span.source_callsite()),
-                                "..",
-                                &mut applicability,
-                            );
-                            (macro_call.span, format!("({snippet})"))
-                        },
-                        _ => unreachable!(),
-                    };
+                    let (sugg_span, suggestion) =
+                        match is_async_move_desugar(expr).unwrap_or(expr).peel_drop_temps().kind {
+                            // dbg!()
+                            ExprKind::Block(..) => {
+                                // If the `dbg!` macro is a "free" statement and not contained within other expressions,
+                                // remove the whole statement.
+                                if let Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id)
+                                    && let Some(semi_span) =
+                                        cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span)
+                                {
+                                    (macro_call.span.to(semi_span), String::new())
+                                } else {
+                                    (macro_call.span, String::from("()"))
+                                }
+                            },
+                            // dbg!(1)
+                            ExprKind::Match(val, ..) => (
+                                macro_call.span,
+                                snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability)
+                                    .to_string(),
+                            ),
+                            // dbg!(2, 3)
+                            ExprKind::Tup(
+                                [
+                                    Expr {
+                                        kind: ExprKind::Match(first, ..),
+                                        ..
+                                    },
+                                    ..,
+                                    Expr {
+                                        kind: ExprKind::Match(last, ..),
+                                        ..
+                                    },
+                                ],
+                            ) => {
+                                let snippet = snippet_with_applicability(
+                                    cx,
+                                    first.span.source_callsite().to(last.span.source_callsite()),
+                                    "..",
+                                    &mut applicability,
+                                );
+                                (macro_call.span, format!("({snippet})"))
+                            },
+                            _ => unreachable!(),
+                        };
 
                     diag.span_suggestion(
                         sugg_span,
@@ -134,6 +137,35 @@ fn check_crate_post(&mut self, _: &LateContext<'_>) {
     }
 }
 
+fn is_coroutine_desugar(expr: &Expr<'_>) -> bool {
+    matches!(
+        expr.kind,
+        ExprKind::Closure(Closure {
+            kind: ClosureKind::Coroutine(CoroutineKind::Desugared(..)) | ClosureKind::CoroutineClosure(..),
+            ..
+        })
+    )
+}
+
+fn is_async_move_desugar<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
+    if let ExprKind::Block(block, _) = expr.kind
+        && let [
+            Stmt {
+                kind:
+                    StmtKind::Let(LetStmt {
+                        source: LocalSource::AsyncFn,
+                        ..
+                    }),
+                ..
+            },
+        ] = block.stmts
+    {
+        return block.expr;
+    }
+
+    None
+}
+
 fn first_dbg_macro_in_expansion(cx: &LateContext<'_>, span: Span) -> Option<MacroCall> {
     macro_backtrace(span).find(|mc| cx.tcx.is_diagnostic_item(sym::dbg_macro, mc.def_id))
 }
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index a22a2ee..cde9528 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -305,7 +305,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                     RefOp::Method { mutbl, is_ufcs }
                         if !is_lint_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id)
                             // Allow explicit deref in method chains. e.g. `foo.deref().bar()`
-                            && (is_ufcs || !in_postfix_position(cx, expr)) =>
+                            && (is_ufcs || !is_in_method_chain(cx, expr)) =>
                     {
                         let ty_changed_count = usize::from(!deref_method_same_type(expr_ty, typeck.expr_ty(sub_expr)));
                         self.state = Some((
@@ -728,7 +728,13 @@ fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool {
     }
 }
 
-fn in_postfix_position<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool {
+fn is_in_method_chain<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool {
+    if let ExprKind::MethodCall(_, recv, _, _) = e.kind
+        && matches!(recv.kind, ExprKind::MethodCall(..))
+    {
+        return true;
+    }
+
     if let Some(parent) = get_parent_expr(cx, e)
         && parent.span.eq_ctxt(e.span)
     {
@@ -986,6 +992,15 @@ fn report<'tcx>(
             );
         },
         State::DerefedBorrow(state) => {
+            // Do not suggest removing a non-mandatory `&` in `&*rawptr` in an `unsafe` context,
+            // as this may make rustc trigger its `dangerous_implicit_autorefs` lint.
+            if let ExprKind::AddrOf(BorrowKind::Ref, _, subexpr) = data.first_expr.kind
+                && let ExprKind::Unary(UnOp::Deref, subsubexpr) = subexpr.kind
+                && cx.typeck_results().expr_ty_adjusted(subsubexpr).is_raw_ptr()
+            {
+                return;
+            }
+
             let mut app = Applicability::MachineApplicable;
             let (snip, snip_is_macro) =
                 snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app);
diff --git a/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs b/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs
index 8aeb835..cb9d682 100644
--- a/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs
@@ -2,11 +2,10 @@
 use itertools::Itertools;
 use rustc_errors::Applicability;
 use rustc_lint::LateContext;
-use rustc_span::{BytePos, Span};
-use std::cmp::Ordering;
+use rustc_span::BytePos;
 use std::ops::Range;
 
-use super::{DOC_LAZY_CONTINUATION, DOC_OVERINDENTED_LIST_ITEMS};
+use super::{DOC_LAZY_CONTINUATION, DOC_OVERINDENTED_LIST_ITEMS, Fragments};
 
 fn map_container_to_text(c: &super::Container) -> &'static str {
     match c {
@@ -19,29 +18,27 @@ fn map_container_to_text(c: &super::Container) -> &'static str {
 pub(super) fn check(
     cx: &LateContext<'_>,
     doc: &str,
-    range: Range<usize>,
-    mut span: Span,
+    cooked_range: Range<usize>,
+    fragments: &Fragments<'_>,
     containers: &[super::Container],
 ) {
-    if doc[range.clone()].contains('\t') {
-        // We don't do tab stops correctly.
-        return;
-    }
-
-    // Blockquote
-    let ccount = doc[range.clone()].chars().filter(|c| *c == '>').count();
+    // Get blockquotes
+    let ccount = doc[cooked_range.clone()].chars().filter(|c| *c == '>').count();
     let blockquote_level = containers
         .iter()
         .filter(|c| matches!(c, super::Container::Blockquote))
         .count();
-    if ccount < blockquote_level {
+
+    if ccount < blockquote_level
+        && let Some(mut span) = fragments.span(cx, cooked_range.clone())
+    {
         span_lint_and_then(
             cx,
             DOC_LAZY_CONTINUATION,
             span,
             "doc quote line without `>` marker",
             |diag| {
-                let mut doc_start_range = &doc[range];
+                let mut doc_start_range = &doc[cooked_range];
                 let mut suggested = String::new();
                 for c in containers {
                     let text = map_container_to_text(c);
@@ -78,7 +75,7 @@ pub(super) fn check(
     }
 
     // List
-    let leading_spaces = doc[range].chars().filter(|c| *c == ' ').count();
+    let leading_spaces = doc[cooked_range.clone()].chars().filter(|c| *c == ' ').count();
     let list_indentation = containers
         .iter()
         .map(|c| {
@@ -89,36 +86,41 @@ pub(super) fn check(
             }
         })
         .sum();
-    match leading_spaces.cmp(&list_indentation) {
-        Ordering::Less => span_lint_and_then(
-            cx,
-            DOC_LAZY_CONTINUATION,
-            span,
-            "doc list item without indentation",
-            |diag| {
-                // simpler suggestion style for indentation
-                let indent = list_indentation - leading_spaces;
-                diag.span_suggestion_verbose(
-                    span.shrink_to_hi(),
-                    "indent this line",
-                    std::iter::repeat_n(" ", indent).join(""),
-                    Applicability::MaybeIncorrect,
-                );
-                diag.help("if this is supposed to be its own paragraph, add a blank line");
-            },
-        ),
-        Ordering::Greater => {
-            let sugg = std::iter::repeat_n(" ", list_indentation).join("");
-            span_lint_and_sugg(
+
+    if leading_spaces != list_indentation
+        && let Some(span) = fragments.span(cx, cooked_range.clone())
+    {
+        if leading_spaces < list_indentation {
+            span_lint_and_then(
                 cx,
-                DOC_OVERINDENTED_LIST_ITEMS,
+                DOC_LAZY_CONTINUATION,
                 span,
-                "doc list item overindented",
-                format!("try using `{sugg}` ({list_indentation} spaces)"),
-                sugg,
-                Applicability::MaybeIncorrect,
+                "doc list item without indentation",
+                |diag| {
+                    // simpler suggestion style for indentation
+                    let indent = list_indentation - leading_spaces;
+                    diag.span_suggestion_verbose(
+                        span.shrink_to_hi(),
+                        "indent this line",
+                        std::iter::repeat_n(" ", indent).join(""),
+                        Applicability::MaybeIncorrect,
+                    );
+                    diag.help("if this is supposed to be its own paragraph, add a blank line");
+                },
             );
-        },
-        Ordering::Equal => {},
+
+            return;
+        }
+
+        let sugg = std::iter::repeat_n(" ", list_indentation).join("");
+        span_lint_and_sugg(
+            cx,
+            DOC_OVERINDENTED_LIST_ITEMS,
+            span,
+            "doc list item overindented",
+            format!("try using `{sugg}` ({list_indentation} spaces)"),
+            sugg,
+            Applicability::MaybeIncorrect,
+        );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/doc/markdown.rs b/src/tools/clippy/clippy_lints/src/doc/markdown.rs
index 7a1c7c6..69c3b91 100644
--- a/src/tools/clippy/clippy_lints/src/doc/markdown.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/markdown.rs
@@ -6,13 +6,15 @@
 use rustc_span::{BytePos, Pos, Span};
 use url::Url;
 
-use crate::doc::DOC_MARKDOWN;
+use crate::doc::{DOC_MARKDOWN, Fragments};
+use std::ops::Range;
 
 pub fn check(
     cx: &LateContext<'_>,
     valid_idents: &FxHashSet<String>,
     text: &str,
-    span: Span,
+    fragments: &Fragments<'_>,
+    fragment_range: Range<usize>,
     code_level: isize,
     blockquote_level: isize,
 ) {
@@ -64,20 +66,31 @@ pub fn check(
             close_parens += 1;
         }
 
-        // Adjust for the current word
-        let offset = word.as_ptr() as usize - text.as_ptr() as usize;
-        let span = Span::new(
-            span.lo() + BytePos::from_usize(offset),
-            span.lo() + BytePos::from_usize(offset + word.len()),
-            span.ctxt(),
-            span.parent(),
-        );
+        // We'll use this offset to calculate the span to lint.
+        let fragment_offset = word.as_ptr() as usize - text.as_ptr() as usize;
 
-        check_word(cx, word, span, code_level, blockquote_level);
+        // Adjust for the current word
+        check_word(
+            cx,
+            word,
+            fragments,
+            &fragment_range,
+            fragment_offset,
+            code_level,
+            blockquote_level,
+        );
     }
 }
 
-fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, blockquote_level: isize) {
+fn check_word(
+    cx: &LateContext<'_>,
+    word: &str,
+    fragments: &Fragments<'_>,
+    range: &Range<usize>,
+    fragment_offset: usize,
+    code_level: isize,
+    blockquote_level: isize,
+) {
     /// Checks if a string is upper-camel-case, i.e., starts with an uppercase and
     /// contains at least two uppercase letters (`Clippy` is ok) and one lower-case
     /// letter (`NASA` is ok).
@@ -117,6 +130,16 @@ fn has_hyphen(s: &str) -> bool {
         // try to get around the fact that `foo::bar` parses as a valid URL
         && !url.cannot_be_a_base()
     {
+        let Some(fragment_span) = fragments.span(cx, range.clone()) else {
+            return;
+        };
+        let span = Span::new(
+            fragment_span.lo() + BytePos::from_usize(fragment_offset),
+            fragment_span.lo() + BytePos::from_usize(fragment_offset + word.len()),
+            fragment_span.ctxt(),
+            fragment_span.parent(),
+        );
+
         span_lint_and_sugg(
             cx,
             DOC_MARKDOWN,
@@ -137,6 +160,17 @@ fn has_hyphen(s: &str) -> bool {
     }
 
     if has_underscore(word) || word.contains("::") || is_camel_case(word) || word.ends_with("()") {
+        let Some(fragment_span) = fragments.span(cx, range.clone()) else {
+            return;
+        };
+
+        let span = Span::new(
+            fragment_span.lo() + BytePos::from_usize(fragment_offset),
+            fragment_span.lo() + BytePos::from_usize(fragment_offset + word.len()),
+            fragment_span.ctxt(),
+            fragment_span.parent(),
+        );
+
         span_lint_and_then(
             cx,
             DOC_MARKDOWN,
diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs
index 87da380..c46dd09 100644
--- a/src/tools/clippy/clippy_lints/src/doc/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs
@@ -3,7 +3,6 @@
 use clippy_config::Conf;
 use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then};
-use clippy_utils::source::snippet_opt;
 use clippy_utils::{is_entrypoint_fn, is_trait_impl_item};
 use pulldown_cmark::Event::{
     Code, DisplayMath, End, FootnoteReference, HardBreak, Html, InlineHtml, InlineMath, Rule, SoftBreak, Start,
@@ -730,7 +729,10 @@ struct Fragments<'a> {
 }
 
 impl Fragments<'_> {
-    fn span(self, cx: &LateContext<'_>, range: Range<usize>) -> Option<Span> {
+    /// get the span for the markdown range. Note that this function is not cheap, use it with
+    /// caution.
+    #[must_use]
+    fn span(&self, cx: &LateContext<'_>, range: Range<usize>) -> Option<Span> {
         source_span_for_markdown_range(cx.tcx, self.doc, &range, self.fragments)
     }
 }
@@ -1068,9 +1070,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                     );
                 } else {
                     for (text, range, assoc_code_level) in text_to_check {
-                        if let Some(span) = fragments.span(cx, range) {
-                            markdown::check(cx, valid_idents, &text, span, assoc_code_level, blockquote_level);
-                        }
+                        markdown::check(cx, valid_idents, &text, &fragments, range, assoc_code_level, blockquote_level);
                     }
                 }
                 text_to_check = Vec::new();
@@ -1081,26 +1081,27 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
             | TaskListMarker(_) | Code(_) | Rule | InlineMath(..) | DisplayMath(..) => (),
             SoftBreak | HardBreak => {
                 if !containers.is_empty()
-                    && let Some((next_event, next_range)) = events.peek()
-                    && let Some(next_span) = fragments.span(cx, next_range.clone())
-                    && let Some(span) = fragments.span(cx, range.clone())
                     && !in_footnote_definition
+                    // Tabs aren't handled correctly vvvv
+                    && !doc[range.clone()].contains('\t')
+                    && let Some((next_event, next_range)) = events.peek()
                     && !matches!(next_event, End(_))
                 {
                     lazy_continuation::check(
                         cx,
                         doc,
                         range.end..next_range.start,
-                        Span::new(span.hi(), next_span.lo(), span.ctxt(), span.parent()),
+                        &fragments,
                         &containers[..],
                     );
                 }
 
-                if let Some(span) = fragments.span(cx, range.clone())
+
+                if event == HardBreak
+                    && !doc[range.clone()].trim().starts_with('\\')
+                    && let Some(span) = fragments.span(cx, range.clone())
                     && !span.from_expansion()
-                    && let Some(snippet) = snippet_opt(cx, span)
-                    && !snippet.trim().starts_with('\\')
-                    && event == HardBreak {
+                    {
                     collected_breaks.push(span);
                 }
             },
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
index 35737f3..f99989e 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
@@ -83,6 +83,13 @@ pub(super) fn check<'tcx>(
                 )[..],
             );
         }
+
+        // If the return type requires adjustments, we need to add a `.map` after the iterator
+        let inner_ret_adjust = cx.typeck_results().expr_adjustments(inner_ret);
+        if !inner_ret_adjust.is_empty() {
+            snippet.push_str(".map(|v| v as _)");
+        }
+
         // Extends to `last_stmt` to include semicolon in case of `return None;`
         let lint_span = span.to(last_stmt.span).to(last_ret.span);
         span_lint_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
index 9b6f97b..81f14b7 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
@@ -3,7 +3,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::visitors::is_local_used;
-use clippy_utils::{higher, path_to_local_id, peel_blocks_with_stmt};
+use clippy_utils::{higher, is_refutable, path_to_local_id, peel_blocks_with_stmt};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Expr, Pat, PatKind};
@@ -28,7 +28,7 @@ pub(super) fn check<'tcx>(
         && let PatKind::Binding(_, pat_hir_id, _, _) = pat.kind
         && path_to_local_id(let_expr, pat_hir_id)
         // Ensure the `if let` statement is for the `Some` variant of `Option` or the `Ok` variant of `Result`
-        && let PatKind::TupleStruct(ref qpath, _, _) = let_pat.kind
+        && let PatKind::TupleStruct(ref qpath, [inner_pat], _) = let_pat.kind
         && let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, let_pat.hir_id)
         && let Some(variant_id) = cx.tcx.opt_parent(ctor_id)
         && let some_ctor = cx.tcx.lang_items().option_some_variant() == Some(variant_id)
@@ -37,6 +37,7 @@ pub(super) fn check<'tcx>(
         // Ensure expr in `if let` is not used afterwards
         && !is_local_used(cx, if_then, pat_hir_id)
         && msrv.meets(cx, msrvs::ITER_FLATTEN)
+        && !is_refutable(cx, inner_pat)
     {
         let if_let_type = if some_ctor { "Some" } else { "Ok" };
         // Prepare the error message
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs
index bd04827..845edb9 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs
@@ -1,68 +1,65 @@
 use super::WHILE_LET_LOOP;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::higher;
-use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::source::{snippet, snippet_indent, snippet_opt};
 use clippy_utils::ty::needs_ordered_drop;
 use clippy_utils::visitors::any_temporaries_need_ordered_drop;
+use clippy_utils::{higher, peel_blocks};
+use rustc_ast::BindingMode;
 use rustc_errors::Applicability;
-use rustc_hir::{Block, Expr, ExprKind, LetStmt, MatchSource, Pat, StmtKind};
+use rustc_hir::{Block, Expr, ExprKind, LetStmt, MatchSource, Pat, PatKind, Path, QPath, StmtKind, Ty};
 use rustc_lint::LateContext;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'tcx Block<'_>) {
-    let (init, has_trailing_exprs) = match (loop_block.stmts, loop_block.expr) {
-        ([stmt, stmts @ ..], expr) => {
-            if let StmtKind::Let(&LetStmt {
+    let (init, let_info) = match (loop_block.stmts, loop_block.expr) {
+        ([stmt, ..], _) => match stmt.kind {
+            StmtKind::Let(LetStmt {
                 init: Some(e),
                 els: None,
+                pat,
+                ty,
                 ..
-            })
-            | StmtKind::Semi(e)
-            | StmtKind::Expr(e) = stmt.kind
-            {
-                (e, !stmts.is_empty() || expr.is_some())
-            } else {
-                return;
-            }
+            }) => (*e, Some((*pat, *ty))),
+            StmtKind::Semi(e) | StmtKind::Expr(e) => (e, None),
+            _ => return,
         },
-        ([], Some(e)) => (e, false),
+        ([], Some(e)) => (e, None),
         _ => return,
     };
+    let has_trailing_exprs = loop_block.stmts.len() + usize::from(loop_block.expr.is_some()) > 1;
 
     if let Some(if_let) = higher::IfLet::hir(cx, init)
         && let Some(else_expr) = if_let.if_else
         && is_simple_break_expr(else_expr)
     {
-        could_be_while_let(cx, expr, if_let.let_pat, if_let.let_expr, has_trailing_exprs);
+        could_be_while_let(
+            cx,
+            expr,
+            if_let.let_pat,
+            if_let.let_expr,
+            has_trailing_exprs,
+            let_info,
+            if_let.if_then,
+        );
     } else if let ExprKind::Match(scrutinee, [arm1, arm2], MatchSource::Normal) = init.kind
         && arm1.guard.is_none()
         && arm2.guard.is_none()
         && is_simple_break_expr(arm2.body)
     {
-        could_be_while_let(cx, expr, arm1.pat, scrutinee, has_trailing_exprs);
+        could_be_while_let(cx, expr, arm1.pat, scrutinee, has_trailing_exprs, let_info, arm1.body);
     }
 }
 
-/// Returns `true` if expr contains a single break expression without a label or eub-expression.
+/// Returns `true` if expr contains a single break expression without a label or sub-expression,
+/// possibly embedded in blocks.
 fn is_simple_break_expr(e: &Expr<'_>) -> bool {
-    matches!(peel_blocks(e).kind, ExprKind::Break(dest, None) if dest.label.is_none())
-}
-
-/// Removes any blocks containing only a single expression.
-fn peel_blocks<'tcx>(e: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
     if let ExprKind::Block(b, _) = e.kind {
         match (b.stmts, b.expr) {
-            ([s], None) => {
-                if let StmtKind::Expr(e) | StmtKind::Semi(e) = s.kind {
-                    peel_blocks(e)
-                } else {
-                    e
-                }
-            },
-            ([], Some(e)) => peel_blocks(e),
-            _ => e,
+            ([s], None) => matches!(s.kind, StmtKind::Expr(e) | StmtKind::Semi(e) if is_simple_break_expr(e)),
+            ([], Some(e)) => is_simple_break_expr(e),
+            _ => false,
         }
     } else {
-        e
+        matches!(e.kind, ExprKind::Break(dest, None) if dest.label.is_none())
     }
 }
 
@@ -72,6 +69,8 @@ fn could_be_while_let<'tcx>(
     let_pat: &'tcx Pat<'_>,
     let_expr: &'tcx Expr<'_>,
     has_trailing_exprs: bool,
+    let_info: Option<(&Pat<'_>, Option<&Ty<'_>>)>,
+    inner_expr: &Expr<'_>,
 ) {
     if has_trailing_exprs
         && (needs_ordered_drop(cx, cx.typeck_results().expr_ty(let_expr))
@@ -86,7 +85,24 @@ fn could_be_while_let<'tcx>(
     // 1) it was ugly with big bodies;
     // 2) it was not indented properly;
     // 3) it wasn’t very smart (see #675).
-    let mut applicability = Applicability::HasPlaceholders;
+    let inner_content = if let Some((pat, ty)) = let_info
+        // Prevent trivial reassignments such as `let x = x;` or `let _ = …;`, but
+        // keep them if the type has been explicitly specified.
+        && (!is_trivial_assignment(pat, peel_blocks(inner_expr)) || ty.is_some())
+        && let Some(pat_str) = snippet_opt(cx, pat.span)
+        && let Some(init_str) = snippet_opt(cx, peel_blocks(inner_expr).span)
+    {
+        let ty_str = ty
+            .map(|ty| format!(": {}", snippet(cx, ty.span, "_")))
+            .unwrap_or_default();
+        format!(
+            "\n{indent}    let {pat_str}{ty_str} = {init_str};\n{indent}    ..\n{indent}",
+            indent = snippet_indent(cx, expr.span).unwrap_or_default(),
+        )
+    } else {
+        " .. ".into()
+    };
+
     span_lint_and_sugg(
         cx,
         WHILE_LET_LOOP,
@@ -94,10 +110,21 @@ fn could_be_while_let<'tcx>(
         "this loop could be written as a `while let` loop",
         "try",
         format!(
-            "while let {} = {} {{ .. }}",
-            snippet_with_applicability(cx, let_pat.span, "..", &mut applicability),
-            snippet_with_applicability(cx, let_expr.span, "..", &mut applicability),
+            "while let {} = {} {{{inner_content}}}",
+            snippet(cx, let_pat.span, ".."),
+            snippet(cx, let_expr.span, ".."),
         ),
-        applicability,
+        Applicability::HasPlaceholders,
     );
 }
+
+fn is_trivial_assignment(pat: &Pat<'_>, init: &Expr<'_>) -> bool {
+    match (pat.kind, init.kind) {
+        (PatKind::Wild, _) => true,
+        (
+            PatKind::Binding(BindingMode::NONE, _, pat_ident, None),
+            ExprKind::Path(QPath::Resolved(None, Path { segments: [init], .. })),
+        ) => pat_ident.name == init.ident.name,
+        _ => false,
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs b/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs
index 40aad03..4a61c22 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs
@@ -1,18 +1,22 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::get_parent_expr;
 use clippy_utils::msrvs::{self, Msrv};
-use clippy_utils::source::snippet;
+use clippy_utils::source::{snippet, snippet_opt};
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_errors::Applicability;
+use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
+use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
 use rustc_lint::LateContext;
-use rustc_span::{Span, sym};
+use rustc_middle::ty;
+use rustc_span::{BytePos, Span, sym};
 
 use super::MANUAL_IS_VARIANT_AND;
 
-pub(super) fn check<'tcx>(
+pub(super) fn check(
     cx: &LateContext<'_>,
-    expr: &'tcx rustc_hir::Expr<'_>,
-    map_recv: &'tcx rustc_hir::Expr<'_>,
-    map_arg: &'tcx rustc_hir::Expr<'_>,
+    expr: &Expr<'_>,
+    map_recv: &Expr<'_>,
+    map_arg: &Expr<'_>,
     map_span: Span,
     msrv: Msrv,
 ) {
@@ -57,3 +61,57 @@ pub(super) fn check<'tcx>(
         Applicability::MachineApplicable,
     );
 }
+
+fn emit_lint(cx: &LateContext<'_>, op: BinOpKind, parent: &Expr<'_>, method_span: Span, is_option: bool) {
+    if let Some(before_map_snippet) = snippet_opt(cx, parent.span.with_hi(method_span.lo()))
+        && let Some(after_map_snippet) = snippet_opt(cx, method_span.with_lo(method_span.lo() + BytePos(3)))
+    {
+        span_lint_and_sugg(
+            cx,
+            MANUAL_IS_VARIANT_AND,
+            parent.span,
+            format!(
+                "called `.map() {}= {}()`",
+                if op == BinOpKind::Eq { '=' } else { '!' },
+                if is_option { "Some" } else { "Ok" },
+            ),
+            "use",
+            if is_option && op == BinOpKind::Ne {
+                format!("{before_map_snippet}is_none_or{after_map_snippet}",)
+            } else {
+                format!(
+                    "{}{before_map_snippet}{}{after_map_snippet}",
+                    if op == BinOpKind::Eq { "" } else { "!" },
+                    if is_option { "is_some_and" } else { "is_ok_and" },
+                )
+            },
+            Applicability::MachineApplicable,
+        );
+    }
+}
+
+pub(super) fn check_map(cx: &LateContext<'_>, expr: &Expr<'_>) {
+    if let Some(parent_expr) = get_parent_expr(cx, expr)
+        && let ExprKind::Binary(op, left, right) = parent_expr.kind
+        && matches!(op.node, BinOpKind::Eq | BinOpKind::Ne)
+        && op.span.eq_ctxt(expr.span)
+    {
+        // Check `left` and `right` expression in any order, and for `Option` and `Result`
+        for (expr1, expr2) in [(left, right), (right, left)] {
+            for item in [sym::Option, sym::Result] {
+                if let ExprKind::Call(call, ..) = expr1.kind
+                    && let ExprKind::Path(QPath::Resolved(_, path)) = call.kind
+                    && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), _) = path.res
+                    && let ty = cx.typeck_results().expr_ty(expr1)
+                    && let ty::Adt(adt, args) = ty.kind()
+                    && cx.tcx.is_diagnostic_item(item, adt.did())
+                    && args.type_at(0).is_bool()
+                    && let ExprKind::MethodCall(_, recv, _, span) = expr2.kind
+                    && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), item)
+                {
+                    return emit_lint(cx, op.node, parent_expr, span, item == sym::Option);
+                }
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index d2d59f0..bc15920 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -4439,7 +4439,7 @@
     /// Checks for usage of `iter().any()` on slices when it can be replaced with `contains()` and suggests doing so.
     ///
     /// ### Why is this bad?
-    /// `contains()` is more concise and idiomatic, sometimes more fast.
+    /// `contains()` is more concise and idiomatic, while also being faster in some cases.
     ///
     /// ### Example
     /// ```no_run
@@ -5203,6 +5203,7 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                         unused_enumerate_index::check(cx, expr, recv, m_arg);
                         map_clone::check(cx, expr, recv, m_arg, self.msrv);
                         map_with_unused_argument_over_ranges::check(cx, expr, recv, m_arg, self.msrv, span);
+                        manual_is_variant_and::check_map(cx, expr);
                         match method_call(recv) {
                             Some((map_name @ (sym::iter | sym::into_iter), recv2, _, _, _)) => {
                                 iter_kv_map::check(cx, map_name, expr, recv2, m_arg, self.msrv);
diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
index 38cb4d5..7bdd999 100644
--- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
@@ -11,8 +11,7 @@
 use rustc_errors::Applicability;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::Span;
-use rustc_span::Symbol;
+use rustc_span::{Span, Symbol};
 use {rustc_ast as ast, rustc_hir as hir};
 
 use super::{OR_FUN_CALL, UNWRAP_OR_DEFAULT};
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 768bbeb..fdccf1f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -44,7 +44,7 @@ pub fn check<'tcx>(
                 return;
             }
             // At this point, we know the call is of a `to_owned`-like function. The functions
-            // `check_addr_of_expr` and `check_call_arg` determine whether the call is unnecessary
+            // `check_addr_of_expr` and `check_into_iter_call_arg` determine whether the call is unnecessary
             // based on its context, that is, whether it is a referent in an `AddrOf` expression, an
             // argument in a `into_iter` call, or an argument in the call of some other function.
             if check_addr_of_expr(cx, expr, method_name, method_def_id, receiver) {
diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs
index 2fd1049..2f1ab3d 100644
--- a/src/tools/clippy/clippy_lints/src/mut_reference.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs
@@ -79,25 +79,19 @@ fn check_arguments<'tcx>(
     name: &str,
     fn_kind: &str,
 ) {
-    match type_definition.kind() {
-        ty::FnDef(..) | ty::FnPtr(..) => {
-            let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs();
-            for (argument, parameter) in iter::zip(arguments, parameters) {
-                match parameter.kind() {
-                    ty::Ref(_, _, Mutability::Not) | ty::RawPtr(_, Mutability::Not) => {
-                        if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _) = argument.kind {
-                            span_lint(
-                                cx,
-                                UNNECESSARY_MUT_PASSED,
-                                argument.span,
-                                format!("the {fn_kind} `{name}` doesn't need a mutable reference"),
-                            );
-                        }
-                    },
-                    _ => (),
-                }
+    if let ty::FnDef(..) | ty::FnPtr(..) = type_definition.kind() {
+        let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs();
+        for (argument, parameter) in iter::zip(arguments, parameters) {
+            if let ty::Ref(_, _, Mutability::Not) | ty::RawPtr(_, Mutability::Not) = parameter.kind()
+                && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _) = argument.kind
+            {
+                span_lint(
+                    cx,
+                    UNNECESSARY_MUT_PASSED,
+                    argument.span,
+                    format!("the {fn_kind} `{name}` doesn't need a mutable reference"),
+                );
             }
-        },
-        _ => (),
+        }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/needless_for_each.rs b/src/tools/clippy/clippy_lints/src/needless_for_each.rs
index 7dd96f1..6a7c843 100644
--- a/src/tools/clippy/clippy_lints/src/needless_for_each.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_for_each.rs
@@ -74,7 +74,7 @@ fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
             && let body = cx.tcx.hir_body(body)
             // Skip the lint if the body is not safe, so as not to suggest `for … in … unsafe {}`
             // and suggesting `for … in … { unsafe { } }` is a little ugly.
-            && let ExprKind::Block(Block { rules: BlockCheckMode::DefaultBlock, .. }, ..) = body.value.kind
+            && !matches!(body.value.kind, ExprKind::Block(Block { rules: BlockCheckMode::UnsafeBlock(_), .. }, ..))
         {
             let mut ret_collector = RetCollector::default();
             ret_collector.visit_expr(body.value);
@@ -99,11 +99,21 @@ fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
                 )
             };
 
+            let body_param_sugg = snippet_with_applicability(cx, body.params[0].pat.span, "..", &mut applicability);
+            let for_each_rev_sugg = snippet_with_applicability(cx, for_each_recv.span, "..", &mut applicability);
+            let body_value_sugg = snippet_with_applicability(cx, body.value.span, "..", &mut applicability);
+
             let sugg = format!(
                 "for {} in {} {}",
-                snippet_with_applicability(cx, body.params[0].pat.span, "..", &mut applicability),
-                snippet_with_applicability(cx, for_each_recv.span, "..", &mut applicability),
-                snippet_with_applicability(cx, body.value.span, "..", &mut applicability),
+                body_param_sugg,
+                for_each_rev_sugg,
+                match body.value.kind {
+                    ExprKind::Block(block, _) if is_let_desugar(block) => {
+                        format!("{{ {body_value_sugg} }}")
+                    },
+                    ExprKind::Block(_, _) => body_value_sugg.to_string(),
+                    _ => format!("{{ {body_value_sugg}; }}"),
+                }
             );
 
             span_lint_and_then(cx, NEEDLESS_FOR_EACH, stmt.span, "needless use of `for_each`", |diag| {
@@ -116,6 +126,20 @@ fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
     }
 }
 
+/// Check if the block is a desugared `_ = expr` statement.
+fn is_let_desugar(block: &Block<'_>) -> bool {
+    matches!(
+        block,
+        Block {
+            stmts: [Stmt {
+                kind: StmtKind::Let(_),
+                ..
+            },],
+            ..
+        }
+    )
+}
+
 /// This type plays two roles.
 /// 1. Collect spans of `return` in the closure body.
 /// 2. Detect use of `return` in `Loop` in the closure body.
diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
index 4be4226..9c6141d 100644
--- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
@@ -1,8 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::Msrv;
+use clippy_utils::qualify_min_const_fn::is_stable_const_fn;
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::visitors::for_each_expr_without_closures;
-use clippy_utils::{binop_traits, eq_expr_value, trait_ref_of_method};
+use clippy_utils::{binop_traits, eq_expr_value, is_in_const_context, trait_ref_of_method};
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -19,6 +21,7 @@ pub(super) fn check<'tcx>(
     expr: &'tcx hir::Expr<'_>,
     assignee: &'tcx hir::Expr<'_>,
     e: &'tcx hir::Expr<'_>,
+    msrv: Msrv,
 ) {
     if let hir::ExprKind::Binary(op, l, r) = &e.kind {
         let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| {
@@ -40,6 +43,15 @@ pub(super) fn check<'tcx>(
                         return;
                     }
                 }
+
+                // Skip if the trait is not stable in const contexts
+                if is_in_const_context(cx)
+                    && let Some(binop_id) = cx.tcx.associated_item_def_ids(trait_id).first()
+                    && !is_stable_const_fn(cx, *binop_id, msrv)
+                {
+                    return;
+                }
+
                 span_lint_and_then(
                     cx,
                     ASSIGN_OP_PATTERN,
diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs
index d32c062..2f4e8e9 100644
--- a/src/tools/clippy/clippy_lints/src/operators/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs
@@ -919,7 +919,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
                 modulo_arithmetic::check(cx, e, bin_op, lhs, rhs, false);
             },
             ExprKind::Assign(lhs, rhs, _) => {
-                assign_op_pattern::check(cx, e, lhs, rhs);
+                assign_op_pattern::check(cx, e, lhs, rhs, self.msrv);
                 self_assignment::check(cx, e, lhs, rhs);
             },
             ExprKind::Unary(op, arg) => {
diff --git a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
index 691d7b9..b794616 100644
--- a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
@@ -34,14 +34,10 @@ pub(super) fn check<'tcx>(
 }
 
 fn used_in_comparison_with_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    let Node::Expr(parent_expr) = cx.tcx.parent_hir_node(expr.hir_id) else {
-        return false;
-    };
-    let ExprKind::Binary(op, lhs, rhs) = parent_expr.kind else {
-        return false;
-    };
-
-    if op.node == BinOpKind::Eq || op.node == BinOpKind::Ne {
+    if let Node::Expr(parent_expr) = cx.tcx.parent_hir_node(expr.hir_id)
+        && let ExprKind::Binary(op, lhs, rhs) = parent_expr.kind
+        && let BinOpKind::Eq | BinOpKind::Ne = op.node
+    {
         let ecx = ConstEvalCtxt::new(cx);
         matches!(ecx.eval(lhs), Some(Constant::Int(0))) || matches!(ecx.eval(rhs), Some(Constant::Int(0)))
     } else {
@@ -56,35 +52,28 @@ struct OperandInfo {
 }
 
 fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<OperandInfo> {
-    match ConstEvalCtxt::new(cx).eval(operand) {
-        Some(Constant::Int(v)) => match *cx.typeck_results().expr_ty(expr).kind() {
+    match ConstEvalCtxt::new(cx).eval(operand)? {
+        Constant::Int(v) => match *cx.typeck_results().expr_ty(expr).kind() {
             ty::Int(ity) => {
                 let value = sext(cx.tcx, v, ity);
-                return Some(OperandInfo {
+                Some(OperandInfo {
                     string_representation: Some(value.to_string()),
                     is_negative: value < 0,
                     is_integral: true,
-                });
+                })
             },
-            ty::Uint(_) => {
-                return Some(OperandInfo {
-                    string_representation: None,
-                    is_negative: false,
-                    is_integral: true,
-                });
-            },
-            _ => {},
+            ty::Uint(_) => Some(OperandInfo {
+                string_representation: None,
+                is_negative: false,
+                is_integral: true,
+            }),
+            _ => None,
         },
         // FIXME(f16_f128): add when casting is available on all platforms
-        Some(Constant::F32(f)) => {
-            return Some(floating_point_operand_info(&f));
-        },
-        Some(Constant::F64(f)) => {
-            return Some(floating_point_operand_info(&f));
-        },
-        _ => {},
+        Constant::F32(f) => Some(floating_point_operand_info(&f)),
+        Constant::F64(f) => Some(floating_point_operand_info(&f)),
+        _ => None,
     }
-    None
 }
 
 fn floating_point_operand_info<T: Display + PartialOrd + From<f32>>(f: &T) -> OperandInfo {
diff --git a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
index 8962f36..449d3da 100644
--- a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
+++ b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
@@ -152,7 +152,6 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                 expr.span,
                 "`panic_any` should not be present in production code",
             );
-            return;
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index 5d30b66..dadf49b 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -1,5 +1,3 @@
-use std::{cmp, iter};
-
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
@@ -20,6 +18,7 @@
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{Span, sym};
+use std::iter;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -33,10 +32,8 @@
     /// registers.
     ///
     /// ### Known problems
-    /// This lint is target register size dependent, it is
-    /// limited to 32-bit to try and reduce portability problems between 32 and
-    /// 64-bit, but if you are compiling for 8 or 16-bit targets then the limit
-    /// will be different.
+    /// This lint is target dependent, some cases will lint on 64-bit targets but
+    /// not 32-bit or lower targets.
     ///
     /// The configuration option `trivial_copy_size_limit` can be set to override
     /// this limit for a project.
@@ -112,16 +109,9 @@ pub struct PassByRefOrValue {
 
 impl PassByRefOrValue {
     pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
-        let ref_min_size = conf.trivial_copy_size_limit.unwrap_or_else(|| {
-            let bit_width = u64::from(tcx.sess.target.pointer_width);
-            // Cap the calculated bit width at 32-bits to reduce
-            // portability problems between 32 and 64-bit targets
-            let bit_width = cmp::min(bit_width, 32);
-            #[expect(clippy::integer_division)]
-            let byte_width = bit_width / 8;
-            // Use a limit of 2 times the register byte width
-            byte_width * 2
-        });
+        let ref_min_size = conf
+            .trivial_copy_size_limit
+            .unwrap_or_else(|| u64::from(tcx.sess.target.pointer_width / 8));
 
         Self {
             ref_min_size,
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 6bc5af2..e0c9315 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -435,7 +435,9 @@ fn check_final_expr<'tcx>(
         ExprKind::If(_, then, else_clause_opt) => {
             check_block_return(cx, &then.kind, peeled_drop_expr.span, semi_spans.clone());
             if let Some(else_clause) = else_clause_opt {
-                check_block_return(cx, &else_clause.kind, peeled_drop_expr.span, semi_spans);
+                // The `RetReplacement` won't be used there as `else_clause` will be either a block or
+                // a `if` expression.
+                check_final_expr(cx, else_clause, semi_spans, RetReplacement::Empty, match_ty_opt);
             }
         },
         // a match expr, check all arms
diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
index 67ceac9..39f4130 100644
--- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
@@ -5,7 +5,7 @@
 use rustc_middle::ty;
 use rustc_middle::ty::{ClauseKind, GenericPredicates, ProjectionPredicate, TraitPredicate};
 use rustc_session::declare_lint_pass;
-use rustc_span::{BytePos, Span, sym};
+use rustc_span::{BytePos, Span, Symbol, sym};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -36,21 +36,26 @@
 
 declare_lint_pass!(UnitReturnExpectingOrd => [UNIT_RETURN_EXPECTING_ORD]);
 
-fn get_trait_predicates_for_trait_id<'tcx>(
+// For each
+fn get_trait_predicates_for_trait_ids<'tcx>(
     cx: &LateContext<'tcx>,
     generics: GenericPredicates<'tcx>,
-    trait_id: Option<DefId>,
-) -> Vec<TraitPredicate<'tcx>> {
-    let mut preds = Vec::new();
+    trait_ids: &[Option<DefId>], // At least 2 ids
+) -> [Vec<TraitPredicate<'tcx>>; 3] {
+    debug_assert!(trait_ids.len() >= 2);
+    let mut preds = [Vec::new(), Vec::new(), Vec::new()];
     for (pred, _) in generics.predicates {
-        if let ClauseKind::Trait(poly_trait_pred) = pred.kind().skip_binder()
-            && let trait_pred = cx
+        if let ClauseKind::Trait(poly_trait_pred) = pred.kind().skip_binder() {
+            let trait_pred = cx
                 .tcx
-                .instantiate_bound_regions_with_erased(pred.kind().rebind(poly_trait_pred))
-            && let Some(trait_def_id) = trait_id
-            && trait_def_id == trait_pred.trait_ref.def_id
-        {
-            preds.push(trait_pred);
+                .instantiate_bound_regions_with_erased(pred.kind().rebind(poly_trait_pred));
+            for (i, tid) in trait_ids.iter().enumerate() {
+                if let Some(tid) = tid
+                    && *tid == trait_pred.trait_ref.def_id
+                {
+                    preds[i].push(trait_pred);
+                }
+            }
         }
     }
     preds
@@ -74,15 +79,24 @@ fn get_projection_pred<'tcx>(
     })
 }
 
-fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Vec<(usize, String)> {
+fn get_args_to_check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'tcx>,
+    args_len: usize,
+    fn_mut_trait: DefId,
+    ord_trait: Option<DefId>,
+    partial_ord_trait: Option<DefId>,
+) -> Vec<(usize, Symbol)> {
     let mut args_to_check = Vec::new();
     if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
         let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity();
         let generics = cx.tcx.predicates_of(def_id);
-        let fn_mut_preds = get_trait_predicates_for_trait_id(cx, generics, cx.tcx.lang_items().fn_mut_trait());
-        let ord_preds = get_trait_predicates_for_trait_id(cx, generics, cx.tcx.get_diagnostic_item(sym::Ord));
-        let partial_ord_preds =
-            get_trait_predicates_for_trait_id(cx, generics, cx.tcx.lang_items().partial_ord_trait());
+        let [fn_mut_preds, ord_preds, partial_ord_preds] =
+            get_trait_predicates_for_trait_ids(cx, generics, &[Some(fn_mut_trait), ord_trait, partial_ord_trait]);
+        if fn_mut_preds.is_empty() {
+            return vec![];
+        }
+
         // Trying to call instantiate_bound_regions_with_erased on fn_sig.inputs() gives the following error
         // The trait `rustc::ty::TypeFoldable<'_>` is not implemented for
         // `&[rustc_middle::ty::Ty<'_>]`
@@ -102,12 +116,18 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve
                             .iter()
                             .any(|ord| Some(ord.self_ty()) == return_ty_pred.term.as_type())
                         {
-                            args_to_check.push((i, "Ord".to_string()));
+                            args_to_check.push((i, sym::Ord));
+                            if args_to_check.len() == args_len - 1 {
+                                break;
+                            }
                         } else if partial_ord_preds
                             .iter()
                             .any(|pord| pord.self_ty() == return_ty_pred.term.expect_type())
                         {
-                            args_to_check.push((i, "PartialOrd".to_string()));
+                            args_to_check.push((i, sym::PartialOrd));
+                            if args_to_check.len() == args_len - 1 {
+                                break;
+                            }
                         }
                     }
                 }
@@ -142,38 +162,50 @@ fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Spa
 
 impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if let ExprKind::MethodCall(_, receiver, args, _) = expr.kind {
-            let arg_indices = get_args_to_check(cx, expr);
+        if let ExprKind::MethodCall(_, receiver, args, _) = expr.kind
+            && args.iter().any(|arg| {
+                matches!(
+                    arg.peel_blocks().peel_borrows().peel_drop_temps().kind,
+                    ExprKind::Path(_) | ExprKind::Closure(_)
+                )
+            })
+            && let Some(fn_mut_trait) = cx.tcx.lang_items().fn_mut_trait()
+        {
+            let ord_trait = cx.tcx.get_diagnostic_item(sym::Ord);
+            let partial_ord_trait = cx.tcx.lang_items().partial_ord_trait();
+            if (ord_trait, partial_ord_trait) == (None, None) {
+                return;
+            }
+
             let args = std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>();
+            let arg_indices = get_args_to_check(cx, expr, args.len(), fn_mut_trait, ord_trait, partial_ord_trait);
             for (i, trait_name) in arg_indices {
-                if i < args.len() {
-                    match check_arg(cx, args[i]) {
-                        Some((span, None)) => {
-                            span_lint(
-                                cx,
-                                UNIT_RETURN_EXPECTING_ORD,
-                                span,
-                                format!(
-                                    "this closure returns \
+                match check_arg(cx, args[i]) {
+                    Some((span, None)) => {
+                        span_lint(
+                            cx,
+                            UNIT_RETURN_EXPECTING_ORD,
+                            span,
+                            format!(
+                                "this closure returns \
                                    the unit type which also implements {trait_name}"
-                                ),
-                            );
-                        },
-                        Some((span, Some(last_semi))) => {
-                            span_lint_and_help(
-                                cx,
-                                UNIT_RETURN_EXPECTING_ORD,
-                                span,
-                                format!(
-                                    "this closure returns \
+                            ),
+                        );
+                    },
+                    Some((span, Some(last_semi))) => {
+                        span_lint_and_help(
+                            cx,
+                            UNIT_RETURN_EXPECTING_ORD,
+                            span,
+                            format!(
+                                "this closure returns \
                                    the unit type which also implements {trait_name}"
-                                ),
-                                Some(last_semi),
-                                "probably caused by this trailing semicolon",
-                            );
-                        },
-                        None => {},
-                    }
+                            ),
+                            Some(last_semi),
+                            "probably caused by this trailing semicolon",
+                        );
+                    },
+                    None => {},
                 }
             }
         }
diff --git a/src/tools/clippy/clippy_utils/README.md b/src/tools/clippy/clippy_utils/README.md
index c9083f6..efbacbd 100644
--- a/src/tools/clippy/clippy_utils/README.md
+++ b/src/tools/clippy/clippy_utils/README.md
@@ -8,7 +8,7 @@
 
 <!-- begin autogenerated nightly -->
 ```
-nightly-2025-05-21
+nightly-2025-05-31
 ```
 <!-- end autogenerated nightly -->
 
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 a0503a6..6c186ab 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -437,10 +437,10 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
                 && both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r))
         },
         (Enum(li, lg, le), Enum(ri, rg, re)) => {
-            eq_id(*li, *ri) && eq_generics(lg, rg) && over(&le.variants, &re.variants, eq_variant) 
+            eq_id(*li, *ri) && eq_generics(lg, rg) && over(&le.variants, &re.variants, eq_variant)
         },
         (Struct(li, lg, lv), Struct(ri, rg, rv)) | (Union(li, lg, lv), Union(ri, rg, rv)) => {
-            eq_id(*li, *ri) && eq_generics(lg, rg) && eq_variant_data(lv, rv) 
+            eq_id(*li, *ri) && eq_generics(lg, rg) && eq_variant_data(lv, rv)
         },
         (
             Trait(box ast::Trait {
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 2020f3d..f6ef638 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1565,10 +1565,10 @@ pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_
 /// Returns `true` if a pattern is refutable.
 // TODO: should be implemented using rustc/mir_build/thir machinery
 pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
-    fn is_enum_variant(cx: &LateContext<'_>, qpath: &QPath<'_>, id: HirId) -> bool {
-        matches!(
+    fn is_qpath_refutable(cx: &LateContext<'_>, qpath: &QPath<'_>, id: HirId) -> bool {
+        !matches!(
             cx.qpath_res(qpath, id),
-            Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), _)
+            Res::Def(DefKind::Struct, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Struct, _), _)
         )
     }
 
@@ -1585,16 +1585,18 @@ fn are_refutable<'a, I: IntoIterator<Item = &'a Pat<'a>>>(cx: &LateContext<'_>,
             kind: PatExprKind::Path(qpath),
             hir_id,
             ..
-        }) => is_enum_variant(cx, qpath, *hir_id),
+        }) => is_qpath_refutable(cx, qpath, *hir_id),
         PatKind::Or(pats) => {
             // TODO: should be the honest check, that pats is exhaustive set
             are_refutable(cx, pats)
         },
         PatKind::Tuple(pats, _) => are_refutable(cx, pats),
         PatKind::Struct(ref qpath, fields, _) => {
-            is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| field.pat))
+            is_qpath_refutable(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| field.pat))
         },
-        PatKind::TupleStruct(ref qpath, pats, _) => is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats),
+        PatKind::TupleStruct(ref qpath, pats, _) => {
+            is_qpath_refutable(cx, qpath, pat.hir_id) || are_refutable(cx, pats)
+        },
         PatKind::Slice(head, middle, tail) => {
             match &cx.typeck_results().node_type(pat.hir_id).kind() {
                 rustc_ty::Slice(..) => {
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index bb04520..5b4ec12 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -393,7 +393,8 @@ fn check_terminator<'tcx>(
     }
 }
 
-fn is_stable_const_fn(cx: &LateContext<'_>, def_id: DefId, msrv: Msrv) -> bool {
+/// Checks if the given `def_id` is a stable const fn, in respect to the given MSRV.
+pub fn is_stable_const_fn(cx: &LateContext<'_>, def_id: DefId, msrv: Msrv) -> bool {
     cx.tcx.is_const_fn(def_id)
         && cx
             .tcx
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index f4dfc8f..6974e65 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -940,7 +940,7 @@ fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
                         // note: unable to trigger `Subslice` kind in tests
                         ProjectionKind::Subslice |
                         // Doesn't have surface syntax. Only occurs in patterns.
-                        ProjectionKind::OpaqueCast => (),
+                        ProjectionKind::OpaqueCast |
                         // Only occurs in closure captures.
                         ProjectionKind::UnwrapUnsafeBinder => (),
                         ProjectionKind::Deref => {
diff --git a/src/tools/clippy/lintcheck/src/input.rs b/src/tools/clippy/lintcheck/src/input.rs
index 83eb0a5..408a2e0 100644
--- a/src/tools/clippy/lintcheck/src/input.rs
+++ b/src/tools/clippy/lintcheck/src/input.rs
@@ -8,7 +8,7 @@
 use serde::Deserialize;
 use walkdir::{DirEntry, WalkDir};
 
-use crate::{Crate, LINTCHECK_DOWNLOADS, LINTCHECK_SOURCES};
+use crate::{Crate, lintcheck_sources, target_dir};
 
 const DEFAULT_DOCS_LINK: &str = "https://docs.rs/{krate}/{version}/src/{krate_}/{file}.html#{line}";
 const DEFAULT_GITHUB_LINK: &str = "{url}/blob/{hash}/src/{file}#L{line}";
@@ -201,8 +201,10 @@ fn get(path: &str) -> Result<ureq::Response, ureq::Error> {
         let file_link = &self.file_link;
         match &self.source {
             CrateSource::CratesIo { version } => {
-                let extract_dir = PathBuf::from(LINTCHECK_SOURCES);
-                let krate_download_dir = PathBuf::from(LINTCHECK_DOWNLOADS);
+                let extract_dir = PathBuf::from(lintcheck_sources());
+                // Keep constant downloads path to avoid repeating work and
+                // filling up disk space unnecessarily.
+                let krate_download_dir = PathBuf::from("target/lintcheck/downloads/");
 
                 // url to download the crate from crates.io
                 let url = format!("https://crates.io/api/v1/crates/{name}/{version}/download");
@@ -211,7 +213,7 @@ fn get(path: &str) -> Result<ureq::Response, ureq::Error> {
 
                 let krate_file_path = krate_download_dir.join(format!("{name}-{version}.crate.tar.gz"));
                 // don't download/extract if we already have done so
-                if !krate_file_path.is_file() {
+                if !krate_file_path.is_file() || !extract_dir.join(format!("{name}-{version}")).exists() {
                     // create a file path to download and write the crate data into
                     let mut krate_dest = fs::File::create(&krate_file_path).unwrap();
                     let mut krate_req = get(&url).unwrap().into_reader();
@@ -236,7 +238,7 @@ fn get(path: &str) -> Result<ureq::Response, ureq::Error> {
             },
             CrateSource::Git { url, commit } => {
                 let repo_path = {
-                    let mut repo_path = PathBuf::from(LINTCHECK_SOURCES);
+                    let mut repo_path = PathBuf::from(lintcheck_sources());
                     // add a -git suffix in case we have the same crate from crates.io and a git repo
                     repo_path.push(format!("{name}-git"));
                     repo_path
@@ -286,7 +288,7 @@ fn is_cache_dir(entry: &DirEntry) -> bool {
                 // copy path into the dest_crate_root but skip directories that contain a CACHEDIR.TAG file.
                 // The target/ directory contains a CACHEDIR.TAG file so it is the most commonly skipped directory
                 // as a result of this filter.
-                let dest_crate_root = PathBuf::from(LINTCHECK_SOURCES).join(name);
+                let dest_crate_root = PathBuf::from(lintcheck_sources()).join(name);
                 if dest_crate_root.exists() {
                     println!("Deleting existing directory at `{}`", dest_crate_root.display());
                     fs::remove_dir_all(&dest_crate_root).unwrap();
@@ -326,15 +328,16 @@ fn is_cache_dir(entry: &DirEntry) -> bool {
 ///
 /// This function panics if creating one of the dirs fails.
 fn create_dirs(krate_download_dir: &Path, extract_dir: &Path) {
-    fs::create_dir("target/lintcheck/").unwrap_or_else(|err| {
+    fs::create_dir(format!("{}/lintcheck/", target_dir())).unwrap_or_else(|err| {
         assert_eq!(
             err.kind(),
             ErrorKind::AlreadyExists,
             "cannot create lintcheck target dir"
         );
     });
-    fs::create_dir(krate_download_dir).unwrap_or_else(|err| {
-        assert_eq!(err.kind(), ErrorKind::AlreadyExists, "cannot create crate download dir");
+    fs::create_dir_all(krate_download_dir).unwrap_or_else(|err| {
+        // We are allowed to reuse download dirs
+        assert_ne!(err.kind(), ErrorKind::AlreadyExists);
     });
     fs::create_dir(extract_dir).unwrap_or_else(|err| {
         assert_eq!(
diff --git a/src/tools/clippy/lintcheck/src/main.rs b/src/tools/clippy/lintcheck/src/main.rs
index d4bf6cd..8418383 100644
--- a/src/tools/clippy/lintcheck/src/main.rs
+++ b/src/tools/clippy/lintcheck/src/main.rs
@@ -43,8 +43,14 @@
 use output::{ClippyCheckOutput, ClippyWarning, RustcIce};
 use rayon::prelude::*;
 
-const LINTCHECK_DOWNLOADS: &str = "target/lintcheck/downloads";
-const LINTCHECK_SOURCES: &str = "target/lintcheck/sources";
+#[must_use]
+pub fn target_dir() -> String {
+    env::var("CARGO_TARGET_DIR").unwrap_or("target".to_owned())
+}
+
+fn lintcheck_sources() -> String {
+    format!("{}/lintcheck/sources", target_dir())
+}
 
 /// Represents the actual source code of a crate that we ran "cargo clippy" on
 #[derive(Debug)]
@@ -307,7 +313,8 @@ fn main() {
 fn lintcheck(config: LintcheckConfig) {
     let clippy_ver = build_clippy(config.perf);
     let clippy_driver_path = fs::canonicalize(format!(
-        "target/{}/clippy-driver{EXE_SUFFIX}",
+        "{}/{}/clippy-driver{EXE_SUFFIX}",
+        target_dir(),
         if config.perf { "release" } else { "debug" }
     ))
     .unwrap();
@@ -315,7 +322,8 @@ fn lintcheck(config: LintcheckConfig) {
     // assert that clippy is found
     assert!(
         clippy_driver_path.is_file(),
-        "target/{}/clippy-driver binary not found! {}",
+        "{}/{}/clippy-driver binary not found! {}",
+        target_dir(),
         if config.perf { "release" } else { "debug" },
         clippy_driver_path.display()
     );
@@ -386,7 +394,7 @@ fn lintcheck(config: LintcheckConfig) {
         .unwrap();
 
     let server = config.recursive.then(|| {
-        let _: io::Result<()> = fs::remove_dir_all("target/lintcheck/shared_target_dir/recursive");
+        let _: io::Result<()> = fs::remove_dir_all(format!("{}/lintcheck/shared_target_dir/recursive", target_dir()));
 
         LintcheckServer::spawn(recursive_options)
     });
@@ -488,7 +496,7 @@ fn clippy_project_root() -> &'static Path {
 #[must_use]
 fn shared_target_dir(qualifier: &str) -> PathBuf {
     clippy_project_root()
-        .join("target/lintcheck/shared_target_dir")
+        .join(format!("{}/lintcheck/shared_target_dir", target_dir()))
         .join(qualifier)
 }
 
diff --git a/src/tools/clippy/lintcheck/src/output.rs b/src/tools/clippy/lintcheck/src/output.rs
index dcc1ec3..d7fe091 100644
--- a/src/tools/clippy/lintcheck/src/output.rs
+++ b/src/tools/clippy/lintcheck/src/output.rs
@@ -162,9 +162,9 @@ pub fn summarize_and_print_changes(
 fn gather_stats(warnings: &[ClippyWarning]) -> (String, HashMap<&String, usize>) {
     // count lint type occurrences
     let mut counter: HashMap<&String, usize> = HashMap::new();
-    warnings
-        .iter()
-        .for_each(|wrn| *counter.entry(&wrn.name).or_insert(0) += 1);
+    for wrn in warnings {
+        *counter.entry(&wrn.name).or_insert(0) += 1;
+    }
 
     // collect into a tupled list for sorting
     let mut stats: Vec<(&&String, &usize)> = counter.iter().collect();
diff --git a/src/tools/clippy/rust-toolchain.toml b/src/tools/clippy/rust-toolchain.toml
index 0b9ebe5..b6817d9 100644
--- a/src/tools/clippy/rust-toolchain.toml
+++ b/src/tools/clippy/rust-toolchain.toml
@@ -1,6 +1,6 @@
 [toolchain]
 # begin autogenerated nightly
-channel = "nightly-2025-05-21"
+channel = "nightly-2025-05-31"
 # end autogenerated nightly
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
 profile = "minimal"
diff --git a/src/tools/clippy/rustfmt.toml b/src/tools/clippy/rustfmt.toml
index 0dc6adc..0ed58a2 100644
--- a/src/tools/clippy/rustfmt.toml
+++ b/src/tools/clippy/rustfmt.toml
@@ -6,4 +6,8 @@
 error_on_line_overflow = true
 imports_granularity = "Module"
 style_edition = "2024"
-ignore = ["tests/ui/crashes/ice-10912.rs"]
+ignore = [
+    "tests/ui/crashes/ice-9405.rs",
+    "tests/ui/crashes/ice-10912.rs",
+    "tests/ui/non_expressive_names_error_recovery.rs",
+]
diff --git a/src/tools/clippy/tests/headers.rs b/src/tools/clippy/tests/headers.rs
deleted file mode 100644
index d1f986e..0000000
--- a/src/tools/clippy/tests/headers.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-use regex::Regex;
-use std::fs;
-use walkdir::WalkDir;
-
-#[test]
-fn old_test_headers() {
-    let old_headers = Regex::new(
-        r"^//( ?\[\w+\])? ?((check|build|run|ignore|aux|only|needs|rustc|unset|no|normalize|run|compile)-|edition|incremental|revisions).*",
-    )
-    .unwrap();
-    let mut failed = false;
-
-    for entry in WalkDir::new("tests") {
-        let entry = entry.unwrap();
-        let is_hidden_file = entry
-            .file_name()
-            .to_str()
-            .expect("non-UTF-8 file name")
-            .starts_with('.');
-        if is_hidden_file || !entry.file_type().is_file() {
-            continue;
-        }
-
-        let file = fs::read_to_string(entry.path()).unwrap_or_else(|err| panic!("{}: {err}", entry.path().display()));
-
-        if let Some(header) = old_headers.find(&file) {
-            println!("Found header `{}` in {}", header.as_str(), entry.path().display());
-
-            failed = true;
-        }
-    }
-
-    assert!(!failed, "use `//@foo` style test headers instead");
-}
diff --git a/src/tools/clippy/tests/ui/assign_ops.fixed b/src/tools/clippy/tests/ui/assign_ops.fixed
index 429c20f..3bc6885 100644
--- a/src/tools/clippy/tests/ui/assign_ops.fixed
+++ b/src/tools/clippy/tests/ui/assign_ops.fixed
@@ -1,5 +1,6 @@
 #![allow(clippy::useless_vec)]
 #![warn(clippy::assign_op_pattern)]
+#![feature(const_trait_impl, const_ops)]
 
 use core::num::Wrapping;
 use std::ops::{Mul, MulAssign};
@@ -73,3 +74,33 @@
         *self = *self * rhs
     }
 }
+
+mod issue14871 {
+
+    use std::ops::{Add, AddAssign};
+
+    pub trait Number: Copy + Add<Self, Output = Self> + AddAssign {
+        const ZERO: Self;
+        const ONE: Self;
+    }
+
+    #[const_trait]
+    pub trait NumberConstants {
+        fn constant(value: usize) -> Self;
+    }
+
+    impl<T> const NumberConstants for T
+    where
+        T: Number + ~const core::ops::Add,
+    {
+        fn constant(value: usize) -> Self {
+            let mut res = Self::ZERO;
+            let mut count = 0;
+            while count < value {
+                res = res + Self::ONE;
+                count += 1;
+            }
+            res
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/assign_ops.rs b/src/tools/clippy/tests/ui/assign_ops.rs
index 480ff07..f1f8f9d 100644
--- a/src/tools/clippy/tests/ui/assign_ops.rs
+++ b/src/tools/clippy/tests/ui/assign_ops.rs
@@ -1,5 +1,6 @@
 #![allow(clippy::useless_vec)]
 #![warn(clippy::assign_op_pattern)]
+#![feature(const_trait_impl, const_ops)]
 
 use core::num::Wrapping;
 use std::ops::{Mul, MulAssign};
@@ -73,3 +74,33 @@ fn mul_assign(&mut self, rhs: i64) {
         *self = *self * rhs
     }
 }
+
+mod issue14871 {
+
+    use std::ops::{Add, AddAssign};
+
+    pub trait Number: Copy + Add<Self, Output = Self> + AddAssign {
+        const ZERO: Self;
+        const ONE: Self;
+    }
+
+    #[const_trait]
+    pub trait NumberConstants {
+        fn constant(value: usize) -> Self;
+    }
+
+    impl<T> const NumberConstants for T
+    where
+        T: Number + ~const core::ops::Add,
+    {
+        fn constant(value: usize) -> Self {
+            let mut res = Self::ZERO;
+            let mut count = 0;
+            while count < value {
+                res = res + Self::ONE;
+                count += 1;
+            }
+            res
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/assign_ops.stderr b/src/tools/clippy/tests/ui/assign_ops.stderr
index 881a333..c5e698b 100644
--- a/src/tools/clippy/tests/ui/assign_ops.stderr
+++ b/src/tools/clippy/tests/ui/assign_ops.stderr
@@ -1,5 +1,5 @@
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:9:5
+  --> tests/ui/assign_ops.rs:10:5
    |
 LL |     a = a + 1;
    |     ^^^^^^^^^ help: replace it with: `a += 1`
@@ -8,67 +8,67 @@
    = help: to override `-D warnings` add `#[allow(clippy::assign_op_pattern)]`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:11:5
+  --> tests/ui/assign_ops.rs:12:5
    |
 LL |     a = 1 + a;
    |     ^^^^^^^^^ help: replace it with: `a += 1`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:13:5
+  --> tests/ui/assign_ops.rs:14:5
    |
 LL |     a = a - 1;
    |     ^^^^^^^^^ help: replace it with: `a -= 1`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:15:5
+  --> tests/ui/assign_ops.rs:16:5
    |
 LL |     a = a * 99;
    |     ^^^^^^^^^^ help: replace it with: `a *= 99`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:17:5
+  --> tests/ui/assign_ops.rs:18:5
    |
 LL |     a = 42 * a;
    |     ^^^^^^^^^^ help: replace it with: `a *= 42`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:19:5
+  --> tests/ui/assign_ops.rs:20:5
    |
 LL |     a = a / 2;
    |     ^^^^^^^^^ help: replace it with: `a /= 2`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:21:5
+  --> tests/ui/assign_ops.rs:22:5
    |
 LL |     a = a % 5;
    |     ^^^^^^^^^ help: replace it with: `a %= 5`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:23:5
+  --> tests/ui/assign_ops.rs:24:5
    |
 LL |     a = a & 1;
    |     ^^^^^^^^^ help: replace it with: `a &= 1`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:30:5
+  --> tests/ui/assign_ops.rs:31:5
    |
 LL |     s = s + "bla";
    |     ^^^^^^^^^^^^^ help: replace it with: `s += "bla"`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:35:5
+  --> tests/ui/assign_ops.rs:36:5
    |
 LL |     a = a + Wrapping(1u32);
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a += Wrapping(1u32)`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:38:5
+  --> tests/ui/assign_ops.rs:39:5
    |
 LL |     v[0] = v[0] + v[1];
    |     ^^^^^^^^^^^^^^^^^^ help: replace it with: `v[0] += v[1]`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:51:5
+  --> tests/ui/assign_ops.rs:52:5
    |
 LL |     buf = buf + cows.clone();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `buf += cows.clone()`
diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed
index 3b9dee8..5993c2f 100644
--- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed
+++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed
@@ -123,3 +123,19 @@
         //~^ dbg_macro
     }
 }
+
+mod issue14914 {
+    use std::future::Future;
+
+    fn takes_async_fn<F, Fut>(_f: F)
+    where
+        F: FnOnce(i32) -> Fut,
+        Fut: Future<Output = i32>,
+    {
+    }
+
+    fn should_not_panic() {
+        takes_async_fn(async |val| val);
+        //~^ dbg_macro
+    }
+}
diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs
index 1dbbc6f..58d7e10 100644
--- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs
+++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs
@@ -123,3 +123,19 @@ fn dbg_in_print(s: &str) {
         //~^ dbg_macro
     }
 }
+
+mod issue14914 {
+    use std::future::Future;
+
+    fn takes_async_fn<F, Fut>(_f: F)
+    where
+        F: FnOnce(i32) -> Fut,
+        Fut: Future<Output = i32>,
+    {
+    }
+
+    fn should_not_panic() {
+        takes_async_fn(async |val| dbg!(val));
+        //~^ dbg_macro
+    }
+}
diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr
index f141202..5a65b38 100644
--- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr
+++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr
@@ -230,5 +230,17 @@
 LL +         print!("{}", s);
    |
 
-error: aborting due to 19 previous errors
+error: the `dbg!` macro is intended as a debugging tool
+  --> tests/ui/dbg_macro/dbg_macro.rs:138:36
+   |
+LL |         takes_async_fn(async |val| dbg!(val));
+   |                                    ^^^^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL -         takes_async_fn(async |val| dbg!(val));
+LL +         takes_async_fn(async |val| val);
+   |
+
+error: aborting due to 20 previous errors
 
diff --git a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.fixed b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.fixed
index fb0f40b..e013658 100644
--- a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.fixed
+++ b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.fixed
@@ -1,11 +1,37 @@
-// This test checks that words starting with capital letters and ending with "ified" don't
-// trigger the lint.
-
 #![deny(clippy::doc_markdown)]
+#![allow(clippy::doc_lazy_continuation)]
 
+mod issue13097 {
+    // This test checks that words starting with capital letters and ending with "ified" don't
+    // trigger the lint.
+    pub enum OutputFormat {
+        /// `HumaNified`
+        //~^ ERROR: item in documentation is missing backticks
+        Plain,
+        // Should not warn!
+        /// JSONified console output
+        Json,
+    }
+}
+
+#[rustfmt::skip]
 pub enum OutputFormat {
-    /// `HumaNified`
-    //~^ ERROR: item in documentation is missing backticks
+    /**
+     * `HumaNified`
+     //~^ ERROR: item in documentation is missing backticks
+     * Before \u{08888} `HumaNified` \{u08888} After
+     //~^ ERROR: item in documentation is missing backticks
+     * meow meow \[`meow_meow`\] meow meow?
+     //~^ ERROR: item in documentation is missing backticks
+     * \u{08888} `meow_meow` \[meow meow] meow?
+     //~^ ERROR: item in documentation is missing backticks
+     * Above
+     * \u{08888}
+     * \[hi\](<https://example.com>) `HumaNified` \[example](<https://example.com>)
+     //~^ ERROR: item in documentation is missing backticks
+     * \u{08888}
+     * Below
+     */
     Plain,
     // Should not warn!
     /// JSONified console output
diff --git a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.rs b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.rs
index 8c1e1a3..2e89fe6 100644
--- a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.rs
+++ b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.rs
@@ -1,11 +1,37 @@
-// This test checks that words starting with capital letters and ending with "ified" don't
-// trigger the lint.
-
 #![deny(clippy::doc_markdown)]
+#![allow(clippy::doc_lazy_continuation)]
 
+mod issue13097 {
+    // This test checks that words starting with capital letters and ending with "ified" don't
+    // trigger the lint.
+    pub enum OutputFormat {
+        /// HumaNified
+        //~^ ERROR: item in documentation is missing backticks
+        Plain,
+        // Should not warn!
+        /// JSONified console output
+        Json,
+    }
+}
+
+#[rustfmt::skip]
 pub enum OutputFormat {
-    /// HumaNified
-    //~^ ERROR: item in documentation is missing backticks
+    /**
+     * HumaNified
+     //~^ ERROR: item in documentation is missing backticks
+     * Before \u{08888} HumaNified \{u08888} After
+     //~^ ERROR: item in documentation is missing backticks
+     * meow meow \[meow_meow\] meow meow?
+     //~^ ERROR: item in documentation is missing backticks
+     * \u{08888} meow_meow \[meow meow] meow?
+     //~^ ERROR: item in documentation is missing backticks
+     * Above
+     * \u{08888}
+     * \[hi\](<https://example.com>) HumaNified \[example](<https://example.com>)
+     //~^ ERROR: item in documentation is missing backticks
+     * \u{08888}
+     * Below
+     */
     Plain,
     // Should not warn!
     /// JSONified console output
diff --git a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.stderr b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.stderr
index 65b8f2e..cea7883 100644
--- a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.stderr
+++ b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.stderr
@@ -1,19 +1,79 @@
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc_markdown-issue_13097.rs:7:9
+  --> tests/ui/doc/doc_markdown-issue_13097.rs:8:13
    |
-LL |     /// HumaNified
-   |         ^^^^^^^^^^
+LL |         /// HumaNified
+   |             ^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> tests/ui/doc/doc_markdown-issue_13097.rs:4:9
+  --> tests/ui/doc/doc_markdown-issue_13097.rs:1:9
    |
 LL | #![deny(clippy::doc_markdown)]
    |         ^^^^^^^^^^^^^^^^^^^^
 help: try
    |
-LL -     /// HumaNified
-LL +     /// `HumaNified`
+LL -         /// HumaNified
+LL +         /// `HumaNified`
    |
 
-error: aborting due to 1 previous error
+error: item in documentation is missing backticks
+  --> tests/ui/doc/doc_markdown-issue_13097.rs:20:8
+   |
+LL |      * HumaNified
+   |        ^^^^^^^^^^
+   |
+help: try
+   |
+LL -      * HumaNified
+LL +      * `HumaNified`
+   |
+
+error: item in documentation is missing backticks
+  --> tests/ui/doc/doc_markdown-issue_13097.rs:22:25
+   |
+LL |      * Before \u{08888} HumaNified \{u08888} After
+   |                         ^^^^^^^^^^
+   |
+help: try
+   |
+LL -      * Before \u{08888} HumaNified \{u08888} After
+LL +      * Before \u{08888} `HumaNified` \{u08888} After
+   |
+
+error: item in documentation is missing backticks
+  --> tests/ui/doc/doc_markdown-issue_13097.rs:24:20
+   |
+LL |      * meow meow \[meow_meow\] meow meow?
+   |                    ^^^^^^^^^
+   |
+help: try
+   |
+LL -      * meow meow \[meow_meow\] meow meow?
+LL +      * meow meow \[`meow_meow`\] meow meow?
+   |
+
+error: item in documentation is missing backticks
+  --> tests/ui/doc/doc_markdown-issue_13097.rs:26:18
+   |
+LL |      * \u{08888} meow_meow \[meow meow] meow?
+   |                  ^^^^^^^^^
+   |
+help: try
+   |
+LL -      * \u{08888} meow_meow \[meow meow] meow?
+LL +      * \u{08888} `meow_meow` \[meow meow] meow?
+   |
+
+error: item in documentation is missing backticks
+  --> tests/ui/doc/doc_markdown-issue_13097.rs:30:38
+   |
+LL |      * \[hi\](<https://example.com>) HumaNified \[example](<https://example.com>)
+   |                                      ^^^^^^^^^^
+   |
+help: try
+   |
+LL -      * \[hi\](<https://example.com>) HumaNified \[example](<https://example.com>)
+LL +      * \[hi\](<https://example.com>) `HumaNified` \[example](<https://example.com>)
+   |
+
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.fixed b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
index 619329a..52c4d1b 100644
--- a/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
+++ b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
@@ -81,12 +81,10 @@
     let b: String = concat(just_return(a));
     //~^ explicit_deref_methods
 
-    let b: &str = &**a;
-    //~^ explicit_deref_methods
+    let b: &str = a.deref().deref();
 
     let opt_a = Some(a.clone());
-    let b = &*opt_a.unwrap();
-    //~^ explicit_deref_methods
+    let b = opt_a.unwrap().deref();
 
     Aaa::deref(&Aaa);
     Aaa::deref_mut(&mut Aaa);
diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.rs b/src/tools/clippy/tests/ui/explicit_deref_methods.rs
index 9f2d513..706d6cb 100644
--- a/src/tools/clippy/tests/ui/explicit_deref_methods.rs
+++ b/src/tools/clippy/tests/ui/explicit_deref_methods.rs
@@ -82,11 +82,9 @@ fn main() {
     //~^ explicit_deref_methods
 
     let b: &str = a.deref().deref();
-    //~^ explicit_deref_methods
 
     let opt_a = Some(a.clone());
     let b = opt_a.unwrap().deref();
-    //~^ explicit_deref_methods
 
     Aaa::deref(&Aaa);
     Aaa::deref_mut(&mut Aaa);
diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.stderr b/src/tools/clippy/tests/ui/explicit_deref_methods.stderr
index a81e2f6..5036884 100644
--- a/src/tools/clippy/tests/ui/explicit_deref_methods.stderr
+++ b/src/tools/clippy/tests/ui/explicit_deref_methods.stderr
@@ -56,40 +56,28 @@
    |                            ^^^^^^^^^^^^^^^^^^^^^^ help: try: `just_return(a)`
 
 error: explicit `deref` method call
-  --> tests/ui/explicit_deref_methods.rs:84:19
-   |
-LL |     let b: &str = a.deref().deref();
-   |                   ^^^^^^^^^^^^^^^^^ help: try: `&**a`
-
-error: explicit `deref` method call
-  --> tests/ui/explicit_deref_methods.rs:88:13
-   |
-LL |     let b = opt_a.unwrap().deref();
-   |             ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*opt_a.unwrap()`
-
-error: explicit `deref` method call
-  --> tests/ui/explicit_deref_methods.rs:123:31
+  --> tests/ui/explicit_deref_methods.rs:121:31
    |
 LL |     let b: &str = expr_deref!(a.deref());
    |                               ^^^^^^^^^ help: try: `&*a`
 
 error: explicit `deref` method call
-  --> tests/ui/explicit_deref_methods.rs:141:14
+  --> tests/ui/explicit_deref_methods.rs:139:14
    |
 LL |     let _ = &Deref::deref(&"foo");
    |              ^^^^^^^^^^^^^^^^^^^^ help: try: `*&"foo"`
 
 error: explicit `deref_mut` method call
-  --> tests/ui/explicit_deref_methods.rs:143:14
+  --> tests/ui/explicit_deref_methods.rs:141:14
    |
 LL |     let _ = &DerefMut::deref_mut(&mut x);
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut **&mut x`
 
 error: explicit `deref_mut` method call
-  --> tests/ui/explicit_deref_methods.rs:144:14
+  --> tests/ui/explicit_deref_methods.rs:142:14
    |
 LL |     let _ = &DerefMut::deref_mut((&mut &mut x).deref_mut());
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut ***(&mut &mut x)`
 
-error: aborting due to 15 previous errors
+error: aborting due to 13 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_find_fixable.fixed b/src/tools/clippy/tests/ui/manual_find_fixable.fixed
index 5e6849a..01b3eba 100644
--- a/src/tools/clippy/tests/ui/manual_find_fixable.fixed
+++ b/src/tools/clippy/tests/ui/manual_find_fixable.fixed
@@ -179,3 +179,13 @@
 }
 
 fn main() {}
+
+mod issue14826 {
+    fn adjust_fixable(needle: &str) -> Option<&'static str> {
+        ["foo", "bar"].iter().find(|&candidate| candidate.eq_ignore_ascii_case(needle)).map(|v| v as _)
+    }
+
+    fn adjust_unfixable(needle: &str) -> Option<*const str> {
+        ["foo", "bar"].iter().find(|&&candidate| candidate.eq_ignore_ascii_case(needle)).copied().map(|v| v as _)
+    }
+}
diff --git a/src/tools/clippy/tests/ui/manual_find_fixable.rs b/src/tools/clippy/tests/ui/manual_find_fixable.rs
index 08a7dd2..ce62a4b 100644
--- a/src/tools/clippy/tests/ui/manual_find_fixable.rs
+++ b/src/tools/clippy/tests/ui/manual_find_fixable.rs
@@ -251,3 +251,25 @@ fn two_bindings(v: Vec<(u8, u8)>) -> Option<u8> {
 }
 
 fn main() {}
+
+mod issue14826 {
+    fn adjust_fixable(needle: &str) -> Option<&'static str> {
+        for candidate in &["foo", "bar"] {
+            //~^ manual_find
+            if candidate.eq_ignore_ascii_case(needle) {
+                return Some(candidate);
+            }
+        }
+        None
+    }
+
+    fn adjust_unfixable(needle: &str) -> Option<*const str> {
+        for &candidate in &["foo", "bar"] {
+            //~^ manual_find
+            if candidate.eq_ignore_ascii_case(needle) {
+                return Some(candidate);
+            }
+        }
+        None
+    }
+}
diff --git a/src/tools/clippy/tests/ui/manual_find_fixable.stderr b/src/tools/clippy/tests/ui/manual_find_fixable.stderr
index afa453c..020635d 100644
--- a/src/tools/clippy/tests/ui/manual_find_fixable.stderr
+++ b/src/tools/clippy/tests/ui/manual_find_fixable.stderr
@@ -139,5 +139,27 @@
 LL | |         None
    | |____________^ help: replace with an iterator: `arr.into_iter().find(|&x| x < 1)`
 
-error: aborting due to 12 previous errors
+error: manual implementation of `Iterator::find`
+  --> tests/ui/manual_find_fixable.rs:257:9
+   |
+LL | /         for candidate in &["foo", "bar"] {
+LL | |
+LL | |             if candidate.eq_ignore_ascii_case(needle) {
+LL | |                 return Some(candidate);
+...  |
+LL | |         None
+   | |____________^ help: replace with an iterator: `["foo", "bar"].iter().find(|&candidate| candidate.eq_ignore_ascii_case(needle)).map(|v| v as _)`
+
+error: manual implementation of `Iterator::find`
+  --> tests/ui/manual_find_fixable.rs:267:9
+   |
+LL | /         for &candidate in &["foo", "bar"] {
+LL | |
+LL | |             if candidate.eq_ignore_ascii_case(needle) {
+LL | |                 return Some(candidate);
+...  |
+LL | |         None
+   | |____________^ help: replace with an iterator: `["foo", "bar"].iter().find(|&&candidate| candidate.eq_ignore_ascii_case(needle)).copied().map(|v| v as _)`
+
+error: aborting due to 14 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_flatten.rs b/src/tools/clippy/tests/ui/manual_flatten.rs
index 97f35c3..f1a0053 100644
--- a/src/tools/clippy/tests/ui/manual_flatten.rs
+++ b/src/tools/clippy/tests/ui/manual_flatten.rs
@@ -123,6 +123,13 @@ struct Test {
         println!("{}", n);
     }
 
+    // Using nested `Some` pattern should not trigger the lint
+    for n in vec![Some((1, Some(2)))] {
+        if let Some((_, Some(n))) = n {
+            println!("{}", n);
+        }
+    }
+
     run_unformatted_tests();
 }
 
diff --git a/src/tools/clippy/tests/ui/manual_flatten.stderr b/src/tools/clippy/tests/ui/manual_flatten.stderr
index 5ab2565..9a846fe 100644
--- a/src/tools/clippy/tests/ui/manual_flatten.stderr
+++ b/src/tools/clippy/tests/ui/manual_flatten.stderr
@@ -178,7 +178,7 @@
    | |_________^
 
 error: unnecessary `if let` since only the `Some` variant of the iterator element is used
-  --> tests/ui/manual_flatten.rs:132:5
+  --> tests/ui/manual_flatten.rs:139:5
    |
 LL | /     for n in vec![
 LL | |
@@ -189,7 +189,7 @@
    | |_____^
    |
 help: remove the `if let` statement in the for loop and then...
-  --> tests/ui/manual_flatten.rs:139:9
+  --> tests/ui/manual_flatten.rs:146:9
    |
 LL | /         if let Some(n) = n {
 LL | |             println!("{:?}", n);
diff --git a/src/tools/clippy/tests/ui/manual_is_variant_and.fixed b/src/tools/clippy/tests/ui/manual_is_variant_and.fixed
index c9c1845..18a7218 100644
--- a/src/tools/clippy/tests/ui/manual_is_variant_and.fixed
+++ b/src/tools/clippy/tests/ui/manual_is_variant_and.fixed
@@ -4,6 +4,44 @@
 #[macro_use]
 extern crate option_helpers;
 
+struct Foo<T>(T);
+
+impl<T> Foo<T> {
+    fn map<F: FnMut(T) -> bool>(self, mut f: F) -> Option<bool> {
+        Some(f(self.0))
+    }
+}
+
+fn foo() -> Option<bool> {
+    Some(true)
+}
+
+macro_rules! some_true {
+    () => {
+        Some(true)
+    };
+}
+macro_rules! some_false {
+    () => {
+        Some(false)
+    };
+}
+
+macro_rules! mac {
+    (some $e:expr) => {
+        Some($e)
+    };
+    (some_map $e:expr) => {
+        Some($e).map(|x| x % 2 == 0)
+    };
+    (map $e:expr) => {
+        $e.map(|x| x % 2 == 0)
+    };
+    (eq $a:expr, $b:expr) => {
+        $a == $b
+    };
+}
+
 #[rustfmt::skip]
 fn option_methods() {
     let opt = Some(1);
@@ -21,6 +59,15 @@
     let _ = opt
         .is_some_and(|x| x > 1);
 
+    let _ = Some(2).is_some_and(|x| x % 2 == 0);
+    //~^ manual_is_variant_and
+    let _ = Some(2).is_none_or(|x| x % 2 == 0);
+    //~^ manual_is_variant_and
+    let _ = Some(2).is_some_and(|x| x % 2 == 0);
+    //~^ manual_is_variant_and
+    let _ = Some(2).is_none_or(|x| x % 2 == 0);
+    //~^ manual_is_variant_and
+
     // won't fix because the return type of the closure is not `bool`
     let _ = opt.map(|x| x + 1).unwrap_or_default();
 
@@ -28,6 +75,14 @@
     let _ = opt2.is_some_and(char::is_alphanumeric); // should lint
     //~^ manual_is_variant_and
     let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint
+
+    // Should not lint.
+    let _ = Foo::<u32>(0).map(|x| x % 2 == 0) == Some(true);
+    let _ = Some(2).map(|x| x % 2 == 0) != foo();
+    let _ = mac!(eq Some(2).map(|x| x % 2 == 0), Some(true));
+    let _ = mac!(some 2).map(|x| x % 2 == 0) == Some(true);
+    let _ = mac!(some_map 2) == Some(true);
+    let _ = mac!(map Some(2)) == Some(true);
 }
 
 #[rustfmt::skip]
@@ -41,6 +96,13 @@
     });
     let _ = res.is_ok_and(|x| x > 1);
 
+    let _ = Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0);
+    //~^ manual_is_variant_and
+    let _ = !Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0);
+    //~^ manual_is_variant_and
+    let _ = !Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0);
+    //~^ manual_is_variant_and
+
     // won't fix because the return type of the closure is not `bool`
     let _ = res.map(|x| x + 1).unwrap_or_default();
 
diff --git a/src/tools/clippy/tests/ui/manual_is_variant_and.rs b/src/tools/clippy/tests/ui/manual_is_variant_and.rs
index 52c7b56..a92f7c0 100644
--- a/src/tools/clippy/tests/ui/manual_is_variant_and.rs
+++ b/src/tools/clippy/tests/ui/manual_is_variant_and.rs
@@ -4,6 +4,44 @@
 #[macro_use]
 extern crate option_helpers;
 
+struct Foo<T>(T);
+
+impl<T> Foo<T> {
+    fn map<F: FnMut(T) -> bool>(self, mut f: F) -> Option<bool> {
+        Some(f(self.0))
+    }
+}
+
+fn foo() -> Option<bool> {
+    Some(true)
+}
+
+macro_rules! some_true {
+    () => {
+        Some(true)
+    };
+}
+macro_rules! some_false {
+    () => {
+        Some(false)
+    };
+}
+
+macro_rules! mac {
+    (some $e:expr) => {
+        Some($e)
+    };
+    (some_map $e:expr) => {
+        Some($e).map(|x| x % 2 == 0)
+    };
+    (map $e:expr) => {
+        $e.map(|x| x % 2 == 0)
+    };
+    (eq $a:expr, $b:expr) => {
+        $a == $b
+    };
+}
+
 #[rustfmt::skip]
 fn option_methods() {
     let opt = Some(1);
@@ -27,6 +65,15 @@ fn option_methods() {
         //~^ manual_is_variant_and
         .unwrap_or_default();
 
+    let _ = Some(2).map(|x| x % 2 == 0) == Some(true);
+    //~^ manual_is_variant_and
+    let _ = Some(2).map(|x| x % 2 == 0) != Some(true);
+    //~^ manual_is_variant_and
+    let _ = Some(2).map(|x| x % 2 == 0) == some_true!();
+    //~^ manual_is_variant_and
+    let _ = Some(2).map(|x| x % 2 == 0) != some_false!();
+    //~^ manual_is_variant_and
+
     // won't fix because the return type of the closure is not `bool`
     let _ = opt.map(|x| x + 1).unwrap_or_default();
 
@@ -34,6 +81,14 @@ fn option_methods() {
     let _ = opt2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
     //~^ manual_is_variant_and
     let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint
+
+    // Should not lint.
+    let _ = Foo::<u32>(0).map(|x| x % 2 == 0) == Some(true);
+    let _ = Some(2).map(|x| x % 2 == 0) != foo();
+    let _ = mac!(eq Some(2).map(|x| x % 2 == 0), Some(true));
+    let _ = mac!(some 2).map(|x| x % 2 == 0) == Some(true);
+    let _ = mac!(some_map 2) == Some(true);
+    let _ = mac!(map Some(2)) == Some(true);
 }
 
 #[rustfmt::skip]
@@ -50,6 +105,13 @@ fn result_methods() {
     //~^ manual_is_variant_and
         .unwrap_or_default();
 
+    let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) == Ok(true);
+    //~^ manual_is_variant_and
+    let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) != Ok(true);
+    //~^ manual_is_variant_and
+    let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) != Ok(true);
+    //~^ manual_is_variant_and
+
     // won't fix because the return type of the closure is not `bool`
     let _ = res.map(|x| x + 1).unwrap_or_default();
 
diff --git a/src/tools/clippy/tests/ui/manual_is_variant_and.stderr b/src/tools/clippy/tests/ui/manual_is_variant_and.stderr
index a4fa500..1fb437a 100644
--- a/src/tools/clippy/tests/ui/manual_is_variant_and.stderr
+++ b/src/tools/clippy/tests/ui/manual_is_variant_and.stderr
@@ -1,5 +1,5 @@
 error: called `map(<f>).unwrap_or_default()` on an `Option` value
-  --> tests/ui/manual_is_variant_and.rs:13:17
+  --> tests/ui/manual_is_variant_and.rs:51:17
    |
 LL |       let _ = opt.map(|x| x > 1)
    |  _________________^
@@ -11,7 +11,7 @@
    = help: to override `-D warnings` add `#[allow(clippy::manual_is_variant_and)]`
 
 error: called `map(<f>).unwrap_or_default()` on an `Option` value
-  --> tests/ui/manual_is_variant_and.rs:18:17
+  --> tests/ui/manual_is_variant_and.rs:56:17
    |
 LL |       let _ = opt.map(|x| {
    |  _________________^
@@ -30,13 +30,13 @@
    |
 
 error: called `map(<f>).unwrap_or_default()` on an `Option` value
-  --> tests/ui/manual_is_variant_and.rs:23:17
+  --> tests/ui/manual_is_variant_and.rs:61:17
    |
 LL |     let _ = opt.map(|x| x > 1).unwrap_or_default();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_some_and(|x| x > 1)`
 
 error: called `map(<f>).unwrap_or_default()` on an `Option` value
-  --> tests/ui/manual_is_variant_and.rs:26:10
+  --> tests/ui/manual_is_variant_and.rs:64:10
    |
 LL |           .map(|x| x > 1)
    |  __________^
@@ -44,14 +44,38 @@
 LL | |         .unwrap_or_default();
    | |____________________________^ help: use: `is_some_and(|x| x > 1)`
 
+error: called `.map() == Some()`
+  --> tests/ui/manual_is_variant_and.rs:68:13
+   |
+LL |     let _ = Some(2).map(|x| x % 2 == 0) == Some(true);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Some(2).is_some_and(|x| x % 2 == 0)`
+
+error: called `.map() != Some()`
+  --> tests/ui/manual_is_variant_and.rs:70:13
+   |
+LL |     let _ = Some(2).map(|x| x % 2 == 0) != Some(true);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Some(2).is_none_or(|x| x % 2 == 0)`
+
+error: called `.map() == Some()`
+  --> tests/ui/manual_is_variant_and.rs:72:13
+   |
+LL |     let _ = Some(2).map(|x| x % 2 == 0) == some_true!();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Some(2).is_some_and(|x| x % 2 == 0)`
+
+error: called `.map() != Some()`
+  --> tests/ui/manual_is_variant_and.rs:74:13
+   |
+LL |     let _ = Some(2).map(|x| x % 2 == 0) != some_false!();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Some(2).is_none_or(|x| x % 2 == 0)`
+
 error: called `map(<f>).unwrap_or_default()` on an `Option` value
-  --> tests/ui/manual_is_variant_and.rs:34:18
+  --> tests/ui/manual_is_variant_and.rs:81:18
    |
 LL |     let _ = opt2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_some_and(char::is_alphanumeric)`
 
 error: called `map(<f>).unwrap_or_default()` on a `Result` value
-  --> tests/ui/manual_is_variant_and.rs:44:17
+  --> tests/ui/manual_is_variant_and.rs:99:17
    |
 LL |       let _ = res.map(|x| {
    |  _________________^
@@ -70,7 +94,7 @@
    |
 
 error: called `map(<f>).unwrap_or_default()` on a `Result` value
-  --> tests/ui/manual_is_variant_and.rs:49:17
+  --> tests/ui/manual_is_variant_and.rs:104:17
    |
 LL |       let _ = res.map(|x| x > 1)
    |  _________________^
@@ -78,11 +102,29 @@
 LL | |         .unwrap_or_default();
    | |____________________________^ help: use: `is_ok_and(|x| x > 1)`
 
+error: called `.map() == Ok()`
+  --> tests/ui/manual_is_variant_and.rs:108:13
+   |
+LL |     let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) == Ok(true);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0)`
+
+error: called `.map() != Ok()`
+  --> tests/ui/manual_is_variant_and.rs:110:13
+   |
+LL |     let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) != Ok(true);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0)`
+
+error: called `.map() != Ok()`
+  --> tests/ui/manual_is_variant_and.rs:112:13
+   |
+LL |     let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) != Ok(true);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0)`
+
 error: called `map(<f>).unwrap_or_default()` on a `Result` value
-  --> tests/ui/manual_is_variant_and.rs:57:18
+  --> tests/ui/manual_is_variant_and.rs:119:18
    |
 LL |     let _ = res2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_ok_and(char::is_alphanumeric)`
 
-error: aborting due to 8 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed
index d7d3444..54cad2e 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.fixed
+++ b/src/tools/clippy/tests/ui/needless_borrow.fixed
@@ -107,9 +107,6 @@
     let x = (1, 2);
     let _ = x.0;
     //~^ needless_borrow
-    let x = &x as *const (i32, i32);
-    let _ = unsafe { (*x).0 };
-    //~^ needless_borrow
 
     // Issue #8367
     trait Foo {
@@ -289,3 +286,15 @@
 
     // compiler
 }
+
+fn issue_14743<T>(slice: &[T]) {
+    let _ = slice.len();
+    //~^ needless_borrow
+
+    let slice = slice as *const [T];
+    let _ = unsafe { (&*slice).len() };
+
+    // Check that rustc would actually warn if Clippy had suggested removing the reference
+    #[expect(dangerous_implicit_autorefs)]
+    let _ = unsafe { (*slice).len() };
+}
diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs
index 1f05b90..b698c6b 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.rs
+++ b/src/tools/clippy/tests/ui/needless_borrow.rs
@@ -107,9 +107,6 @@ fn ref_mut_i32(_: &mut i32) {}
     let x = (1, 2);
     let _ = (&x).0;
     //~^ needless_borrow
-    let x = &x as *const (i32, i32);
-    let _ = unsafe { (&*x).0 };
-    //~^ needless_borrow
 
     // Issue #8367
     trait Foo {
@@ -289,3 +286,15 @@ fn issue_12268() {
 
     // compiler
 }
+
+fn issue_14743<T>(slice: &[T]) {
+    let _ = (&slice).len();
+    //~^ needless_borrow
+
+    let slice = slice as *const [T];
+    let _ = unsafe { (&*slice).len() };
+
+    // Check that rustc would actually warn if Clippy had suggested removing the reference
+    #[expect(dangerous_implicit_autorefs)]
+    let _ = unsafe { (*slice).len() };
+}
diff --git a/src/tools/clippy/tests/ui/needless_borrow.stderr b/src/tools/clippy/tests/ui/needless_borrow.stderr
index b036b1e..172d36b 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.stderr
+++ b/src/tools/clippy/tests/ui/needless_borrow.stderr
@@ -103,71 +103,71 @@
 LL |     let _ = (&x).0;
    |             ^^^^ help: change this to: `x`
 
-error: this expression borrows a value the compiler would automatically borrow
-  --> tests/ui/needless_borrow.rs:111:22
-   |
-LL |     let _ = unsafe { (&*x).0 };
-   |                      ^^^^^ help: change this to: `(*x)`
-
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> tests/ui/needless_borrow.rs:122:5
+  --> tests/ui/needless_borrow.rs:119:5
    |
 LL |     (&&()).foo();
    |     ^^^^^^ help: change this to: `(&())`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> tests/ui/needless_borrow.rs:132:5
+  --> tests/ui/needless_borrow.rs:129:5
    |
 LL |     (&&5).foo();
    |     ^^^^^ help: change this to: `(&5)`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> tests/ui/needless_borrow.rs:159:23
+  --> tests/ui/needless_borrow.rs:156:23
    |
 LL |     let x: (&str,) = (&"",);
    |                       ^^^ help: change this to: `""`
 
 error: this expression borrows a value the compiler would automatically borrow
-  --> tests/ui/needless_borrow.rs:202:13
+  --> tests/ui/needless_borrow.rs:199:13
    |
 LL |             (&self.f)()
    |             ^^^^^^^^^ help: change this to: `(self.f)`
 
 error: this expression borrows a value the compiler would automatically borrow
-  --> tests/ui/needless_borrow.rs:212:13
+  --> tests/ui/needless_borrow.rs:209:13
    |
 LL |             (&mut self.f)()
    |             ^^^^^^^^^^^^^ help: change this to: `(self.f)`
 
 error: this expression borrows a value the compiler would automatically borrow
-  --> tests/ui/needless_borrow.rs:250:22
+  --> tests/ui/needless_borrow.rs:247:22
    |
 LL |         let _ = &mut (&mut { x.u }).x;
    |                      ^^^^^^^^^^^^^^ help: change this to: `{ x.u }`
 
 error: this expression borrows a value the compiler would automatically borrow
-  --> tests/ui/needless_borrow.rs:258:22
+  --> tests/ui/needless_borrow.rs:255:22
    |
 LL |         let _ = &mut (&mut { x.u }).x;
    |                      ^^^^^^^^^^^^^^ help: change this to: `{ x.u }`
 
 error: this expression borrows a value the compiler would automatically borrow
-  --> tests/ui/needless_borrow.rs:263:22
+  --> tests/ui/needless_borrow.rs:260:22
    |
 LL |         let _ = &mut (&mut x.u).x;
    |                      ^^^^^^^^^^ help: change this to: `x.u`
 
 error: this expression borrows a value the compiler would automatically borrow
-  --> tests/ui/needless_borrow.rs:265:22
+  --> tests/ui/needless_borrow.rs:262:22
    |
 LL |         let _ = &mut (&mut { x.u }).x;
    |                      ^^^^^^^^^^^^^^ help: change this to: `{ x.u }`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> tests/ui/needless_borrow.rs:287:23
+  --> tests/ui/needless_borrow.rs:284:23
    |
 LL |     option.unwrap_or((&x.0,));
    |                       ^^^^ help: change this to: `x.0`
 
+error: this expression creates a reference which is immediately dereferenced by the compiler
+  --> tests/ui/needless_borrow.rs:291:13
+   |
+LL |     let _ = (&slice).len();
+   |             ^^^^^^^^ help: change this to: `slice`
+
 error: aborting due to 28 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed b/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed
index fa23e18..a73aff5 100644
--- a/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed
+++ b/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed
@@ -128,3 +128,18 @@
 }
 
 fn main() {}
+
+mod issue14734 {
+    fn let_desugar(rows: &[u8]) {
+        let mut v = vec![];
+        for x in rows.iter() { _ = v.push(x) }
+        //~^ needless_for_each
+    }
+
+    fn do_something(_: &u8, _: u8) {}
+
+    fn single_expr(rows: &[u8]) {
+        for x in rows.iter() { do_something(x, 1u8); }
+        //~^ needless_for_each
+    }
+}
diff --git a/src/tools/clippy/tests/ui/needless_for_each_fixable.rs b/src/tools/clippy/tests/ui/needless_for_each_fixable.rs
index 2c7e68a..d92f055 100644
--- a/src/tools/clippy/tests/ui/needless_for_each_fixable.rs
+++ b/src/tools/clippy/tests/ui/needless_for_each_fixable.rs
@@ -128,3 +128,18 @@ fn iter(&self) -> impl Iterator<Item = &i32> {
 }
 
 fn main() {}
+
+mod issue14734 {
+    fn let_desugar(rows: &[u8]) {
+        let mut v = vec![];
+        rows.iter().for_each(|x| _ = v.push(x));
+        //~^ needless_for_each
+    }
+
+    fn do_something(_: &u8, _: u8) {}
+
+    fn single_expr(rows: &[u8]) {
+        rows.iter().for_each(|x| do_something(x, 1u8));
+        //~^ needless_for_each
+    }
+}
diff --git a/src/tools/clippy/tests/ui/needless_for_each_fixable.stderr b/src/tools/clippy/tests/ui/needless_for_each_fixable.stderr
index 013a3fa..f801445 100644
--- a/src/tools/clippy/tests/ui/needless_for_each_fixable.stderr
+++ b/src/tools/clippy/tests/ui/needless_for_each_fixable.stderr
@@ -136,5 +136,17 @@
 LL +     }
    |
 
-error: aborting due to 8 previous errors
+error: needless use of `for_each`
+  --> tests/ui/needless_for_each_fixable.rs:135:9
+   |
+LL |         rows.iter().for_each(|x| _ = v.push(x));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in rows.iter() { _ = v.push(x) }`
+
+error: needless use of `for_each`
+  --> tests/ui/needless_for_each_fixable.rs:142:9
+   |
+LL |         rows.iter().for_each(|x| do_something(x, 1u8));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in rows.iter() { do_something(x, 1u8); }`
+
+error: aborting due to 10 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed
index 17d3862..d571b97 100644
--- a/src/tools/clippy/tests/ui/needless_return.fixed
+++ b/src/tools/clippy/tests/ui/needless_return.fixed
@@ -452,3 +452,68 @@
     (unsafe { todo() } as *const i32)
     //~^ needless_return
 }
+
+mod else_ifs {
+    fn test1(a: i32) -> u32 {
+        if a == 0 {
+            1
+        //~^ needless_return
+        } else if a < 10 {
+            2
+        //~^ needless_return
+        } else {
+            3
+            //~^ needless_return
+        }
+    }
+
+    fn test2(a: i32) -> u32 {
+        if a == 0 {
+            1
+        //~^ needless_return
+        } else if a < 10 {
+            2
+        } else {
+            3
+            //~^ needless_return
+        }
+    }
+
+    fn test3(a: i32) -> u32 {
+        if a == 0 {
+            1
+        //~^ needless_return
+        } else if a < 10 {
+            2
+        } else {
+            3
+            //~^ needless_return
+        }
+    }
+
+    #[allow(clippy::match_single_binding, clippy::redundant_pattern)]
+    fn test4(a: i32) -> u32 {
+        if a == 0 {
+            1
+            //~^ needless_return
+        } else if if if a > 0x1_1 {
+            return 2;
+        } else {
+            return 5;
+        } {
+            true
+        } else {
+            true
+        } {
+            0xDEADC0DE
+        } else if match a {
+            b @ _ => {
+                return 1;
+            },
+        } {
+            0xDEADBEEF
+        } else {
+            1
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs
index 1c6e7ff..2e4348e 100644
--- a/src/tools/clippy/tests/ui/needless_return.rs
+++ b/src/tools/clippy/tests/ui/needless_return.rs
@@ -461,3 +461,68 @@ pub unsafe fn issue_12157() -> *const i32 {
     return unsafe { todo() } as *const i32;
     //~^ needless_return
 }
+
+mod else_ifs {
+    fn test1(a: i32) -> u32 {
+        if a == 0 {
+            return 1;
+        //~^ needless_return
+        } else if a < 10 {
+            return 2;
+        //~^ needless_return
+        } else {
+            return 3;
+            //~^ needless_return
+        }
+    }
+
+    fn test2(a: i32) -> u32 {
+        if a == 0 {
+            return 1;
+        //~^ needless_return
+        } else if a < 10 {
+            2
+        } else {
+            return 3;
+            //~^ needless_return
+        }
+    }
+
+    fn test3(a: i32) -> u32 {
+        if a == 0 {
+            return 1;
+        //~^ needless_return
+        } else if a < 10 {
+            2
+        } else {
+            return 3;
+            //~^ needless_return
+        }
+    }
+
+    #[allow(clippy::match_single_binding, clippy::redundant_pattern)]
+    fn test4(a: i32) -> u32 {
+        if a == 0 {
+            return 1;
+            //~^ needless_return
+        } else if if if a > 0x1_1 {
+            return 2;
+        } else {
+            return 5;
+        } {
+            true
+        } else {
+            true
+        } {
+            0xDEADC0DE
+        } else if match a {
+            b @ _ => {
+                return 1;
+            },
+        } {
+            0xDEADBEEF
+        } else {
+            1
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr
index 26dd265..206bd8e 100644
--- a/src/tools/clippy/tests/ui/needless_return.stderr
+++ b/src/tools/clippy/tests/ui/needless_return.stderr
@@ -685,5 +685,101 @@
 LL +     (unsafe { todo() } as *const i32)
    |
 
-error: aborting due to 55 previous errors
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:468:13
+   |
+LL |             return 1;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 1;
+LL +             1
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:471:13
+   |
+LL |             return 2;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 2;
+LL +             2
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:474:13
+   |
+LL |             return 3;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 3;
+LL +             3
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:481:13
+   |
+LL |             return 1;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 1;
+LL +             1
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:486:13
+   |
+LL |             return 3;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 3;
+LL +             3
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:493:13
+   |
+LL |             return 1;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 1;
+LL +             1
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:498:13
+   |
+LL |             return 3;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 3;
+LL +             3
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:506:13
+   |
+LL |             return 1;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 1;
+LL +             1
+   |
+
+error: aborting due to 63 previous errors
 
diff --git a/src/tools/clippy/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.fixed b/src/tools/clippy/tests/ui/non_expressive_names_error_recovery.fixed
similarity index 100%
rename from src/tools/clippy/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.fixed
rename to src/tools/clippy/tests/ui/non_expressive_names_error_recovery.fixed
diff --git a/src/tools/clippy/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.rs b/src/tools/clippy/tests/ui/non_expressive_names_error_recovery.rs
similarity index 100%
rename from src/tools/clippy/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.rs
rename to src/tools/clippy/tests/ui/non_expressive_names_error_recovery.rs
diff --git a/src/tools/clippy/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.stderr b/src/tools/clippy/tests/ui/non_expressive_names_error_recovery.stderr
similarity index 81%
rename from src/tools/clippy/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.stderr
rename to src/tools/clippy/tests/ui/non_expressive_names_error_recovery.stderr
index 4998b9b..28d9a42 100644
--- a/src/tools/clippy/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.stderr
+++ b/src/tools/clippy/tests/ui/non_expressive_names_error_recovery.stderr
@@ -1,5 +1,5 @@
 error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `)`
-  --> tests/ui/skip_rustfmt/non_expressive_names_error_recovery.rs:6:19
+  --> tests/ui/non_expressive_names_error_recovery.rs:6:19
    |
 LL | fn aa(a: Aa<String) {
    |                   ^ expected one of 7 possible tokens
diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed
index 507bc2b..60dc1c1 100644
--- a/src/tools/clippy/tests/ui/question_mark.fixed
+++ b/src/tools/clippy/tests/ui/question_mark.fixed
@@ -443,3 +443,13 @@
     //~^^^ question_mark
     Some(format!("{a}"))
 }
+
+fn const_in_pattern(x: Option<(i32, i32)>) -> Option<()> {
+    const N: i32 = 0;
+
+    let Some((x, N)) = x else {
+        return None;
+    };
+
+    None
+}
diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs
index 64b51b8..99d0122 100644
--- a/src/tools/clippy/tests/ui/question_mark.rs
+++ b/src/tools/clippy/tests/ui/question_mark.rs
@@ -539,3 +539,13 @@ fn issue_14615(a: MutexGuard<Option<u32>>) -> Option<String> {
     //~^^^ question_mark
     Some(format!("{a}"))
 }
+
+fn const_in_pattern(x: Option<(i32, i32)>) -> Option<()> {
+    const N: i32 = 0;
+
+    let Some((x, N)) = x else {
+        return None;
+    };
+
+    None
+}
diff --git a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.fixed b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.fixed
new file mode 100644
index 0000000..af7d821
--- /dev/null
+++ b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.fixed
@@ -0,0 +1,179 @@
+//@normalize-stderr-test: "\(\d+ byte\)" -> "(N byte)"
+//@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: N byte)"
+#![deny(clippy::trivially_copy_pass_by_ref)]
+#![allow(
+    clippy::disallowed_names,
+    clippy::extra_unused_lifetimes,
+    clippy::needless_lifetimes,
+    clippy::needless_pass_by_ref_mut,
+    clippy::redundant_field_names,
+    clippy::uninlined_format_args
+)]
+
+#[derive(Copy, Clone)]
+struct Foo(u32);
+
+#[derive(Copy, Clone)]
+struct Bar([u8; 24]);
+
+#[derive(Copy, Clone)]
+pub struct Color {
+    pub r: u8,
+    pub g: u8,
+    pub b: u8,
+    pub a: u8,
+}
+
+struct FooRef<'a> {
+    foo: &'a Foo,
+}
+
+type Baz = u32;
+
+fn good(a: &mut u32, b: u32, c: &Bar) {}
+
+fn good_return_implicit_lt_ref(foo: &Foo) -> &u32 {
+    &foo.0
+}
+
+#[allow(clippy::needless_lifetimes)]
+fn good_return_explicit_lt_ref<'a>(foo: &'a Foo) -> &'a u32 {
+    &foo.0
+}
+
+fn good_return_implicit_lt_struct(foo: &Foo) -> FooRef {
+    FooRef { foo }
+}
+
+#[allow(clippy::needless_lifetimes)]
+fn good_return_explicit_lt_struct<'a>(foo: &'a Foo) -> FooRef<'a> {
+    FooRef { foo }
+}
+
+fn bad(x: u32, y: Foo, z: Baz) {}
+//~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+//~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+//~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+
+impl Foo {
+    fn good(self, a: &mut u32, b: u32, c: &Bar) {}
+
+    fn good2(&mut self) {}
+
+    fn bad(self, x: u32, y: Foo, z: Baz) {}
+    //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+    //~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+    //~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+    //~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+
+    fn bad2(x: u32, y: Foo, z: Baz) {}
+    //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+    //~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+    //~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+
+    fn bad_issue7518(self, other: Self) {}
+    //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if
+}
+
+impl AsRef<u32> for Foo {
+    fn as_ref(&self) -> &u32 {
+        &self.0
+    }
+}
+
+impl Bar {
+    fn good(&self, a: &mut u32, b: u32, c: &Bar) {}
+
+    fn bad2(x: u32, y: Foo, z: Baz) {}
+    //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if
+    //~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if
+    //~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if
+}
+
+trait MyTrait {
+    fn trait_method(&self, foo: Foo);
+    //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if
+}
+
+pub trait MyTrait2 {
+    fn trait_method2(&self, color: &Color);
+}
+
+trait MyTrait3 {
+    #[expect(clippy::trivially_copy_pass_by_ref)]
+    fn trait_method(&self, foo: &Foo);
+}
+
+// Trait impls should not warn
+impl MyTrait3 for Foo {
+    fn trait_method(&self, foo: &Foo) {
+        unimplemented!()
+    }
+}
+
+mod issue3992 {
+    pub trait A {
+        #[allow(clippy::trivially_copy_pass_by_ref)]
+        fn a(b: &u16) {}
+    }
+
+    #[allow(clippy::trivially_copy_pass_by_ref)]
+    pub fn c(d: &u16) {}
+}
+
+mod issue5876 {
+    // Don't lint here as it is always inlined
+    #[inline(always)]
+    fn foo_always(x: &i32) {
+        println!("{}", x);
+    }
+
+    #[inline(never)]
+    fn foo_never(x: i32) {
+        //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+        println!("{}", x);
+    }
+
+    #[inline]
+    fn foo(x: i32) {
+        //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+        println!("{}", x);
+    }
+}
+
+fn ref_to_opt_ref_implicit(x: &u32) -> Option<&u32> {
+    Some(x)
+}
+
+fn ref_to_opt_ref_explicit<'a>(x: &'a u32) -> Option<&'a u32> {
+    Some(x)
+}
+
+fn with_constraint<'a, 'b: 'a>(x: &'b u32, y: &'a u32) -> &'a u32 {
+    if true { x } else { y }
+}
+
+async fn async_implicit(x: &u32) -> &u32 {
+    x
+}
+
+async fn async_explicit<'a>(x: &'a u32) -> &'a u32 {
+    x
+}
+
+fn unrelated_lifetimes<'a, 'b>(_x: u32, y: &'b u32) -> &'b u32 {
+    //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+    y
+}
+
+fn return_ptr(x: &u32) -> *const u32 {
+    x
+}
+
+fn return_field_ptr(x: &(u32, u32)) -> *const u32 {
+    &x.0
+}
+
+fn return_field_ptr_addr_of(x: &(u32, u32)) -> *const u32 {
+    core::ptr::addr_of!(x.0)
+}
diff --git a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs
index 37bc6f8..00e11a1 100644
--- a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs
+++ b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs
@@ -1,14 +1,15 @@
 //@normalize-stderr-test: "\(\d+ byte\)" -> "(N byte)"
-//@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: 8 byte)"
+//@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: N byte)"
 #![deny(clippy::trivially_copy_pass_by_ref)]
 #![allow(
     clippy::disallowed_names,
+    clippy::extra_unused_lifetimes,
     clippy::needless_lifetimes,
+    clippy::needless_pass_by_ref_mut,
     clippy::redundant_field_names,
-    clippy::uninlined_format_args,
-    clippy::needless_pass_by_ref_mut
+    clippy::uninlined_format_args
 )]
-//@no-rustfix
+
 #[derive(Copy, Clone)]
 struct Foo(u32);
 
@@ -90,21 +91,26 @@ fn bad2(x: &u32, y: &Foo, z: &Baz) {}
 }
 
 trait MyTrait {
-    fn trait_method(&self, _foo: &Foo);
+    fn trait_method(&self, foo: &Foo);
     //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if
 }
 
 pub trait MyTrait2 {
-    fn trait_method2(&self, _color: &Color);
+    fn trait_method2(&self, color: &Color);
 }
 
-impl MyTrait for Foo {
-    fn trait_method(&self, _foo: &Foo) {
+trait MyTrait3 {
+    #[expect(clippy::trivially_copy_pass_by_ref)]
+    fn trait_method(&self, foo: &Foo);
+}
+
+// Trait impls should not warn
+impl MyTrait3 for Foo {
+    fn trait_method(&self, foo: &Foo) {
         unimplemented!()
     }
 }
 
-#[allow(unused_variables)]
 mod issue3992 {
     pub trait A {
         #[allow(clippy::trivially_copy_pass_by_ref)]
@@ -135,57 +141,39 @@ fn foo(x: &i32) {
     }
 }
 
-fn _ref_to_opt_ref_implicit(x: &u32) -> Option<&u32> {
+fn ref_to_opt_ref_implicit(x: &u32) -> Option<&u32> {
     Some(x)
 }
 
-#[allow(clippy::needless_lifetimes)]
-fn _ref_to_opt_ref_explicit<'a>(x: &'a u32) -> Option<&'a u32> {
+fn ref_to_opt_ref_explicit<'a>(x: &'a u32) -> Option<&'a u32> {
     Some(x)
 }
 
-fn _with_constraint<'a, 'b: 'a>(x: &'b u32, y: &'a u32) -> &'a u32 {
+fn with_constraint<'a, 'b: 'a>(x: &'b u32, y: &'a u32) -> &'a u32 {
     if true { x } else { y }
 }
 
-async fn _async_implicit(x: &u32) -> &u32 {
+async fn async_implicit(x: &u32) -> &u32 {
     x
 }
 
-#[allow(clippy::needless_lifetimes)]
-async fn _async_explicit<'a>(x: &'a u32) -> &'a u32 {
+async fn async_explicit<'a>(x: &'a u32) -> &'a u32 {
     x
 }
 
-fn _unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 {
+fn unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 {
     //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
     y
 }
 
-fn _return_ptr(x: &u32) -> *const u32 {
+fn return_ptr(x: &u32) -> *const u32 {
     x
 }
 
-fn _return_field_ptr(x: &(u32, u32)) -> *const u32 {
+fn return_field_ptr(x: &(u32, u32)) -> *const u32 {
     &x.0
 }
 
-fn _return_field_ptr_addr_of(x: &(u32, u32)) -> *const u32 {
+fn return_field_ptr_addr_of(x: &(u32, u32)) -> *const u32 {
     core::ptr::addr_of!(x.0)
 }
-
-fn main() {
-    let (mut foo, bar) = (Foo(0), Bar([0; 24]));
-    let (mut a, b, c, x, y, z) = (0, 0, Bar([0; 24]), 0, Foo(0), 0);
-    good(&mut a, b, &c);
-    good_return_implicit_lt_ref(&y);
-    good_return_explicit_lt_ref(&y);
-    bad(&x, &y, &z);
-    foo.good(&mut a, b, &c);
-    foo.good2();
-    foo.bad(&x, &y, &z);
-    Foo::bad2(&x, &y, &z);
-    bar.good(&mut a, b, &c);
-    Bar::bad2(&x, &y, &z);
-    foo.as_ref();
-}
diff --git a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr
index e813fec..f101ac5 100644
--- a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr
+++ b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr
@@ -1,5 +1,5 @@
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:52:11
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:53:11
    |
 LL | fn bad(x: &u32, y: &Foo, z: &Baz) {}
    |           ^^^^ help: consider passing by value instead: `u32`
@@ -10,107 +10,107 @@
 LL | #![deny(clippy::trivially_copy_pass_by_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:52:20
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:53:20
    |
 LL | fn bad(x: &u32, y: &Foo, z: &Baz) {}
    |                    ^^^^ help: consider passing by value instead: `Foo`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:52:29
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:53:29
    |
 LL | fn bad(x: &u32, y: &Foo, z: &Baz) {}
    |                             ^^^^ help: consider passing by value instead: `Baz`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:62:12
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:63:12
    |
 LL |     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
    |            ^^^^^ help: consider passing by value instead: `self`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:62:22
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:63:22
    |
 LL |     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
    |                      ^^^^ help: consider passing by value instead: `u32`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:62:31
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:63:31
    |
 LL |     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
    |                               ^^^^ help: consider passing by value instead: `Foo`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:62:40
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:63:40
    |
 LL |     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
    |                                        ^^^^ help: consider passing by value instead: `Baz`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:68:16
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:69:16
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                ^^^^ help: consider passing by value instead: `u32`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:68:25
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:69:25
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                         ^^^^ help: consider passing by value instead: `Foo`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:68:34
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:69:34
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                                  ^^^^ help: consider passing by value instead: `Baz`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:73:35
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:74:35
    |
 LL |     fn bad_issue7518(self, other: &Self) {}
    |                                   ^^^^^ help: consider passing by value instead: `Self`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:86:16
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:87:16
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                ^^^^ help: consider passing by value instead: `u32`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:86:25
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:87:25
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                         ^^^^ help: consider passing by value instead: `Foo`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:86:34
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:87:34
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                                  ^^^^ help: consider passing by value instead: `Baz`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:93:34
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:94:33
    |
-LL |     fn trait_method(&self, _foo: &Foo);
-   |                                  ^^^^ help: consider passing by value instead: `Foo`
+LL |     fn trait_method(&self, foo: &Foo);
+   |                                 ^^^^ help: consider passing by value instead: `Foo`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:126:21
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:132:21
    |
 LL |     fn foo_never(x: &i32) {
    |                     ^^^^ help: consider passing by value instead: `i32`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:132:15
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:138:15
    |
 LL |     fn foo(x: &i32) {
    |               ^^^^ help: consider passing by value instead: `i32`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:160:37
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:164:36
    |
-LL | fn _unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 {
-   |                                     ^^^^^^^ help: consider passing by value instead: `u32`
+LL | fn unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 {
+   |                                    ^^^^^^^ help: consider passing by value instead: `u32`
 
 error: aborting due to 18 previous errors
 
diff --git a/src/tools/clippy/tests/ui/while_let_loop.rs b/src/tools/clippy/tests/ui/while_let_loop.rs
index d591ab9..95062c9 100644
--- a/src/tools/clippy/tests/ui/while_let_loop.rs
+++ b/src/tools/clippy/tests/ui/while_let_loop.rs
@@ -154,3 +154,89 @@ fn issue_5715(mut m: core::cell::RefCell<Option<u32>>) {
         m = core::cell::RefCell::new(Some(x + 1));
     }
 }
+
+mod issue_362 {
+    pub fn merge_sorted<T>(xs: Vec<T>, ys: Vec<T>) -> Vec<T>
+    where
+        T: PartialOrd,
+    {
+        let total_len = xs.len() + ys.len();
+        let mut res = Vec::with_capacity(total_len);
+        let mut ix = xs.into_iter().peekable();
+        let mut iy = ys.into_iter().peekable();
+        loop {
+            //~^ while_let_loop
+            let lt = match (ix.peek(), iy.peek()) {
+                (Some(x), Some(y)) => x < y,
+                _ => break,
+            };
+            res.push(if lt { &mut ix } else { &mut iy }.next().unwrap());
+        }
+        res.extend(ix);
+        res.extend(iy);
+        res
+    }
+}
+
+fn let_assign() {
+    loop {
+        //~^ while_let_loop
+        let x = if let Some(y) = Some(3) {
+            y
+        } else {
+            break;
+        };
+        if x == 3 {
+            break;
+        }
+    }
+
+    loop {
+        //~^ while_let_loop
+        let x: u32 = if let Some(y) = Some(3) {
+            y
+        } else {
+            break;
+        };
+        if x == 3 {
+            break;
+        }
+    }
+
+    loop {
+        //~^ while_let_loop
+        let x = if let Some(x) = Some(3) {
+            x
+        } else {
+            break;
+        };
+        if x == 3 {
+            break;
+        }
+    }
+
+    loop {
+        //~^ while_let_loop
+        let x: u32 = if let Some(x) = Some(3) {
+            x
+        } else {
+            break;
+        };
+        if x == 3 {
+            break;
+        }
+    }
+
+    loop {
+        //~^ while_let_loop
+        let x = if let Some(x) = Some(2) {
+            let t = 1;
+            t + x
+        } else {
+            break;
+        };
+        if x == 3 {
+            break;
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/while_let_loop.stderr b/src/tools/clippy/tests/ui/while_let_loop.stderr
index bd48285..ed42628 100644
--- a/src/tools/clippy/tests/ui/while_let_loop.stderr
+++ b/src/tools/clippy/tests/ui/while_let_loop.stderr
@@ -57,7 +57,125 @@
 ...  |
 LL | |         let _ = (e, l);
 LL | |     }
-   | |_____^ help: try: `while let Some(word) = "".split_whitespace().next() { .. }`
+   | |_____^
+   |
+help: try
+   |
+LL ~     while let Some(word) = "".split_whitespace().next() {
+LL +         let (e, l) = (word.is_empty(), word.len());
+LL +         ..
+LL +     }
+   |
 
-error: aborting due to 5 previous errors
+error: this loop could be written as a `while let` loop
+  --> tests/ui/while_let_loop.rs:167:9
+   |
+LL | /         loop {
+LL | |
+LL | |             let lt = match (ix.peek(), iy.peek()) {
+LL | |                 (Some(x), Some(y)) => x < y,
+...  |
+LL | |             res.push(if lt { &mut ix } else { &mut iy }.next().unwrap());
+LL | |         }
+   | |_________^
+   |
+help: try
+   |
+LL ~         while let (Some(x), Some(y)) = (ix.peek(), iy.peek()) {
+LL +             let lt = x < y;
+LL +             ..
+LL +         }
+   |
+
+error: this loop could be written as a `while let` loop
+  --> tests/ui/while_let_loop.rs:182:5
+   |
+LL | /     loop {
+LL | |
+LL | |         let x = if let Some(y) = Some(3) {
+LL | |             y
+...  |
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     while let Some(y) = Some(3) {
+LL +         let x = y;
+LL +         ..
+LL +     }
+   |
+
+error: this loop could be written as a `while let` loop
+  --> tests/ui/while_let_loop.rs:194:5
+   |
+LL | /     loop {
+LL | |
+LL | |         let x: u32 = if let Some(y) = Some(3) {
+LL | |             y
+...  |
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     while let Some(y) = Some(3) {
+LL +         let x: u32 = y;
+LL +         ..
+LL +     }
+   |
+
+error: this loop could be written as a `while let` loop
+  --> tests/ui/while_let_loop.rs:206:5
+   |
+LL | /     loop {
+LL | |
+LL | |         let x = if let Some(x) = Some(3) {
+LL | |             x
+...  |
+LL | |     }
+   | |_____^ help: try: `while let Some(x) = Some(3) { .. }`
+
+error: this loop could be written as a `while let` loop
+  --> tests/ui/while_let_loop.rs:218:5
+   |
+LL | /     loop {
+LL | |
+LL | |         let x: u32 = if let Some(x) = Some(3) {
+LL | |             x
+...  |
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     while let Some(x) = Some(3) {
+LL +         let x: u32 = x;
+LL +         ..
+LL +     }
+   |
+
+error: this loop could be written as a `while let` loop
+  --> tests/ui/while_let_loop.rs:230:5
+   |
+LL | /     loop {
+LL | |
+LL | |         let x = if let Some(x) = Some(2) {
+LL | |             let t = 1;
+...  |
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     while let Some(x) = Some(2) {
+LL +         let x = {
+LL +             let t = 1;
+LL +             t + x
+LL +         };
+LL +         ..
+LL +     }
+   |
+
+error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml
index 389f22c..16557a4 100644
--- a/src/tools/clippy/triagebot.toml
+++ b/src/tools/clippy/triagebot.toml
@@ -45,6 +45,7 @@
 users_on_vacation = [
     "matthiaskrgr",
     "Manishearth",
+    "blyxyas",
 ]
 
 [assign.owners]
diff --git a/src/tools/clippy/util/gh-pages/index_template.html b/src/tools/clippy/util/gh-pages/index_template.html
index 19dc1ec..865b952 100644
--- a/src/tools/clippy/util/gh-pages/index_template.html
+++ b/src/tools/clippy/util/gh-pages/index_template.html
@@ -50,7 +50,7 @@
 
     <div class="container"> {# #}
         <div class="page-header"> {# #}
-            <h1>Clippy Lints</h1> {# #}
+            <h1>Clippy Lints <span id="lint-count" class="badge"></span></h1> {# #}
         </div> {# #}
 
         <noscript> {# #}
diff --git a/src/tools/clippy/util/gh-pages/script.js b/src/tools/clippy/util/gh-pages/script.js
index c942a6a..fec8839 100644
--- a/src/tools/clippy/util/gh-pages/script.js
+++ b/src/tools/clippy/util/gh-pages/script.js
@@ -71,6 +71,7 @@
         } else {
             window.location.hash = '';
         }
+        updateLintCount();
     },
 };
 
@@ -598,3 +599,14 @@
 parseURLFilters();
 scrollToLintByURL();
 filters.filterLints();
+updateLintCount();
+
+function updateLintCount() {
+    const allLints = filters.getAllLints();
+    const totalLints = allLints.length;
+    
+    const countElement = document.getElementById("lint-count");
+    if (countElement) {
+        countElement.innerText = `Total number: ${totalLints}`;
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
index 321ee8f..8024823 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
@@ -42,6 +42,49 @@ pub fn into_file_id(self, db: &dyn ExpandDatabase) -> FilePositionWrapper<FileId
         FilePositionWrapper { file_id: self.file_id.file_id(db), offset: self.offset }
     }
 }
+
+impl From<FileRange> for HirFileRange {
+    fn from(value: FileRange) -> Self {
+        HirFileRange { file_id: value.file_id.into(), range: value.range }
+    }
+}
+
+impl From<FilePosition> for HirFilePosition {
+    fn from(value: FilePosition) -> Self {
+        HirFilePosition { file_id: value.file_id.into(), offset: value.offset }
+    }
+}
+
+impl FilePositionWrapper<span::FileId> {
+    pub fn with_edition(self, db: &dyn ExpandDatabase, edition: span::Edition) -> FilePosition {
+        FilePositionWrapper {
+            file_id: EditionedFileId::new(db, self.file_id, edition),
+            offset: self.offset,
+        }
+    }
+}
+
+impl FileRangeWrapper<span::FileId> {
+    pub fn with_edition(self, db: &dyn ExpandDatabase, edition: span::Edition) -> FileRange {
+        FileRangeWrapper {
+            file_id: EditionedFileId::new(db, self.file_id, edition),
+            range: self.range,
+        }
+    }
+}
+
+impl<T> InFileWrapper<span::FileId, T> {
+    pub fn with_edition(self, db: &dyn ExpandDatabase, edition: span::Edition) -> InRealFile<T> {
+        InRealFile { file_id: EditionedFileId::new(db, self.file_id, edition), value: self.value }
+    }
+}
+
+impl HirFileRange {
+    pub fn file_range(self) -> Option<FileRange> {
+        Some(FileRange { file_id: self.file_id.file_id()?, range: self.range })
+    }
+}
+
 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
 pub struct FileRangeWrapper<FileKind> {
     pub file_id: FileKind,
@@ -194,6 +237,9 @@ impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, N> {
     pub fn syntax(&self) -> InFileWrapper<FileId, &SyntaxNode> {
         self.with_value(self.value.syntax())
     }
+    pub fn node_file_range(&self) -> FileRangeWrapper<FileId> {
+        FileRangeWrapper { file_id: self.file_id, range: self.value.syntax().text_range() }
+    }
 }
 
 impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, &N> {
@@ -204,9 +250,9 @@ pub fn syntax_ref(&self) -> InFileWrapper<FileId, &SyntaxNode> {
 }
 
 // region:specific impls
-impl<SN: Borrow<SyntaxNode>> InRealFile<SN> {
-    pub fn file_range(&self) -> FileRange {
-        FileRange { file_id: self.file_id, range: self.value.borrow().text_range() }
+impl<FileId: Copy, SN: Borrow<SyntaxNode>> InFileWrapper<FileId, SN> {
+    pub fn file_range(&self) -> FileRangeWrapper<FileId> {
+        FileRangeWrapper { file_id: self.file_id, range: self.value.borrow().text_range() }
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
index d844d8f..6ecac14 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
@@ -392,6 +392,10 @@ pub fn original_call_node(self, db: &dyn ExpandDatabase) -> Option<InRealFile<Sy
         }
     }
 
+    pub fn call_node(self, db: &dyn ExpandDatabase) -> Option<InFile<SyntaxNode>> {
+        Some(db.lookup_intern_macro_call(self.macro_file()?).to_node(db))
+    }
+
     pub fn as_builtin_derive_attr_node(
         &self,
         db: &dyn ExpandDatabase,
@@ -848,7 +852,10 @@ pub fn map_node_range_up(
         map_node_range_up(db, &self.exp_map, range)
     }
 
-    /// Maps up the text range out of the expansion into is macro call.
+    /// Maps up the text range out of the expansion into its macro call.
+    ///
+    /// Note that this may return multiple ranges as we lose the precise association between input to output
+    /// and as such we may consider inputs that are unrelated.
     pub fn map_range_up_once(
         &self,
         db: &dyn ExpandDatabase,
@@ -864,11 +871,10 @@ pub fn map_range_up_once(
                 InFile { file_id, value: smallvec::smallvec![span.range + anchor_offset] }
             }
             SpanMap::ExpansionSpanMap(arg_map) => {
-                let arg_range = self
-                    .arg
-                    .value
-                    .as_ref()
-                    .map_or_else(|| TextRange::empty(TextSize::from(0)), |it| it.text_range());
+                let Some(arg_node) = &self.arg.value else {
+                    return InFile::new(self.arg.file_id, smallvec::smallvec![]);
+                };
+                let arg_range = arg_node.text_range();
                 InFile::new(
                     self.arg.file_id,
                     arg_map
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs b/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs
index 11cc434..6134c3a 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs
@@ -20,42 +20,46 @@ pub fn prettify_macro_expansion(
     let span_offset = syn.text_range().start();
     let target_crate = target_crate_id.data(db);
     let mut syntax_ctx_id_to_dollar_crate_replacement = FxHashMap::default();
-    syntax_bridge::prettify_macro_expansion::prettify_macro_expansion(syn, &mut |dollar_crate| {
-        let ctx = span_map.span_at(dollar_crate.text_range().start() + span_offset).ctx;
-        let replacement =
-            syntax_ctx_id_to_dollar_crate_replacement.entry(ctx).or_insert_with(|| {
-                let macro_call_id =
-                    ctx.outer_expn(db).expect("`$crate` cannot come from `SyntaxContextId::ROOT`");
-                let macro_call = db.lookup_intern_macro_call(macro_call_id.into());
-                let macro_def_crate = macro_call.def.krate;
-                // First, if this is the same crate as the macro, nothing will work but `crate`.
-                // If not, if the target trait has the macro's crate as a dependency, using the dependency name
-                // will work in inserted code and match the user's expectation.
-                // If not, the crate's display name is what the dependency name is likely to be once such dependency
-                // is inserted, and also understandable to the user.
-                // Lastly, if nothing else found, resort to leaving `$crate`.
-                if target_crate_id == macro_def_crate {
-                    make::tokens::crate_kw()
-                } else if let Some(dep) =
-                    target_crate.dependencies.iter().find(|dep| dep.crate_id == macro_def_crate)
-                {
-                    make::tokens::ident(dep.name.as_str())
-                } else if let Some(crate_name) = &macro_def_crate.extra_data(db).display_name {
-                    make::tokens::ident(crate_name.crate_name().as_str())
-                } else {
-                    return dollar_crate.clone();
-                }
-            });
-        if replacement.text() == "$crate" {
-            // The parent may have many children, and looking for the token may yield incorrect results.
-            return dollar_crate.clone();
-        }
-        // We need to `clone_subtree()` but rowan doesn't provide such operation for tokens.
-        let parent = replacement.parent().unwrap().clone_subtree().clone_for_update();
-        parent
-            .children_with_tokens()
-            .filter_map(NodeOrToken::into_token)
-            .find(|it| it.kind() == replacement.kind())
-            .unwrap()
-    })
+    syntax_bridge::prettify_macro_expansion::prettify_macro_expansion(
+        syn,
+        &mut |dollar_crate| {
+            let ctx = span_map.span_at(dollar_crate.text_range().start() + span_offset).ctx;
+            let replacement =
+                syntax_ctx_id_to_dollar_crate_replacement.entry(ctx).or_insert_with(|| {
+                    let macro_call_id = ctx
+                        .outer_expn(db)
+                        .expect("`$crate` cannot come from `SyntaxContextId::ROOT`");
+                    let macro_call = db.lookup_intern_macro_call(macro_call_id.into());
+                    let macro_def_crate = macro_call.def.krate;
+                    // First, if this is the same crate as the macro, nothing will work but `crate`.
+                    // If not, if the target trait has the macro's crate as a dependency, using the dependency name
+                    // will work in inserted code and match the user's expectation.
+                    // If not, the crate's display name is what the dependency name is likely to be once such dependency
+                    // is inserted, and also understandable to the user.
+                    // Lastly, if nothing else found, resort to leaving `$crate`.
+                    if target_crate_id == macro_def_crate {
+                        make::tokens::crate_kw()
+                    } else if let Some(dep) =
+                        target_crate.dependencies.iter().find(|dep| dep.crate_id == macro_def_crate)
+                    {
+                        make::tokens::ident(dep.name.as_str())
+                    } else if let Some(crate_name) = &macro_def_crate.extra_data(db).display_name {
+                        make::tokens::ident(crate_name.crate_name().as_str())
+                    } else {
+                        return dollar_crate.clone();
+                    }
+                });
+            if replacement.text() == "$crate" {
+                // The parent may have many children, and looking for the token may yield incorrect results.
+                return None;
+            }
+            // We need to `clone_subtree()` but rowan doesn't provide such operation for tokens.
+            let parent = replacement.parent().unwrap().clone_subtree().clone_for_update();
+            parent
+                .children_with_tokens()
+                .filter_map(NodeOrToken::into_token)
+                .find(|it| it.kind() == replacement.kind())
+        },
+        |_| (),
+    )
 }
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index aea2254..e017746 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -24,7 +24,7 @@
     attrs::collect_attrs,
     builtin::{BuiltinFnLikeExpander, EagerExpander},
     db::ExpandDatabase,
-    files::{FileRangeWrapper, InRealFile},
+    files::{FileRangeWrapper, HirFileRange, InRealFile},
     inert_attr_macro::find_builtin_attr_idx,
     mod_path::{ModPath, PathKind},
     name::AsName,
@@ -262,6 +262,17 @@ pub fn file_to_module_defs(&self, file: impl Into<FileId>) -> impl Iterator<Item
         self.imp.file_to_module_defs(file.into())
     }
 
+    pub fn hir_file_to_module_def(&self, file: impl Into<HirFileId>) -> Option<Module> {
+        self.imp.hir_file_to_module_defs(file.into()).next()
+    }
+
+    pub fn hir_file_to_module_defs(
+        &self,
+        file: impl Into<HirFileId>,
+    ) -> impl Iterator<Item = Module> {
+        self.imp.hir_file_to_module_defs(file.into())
+    }
+
     pub fn to_adt_def(&self, a: &ast::Adt) -> Option<Adt> {
         self.imp.to_def(a)
     }
@@ -357,6 +368,15 @@ pub fn parse_guess_edition(&self, file_id: FileId) -> ast::SourceFile {
         tree
     }
 
+    pub fn adjust_edition(&self, file_id: HirFileId) -> HirFileId {
+        if let Some(editioned_file_id) = file_id.file_id() {
+            self.attach_first_edition(editioned_file_id.file_id(self.db))
+                .map_or(file_id, Into::into)
+        } else {
+            file_id
+        }
+    }
+
     pub fn find_parent_file(&self, file_id: HirFileId) -> Option<InFile<SyntaxNode>> {
         match file_id {
             HirFileId::FileId(file_id) => {
@@ -653,7 +673,7 @@ pub fn as_format_args_parts(
         string: &ast::String,
     ) -> Option<Vec<(TextRange, Option<Either<PathResolution, InlineAsmOperand>>)>> {
         let string_start = string.syntax().text_range().start();
-        let token = self.wrap_token_infile(string.syntax().clone()).into_real_file().ok()?;
+        let token = self.wrap_token_infile(string.syntax().clone());
         self.descend_into_macros_breakable(token, |token, _| {
             (|| {
                 let token = token.value;
@@ -693,50 +713,95 @@ pub fn as_format_args_parts(
     }
 
     /// Retrieves the formatting part of the format_args! template string at the given offset.
+    ///
+    // FIXME: Type the return type
+    /// Returns the range (pre-expansion) in the string literal corresponding to the resolution,
+    /// absolute file range (post-expansion)
+    /// of the part in the format string, the corresponding string token and the resolution if it
+    /// exists.
+    // FIXME: Remove this in favor of `check_for_format_args_template_with_file`
     pub fn check_for_format_args_template(
         &self,
         original_token: SyntaxToken,
         offset: TextSize,
-    ) -> Option<(TextRange, Option<Either<PathResolution, InlineAsmOperand>>)> {
-        let string_start = original_token.text_range().start();
-        let original_token = self.wrap_token_infile(original_token).into_real_file().ok()?;
-        self.descend_into_macros_breakable(original_token, |token, _| {
-            (|| {
-                let token = token.value;
-                self.resolve_offset_in_format_args(
-                    ast::String::cast(token)?,
-                    offset.checked_sub(string_start)?,
-                )
-                .map(|(range, res)| (range + string_start, res))
-            })()
-            .map_or(ControlFlow::Continue(()), ControlFlow::Break)
-        })
+    ) -> Option<(
+        TextRange,
+        HirFileRange,
+        ast::String,
+        Option<Either<PathResolution, InlineAsmOperand>>,
+    )> {
+        let original_token =
+            self.wrap_token_infile(original_token).map(ast::String::cast).transpose()?;
+        self.check_for_format_args_template_with_file(original_token, offset)
+    }
+
+    /// Retrieves the formatting part of the format_args! template string at the given offset.
+    ///
+    // FIXME: Type the return type
+    /// Returns the range (pre-expansion) in the string literal corresponding to the resolution,
+    /// absolute file range (post-expansion)
+    /// of the part in the format string, the corresponding string token and the resolution if it
+    /// exists.
+    pub fn check_for_format_args_template_with_file(
+        &self,
+        original_token: InFile<ast::String>,
+        offset: TextSize,
+    ) -> Option<(
+        TextRange,
+        HirFileRange,
+        ast::String,
+        Option<Either<PathResolution, InlineAsmOperand>>,
+    )> {
+        let relative_offset =
+            offset.checked_sub(original_token.value.syntax().text_range().start())?;
+        self.descend_into_macros_breakable(
+            original_token.as_ref().map(|it| it.syntax().clone()),
+            |token, _| {
+                (|| {
+                    let token = token.map(ast::String::cast).transpose()?;
+                    self.resolve_offset_in_format_args(token.as_ref(), relative_offset).map(
+                        |(range, res)| {
+                            (
+                                range + original_token.value.syntax().text_range().start(),
+                                HirFileRange {
+                                    file_id: token.file_id,
+                                    range: range + token.value.syntax().text_range().start(),
+                                },
+                                token.value,
+                                res,
+                            )
+                        },
+                    )
+                })()
+                .map_or(ControlFlow::Continue(()), ControlFlow::Break)
+            },
+        )
     }
 
     fn resolve_offset_in_format_args(
         &self,
-        string: ast::String,
+        InFile { value: string, file_id }: InFile<&ast::String>,
         offset: TextSize,
     ) -> Option<(TextRange, Option<Either<PathResolution, InlineAsmOperand>>)> {
         debug_assert!(offset <= string.syntax().text_range().len());
         let literal = string.syntax().parent().filter(|it| it.kind() == SyntaxKind::LITERAL)?;
         let parent = literal.parent()?;
         if let Some(format_args) = ast::FormatArgsExpr::cast(parent.clone()) {
-            let source_analyzer = &self.analyze_no_infer(format_args.syntax())?;
-            let format_args = self.wrap_node_infile(format_args);
+            let source_analyzer =
+                &self.analyze_impl(InFile::new(file_id, format_args.syntax()), None, false)?;
             source_analyzer
-                .resolve_offset_in_format_args(self.db, format_args.as_ref(), offset)
+                .resolve_offset_in_format_args(self.db, InFile::new(file_id, &format_args), offset)
                 .map(|(range, res)| (range, res.map(Either::Left)))
         } else {
             let asm = ast::AsmExpr::cast(parent)?;
-            let source_analyzer = &self.analyze_no_infer(asm.syntax())?;
+            let source_analyzer =
+                self.analyze_impl(InFile::new(file_id, asm.syntax()), None, false)?;
             let line = asm.template().position(|it| *it.syntax() == literal)?;
-            let asm = self.wrap_node_infile(asm);
-            source_analyzer.resolve_offset_in_asm_template(asm.as_ref(), line, offset).map(
-                |(owner, (expr, range, index))| {
+            source_analyzer
+                .resolve_offset_in_asm_template(InFile::new(file_id, &asm), line, offset)
+                .map(|(owner, (expr, range, index))| {
                     (range, Some(Either::Right(InlineAsmOperand { owner, expr, index })))
-                },
-            )
+                })
         }
     }
 
@@ -809,14 +874,11 @@ pub fn descend_token_into_include_expansion(
             None => return res,
         };
         let file = self.find_file(node.syntax());
-        let Some(file_id) = file.file_id.file_id() else {
-            return res;
-        };
 
         if first == last {
             // node is just the token, so descend the token
             self.descend_into_macros_impl(
-                InRealFile::new(file_id, first),
+                InFile::new(file.file_id, first),
                 &mut |InFile { value, .. }, _ctx| {
                     if let Some(node) = value
                         .parent_ancestors()
@@ -831,14 +893,14 @@ pub fn descend_token_into_include_expansion(
         } else {
             // Descend first and last token, then zip them to look for the node they belong to
             let mut scratch: SmallVec<[_; 1]> = smallvec![];
-            self.descend_into_macros_impl(InRealFile::new(file_id, first), &mut |token, _ctx| {
+            self.descend_into_macros_impl(InFile::new(file.file_id, first), &mut |token, _ctx| {
                 scratch.push(token);
                 CONTINUE_NO_BREAKS
             });
 
             let mut scratch = scratch.into_iter();
             self.descend_into_macros_impl(
-                InRealFile::new(file_id, last),
+                InFile::new(file.file_id, last),
                 &mut |InFile { value: last, file_id: last_fid }, _ctx| {
                     if let Some(InFile { value: first, file_id: first_fid }) = scratch.next() {
                         if first_fid == last_fid {
@@ -900,22 +962,18 @@ pub fn descend_into_macros_cb(
         token: SyntaxToken,
         mut cb: impl FnMut(InFile<SyntaxToken>, SyntaxContext),
     ) {
-        if let Ok(token) = self.wrap_token_infile(token).into_real_file() {
-            self.descend_into_macros_impl(token, &mut |t, ctx| {
-                cb(t, ctx);
-                CONTINUE_NO_BREAKS
-            });
-        }
+        self.descend_into_macros_impl(self.wrap_token_infile(token), &mut |t, ctx| {
+            cb(t, ctx);
+            CONTINUE_NO_BREAKS
+        });
     }
 
     pub fn descend_into_macros(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> {
         let mut res = smallvec![];
-        if let Ok(token) = self.wrap_token_infile(token.clone()).into_real_file() {
-            self.descend_into_macros_impl(token, &mut |t, _ctx| {
-                res.push(t.value);
-                CONTINUE_NO_BREAKS
-            });
-        }
+        self.descend_into_macros_impl(self.wrap_token_infile(token.clone()), &mut |t, _ctx| {
+            res.push(t.value);
+            CONTINUE_NO_BREAKS
+        });
         if res.is_empty() {
             res.push(token);
         }
@@ -928,15 +986,13 @@ pub fn descend_into_macros_no_opaque(
     ) -> SmallVec<[InFile<SyntaxToken>; 1]> {
         let mut res = smallvec![];
         let token = self.wrap_token_infile(token);
-        if let Ok(token) = token.clone().into_real_file() {
-            self.descend_into_macros_impl(token, &mut |t, ctx| {
-                if !ctx.is_opaque(self.db) {
-                    // Don't descend into opaque contexts
-                    res.push(t);
-                }
-                CONTINUE_NO_BREAKS
-            });
-        }
+        self.descend_into_macros_impl(token.clone(), &mut |t, ctx| {
+            if !ctx.is_opaque(self.db) {
+                // Don't descend into opaque contexts
+                res.push(t);
+            }
+            CONTINUE_NO_BREAKS
+        });
         if res.is_empty() {
             res.push(token);
         }
@@ -945,7 +1001,7 @@ pub fn descend_into_macros_no_opaque(
 
     pub fn descend_into_macros_breakable<T>(
         &self,
-        token: InRealFile<SyntaxToken>,
+        token: InFile<SyntaxToken>,
         mut cb: impl FnMut(InFile<SyntaxToken>, SyntaxContext) -> ControlFlow<T>,
     ) -> Option<T> {
         self.descend_into_macros_impl(token, &mut cb)
@@ -974,33 +1030,58 @@ pub fn descend_into_macros_breakable<T>(
         r
     }
 
+    /// Descends the token into expansions, returning the tokens that matches the input
+    /// token's [`SyntaxKind`] and text.
+    pub fn descend_into_macros_exact_with_file(
+        &self,
+        token: SyntaxToken,
+    ) -> SmallVec<[InFile<SyntaxToken>; 1]> {
+        let mut r = smallvec![];
+        let text = token.text();
+        let kind = token.kind();
+
+        self.descend_into_macros_cb(token.clone(), |InFile { value, file_id }, ctx| {
+            let mapped_kind = value.kind();
+            let any_ident_match = || kind.is_any_identifier() && value.kind().is_any_identifier();
+            let matches = (kind == mapped_kind || any_ident_match())
+                && text == value.text()
+                && !ctx.is_opaque(self.db);
+            if matches {
+                r.push(InFile { value, file_id });
+            }
+        });
+        if r.is_empty() {
+            r.push(self.wrap_token_infile(token));
+        }
+        r
+    }
+
     /// Descends the token into expansions, returning the first token that matches the input
     /// token's [`SyntaxKind`] and text.
     pub fn descend_into_macros_single_exact(&self, token: SyntaxToken) -> SyntaxToken {
         let text = token.text();
         let kind = token.kind();
-        if let Ok(token) = self.wrap_token_infile(token.clone()).into_real_file() {
-            self.descend_into_macros_breakable(token, |InFile { value, file_id: _ }, _ctx| {
+        self.descend_into_macros_breakable(
+            self.wrap_token_infile(token.clone()),
+            |InFile { value, file_id: _ }, _ctx| {
                 let mapped_kind = value.kind();
                 let any_ident_match =
                     || kind.is_any_identifier() && value.kind().is_any_identifier();
                 let matches = (kind == mapped_kind || any_ident_match()) && text == value.text();
                 if matches { ControlFlow::Break(value) } else { ControlFlow::Continue(()) }
-            })
-        } else {
-            None
-        }
+            },
+        )
         .unwrap_or(token)
     }
 
     fn descend_into_macros_impl<T>(
         &self,
-        InRealFile { value: token, file_id }: InRealFile<SyntaxToken>,
+        InFile { value: token, file_id }: InFile<SyntaxToken>,
         f: &mut dyn FnMut(InFile<SyntaxToken>, SyntaxContext) -> ControlFlow<T>,
     ) -> Option<T> {
         let _p = tracing::info_span!("descend_into_macros_impl").entered();
 
-        let span = self.db.real_span_map(file_id).span_for_range(token.text_range());
+        let span = self.db.span_map(file_id).span_for_range(token.text_range());
 
         // Process the expansion of a call, pushing all tokens with our span in the expansion back onto our stack
         let process_expansion_for_token = |stack: &mut Vec<_>, macro_file| {
@@ -1024,17 +1105,16 @@ fn descend_into_macros_impl<T>(
         // the tokens themselves aren't that interesting as the span that is being used to map
         // things down never changes.
         let mut stack: Vec<(_, SmallVec<[_; 2]>)> = vec![];
-        let include = self.s2d_cache.borrow_mut().get_or_insert_include_for(self.db, file_id);
+        let include = file_id.file_id().and_then(|file_id| {
+            self.s2d_cache.borrow_mut().get_or_insert_include_for(self.db, file_id)
+        });
         match include {
             Some(include) => {
                 // include! inputs are always from real files, so they only need to be handled once upfront
                 process_expansion_for_token(&mut stack, include)?;
             }
             None => {
-                stack.push((
-                    file_id.into(),
-                    smallvec![(token, SyntaxContext::root(file_id.edition(self.db)))],
-                ));
+                stack.push((file_id, smallvec![(token, span.ctx)]));
             }
         }
 
@@ -1678,6 +1758,11 @@ fn file_to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> {
         self.with_ctx(|ctx| ctx.file_to_def(file).to_owned()).into_iter().map(Module::from)
     }
 
+    fn hir_file_to_module_defs(&self, file: HirFileId) -> impl Iterator<Item = Module> {
+        // FIXME: Do we need to care about inline modules for macro expansions?
+        self.file_to_module_defs(file.original_file_respecting_includes(self.db).file_id(self.db))
+    }
+
     pub fn scope(&self, node: &SyntaxNode) -> Option<SemanticsScope<'db>> {
         self.analyze_no_infer(node).map(|SourceAnalyzer { file_id, resolver, .. }| SemanticsScope {
             db: self.db,
diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
index d22812d..ec2ccf8 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -1303,6 +1303,7 @@ pub(crate) fn is_unsafe_macro_call_expr(
         false
     }
 
+    /// Returns the range of the implicit template argument and its resolution at the given `offset`
     pub(crate) fn resolve_offset_in_format_args(
         &self,
         db: &'db dyn HirDatabase,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs
index d310e110..f3243d3 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs
@@ -128,11 +128,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
             format!("Import `{import_name}`"),
             range,
             |builder| {
-                let scope = match scope.clone() {
-                    ImportScope::File(it) => ImportScope::File(builder.make_mut(it)),
-                    ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
-                    ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
-                };
+                let scope = builder.make_import_scope_mut(scope.clone());
                 insert_use(&scope, mod_path_to_ast(&import_path, edition), &ctx.config.insert_use);
             },
         );
@@ -153,11 +149,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
                     format!("Import `{import_name} as _`"),
                     range,
                     |builder| {
-                        let scope = match scope.clone() {
-                            ImportScope::File(it) => ImportScope::File(builder.make_mut(it)),
-                            ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
-                            ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
-                        };
+                        let scope = builder.make_import_scope_mut(scope.clone());
                         insert_use_as_alias(
                             &scope,
                             mod_path_to_ast(&import_path, edition),
@@ -1877,4 +1869,30 @@ fn main() {
 ",
         );
     }
+
+    #[test]
+    fn carries_cfg_attr() {
+        check_assist(
+            auto_import,
+            r#"
+mod m {
+    pub struct S;
+}
+
+#[cfg(test)]
+fn foo(_: S$0) {}
+"#,
+            r#"
+#[cfg(test)]
+use m::S;
+
+mod m {
+    pub struct S;
+}
+
+#[cfg(test)]
+fn foo(_: S) {}
+"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs
index 00e9fdf..f73b8c4 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs
@@ -312,12 +312,8 @@ fn replace_usages(
                 }
 
                 // add imports across modules where needed
-                if let Some((import_scope, path)) = import_data {
-                    let scope = match import_scope {
-                        ImportScope::File(it) => ImportScope::File(edit.make_mut(it)),
-                        ImportScope::Module(it) => ImportScope::Module(edit.make_mut(it)),
-                        ImportScope::Block(it) => ImportScope::Block(edit.make_mut(it)),
-                    };
+                if let Some((scope, path)) = import_data {
+                    let scope = edit.make_import_scope_mut(scope);
                     delayed_mutations.push((scope, path));
                 }
             },
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
index ed8aad7..5d75e44 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
@@ -996,7 +996,8 @@ pub struct $0Foo {
 }
 "#,
             r#"
-pub struct Foo(#[my_custom_attr] u32);
+pub struct Foo(#[my_custom_attr]
+u32);
 "#,
         );
     }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
index 777e366..0c0b93b 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
@@ -923,7 +923,8 @@ fn fields_with_attrs() {
 pub struct $0Foo(#[my_custom_attr] u32);
 "#,
             r#"
-pub struct Foo { #[my_custom_attr] field1: u32 }
+pub struct Foo { #[my_custom_attr]
+field1: u32 }
 "#,
         );
     }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
index e977798..cf45ea0 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
@@ -204,12 +204,7 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
                 .kind
                 .is_some_and(|kind| matches!(kind, FlowKind::Break(_, _) | FlowKind::Continue(_)))
             {
-                let scope = match scope {
-                    ImportScope::File(it) => ImportScope::File(builder.make_mut(it)),
-                    ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
-                    ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
-                };
-
+                let scope = builder.make_import_scope_mut(scope);
                 let control_flow_enum =
                     FamousDefs(&ctx.sema, module.krate()).core_ops_ControlFlow();
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
index c067747..fa005a4 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
@@ -81,11 +81,7 @@ pub(crate) fn replace_qualified_name_with_use(
         |builder| {
             // Now that we've brought the name into scope, re-qualify all paths that could be
             // affected (that is, all paths inside the node we added the `use` to).
-            let scope = match scope {
-                ImportScope::File(it) => ImportScope::File(builder.make_mut(it)),
-                ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
-                ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
-            };
+            let scope = builder.make_import_scope_mut(scope);
             shorten_paths(scope.as_syntax_node(), &original_path);
             let path = drop_generic_args(&original_path);
             let edition = ctx
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs
index ebb8ef9..1f89a3d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs
@@ -1,4 +1,3 @@
-use ide_db::imports::insert_use::ImportScope;
 use syntax::{
     TextRange,
     ast::{self, AstNode, HasArgList, prec::ExprPrecedence},
@@ -114,11 +113,7 @@ fn add_import(
         );
 
         if let Some(scope) = scope {
-            let scope = match scope {
-                ImportScope::File(it) => ImportScope::File(edit.make_mut(it)),
-                ImportScope::Module(it) => ImportScope::Module(edit.make_mut(it)),
-                ImportScope::Block(it) => ImportScope::Block(edit.make_mut(it)),
-            };
+            let scope = edit.make_import_scope_mut(scope);
             ide_db::imports::insert_use::insert_use(&scope, import, &ctx.config.insert_use);
         }
     }
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs
index d26e5d6..813f383 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs
@@ -60,107 +60,87 @@ pub struct InsertUseConfig {
 }
 
 #[derive(Debug, Clone)]
-pub enum ImportScope {
+pub struct ImportScope {
+    pub kind: ImportScopeKind,
+    pub required_cfgs: Vec<ast::Attr>,
+}
+
+#[derive(Debug, Clone)]
+pub enum ImportScopeKind {
     File(ast::SourceFile),
     Module(ast::ItemList),
     Block(ast::StmtList),
 }
 
 impl ImportScope {
-    // FIXME: Remove this?
-    #[cfg(test)]
-    fn from(syntax: SyntaxNode) -> Option<Self> {
-        use syntax::match_ast;
-        fn contains_cfg_attr(attrs: &dyn HasAttrs) -> bool {
-            attrs.attrs().any(|attr| attr.as_simple_call().is_some_and(|(ident, _)| ident == "cfg"))
-        }
-        match_ast! {
-            match syntax {
-                ast::Module(module) => module.item_list().map(ImportScope::Module),
-                ast::SourceFile(file) => Some(ImportScope::File(file)),
-                ast::Fn(func) => contains_cfg_attr(&func).then(|| func.body().and_then(|it| it.stmt_list().map(ImportScope::Block))).flatten(),
-                ast::Const(konst) => contains_cfg_attr(&konst).then(|| match konst.body()? {
-                    ast::Expr::BlockExpr(block) => Some(block),
-                    _ => None,
-                }).flatten().and_then(|it| it.stmt_list().map(ImportScope::Block)),
-                ast::Static(statik) => contains_cfg_attr(&statik).then(|| match statik.body()? {
-                    ast::Expr::BlockExpr(block) => Some(block),
-                    _ => None,
-                }).flatten().and_then(|it| it.stmt_list().map(ImportScope::Block)),
-                _ => None,
-
-            }
-        }
-    }
-
     /// Determines the containing syntax node in which to insert a `use` statement affecting `position`.
     /// Returns the original source node inside attributes.
     pub fn find_insert_use_container(
         position: &SyntaxNode,
         sema: &Semantics<'_, RootDatabase>,
     ) -> Option<Self> {
-        fn contains_cfg_attr(attrs: &dyn HasAttrs) -> bool {
-            attrs.attrs().any(|attr| attr.as_simple_call().is_some_and(|(ident, _)| ident == "cfg"))
-        }
-
+        // The closest block expression ancestor
+        let mut block = None;
+        let mut required_cfgs = Vec::new();
         // Walk up the ancestor tree searching for a suitable node to do insertions on
         // with special handling on cfg-gated items, in which case we want to insert imports locally
         // or FIXME: annotate inserted imports with the same cfg
         for syntax in sema.ancestors_with_macros(position.clone()) {
             if let Some(file) = ast::SourceFile::cast(syntax.clone()) {
-                return Some(ImportScope::File(file));
-            } else if let Some(item) = ast::Item::cast(syntax) {
-                return match item {
-                    ast::Item::Const(konst) if contains_cfg_attr(&konst) => {
-                        // FIXME: Instead of bailing out with None, we should note down that
-                        // this import needs an attribute added
-                        match sema.original_ast_node(konst)?.body()? {
-                            ast::Expr::BlockExpr(block) => block,
-                            _ => return None,
+                return Some(ImportScope { kind: ImportScopeKind::File(file), required_cfgs });
+            } else if let Some(module) = ast::Module::cast(syntax.clone()) {
+                // early return is important here, if we can't find the original module
+                // in the input there is no way for us to insert an import anywhere.
+                return sema
+                    .original_ast_node(module)?
+                    .item_list()
+                    .map(ImportScopeKind::Module)
+                    .map(|kind| ImportScope { kind, required_cfgs });
+            } else if let Some(has_attrs) = ast::AnyHasAttrs::cast(syntax) {
+                if block.is_none() {
+                    if let Some(b) = ast::BlockExpr::cast(has_attrs.syntax().clone()) {
+                        if let Some(b) = sema.original_ast_node(b) {
+                            block = b.stmt_list();
                         }
-                        .stmt_list()
-                        .map(ImportScope::Block)
                     }
-                    ast::Item::Fn(func) if contains_cfg_attr(&func) => {
-                        // FIXME: Instead of bailing out with None, we should note down that
-                        // this import needs an attribute added
-                        sema.original_ast_node(func)?.body()?.stmt_list().map(ImportScope::Block)
+                }
+                if has_attrs
+                    .attrs()
+                    .any(|attr| attr.as_simple_call().is_some_and(|(ident, _)| ident == "cfg"))
+                {
+                    if let Some(b) = block {
+                        return Some(ImportScope {
+                            kind: ImportScopeKind::Block(b),
+                            required_cfgs,
+                        });
                     }
-                    ast::Item::Static(statik) if contains_cfg_attr(&statik) => {
-                        // FIXME: Instead of bailing out with None, we should note down that
-                        // this import needs an attribute added
-                        match sema.original_ast_node(statik)?.body()? {
-                            ast::Expr::BlockExpr(block) => block,
-                            _ => return None,
-                        }
-                        .stmt_list()
-                        .map(ImportScope::Block)
-                    }
-                    ast::Item::Module(module) => {
-                        // early return is important here, if we can't find the original module
-                        // in the input there is no way for us to insert an import anywhere.
-                        sema.original_ast_node(module)?.item_list().map(ImportScope::Module)
-                    }
-                    _ => continue,
-                };
+                    required_cfgs.extend(has_attrs.attrs().filter(|attr| {
+                        attr.as_simple_call().is_some_and(|(ident, _)| ident == "cfg")
+                    }));
+                }
             }
         }
         None
     }
 
     pub fn as_syntax_node(&self) -> &SyntaxNode {
-        match self {
-            ImportScope::File(file) => file.syntax(),
-            ImportScope::Module(item_list) => item_list.syntax(),
-            ImportScope::Block(block) => block.syntax(),
+        match &self.kind {
+            ImportScopeKind::File(file) => file.syntax(),
+            ImportScopeKind::Module(item_list) => item_list.syntax(),
+            ImportScopeKind::Block(block) => block.syntax(),
         }
     }
 
     pub fn clone_for_update(&self) -> Self {
-        match self {
-            ImportScope::File(file) => ImportScope::File(file.clone_for_update()),
-            ImportScope::Module(item_list) => ImportScope::Module(item_list.clone_for_update()),
-            ImportScope::Block(block) => ImportScope::Block(block.clone_for_update()),
+        Self {
+            kind: match &self.kind {
+                ImportScopeKind::File(file) => ImportScopeKind::File(file.clone_for_update()),
+                ImportScopeKind::Module(item_list) => {
+                    ImportScopeKind::Module(item_list.clone_for_update())
+                }
+                ImportScopeKind::Block(block) => ImportScopeKind::Block(block.clone_for_update()),
+            },
+            required_cfgs: self.required_cfgs.iter().map(|attr| attr.clone_for_update()).collect(),
         }
     }
 }
@@ -216,6 +196,11 @@ fn insert_use_with_alias_option(
         use_tree.wrap_in_tree_list();
     }
     let use_item = make::use_(None, use_tree).clone_for_update();
+    for attr in
+        scope.required_cfgs.iter().map(|attr| attr.syntax().clone_subtree().clone_for_update())
+    {
+        ted::insert(ted::Position::first_child_of(use_item.syntax()), attr);
+    }
 
     // merge into existing imports if possible
     if let Some(mb) = mb {
@@ -229,7 +214,6 @@ fn insert_use_with_alias_option(
             }
         }
     }
-
     // either we weren't allowed to merge or there is no import that fits the merge conditions
     // so look for the place we have to insert to
     insert_use_(scope, use_item, cfg.group);
@@ -316,10 +300,10 @@ fn guess_granularity_from_scope(scope: &ImportScope) -> ImportGranularityGuess {
         }
         _ => None,
     };
-    let mut use_stmts = match scope {
-        ImportScope::File(f) => f.items(),
-        ImportScope::Module(m) => m.items(),
-        ImportScope::Block(b) => b.items(),
+    let mut use_stmts = match &scope.kind {
+        ImportScopeKind::File(f) => f.items(),
+        ImportScopeKind::Module(m) => m.items(),
+        ImportScopeKind::Block(b) => b.items(),
     }
     .filter_map(use_stmt);
     let mut res = ImportGranularityGuess::Unknown;
@@ -463,12 +447,12 @@ fn insert_use_(scope: &ImportScope, use_item: ast::Use, group_imports: bool) {
         }
     }
 
-    let l_curly = match scope {
-        ImportScope::File(_) => None,
+    let l_curly = match &scope.kind {
+        ImportScopeKind::File(_) => None,
         // don't insert the imports before the item list/block expr's opening curly brace
-        ImportScope::Module(item_list) => item_list.l_curly_token(),
+        ImportScopeKind::Module(item_list) => item_list.l_curly_token(),
         // don't insert the imports before the item list's opening curly brace
-        ImportScope::Block(block) => block.l_curly_token(),
+        ImportScopeKind::Block(block) => block.l_curly_token(),
     };
     // there are no imports in this file at all
     // so put the import after all inner module attributes and possible license header comments
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs
index 428ba1d..4a00854 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs
@@ -23,7 +23,7 @@ fn trailing_comment_in_empty_file() {
 }
 
 #[test]
-fn respects_cfg_attr_fn() {
+fn respects_cfg_attr_fn_body() {
     check(
         r"bar::Bar",
         r#"
@@ -41,6 +41,25 @@ fn foo() {
 }
 
 #[test]
+fn respects_cfg_attr_fn_sig() {
+    check(
+        r"bar::Bar",
+        r#"
+#[cfg(test)]
+fn foo($0) {}
+"#,
+        r#"
+#[cfg(test)]
+use bar::Bar;
+
+#[cfg(test)]
+fn foo() {}
+"#,
+        ImportGranularity::Crate,
+    );
+}
+
+#[test]
 fn respects_cfg_attr_const() {
     check(
         r"bar::Bar",
@@ -59,6 +78,51 @@ fn respects_cfg_attr_const() {
 }
 
 #[test]
+fn respects_cfg_attr_impl() {
+    check(
+        r"bar::Bar",
+        r#"
+#[cfg(test)]
+impl () {$0}
+"#,
+        r#"
+#[cfg(test)]
+use bar::Bar;
+
+#[cfg(test)]
+impl () {}
+"#,
+        ImportGranularity::Crate,
+    );
+}
+
+#[test]
+fn respects_cfg_attr_multiple_layers() {
+    check(
+        r"bar::Bar",
+        r#"
+#[cfg(test)]
+impl () {
+    #[cfg(test2)]
+    fn f($0) {}
+}
+"#,
+        r#"
+#[cfg(test)]
+#[cfg(test2)]
+use bar::Bar;
+
+#[cfg(test)]
+impl () {
+    #[cfg(test2)]
+    fn f() {}
+}
+"#,
+        ImportGranularity::Crate,
+    );
+}
+
+#[test]
 fn insert_skips_lone_glob_imports() {
     check(
         "use foo::baz::A",
@@ -813,7 +877,7 @@ fn merge_groups_skip_pub_crate() {
 }
 
 #[test]
-fn merge_groups_skip_attributed() {
+fn merge_groups_cfg_vs_no_cfg() {
     check_crate(
         "std::io",
         r#"
@@ -837,6 +901,25 @@ fn merge_groups_skip_attributed() {
 }
 
 #[test]
+fn merge_groups_cfg_matching() {
+    check_crate(
+        "std::io",
+        r#"
+#[cfg(feature = "gated")] use std::fmt::{Result, Display};
+
+#[cfg(feature = "gated")]
+fn f($0) {}
+"#,
+        r#"
+#[cfg(feature = "gated")] use std::{fmt::{Display, Result}, io};
+
+#[cfg(feature = "gated")]
+fn f() {}
+"#,
+    );
+}
+
+#[test]
 fn split_out_merge() {
     // FIXME: This is suboptimal, we want to get `use std::fmt::{self, Result}`
     // instead.
@@ -1259,12 +1342,14 @@ fn check_with_config(
     };
     let sema = &Semantics::new(&db);
     let source_file = sema.parse(file_id);
-    let syntax = source_file.syntax().clone_for_update();
     let file = pos
-        .and_then(|pos| syntax.token_at_offset(pos.expect_offset()).next()?.parent())
+        .and_then(|pos| source_file.syntax().token_at_offset(pos.expect_offset()).next()?.parent())
         .and_then(|it| ImportScope::find_insert_use_container(&it, sema))
-        .or_else(|| ImportScope::from(syntax))
-        .unwrap();
+        .unwrap_or_else(|| ImportScope {
+            kind: ImportScopeKind::File(source_file),
+            required_cfgs: vec![],
+        })
+        .clone_for_update();
     let path = ast::SourceFile::parse(&format!("use {path};"), span::Edition::CURRENT)
         .tree()
         .syntax()
@@ -1349,7 +1434,7 @@ fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior
 }
 
 fn check_guess(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected: ImportGranularityGuess) {
-    let syntax = ast::SourceFile::parse(ra_fixture, span::Edition::CURRENT).tree().syntax().clone();
-    let file = ImportScope::from(syntax).unwrap();
+    let syntax = ast::SourceFile::parse(ra_fixture, span::Edition::CURRENT).tree();
+    let file = ImportScope { kind: ImportScopeKind::File(syntax), required_cfgs: vec![] };
     assert_eq!(super::guess_granularity_from_scope(&file), expected);
 }
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
index d4ab759..c5ad64e 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
@@ -961,12 +961,16 @@ pub fn search(&self, sink: &mut dyn FnMut(EditionedFileId, FileReference) -> boo
             // Search for occurrences of the items name
             for offset in Self::match_indices(&text, finder, search_range) {
                 let ret = tree.token_at_offset(offset).any(|token| {
-                    let Some(str_token) = ast::String::cast(token.clone()) else { return false };
-                    if let Some((range, Some(nameres))) =
-                        sema.check_for_format_args_template(token, offset)
+                    if let Some((range, _frange, string_token, Some(nameres))) =
+                        sema.check_for_format_args_template(token.clone(), offset)
                     {
-                        return self
-                            .found_format_args_ref(file_id, range, str_token, nameres, sink);
+                        return self.found_format_args_ref(
+                            file_id,
+                            range,
+                            string_token,
+                            nameres,
+                            sink,
+                        );
                     }
                     false
                 });
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs
index b1b58d6..16c0d8d 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs
@@ -5,6 +5,7 @@
 
 use std::{collections::hash_map::Entry, fmt, iter, mem};
 
+use crate::imports::insert_use::{ImportScope, ImportScopeKind};
 use crate::text_edit::{TextEdit, TextEditBuilder};
 use crate::{SnippetCap, assists::Command, syntax_helpers::tree_diff::diff};
 use base_db::AnchoredPathBuf;
@@ -367,6 +368,17 @@ fn commit(&mut self) {
     pub fn make_mut<N: AstNode>(&mut self, node: N) -> N {
         self.mutated_tree.get_or_insert_with(|| TreeMutator::new(node.syntax())).make_mut(&node)
     }
+
+    pub fn make_import_scope_mut(&mut self, scope: ImportScope) -> ImportScope {
+        ImportScope {
+            kind: match scope.kind.clone() {
+                ImportScopeKind::File(it) => ImportScopeKind::File(self.make_mut(it)),
+                ImportScopeKind::Module(it) => ImportScopeKind::Module(self.make_mut(it)),
+                ImportScopeKind::Block(it) => ImportScopeKind::Block(self.make_mut(it)),
+            },
+            required_cfgs: scope.required_cfgs.iter().map(|it| self.make_mut(it.clone())).collect(),
+        }
+    }
     /// Returns a copy of the `node`, suitable for mutation.
     ///
     /// Syntax trees in rust-analyzer are typically immutable, and mutating
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
index ac1b599..87c9397 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
@@ -137,11 +137,7 @@ pub(crate) fn json_in_items(
                     )
                     .with_fixes(Some(vec![{
                         let mut scb = SourceChangeBuilder::new(vfs_file_id);
-                        let scope = match import_scope {
-                            ImportScope::File(it) => ImportScope::File(scb.make_mut(it)),
-                            ImportScope::Module(it) => ImportScope::Module(scb.make_mut(it)),
-                            ImportScope::Block(it) => ImportScope::Block(scb.make_mut(it)),
-                        };
+                        let scope = scb.make_import_scope_mut(import_scope);
                         let current_module = semantics_scope.module();
 
                         let cfg = ImportPathConfig {
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
index c60ca35..7917aab 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
@@ -67,7 +67,7 @@ pub(crate) fn goto_definition(
         });
     }
 
-    if let Some((range, resolution)) =
+    if let Some((range, _, _, resolution)) =
         sema.check_for_format_args_template(original_token.clone(), offset)
     {
         return Some(RangeInfo::new(
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs
index a78f5cd..a6c7ea2 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs
@@ -53,7 +53,9 @@ pub(crate) fn goto_type_definition(
             }
         });
     };
-    if let Some((range, resolution)) = sema.check_for_format_args_template(token.clone(), offset) {
+    if let Some((range, _, _, resolution)) =
+        sema.check_for_format_args_template(token.clone(), offset)
+    {
         if let Some(ty) = resolution.and_then(|res| match Definition::from(res) {
             Definition::Const(it) => Some(it.ty(db)),
             Definition::Static(it) => Some(it.ty(db)),
diff --git a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
index 520ba39..aa94792 100644
--- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
@@ -11,7 +11,6 @@
         preorder_expr_with_ctx_checker,
     },
 };
-use span::FileId;
 use syntax::{
     AstNode,
     SyntaxKind::{self, IDENT, INT_NUMBER},
@@ -61,13 +60,12 @@ pub(crate) fn highlight_related(
     let file_id = sema
         .attach_first_edition(file_id)
         .unwrap_or_else(|| EditionedFileId::current_edition(sema.db, file_id));
-    let span_file_id = file_id.editioned_file_id(sema.db);
     let syntax = sema.parse(file_id).syntax().clone();
 
     let token = pick_best_token(syntax.token_at_offset(offset), |kind| match kind {
         T![?] => 4, // prefer `?` when the cursor is sandwiched like in `await$0?`
         T![->] => 4,
-        kind if kind.is_keyword(span_file_id.edition()) => 3,
+        kind if kind.is_keyword(file_id.edition(sema.db)) => 3,
         IDENT | INT_NUMBER => 2,
         T![|] => 1,
         _ => 0,
@@ -92,18 +90,11 @@ pub(crate) fn highlight_related(
         T![unsafe] if token.parent().and_then(ast::BlockExpr::cast).is_some() => {
             highlight_unsafe_points(sema, token).remove(&file_id)
         }
-        T![|] if config.closure_captures => {
-            highlight_closure_captures(sema, token, file_id, span_file_id.file_id())
+        T![|] if config.closure_captures => highlight_closure_captures(sema, token, file_id),
+        T![move] if config.closure_captures => highlight_closure_captures(sema, token, file_id),
+        _ if config.references => {
+            highlight_references(sema, token, FilePosition { file_id, offset })
         }
-        T![move] if config.closure_captures => {
-            highlight_closure_captures(sema, token, file_id, span_file_id.file_id())
-        }
-        _ if config.references => highlight_references(
-            sema,
-            token,
-            FilePosition { file_id, offset },
-            span_file_id.file_id(),
-        ),
         _ => None,
     }
 }
@@ -112,7 +103,6 @@ fn highlight_closure_captures(
     sema: &Semantics<'_, RootDatabase>,
     token: SyntaxToken,
     file_id: EditionedFileId,
-    vfs_file_id: FileId,
 ) -> Option<Vec<HighlightedRange>> {
     let closure = token.parent_ancestors().take(2).find_map(ast::ClosureExpr::cast)?;
     let search_range = closure.body()?.syntax().text_range();
@@ -145,7 +135,7 @@ fn highlight_closure_captures(
                     .sources(sema.db)
                     .into_iter()
                     .flat_map(|x| x.to_nav(sema.db))
-                    .filter(|decl| decl.file_id == vfs_file_id)
+                    .filter(|decl| decl.file_id == file_id.file_id(sema.db))
                     .filter_map(|decl| decl.focus_range)
                     .map(move |range| HighlightedRange { range, category })
                     .chain(usages)
@@ -158,9 +148,8 @@ fn highlight_references(
     sema: &Semantics<'_, RootDatabase>,
     token: SyntaxToken,
     FilePosition { file_id, offset }: FilePosition,
-    vfs_file_id: FileId,
 ) -> Option<Vec<HighlightedRange>> {
-    let defs = if let Some((range, resolution)) =
+    let defs = if let Some((range, _, _, resolution)) =
         sema.check_for_format_args_template(token.clone(), offset)
     {
         match resolution.map(Definition::from) {
@@ -270,7 +259,7 @@ fn highlight_references(
                     .sources(sema.db)
                     .into_iter()
                     .flat_map(|x| x.to_nav(sema.db))
-                    .filter(|decl| decl.file_id == vfs_file_id)
+                    .filter(|decl| decl.file_id == file_id.file_id(sema.db))
                     .filter_map(|decl| decl.focus_range)
                     .map(|range| HighlightedRange { range, category })
                     .for_each(|x| {
@@ -288,7 +277,7 @@ fn highlight_references(
                     },
                 };
                 for nav in navs {
-                    if nav.file_id != vfs_file_id {
+                    if nav.file_id != file_id.file_id(sema.db) {
                         continue;
                     }
                     let hl_range = nav.focus_range.map(|range| {
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 8bb1c70..5404a9d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -200,7 +200,7 @@ fn hover_offset(
         });
     }
 
-    if let Some((range, resolution)) =
+    if let Some((range, _, _, resolution)) =
         sema.check_for_format_args_template(original_token.clone(), offset)
     {
         let res = hover_for_definition(
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index d649dff..82dbcde 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -514,7 +514,6 @@ pub fn goto_type_definition(
         self.with_db(|db| goto_type_definition::goto_type_definition(db, position))
     }
 
-    /// Finds all usages of the reference at point.
     pub fn find_all_refs(
         &self,
         position: FilePosition,
diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs
index 4fa1164..c6a323d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/references.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/references.rs
@@ -8,6 +8,14 @@
 //! for text occurrences of the identifier. If there's an `ast::NameRef`
 //! at the index that the match starts at and its tree parent is
 //! resolved to the search element definition, we get a reference.
+//!
+//! Special handling for constructors/initializations:
+//! When searching for references to a struct/enum/variant, if the cursor is positioned on:
+//! - `{` after a struct/enum/variant definition
+//! - `(` for tuple structs/variants
+//! - `;` for unit structs
+//! - The type name in a struct/enum/variant definition
+//!   Then only constructor/initialization usages will be shown, filtering out other references.
 
 use hir::{PathResolution, Semantics};
 use ide_db::{
@@ -28,27 +36,76 @@
 
 use crate::{FilePosition, HighlightedRange, NavigationTarget, TryToNav, highlight_related};
 
+/// Result of a reference search operation.
 #[derive(Debug, Clone)]
 pub struct ReferenceSearchResult {
+    /// Information about the declaration site of the searched item.
+    /// For ADTs (structs/enums), this points to the type definition.
+    /// May be None for primitives or items without clear declaration sites.
     pub declaration: Option<Declaration>,
+    /// All references found, grouped by file.
+    /// For ADTs when searching from a constructor position (e.g. on '{', '(', ';'),
+    /// this only includes constructor/initialization usages.
+    /// The map key is the file ID, and the value is a vector of (range, category) pairs.
+    /// - range: The text range of the reference in the file
+    /// - category: Metadata about how the reference is used (read/write/etc)
     pub references: IntMap<FileId, Vec<(TextRange, ReferenceCategory)>>,
 }
 
+/// Information about the declaration site of a searched item.
 #[derive(Debug, Clone)]
 pub struct Declaration {
+    /// Navigation information to jump to the declaration
     pub nav: NavigationTarget,
+    /// Whether the declared item is mutable (relevant for variables)
     pub is_mut: bool,
 }
 
 // Feature: Find All References
 //
-// Shows all references of the item at the cursor location
+// Shows all references of the item at the cursor location. This includes:
+// - Direct references to variables, functions, types, etc.
+// - Constructor/initialization references when cursor is on struct/enum definition tokens
+// - References in patterns and type contexts
+// - References through dereferencing and borrowing
+// - References in macro expansions
+//
+// Special handling for constructors:
+// - When the cursor is on `{`, `(`, or `;` in a struct/enum definition
+// - When the cursor is on the type name in a struct/enum definition
+// These cases will show only constructor/initialization usages of the type
 //
 // | Editor  | Shortcut |
 // |---------|----------|
 // | VS Code | <kbd>Shift+Alt+F12</kbd> |
 //
 // ![Find All References](https://user-images.githubusercontent.com/48062697/113020670-b7c34f00-917a-11eb-8003-370ac5f2b3cb.gif)
+
+/// Find all references to the item at the given position.
+///
+/// # Arguments
+/// * `sema` - Semantic analysis context
+/// * `position` - Position in the file where to look for the item
+/// * `search_scope` - Optional scope to limit the search (e.g. current crate only)
+///
+/// # Returns
+/// Returns `None` if no valid item is found at the position.
+/// Otherwise returns a vector of `ReferenceSearchResult`, usually with one element.
+/// Multiple results can occur in case of ambiguity or when searching for trait items.
+///
+/// # Special cases
+/// - Control flow keywords (break, continue, etc): Shows all related jump points
+/// - Constructor search: When on struct/enum definition tokens (`{`, `(`, `;`), shows only initialization sites
+/// - Format string arguments: Shows template parameter usages
+/// - Lifetime parameters: Shows lifetime constraint usages
+///
+/// # Constructor search
+/// When the cursor is on specific tokens in a struct/enum definition:
+/// - `{` after struct/enum/variant: Shows record literal initializations
+/// - `(` after tuple struct/variant: Shows tuple literal initializations
+/// - `;` after unit struct: Shows unit literal initializations
+/// - Type name in definition: Shows all initialization usages
+///   In these cases, other kinds of references (like type references) are filtered out.
 pub(crate) fn find_all_refs(
     sema: &Semantics<'_, RootDatabase>,
     position: FilePosition,
@@ -143,7 +200,7 @@ pub(crate) fn find_defs(
         )
     })?;
 
-    if let Some((_, resolution)) = sema.check_for_format_args_template(token.clone(), offset) {
+    if let Some((.., resolution)) = sema.check_for_format_args_template(token.clone(), offset) {
         return resolution.map(Definition::from).map(|it| vec![it]);
     }
 
@@ -219,7 +276,19 @@ fn retain_adt_literal_usages(
     }
 }
 
-/// Returns `Some` if the cursor is at a position for an item to search for all its constructor/literal usages
+/// Returns `Some` if the cursor is at a position where we should search for constructor/initialization usages.
+/// This is used to implement the special constructor search behavior when the cursor is on specific tokens
+/// in a struct/enum/variant definition.
+///
+/// # Returns
+/// - `Some(name)` if the cursor is on:
+///   - `{` after a struct/enum/variant definition
+///   - `(` for tuple structs/variants
+///   - `;` for unit structs
+///   - The type name in a struct/enum/variant definition
+/// - `None` otherwise
+///
+/// The returned name is the name of the type whose constructor usages should be searched for.
 fn name_for_constructor_search(syntax: &SyntaxNode, position: FilePosition) -> Option<ast::Name> {
     let token = syntax.token_at_offset(position.offset).right_biased()?;
     let token_parent = token.parent()?;
@@ -257,6 +326,16 @@ fn name_for_constructor_search(syntax: &SyntaxNode, position: FilePosition) -> O
     }
 }
 
+/// Checks if a name reference is part of an enum variant literal expression.
+/// Used to filter references when searching for enum variant constructors.
+///
+/// # Arguments
+/// * `sema` - Semantic analysis context
+/// * `enum_` - The enum type to check against
+/// * `name_ref` - The name reference to check
+///
+/// # Returns
+/// `true` if the name reference is used as part of constructing a variant of the given enum.
 fn is_enum_lit_name_ref(
     sema: &Semantics<'_, RootDatabase>,
     enum_: hir::Enum,
@@ -284,12 +363,19 @@ fn is_enum_lit_name_ref(
         .unwrap_or(false)
 }
 
+/// Checks if a path ends with the given name reference.
+/// Helper function for checking constructor usage patterns.
 fn path_ends_with(path: Option<ast::Path>, name_ref: &ast::NameRef) -> bool {
     path.and_then(|path| path.segment())
         .and_then(|segment| segment.name_ref())
         .map_or(false, |segment| segment == *name_ref)
 }
 
+/// Checks if a name reference is used in a literal (constructor) context.
+/// Used to filter references when searching for struct/variant constructors.
+///
+/// # Returns
+/// `true` if the name reference is used as part of a struct/variant literal expression.
 fn is_lit_name_ref(name_ref: &ast::NameRef) -> bool {
     name_ref.syntax().ancestors().find_map(|ancestor| {
         match_ast! {
diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs
index e6cda60..0423e3d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/rename.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs
@@ -203,7 +203,7 @@ fn find_definitions(
 ) -> RenameResult<impl Iterator<Item = (FileRange, SyntaxKind, Definition)>> {
     let token = syntax.token_at_offset(offset).find(|t| matches!(t.kind(), SyntaxKind::STRING));
 
-    if let Some((range, Some(resolution))) =
+    if let Some((range, _, _, Some(resolution))) =
         token.and_then(|token| sema.check_for_format_args_template(token, offset))
     {
         return Ok(vec![(
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
index e1bc763..3ca1729 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
@@ -542,7 +542,7 @@ fn descend_token(
 
     let mut t = None;
     let mut r = 0;
-    sema.descend_into_macros_breakable(token.clone(), |tok, _ctx| {
+    sema.descend_into_macros_breakable(token.clone().into(), |tok, _ctx| {
         // FIXME: Consider checking ctx transparency for being opaque?
         let my_rank = ranker.rank_token(&tok.value);
 
diff --git a/src/tools/rust-analyzer/crates/mbe/src/tests.rs b/src/tools/rust-analyzer/crates/mbe/src/tests.rs
index 3369dff..769455f 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/tests.rs
@@ -74,7 +74,8 @@ fn check_(
         "{}",
         syntax_bridge::prettify_macro_expansion::prettify_macro_expansion(
             node.syntax_node(),
-            &mut |it| it.clone()
+            &mut |_| None,
+            |_| ()
         )
     );
     expect.assert_eq(&expect_res);
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs
index f04ada3..40d0556 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs
@@ -6,7 +6,7 @@
 
 use ide_db::base_db::{
     DbPanicContext,
-    salsa::{self, Cancelled},
+    salsa::{self, Cancelled, UnexpectedCycle},
 };
 use lsp_server::{ExtractError, Response, ResponseError};
 use serde::{Serialize, de::DeserializeOwned};
@@ -349,11 +349,14 @@ fn thread_result_to_response<R>(
             let mut message = "request handler panicked".to_owned();
             if let Some(panic_message) = panic_message {
                 message.push_str(": ");
-                message.push_str(panic_message)
+                message.push_str(panic_message);
+            } else if let Some(cycle) = panic.downcast_ref::<UnexpectedCycle>() {
+                tracing::error!("{cycle}");
+                message.push_str(": unexpected cycle");
             } else if let Ok(cancelled) = panic.downcast::<Cancelled>() {
                 tracing::error!("Cancellation propagated out of salsa! This is a bug");
                 return Err(HandlerCancelledError::Inner(*cancelled));
-            }
+            };
 
             Ok(lsp_server::Response::new_err(
                 id,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs
index fb8a983..0275761 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs
@@ -103,6 +103,7 @@ pub(crate) fn file_range_uri(
 
 pub(crate) fn assist_kind(kind: lsp_types::CodeActionKind) -> Option<AssistKind> {
     let assist_kind = match &kind {
+        k if k == &lsp_types::CodeActionKind::EMPTY => AssistKind::Generate,
         k if k == &lsp_types::CodeActionKind::QUICKFIX => AssistKind::QuickFix,
         k if k == &lsp_types::CodeActionKind::REFACTOR => AssistKind::Refactor,
         k if k == &lsp_types::CodeActionKind::REFACTOR_EXTRACT => AssistKind::RefactorExtract,
diff --git a/src/tools/rust-analyzer/crates/span/src/lib.rs b/src/tools/rust-analyzer/crates/span/src/lib.rs
index 54f9090..f81648a 100644
--- a/src/tools/rust-analyzer/crates/span/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/span/src/lib.rs
@@ -112,7 +112,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 impl fmt::Debug for EditionedFileId {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_tuple("EditionedFileId").field(&self.file_id()).field(&self.edition()).finish()
+        f.debug_tuple("EditionedFileId")
+            .field(&self.file_id().index())
+            .field(&self.edition())
+            .finish()
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/syntax-bridge/src/prettify_macro_expansion.rs b/src/tools/rust-analyzer/crates/syntax-bridge/src/prettify_macro_expansion.rs
index e815e07..0a5c8df 100644
--- a/src/tools/rust-analyzer/crates/syntax-bridge/src/prettify_macro_expansion.rs
+++ b/src/tools/rust-analyzer/crates/syntax-bridge/src/prettify_macro_expansion.rs
@@ -7,6 +7,13 @@
     ted::{self, Position},
 };
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum PrettifyWsKind {
+    Space,
+    Indent(usize),
+    Newline,
+}
+
 /// Renders a [`SyntaxNode`] with whitespace inserted between tokens that require them.
 ///
 /// This is an internal API that is only exported because `mbe` needs it for tests and cannot depend
@@ -15,7 +22,8 @@
 #[deprecated = "use `hir_expand::prettify_macro_expansion()` instead"]
 pub fn prettify_macro_expansion(
     syn: SyntaxNode,
-    dollar_crate_replacement: &mut dyn FnMut(&SyntaxToken) -> SyntaxToken,
+    dollar_crate_replacement: &mut dyn FnMut(&SyntaxToken) -> Option<SyntaxToken>,
+    inspect_mods: impl FnOnce(&[(Position, PrettifyWsKind)]),
 ) -> SyntaxNode {
     let mut indent = 0;
     let mut last: Option<SyntaxKind> = None;
@@ -27,14 +35,12 @@ pub fn prettify_macro_expansion(
     let after = Position::after;
 
     let do_indent = |pos: fn(_) -> Position, token: &SyntaxToken, indent| {
-        (pos(token.clone()), make::tokens::whitespace(&" ".repeat(4 * indent)))
+        (pos(token.clone()), PrettifyWsKind::Indent(indent))
     };
-    let do_ws = |pos: fn(_) -> Position, token: &SyntaxToken| {
-        (pos(token.clone()), make::tokens::single_space())
-    };
-    let do_nl = |pos: fn(_) -> Position, token: &SyntaxToken| {
-        (pos(token.clone()), make::tokens::single_newline())
-    };
+    let do_ws =
+        |pos: fn(_) -> Position, token: &SyntaxToken| (pos(token.clone()), PrettifyWsKind::Space);
+    let do_nl =
+        |pos: fn(_) -> Position, token: &SyntaxToken| (pos(token.clone()), PrettifyWsKind::Newline);
 
     for event in syn.preorder_with_tokens() {
         let token = match event {
@@ -46,20 +52,19 @@ pub fn prettify_macro_expansion(
                 ) =>
             {
                 if indent > 0 {
-                    mods.push((
-                        Position::after(node.clone()),
-                        make::tokens::whitespace(&" ".repeat(4 * indent)),
-                    ));
+                    mods.push((Position::after(node.clone()), PrettifyWsKind::Indent(indent)));
                 }
                 if node.parent().is_some() {
-                    mods.push((Position::after(node), make::tokens::single_newline()));
+                    mods.push((Position::after(node), PrettifyWsKind::Newline));
                 }
                 continue;
             }
             _ => continue,
         };
         if token.kind() == SyntaxKind::IDENT && token.text() == "$crate" {
-            dollar_crate_replacements.push((token.clone(), dollar_crate_replacement(&token)));
+            if let Some(replacement) = dollar_crate_replacement(&token) {
+                dollar_crate_replacements.push((token.clone(), replacement));
+            }
         }
         let tok = &token;
 
@@ -129,8 +134,16 @@ pub fn prettify_macro_expansion(
         last = Some(tok.kind());
     }
 
+    inspect_mods(&mods);
     for (pos, insert) in mods {
-        ted::insert(pos, insert);
+        ted::insert_raw(
+            pos,
+            match insert {
+                PrettifyWsKind::Space => make::tokens::single_space(),
+                PrettifyWsKind::Indent(indent) => make::tokens::whitespace(&" ".repeat(4 * indent)),
+                PrettifyWsKind::Newline => make::tokens::single_newline(),
+            },
+        );
     }
     for (old, new) in dollar_crate_replacements {
         ted::replace(old, new);
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ted.rs b/src/tools/rust-analyzer/crates/syntax/src/ted.rs
index 64d5ea0..6fcbdd0 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ted.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ted.rs
@@ -5,6 +5,7 @@
 use std::{mem, ops::RangeInclusive};
 
 use parser::T;
+use rowan::TextSize;
 
 use crate::{
     SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken,
@@ -74,6 +75,12 @@ pub fn last_child_of(node: &(impl Into<SyntaxNode> + Clone)) -> Position {
         };
         Position { repr }
     }
+    pub fn offset(&self) -> TextSize {
+        match &self.repr {
+            PositionRepr::FirstChild(node) => node.text_range().start(),
+            PositionRepr::After(elem) => elem.text_range().end(),
+        }
+    }
 }
 
 pub fn insert(position: Position, elem: impl Element) {
@@ -207,5 +214,12 @@ fn ws_between(left: &SyntaxElement, right: &SyntaxElement) -> Option<SyntaxToken
         }
         return Some(make::tokens::whitespace(&format!("\n{indent}")));
     }
+    if left.kind() == SyntaxKind::ATTR {
+        let mut indent = IndentLevel::from_element(right);
+        if right.kind() == SyntaxKind::ATTR {
+            indent.0 = IndentLevel::from_element(left).0.max(indent.0);
+        }
+        return Some(make::tokens::whitespace(&format!("\n{indent}")));
+    }
     Some(make::tokens::single_space())
 }
diff --git a/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs b/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs
index c35b7f2..7e2c787 100644
--- a/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs
+++ b/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs
@@ -39,6 +39,13 @@ pub fn as_path(&self) -> Option<&AbsPath> {
         }
     }
 
+    pub fn into_abs_path(self) -> Option<AbsPathBuf> {
+        match self.0 {
+            VfsPathRepr::PathBuf(it) => Some(it),
+            VfsPathRepr::VirtualPath(_) => None,
+        }
+    }
+
     /// Creates a new `VfsPath` with `path` adjoined to `self`.
     pub fn join(&self, path: &str) -> Option<VfsPath> {
         match &self.0 {
diff --git a/src/tools/rust-analyzer/xtask/src/codegen.rs b/src/tools/rust-analyzer/xtask/src/codegen.rs
index bba7ad7..19ca62e 100644
--- a/src/tools/rust-analyzer/xtask/src/codegen.rs
+++ b/src/tools/rust-analyzer/xtask/src/codegen.rs
@@ -24,8 +24,8 @@ pub(crate) fn run(self, _sh: &Shell) -> anyhow::Result<()> {
                 grammar::generate(self.check);
                 assists_doc_tests::generate(self.check);
                 parser_inline_tests::generate(self.check);
-                feature_docs::generate(self.check)
-                // diagnostics_docs::generate(self.check) doesn't generate any tests
+                feature_docs::generate(self.check);
+                diagnostics_docs::generate(self.check);
                 // lints::generate(self.check) Updating clones the rust repo, so don't run it unless
                 // explicitly asked for
             }
diff --git a/tests/crashes/140255.rs b/tests/crashes/140255.rs
deleted file mode 100644
index 6b0ec17..0000000
--- a/tests/crashes/140255.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-//@ known-bug: #140255
-#[unsafe(macro_use::VAR2)]
-fn dead_code() {}
diff --git a/tests/ui/attributes/auxiliary/external-macro-use.rs b/tests/ui/attributes/auxiliary/external-macro-use.rs
new file mode 100644
index 0000000..beeb7fe
--- /dev/null
+++ b/tests/ui/attributes/auxiliary/external-macro-use.rs
@@ -0,0 +1,7 @@
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn a(_: TokenStream, input: TokenStream) -> TokenStream {
+   input
+}
diff --git a/tests/ui/attributes/illegal-macro-use.rs b/tests/ui/attributes/illegal-macro-use.rs
new file mode 100644
index 0000000..5a56710
--- /dev/null
+++ b/tests/ui/attributes/illegal-macro-use.rs
@@ -0,0 +1,15 @@
+// issue#140255
+
+#[macro_use::a]       //~ ERROR failed to resolve: use of unresolved module or unlinked crate `macro_use`
+fn f0() {}
+
+#[macro_use::a::b]    //~ ERROR failed to resolve: use of unresolved module or unlinked crate `macro_use`
+fn f1() {}
+
+#[macro_escape::a]    //~ ERROR failed to resolve: use of unresolved module or unlinked crate `macro_escape`
+fn f2() {}
+
+#[macro_escape::a::b] //~ ERROR failed to resolve: use of unresolved module or unlinked crate `macro_escape`
+fn f3() {}
+
+fn main() {}
diff --git a/tests/ui/attributes/illegal-macro-use.stderr b/tests/ui/attributes/illegal-macro-use.stderr
new file mode 100644
index 0000000..fa6bb83
--- /dev/null
+++ b/tests/ui/attributes/illegal-macro-use.stderr
@@ -0,0 +1,27 @@
+error[E0433]: failed to resolve: use of unresolved module or unlinked crate `macro_escape`
+  --> $DIR/illegal-macro-use.rs:12:3
+   |
+LL | #[macro_escape::a::b]
+   |   ^^^^^^^^^^^^ use of unresolved module or unlinked crate `macro_escape`
+
+error[E0433]: failed to resolve: use of unresolved module or unlinked crate `macro_escape`
+  --> $DIR/illegal-macro-use.rs:9:3
+   |
+LL | #[macro_escape::a]
+   |   ^^^^^^^^^^^^ use of unresolved module or unlinked crate `macro_escape`
+
+error[E0433]: failed to resolve: use of unresolved module or unlinked crate `macro_use`
+  --> $DIR/illegal-macro-use.rs:6:3
+   |
+LL | #[macro_use::a::b]
+   |   ^^^^^^^^^ use of unresolved module or unlinked crate `macro_use`
+
+error[E0433]: failed to resolve: use of unresolved module or unlinked crate `macro_use`
+  --> $DIR/illegal-macro-use.rs:3:3
+   |
+LL | #[macro_use::a]
+   |   ^^^^^^^^^ use of unresolved module or unlinked crate `macro_use`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/attributes/use-extern-crate-named-macro-use.rs b/tests/ui/attributes/use-extern-crate-named-macro-use.rs
new file mode 100644
index 0000000..5b322cc
--- /dev/null
+++ b/tests/ui/attributes/use-extern-crate-named-macro-use.rs
@@ -0,0 +1,11 @@
+//@ check-pass
+//@ proc-macro: external-macro-use.rs
+
+// issue#140255
+
+extern crate external_macro_use as macro_use;
+
+#[macro_use::a]
+fn f() {}
+
+fn main() {}
diff --git a/tests/ui/resolve/extern-crate-lint-issue-141785.rs b/tests/ui/resolve/extern-crate-lint-issue-141785.rs
new file mode 100644
index 0000000..8d044d6
--- /dev/null
+++ b/tests/ui/resolve/extern-crate-lint-issue-141785.rs
@@ -0,0 +1,11 @@
+//@ check-pass
+//@ edition:2018
+
+#![no_implicit_prelude]
+#![warn(unused_extern_crates)]
+
+extern crate std;
+fn main() {
+    let r = 1u16..10;
+    std::println!("{:?}", r.is_empty());
+}