From 9f5d31ef862489ea87bf3e52812d05b1a700de47 Mon Sep 17 00:00:00 2001
From: y21 <30553356+y21@users.noreply.github.com>
Date: Fri, 29 Mar 2024 16:24:07 +0100
Subject: [PATCH 01/47] clear `DefId` when an expression's type changes to
 non-adt

---
 clippy_utils/src/ty/type_certainty/mod.rs |  2 +-
 tests/ui/crashes/ice-12585.rs             | 26 +++++++++++++++++++++++
 2 files changed, 27 insertions(+), 1 deletion(-)
 create mode 100644 tests/ui/crashes/ice-12585.rs

diff --git a/clippy_utils/src/ty/type_certainty/mod.rs b/clippy_utils/src/ty/type_certainty/mod.rs
index 7913926928f..ad50786eece 100644
--- a/clippy_utils/src/ty/type_certainty/mod.rs
+++ b/clippy_utils/src/ty/type_certainty/mod.rs
@@ -90,7 +90,7 @@ fn expr_type_certainty(cx: &LateContext<'_>, expr: &Expr<'_>) -> Certainty {
     if let Some(def_id) = adt_def_id(expr_ty) {
         certainty.with_def_id(def_id)
     } else {
-        certainty
+        certainty.clear_def_id()
     }
 }
 
diff --git a/tests/ui/crashes/ice-12585.rs b/tests/ui/crashes/ice-12585.rs
new file mode 100644
index 00000000000..7928115c0a9
--- /dev/null
+++ b/tests/ui/crashes/ice-12585.rs
@@ -0,0 +1,26 @@
+#![allow(clippy::unit_arg)]
+
+struct One {
+    x: i32,
+}
+struct Two {
+    x: i32,
+}
+
+struct Product {}
+
+impl Product {
+    pub fn a_method(self, _: ()) {}
+}
+
+fn from_array(_: [i32; 2]) -> Product {
+    todo!()
+}
+
+pub fn main() {
+    let one = One { x: 1 };
+    let two = Two { x: 2 };
+
+    let product = from_array([one.x, two.x]);
+    product.a_method(<()>::default());
+}

From 24e1071d21bc41d3224f4fedcd9779b45ebf62f3 Mon Sep 17 00:00:00 2001
From: Michael Howell <michael@notriddle.com>
Date: Fri, 29 Mar 2024 13:34:01 -0700
Subject: [PATCH 02/47] clippy: fix up `include_str!` spans in diagnostics

---
 clippy_lints/src/large_include_file.rs                |  2 +-
 clippy_lints/src/strings.rs                           |  2 +-
 .../large_include_file/large_include_file.stderr      |  2 --
 tests/ui/empty_docs.stderr                            | 11 ++++++-----
 4 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/clippy_lints/src/large_include_file.rs b/clippy_lints/src/large_include_file.rs
index 1b5981ecc28..553d447d440 100644
--- a/clippy_lints/src/large_include_file.rs
+++ b/clippy_lints/src/large_include_file.rs
@@ -71,7 +71,7 @@ impl LateLintPass<'_> for LargeIncludeFile {
             span_lint_and_note(
                 cx,
                 LARGE_INCLUDE_FILE,
-                expr.span,
+                expr.span.source_callsite(),
                 "attempted to include a large file",
                 None,
                 &format!(
diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs
index 13ae1ff52dd..21790134854 100644
--- a/clippy_lints/src/strings.rs
+++ b/clippy_lints/src/strings.rs
@@ -300,7 +300,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
                     e.span,
                     "calling `as_bytes()` on `include_str!(..)`",
                     "consider using `include_bytes!(..)` instead",
-                    snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability).replacen(
+                    snippet_with_applicability(cx, receiver.span.source_callsite(), r#""foo""#, &mut applicability).replacen(
                         "include_str",
                         "include_bytes",
                         1,
diff --git a/tests/ui-toml/large_include_file/large_include_file.stderr b/tests/ui-toml/large_include_file/large_include_file.stderr
index b45cb11939f..34224065f07 100644
--- a/tests/ui-toml/large_include_file/large_include_file.stderr
+++ b/tests/ui-toml/large_include_file/large_include_file.stderr
@@ -7,7 +7,6 @@ LL | const TOO_BIG_INCLUDE_BYTES: &[u8; 654] = include_bytes!("too_big.txt");
    = note: the configuration allows a maximum size of 600 bytes
    = note: `-D clippy::large-include-file` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::large_include_file)]`
-   = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: attempted to include a large file
   --> tests/ui-toml/large_include_file/large_include_file.rs:14:35
@@ -16,7 +15,6 @@ LL | const TOO_BIG_INCLUDE_STR: &str = include_str!("too_big.txt");
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the configuration allows a maximum size of 600 bytes
-   = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/empty_docs.stderr b/tests/ui/empty_docs.stderr
index 28ebea22c5d..5fd7272d7c1 100644
--- a/tests/ui/empty_docs.stderr
+++ b/tests/ui/empty_docs.stderr
@@ -25,19 +25,20 @@ LL |         ///
    = help: consider removing or filling it
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:30:5
+  --> tests/ui/empty_docs.rs:30:13
    |
 LL |     #[doc = ""]
-   |     ^^^^^^^^^^^
+   |             ^^
    |
    = help: consider removing or filling it
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:33:5
+  --> tests/ui/empty_docs.rs:33:13
    |
-LL | /     #[doc = ""]
+LL |       #[doc = ""]
+   |  _____________^
 LL | |     #[doc = ""]
-   | |_______________^
+   | |______________^
    |
    = help: consider removing or filling it
 

From 9d4a36841ae998579a98c919c31dd25fba2b5ee5 Mon Sep 17 00:00:00 2001
From: Alex Macleod <alex@macleod.io>
Date: Mon, 1 Apr 2024 13:18:27 +0000
Subject: [PATCH 03/47] Reword `arc_with_non_send_sync` note and help messages

---
 clippy_lints/src/arc_with_non_send_sync.rs | 26 ++++++++-----------
 tests/ui/arc_with_non_send_sync.rs         |  7 ------
 tests/ui/arc_with_non_send_sync.stderr     | 29 ++++++++--------------
 3 files changed, 22 insertions(+), 40 deletions(-)

diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs
index 1102c7fb236..38933897389 100644
--- a/clippy_lints/src/arc_with_non_send_sync.rs
+++ b/clippy_lints/src/arc_with_non_send_sync.rs
@@ -56,7 +56,12 @@ impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync {
             && let Some(send) = cx.tcx.get_diagnostic_item(sym::Send)
             && let Some(sync) = cx.tcx.lang_items().sync_trait()
             && let [is_send, is_sync] = [send, sync].map(|id| implements_trait(cx, arg_ty, id, &[]))
-            && !(is_send && is_sync)
+            && let reason = match (is_send, is_sync) {
+                (false, false) => "neither `Send` nor `Sync`",
+                (false, true) => "not `Send`",
+                (true, false) => "not `Sync`",
+                _ => return,
+            }
             && !is_from_proc_macro(cx, expr)
         {
             span_lint_and_then(
@@ -66,21 +71,12 @@ impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync {
                 "usage of an `Arc` that is not `Send` and `Sync`",
                 |diag| {
                     with_forced_trimmed_paths!({
-                        diag.note(format!("`Arc<{arg_ty}>` is not `Send` and `Sync` as:"));
-
-                        if !is_send {
-                            diag.note(format!("- the trait `Send` is not implemented for `{arg_ty}`"));
-                        }
-                        if !is_sync {
-                            diag.note(format!("- the trait `Sync` is not implemented for `{arg_ty}`"));
-                        }
-
-                        diag.help("consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types");
-
-                        diag.note("if you intend to use `Arc` with `Send` and `Sync` traits");
-
                         diag.note(format!(
-                            "wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `{arg_ty}`"
+                            "`Arc<{arg_ty}>` is not `Send` and `Sync` as `{arg_ty}` is {reason}"
+                        ));
+                        diag.help("if the `Arc` will not used be across threads replace it with an `Rc`");
+                        diag.help(format!(
+                            "otherwise make `{arg_ty}` `Send` and `Sync` or consider a wrapper type such as `Mutex`"
                         ));
                     });
                 },
diff --git a/tests/ui/arc_with_non_send_sync.rs b/tests/ui/arc_with_non_send_sync.rs
index 349e81912e3..c287480bb1f 100644
--- a/tests/ui/arc_with_non_send_sync.rs
+++ b/tests/ui/arc_with_non_send_sync.rs
@@ -33,16 +33,9 @@ fn main() {
     let _ = Arc::new(42);
 
     let _ = Arc::new(RefCell::new(42));
-    //~^ ERROR: usage of an `Arc` that is not `Send` and `Sync`
-    //~| NOTE: the trait `Sync` is not implemented for `RefCell<i32>`
 
     let mutex = Mutex::new(1);
     let _ = Arc::new(mutex.lock().unwrap());
-    //~^ ERROR: usage of an `Arc` that is not `Send` and `Sync`
-    //~| NOTE: the trait `Send` is not implemented for `MutexGuard<'_, i32>`
 
     let _ = Arc::new(&42 as *const i32);
-    //~^ ERROR: usage of an `Arc` that is not `Send` and `Sync`
-    //~| NOTE: the trait `Send` is not implemented for `*const i32`
-    //~| NOTE: the trait `Sync` is not implemented for `*const i32`
 }
diff --git a/tests/ui/arc_with_non_send_sync.stderr b/tests/ui/arc_with_non_send_sync.stderr
index d4e63037620..da363a3ebdd 100644
--- a/tests/ui/arc_with_non_send_sync.stderr
+++ b/tests/ui/arc_with_non_send_sync.stderr
@@ -4,38 +4,31 @@ error: usage of an `Arc` that is not `Send` and `Sync`
 LL |     let _ = Arc::new(RefCell::new(42));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `Arc<RefCell<i32>>` is not `Send` and `Sync` as:
-   = note: - the trait `Sync` is not implemented for `RefCell<i32>`
-   = help: consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types
-   = note: if you intend to use `Arc` with `Send` and `Sync` traits
-   = note: wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `RefCell<i32>`
+   = note: `Arc<RefCell<i32>>` is not `Send` and `Sync` as `RefCell<i32>` is not `Sync`
+   = help: if the `Arc` will not used be across threads replace it with an `Rc`
+   = help: otherwise make `RefCell<i32>` `Send` and `Sync` or consider a wrapper type such as `Mutex`
    = note: `-D clippy::arc-with-non-send-sync` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::arc_with_non_send_sync)]`
 
 error: usage of an `Arc` that is not `Send` and `Sync`
-  --> tests/ui/arc_with_non_send_sync.rs:40:13
+  --> tests/ui/arc_with_non_send_sync.rs:38:13
    |
 LL |     let _ = Arc::new(mutex.lock().unwrap());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `Arc<MutexGuard<'_, i32>>` is not `Send` and `Sync` as:
-   = note: - the trait `Send` is not implemented for `MutexGuard<'_, i32>`
-   = help: consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types
-   = note: if you intend to use `Arc` with `Send` and `Sync` traits
-   = note: wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `MutexGuard<'_, i32>`
+   = note: `Arc<MutexGuard<'_, i32>>` is not `Send` and `Sync` as `MutexGuard<'_, i32>` is not `Send`
+   = help: if the `Arc` will not used be across threads replace it with an `Rc`
+   = help: otherwise make `MutexGuard<'_, i32>` `Send` and `Sync` or consider a wrapper type such as `Mutex`
 
 error: usage of an `Arc` that is not `Send` and `Sync`
-  --> tests/ui/arc_with_non_send_sync.rs:44:13
+  --> tests/ui/arc_with_non_send_sync.rs:40:13
    |
 LL |     let _ = Arc::new(&42 as *const i32);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `Arc<*const i32>` is not `Send` and `Sync` as:
-   = note: - the trait `Send` is not implemented for `*const i32`
-   = note: - the trait `Sync` is not implemented for `*const i32`
-   = help: consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types
-   = note: if you intend to use `Arc` with `Send` and `Sync` traits
-   = note: wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `*const i32`
+   = note: `Arc<*const i32>` is not `Send` and `Sync` as `*const i32` is neither `Send` nor `Sync`
+   = help: if the `Arc` will not used be across threads replace it with an `Rc`
+   = help: otherwise make `*const i32` `Send` and `Sync` or consider a wrapper type such as `Mutex`
 
 error: aborting due to 3 previous errors
 

From 6a6a917fe4ff067791c1926d75feac10847ed4be Mon Sep 17 00:00:00 2001
From: Aneesh Kadiyala <143342960+ARandomDev99@users.noreply.github.com>
Date: Mon, 1 Apr 2024 20:18:03 +0530
Subject: [PATCH 04/47] Check for `Default` trait in initial expression

---
 clippy_lints/src/manual_unwrap_or_default.rs |  9 +++++++++
 tests/ui/manual_unwrap_or_default.fixed      | 10 ++++++++++
 tests/ui/manual_unwrap_or_default.rs         | 10 ++++++++++
 tests/ui/manual_unwrap_or_default.stderr     |  2 +-
 4 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/clippy_lints/src/manual_unwrap_or_default.rs b/clippy_lints/src/manual_unwrap_or_default.rs
index c562ceb5bce..a4048e89926 100644
--- a/clippy_lints/src/manual_unwrap_or_default.rs
+++ b/clippy_lints/src/manual_unwrap_or_default.rs
@@ -3,6 +3,7 @@ use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatKind, QPath};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::ty::GenericArgKind;
 use rustc_session::declare_lint_pass;
 use rustc_span::sym;
 
@@ -118,6 +119,10 @@ fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
         && implements_trait(cx, match_ty, default_trait_id, &[])
         // We now get the bodies for both the `Some` and `None` arms.
         && let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2)
+        // We check that the initial expression also implies the `Default` trait.
+        && let Some(match_expr_ty) = cx.typeck_results().expr_ty(match_expr).walk().nth(1)
+        && let GenericArgKind::Type(match_expr_ty) = match_expr_ty.unpack()
+        && implements_trait(cx, match_expr_ty, default_trait_id, &[])
         // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
         && let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(body_some).kind
         && let Res::Local(local_id) = path.res
@@ -154,6 +159,10 @@ fn handle_if_let<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
         && implements_trait(cx, match_ty, default_trait_id, &[])
         && let Some(binding_id) = get_some(cx, let_.pat)
+        // We check that the initial expression also implies the `Default` trait.
+        && let Some(let_ty) = cx.typeck_results().expr_ty(let_.init).walk().nth(1)
+        && let GenericArgKind::Type(let_ty) = let_ty.unpack()
+        && implements_trait(cx, let_ty, default_trait_id, &[])
         // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
         && let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(if_block).kind
         && let Res::Local(local_id) = path.res
diff --git a/tests/ui/manual_unwrap_or_default.fixed b/tests/ui/manual_unwrap_or_default.fixed
index a0b707628a8..d6e736ba9cc 100644
--- a/tests/ui/manual_unwrap_or_default.fixed
+++ b/tests/ui/manual_unwrap_or_default.fixed
@@ -16,6 +16,16 @@ fn main() {
 
     let x: Option<Vec<String>> = None;
     x.unwrap_or_default();
+
+    // Issue #12564
+    // No error as &Vec<_> doesn't implement std::default::Default
+    let mut map = std::collections::HashMap::from([(0, vec![0; 3]), (1, vec![1; 3]), (2, vec![2])]);
+    let x: &[_] = if let Some(x) = map.get(&0) { x } else { &[] };
+    // Same code as above written using match.
+    let x: &[_] = match map.get(&0) {
+        Some(x) => x,
+        None => &[],
+    };
 }
 
 // Issue #12531
diff --git a/tests/ui/manual_unwrap_or_default.rs b/tests/ui/manual_unwrap_or_default.rs
index 1d4cca12f6c..462d5d90ee7 100644
--- a/tests/ui/manual_unwrap_or_default.rs
+++ b/tests/ui/manual_unwrap_or_default.rs
@@ -37,6 +37,16 @@ fn main() {
     } else {
         Vec::default()
     };
+
+    // Issue #12564
+    // No error as &Vec<_> doesn't implement std::default::Default
+    let mut map = std::collections::HashMap::from([(0, vec![0; 3]), (1, vec![1; 3]), (2, vec![2])]);
+    let x: &[_] = if let Some(x) = map.get(&0) { x } else { &[] };
+    // Same code as above written using match.
+    let x: &[_] = match map.get(&0) {
+        Some(x) => x,
+        None => &[],
+    };
 }
 
 // Issue #12531
diff --git a/tests/ui/manual_unwrap_or_default.stderr b/tests/ui/manual_unwrap_or_default.stderr
index d89212e6045..3f1da444301 100644
--- a/tests/ui/manual_unwrap_or_default.stderr
+++ b/tests/ui/manual_unwrap_or_default.stderr
@@ -53,7 +53,7 @@ LL | |     };
    | |_____^ help: replace it with: `x.unwrap_or_default()`
 
 error: match can be simplified with `.unwrap_or_default()`
-  --> tests/ui/manual_unwrap_or_default.rs:46:20
+  --> tests/ui/manual_unwrap_or_default.rs:56:20
    |
 LL |           Some(_) => match *b {
    |  ____________________^

From b2ea5eef445f16f02b9aea08a0bb8ff3e193762e Mon Sep 17 00:00:00 2001
From: Yuxiang Qiu <yuxqiu@proton.me>
Date: Thu, 4 Jan 2024 14:41:38 -0500
Subject: [PATCH 05/47] fix: incorrect suggestions when `.then` and
 `.then_some` is used

---
 clippy_lints/src/methods/search_is_some.rs  | 35 +++++++++++++++++----
 tests/ui/search_is_some_fixable_none.fixed  | 16 ++++++++++
 tests/ui/search_is_some_fixable_none.rs     | 16 ++++++++++
 tests/ui/search_is_some_fixable_none.stderr | 14 ++++++++-
 4 files changed, 74 insertions(+), 7 deletions(-)

diff --git a/clippy_lints/src/methods/search_is_some.rs b/clippy_lints/src/methods/search_is_some.rs
index ac5cc2f01e5..1ea2e93c9de 100644
--- a/clippy_lints/src/methods/search_is_some.rs
+++ b/clippy_lints/src/methods/search_is_some.rs
@@ -2,7 +2,8 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::sugg::deref_closure_args;
 use clippy_utils::ty::is_type_lang_item;
-use clippy_utils::{is_trait_method, strip_pat_refs};
+use clippy_utils::{get_parent_expr, is_trait_method, strip_pat_refs};
+use hir::ExprKind;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::PatKind;
@@ -72,16 +73,24 @@ pub(super) fn check<'tcx>(
                 );
             } else {
                 let iter = snippet(cx, search_recv.span, "..");
+                let sugg = if is_receiver_of_method_call(cx, expr) {
+                    format!(
+                        "(!{iter}.any({}))",
+                        any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
+                    )
+                } else {
+                    format!(
+                        "!{iter}.any({})",
+                        any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
+                    )
+                };
                 span_lint_and_sugg(
                     cx,
                     SEARCH_IS_SOME,
                     expr.span,
                     msg,
                     "consider using",
-                    format!(
-                        "!{iter}.any({})",
-                        any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
-                    ),
+                    sugg,
                     applicability,
                 );
             }
@@ -127,13 +136,18 @@ pub(super) fn check<'tcx>(
                     let string = snippet(cx, search_recv.span, "..");
                     let mut applicability = Applicability::MachineApplicable;
                     let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability);
+                    let sugg = if is_receiver_of_method_call(cx, expr) {
+                        format!("(!{string}.contains({find_arg}))")
+                    } else {
+                        format!("!{string}.contains({find_arg})")
+                    };
                     span_lint_and_sugg(
                         cx,
                         SEARCH_IS_SOME,
                         expr.span,
                         msg,
                         "consider using",
-                        format!("!{string}.contains({find_arg})"),
+                        sugg,
                         applicability,
                     );
                 },
@@ -142,3 +156,12 @@ pub(super) fn check<'tcx>(
         }
     }
 }
+
+fn is_receiver_of_method_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
+    if let Some(parent_expr) = get_parent_expr(cx, expr)
+        && let ExprKind::MethodCall(..) = parent_expr.kind
+    {
+        return true;
+    }
+    false
+}
diff --git a/tests/ui/search_is_some_fixable_none.fixed b/tests/ui/search_is_some_fixable_none.fixed
index 51636392f2b..3e5b3fab5ff 100644
--- a/tests/ui/search_is_some_fixable_none.fixed
+++ b/tests/ui/search_is_some_fixable_none.fixed
@@ -213,3 +213,19 @@ mod issue7392 {
         let _ = !v.iter().any(|fp| test_u32_2(*fp.field));
     }
 }
+
+mod issue_11910 {
+    fn computations() -> u32 {
+        0
+    }
+
+    fn test_then() {
+        let v = vec![3, 2, 1, 0, -1, -2, -3];
+        (!v.iter().any(|x| *x == 42)).then(computations);
+    }
+
+    fn test_then_some() {
+        let v = vec![3, 2, 1, 0, -1, -2, -3];
+        (!v.iter().any(|x| *x == 42)).then_some(0);
+    }
+}
diff --git a/tests/ui/search_is_some_fixable_none.rs b/tests/ui/search_is_some_fixable_none.rs
index c7d773e18a3..e77ae5cecc2 100644
--- a/tests/ui/search_is_some_fixable_none.rs
+++ b/tests/ui/search_is_some_fixable_none.rs
@@ -219,3 +219,19 @@ mod issue7392 {
         let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
     }
 }
+
+mod issue_11910 {
+    fn computations() -> u32 {
+        0
+    }
+
+    fn test_then() {
+        let v = vec![3, 2, 1, 0, -1, -2, -3];
+        v.iter().find(|x| **x == 42).is_none().then(computations);
+    }
+
+    fn test_then_some() {
+        let v = vec![3, 2, 1, 0, -1, -2, -3];
+        v.iter().find(|x| **x == 42).is_none().then_some(0);
+    }
+}
diff --git a/tests/ui/search_is_some_fixable_none.stderr b/tests/ui/search_is_some_fixable_none.stderr
index 4ad1e2508c4..240eb245cdd 100644
--- a/tests/ui/search_is_some_fixable_none.stderr
+++ b/tests/ui/search_is_some_fixable_none.stderr
@@ -282,5 +282,17 @@ error: called `is_none()` after searching an `Iterator` with `find`
 LL |         let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| test_u32_2(*fp.field))`
 
-error: aborting due to 43 previous errors
+error: called `is_none()` after searching an `Iterator` with `find`
+  --> $DIR/search_is_some_fixable_none.rs:230:9
+   |
+LL |         v.iter().find(|x| **x == 42).is_none().then(computations);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `(!v.iter().any(|x| *x == 42))`
+
+error: called `is_none()` after searching an `Iterator` with `find`
+  --> $DIR/search_is_some_fixable_none.rs:235:9
+   |
+LL |         v.iter().find(|x| **x == 42).is_none().then_some(0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `(!v.iter().any(|x| *x == 42))`
+
+error: aborting due to 45 previous errors
 

From 9d1f824878b08f7ad631b21b2c8bf42522af65c0 Mon Sep 17 00:00:00 2001
From: Yuxiang Qiu <yuxqiu@proton.me>
Date: Thu, 4 Jan 2024 20:29:41 -0500
Subject: [PATCH 06/47] fix: check if receiver's hir_id matches expr's hir_id

---
 clippy_lints/src/methods/search_is_some.rs  |  3 ++-
 tests/ui/search_is_some_fixable_none.fixed  |  9 +++++++++
 tests/ui/search_is_some_fixable_none.rs     |  9 +++++++++
 tests/ui/search_is_some_fixable_none.stderr | 12 +++++++++---
 4 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/clippy_lints/src/methods/search_is_some.rs b/clippy_lints/src/methods/search_is_some.rs
index 1ea2e93c9de..1e1a8f9060b 100644
--- a/clippy_lints/src/methods/search_is_some.rs
+++ b/clippy_lints/src/methods/search_is_some.rs
@@ -159,7 +159,8 @@ pub(super) fn check<'tcx>(
 
 fn is_receiver_of_method_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
     if let Some(parent_expr) = get_parent_expr(cx, expr)
-        && let ExprKind::MethodCall(..) = parent_expr.kind
+        && let ExprKind::MethodCall(_, receiver, ..) = parent_expr.kind
+        && receiver.hir_id == expr.hir_id
     {
         return true;
     }
diff --git a/tests/ui/search_is_some_fixable_none.fixed b/tests/ui/search_is_some_fixable_none.fixed
index 3e5b3fab5ff..e5c540e6723 100644
--- a/tests/ui/search_is_some_fixable_none.fixed
+++ b/tests/ui/search_is_some_fixable_none.fixed
@@ -219,6 +219,13 @@ mod issue_11910 {
         0
     }
 
+    struct Foo;
+    impl Foo{
+        fn bar(&self, _ : bool) {
+
+        }
+    }
+
     fn test_then() {
         let v = vec![3, 2, 1, 0, -1, -2, -3];
         (!v.iter().any(|x| *x == 42)).then(computations);
@@ -227,5 +234,7 @@ mod issue_11910 {
     fn test_then_some() {
         let v = vec![3, 2, 1, 0, -1, -2, -3];
         (!v.iter().any(|x| *x == 42)).then_some(0);
+
+        Foo.bar(!v.iter().any(|x| *x == 42));
     }
 }
diff --git a/tests/ui/search_is_some_fixable_none.rs b/tests/ui/search_is_some_fixable_none.rs
index e77ae5cecc2..aeb2be168f3 100644
--- a/tests/ui/search_is_some_fixable_none.rs
+++ b/tests/ui/search_is_some_fixable_none.rs
@@ -225,6 +225,13 @@ mod issue_11910 {
         0
     }
 
+    struct Foo;
+    impl Foo{
+        fn bar(&self, _ : bool) {
+
+        }
+    }
+
     fn test_then() {
         let v = vec![3, 2, 1, 0, -1, -2, -3];
         v.iter().find(|x| **x == 42).is_none().then(computations);
@@ -233,5 +240,7 @@ mod issue_11910 {
     fn test_then_some() {
         let v = vec![3, 2, 1, 0, -1, -2, -3];
         v.iter().find(|x| **x == 42).is_none().then_some(0);
+
+        Foo.bar(v.iter().find(|x| **x == 42).is_none());
     }
 }
diff --git a/tests/ui/search_is_some_fixable_none.stderr b/tests/ui/search_is_some_fixable_none.stderr
index 240eb245cdd..61a1f996d65 100644
--- a/tests/ui/search_is_some_fixable_none.stderr
+++ b/tests/ui/search_is_some_fixable_none.stderr
@@ -283,16 +283,22 @@ LL |         let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| test_u32_2(*fp.field))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some_fixable_none.rs:230:9
+  --> $DIR/search_is_some_fixable_none.rs:237:9
    |
 LL |         v.iter().find(|x| **x == 42).is_none().then(computations);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `(!v.iter().any(|x| *x == 42))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some_fixable_none.rs:235:9
+  --> $DIR/search_is_some_fixable_none.rs:242:9
    |
 LL |         v.iter().find(|x| **x == 42).is_none().then_some(0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `(!v.iter().any(|x| *x == 42))`
 
-error: aborting due to 45 previous errors
+error: called `is_none()` after searching an `Iterator` with `find`
+  --> $DIR/search_is_some_fixable_none.rs:244:17
+   |
+LL |         Foo.bar(v.iter().find(|x| **x == 42).is_none());
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|x| *x == 42)`
+
+error: aborting due to 46 previous errors
 

From 56580406b147f015f74581e78f8f2d796d1475c9 Mon Sep 17 00:00:00 2001
From: Yuxiang Qiu <yuxqiu@proton.me>
Date: Thu, 4 Jan 2024 20:34:38 -0500
Subject: [PATCH 07/47] style: fix fmt

---
 tests/ui/search_is_some_fixable_none.fixed  | 6 ++----
 tests/ui/search_is_some_fixable_none.rs     | 6 ++----
 tests/ui/search_is_some_fixable_none.stderr | 6 +++---
 3 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/tests/ui/search_is_some_fixable_none.fixed b/tests/ui/search_is_some_fixable_none.fixed
index e5c540e6723..cd58c17cc5a 100644
--- a/tests/ui/search_is_some_fixable_none.fixed
+++ b/tests/ui/search_is_some_fixable_none.fixed
@@ -220,10 +220,8 @@ mod issue_11910 {
     }
 
     struct Foo;
-    impl Foo{
-        fn bar(&self, _ : bool) {
-
-        }
+    impl Foo {
+        fn bar(&self, _: bool) {}
     }
 
     fn test_then() {
diff --git a/tests/ui/search_is_some_fixable_none.rs b/tests/ui/search_is_some_fixable_none.rs
index aeb2be168f3..25d9a23bf0b 100644
--- a/tests/ui/search_is_some_fixable_none.rs
+++ b/tests/ui/search_is_some_fixable_none.rs
@@ -226,10 +226,8 @@ mod issue_11910 {
     }
 
     struct Foo;
-    impl Foo{
-        fn bar(&self, _ : bool) {
-
-        }
+    impl Foo {
+        fn bar(&self, _: bool) {}
     }
 
     fn test_then() {
diff --git a/tests/ui/search_is_some_fixable_none.stderr b/tests/ui/search_is_some_fixable_none.stderr
index 61a1f996d65..71bf07bc942 100644
--- a/tests/ui/search_is_some_fixable_none.stderr
+++ b/tests/ui/search_is_some_fixable_none.stderr
@@ -283,19 +283,19 @@ LL |         let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| test_u32_2(*fp.field))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some_fixable_none.rs:237:9
+  --> $DIR/search_is_some_fixable_none.rs:235:9
    |
 LL |         v.iter().find(|x| **x == 42).is_none().then(computations);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `(!v.iter().any(|x| *x == 42))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some_fixable_none.rs:242:9
+  --> $DIR/search_is_some_fixable_none.rs:240:9
    |
 LL |         v.iter().find(|x| **x == 42).is_none().then_some(0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `(!v.iter().any(|x| *x == 42))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some_fixable_none.rs:244:17
+  --> $DIR/search_is_some_fixable_none.rs:242:17
    |
 LL |         Foo.bar(v.iter().find(|x| **x == 42).is_none());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|x| *x == 42)`

From 6f6dd880bc25cbde934e73d23e35dab3033d05b3 Mon Sep 17 00:00:00 2001
From: Yuxiang Qiu <yuxqiu@proton.me>
Date: Sat, 13 Jan 2024 10:45:01 -0500
Subject: [PATCH 08/47] test: update tests

---
 tests/ui/search_is_some_fixable_none.stderr | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tests/ui/search_is_some_fixable_none.stderr b/tests/ui/search_is_some_fixable_none.stderr
index 71bf07bc942..e8bebf8da19 100644
--- a/tests/ui/search_is_some_fixable_none.stderr
+++ b/tests/ui/search_is_some_fixable_none.stderr
@@ -286,19 +286,19 @@ error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:235:9
    |
 LL |         v.iter().find(|x| **x == 42).is_none().then(computations);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `(!v.iter().any(|x| *x == 42))`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!v.iter().any(|x| *x == 42))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:240:9
    |
 LL |         v.iter().find(|x| **x == 42).is_none().then_some(0);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `(!v.iter().any(|x| *x == 42))`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!v.iter().any(|x| *x == 42))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:242:17
    |
 LL |         Foo.bar(v.iter().find(|x| **x == 42).is_none());
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|x| *x == 42)`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| *x == 42)`
 
 error: aborting due to 46 previous errors
 

From e36c7d55b61ce92f2d8a53a048e077b8ecde005e Mon Sep 17 00:00:00 2001
From: Yuxiang Qiu <yuxqiu@proton.me>
Date: Mon, 1 Apr 2024 16:37:28 -0400
Subject: [PATCH 09/47] test: add test cases for str

---
 tests/ui/search_is_some_fixable_none.fixed  | 33 +++++++++-
 tests/ui/search_is_some_fixable_none.rs     | 33 +++++++++-
 tests/ui/search_is_some_fixable_none.stderr | 68 ++++++++++++++++++---
 3 files changed, 121 insertions(+), 13 deletions(-)

diff --git a/tests/ui/search_is_some_fixable_none.fixed b/tests/ui/search_is_some_fixable_none.fixed
index cd58c17cc5a..86a937b4dae 100644
--- a/tests/ui/search_is_some_fixable_none.fixed
+++ b/tests/ui/search_is_some_fixable_none.fixed
@@ -224,15 +224,42 @@ mod issue_11910 {
         fn bar(&self, _: bool) {}
     }
 
-    fn test_then() {
+    fn test_normal_for_iter() {
+        let v = vec![3, 2, 1, 0, -1, -2, -3];
+        let _ = !v.iter().any(|x| *x == 42);
+        Foo.bar(!v.iter().any(|x| *x == 42));
+    }
+
+    fn test_then_for_iter() {
         let v = vec![3, 2, 1, 0, -1, -2, -3];
         (!v.iter().any(|x| *x == 42)).then(computations);
     }
 
-    fn test_then_some() {
+    fn test_then_some_for_iter() {
         let v = vec![3, 2, 1, 0, -1, -2, -3];
         (!v.iter().any(|x| *x == 42)).then_some(0);
+    }
 
-        Foo.bar(!v.iter().any(|x| *x == 42));
+    fn test_normal_for_str() {
+        let s = "hello";
+        let _ = !s.contains("world");
+        Foo.bar(!s.contains("world"));
+        let s = String::from("hello");
+        let _ = !s.contains("world");
+        Foo.bar(!s.contains("world"));
+    }
+
+    fn test_then_for_str() {
+        let s = "hello";
+        let _ = (!s.contains("world")).then(computations);
+        let s = String::from("hello");
+        let _ = (!s.contains("world")).then(computations);
+    }
+
+    fn test_then_some_for_str() {
+        let s = "hello";
+        let _ = (!s.contains("world")).then_some(0);
+        let s = String::from("hello");
+        let _ = (!s.contains("world")).then_some(0);
     }
 }
diff --git a/tests/ui/search_is_some_fixable_none.rs b/tests/ui/search_is_some_fixable_none.rs
index 25d9a23bf0b..c0103a01509 100644
--- a/tests/ui/search_is_some_fixable_none.rs
+++ b/tests/ui/search_is_some_fixable_none.rs
@@ -230,15 +230,42 @@ mod issue_11910 {
         fn bar(&self, _: bool) {}
     }
 
-    fn test_then() {
+    fn test_normal_for_iter() {
+        let v = vec![3, 2, 1, 0, -1, -2, -3];
+        let _ = v.iter().find(|x| **x == 42).is_none();
+        Foo.bar(v.iter().find(|x| **x == 42).is_none());
+    }
+
+    fn test_then_for_iter() {
         let v = vec![3, 2, 1, 0, -1, -2, -3];
         v.iter().find(|x| **x == 42).is_none().then(computations);
     }
 
-    fn test_then_some() {
+    fn test_then_some_for_iter() {
         let v = vec![3, 2, 1, 0, -1, -2, -3];
         v.iter().find(|x| **x == 42).is_none().then_some(0);
+    }
 
-        Foo.bar(v.iter().find(|x| **x == 42).is_none());
+    fn test_normal_for_str() {
+        let s = "hello";
+        let _ = s.find("world").is_none();
+        Foo.bar(s.find("world").is_none());
+        let s = String::from("hello");
+        let _ = s.find("world").is_none();
+        Foo.bar(s.find("world").is_none());
+    }
+
+    fn test_then_for_str() {
+        let s = "hello";
+        let _ = s.find("world").is_none().then(computations);
+        let s = String::from("hello");
+        let _ = s.find("world").is_none().then(computations);
+    }
+
+    fn test_then_some_for_str() {
+        let s = "hello";
+        let _ = s.find("world").is_none().then_some(0);
+        let s = String::from("hello");
+        let _ = s.find("world").is_none().then_some(0);
     }
 }
diff --git a/tests/ui/search_is_some_fixable_none.stderr b/tests/ui/search_is_some_fixable_none.stderr
index e8bebf8da19..a1d37daf825 100644
--- a/tests/ui/search_is_some_fixable_none.stderr
+++ b/tests/ui/search_is_some_fixable_none.stderr
@@ -283,22 +283,76 @@ LL |         let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| test_u32_2(*fp.field))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some_fixable_none.rs:235:9
+  --> $DIR/search_is_some_fixable_none.rs:235:17
+   |
+LL |         let _ = v.iter().find(|x| **x == 42).is_none();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| *x == 42)`
+
+error: called `is_none()` after searching an `Iterator` with `find`
+  --> $DIR/search_is_some_fixable_none.rs:236:17
+   |
+LL |         Foo.bar(v.iter().find(|x| **x == 42).is_none());
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| *x == 42)`
+
+error: called `is_none()` after searching an `Iterator` with `find`
+  --> $DIR/search_is_some_fixable_none.rs:241:9
    |
 LL |         v.iter().find(|x| **x == 42).is_none().then(computations);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!v.iter().any(|x| *x == 42))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some_fixable_none.rs:240:9
+  --> $DIR/search_is_some_fixable_none.rs:246:9
    |
 LL |         v.iter().find(|x| **x == 42).is_none().then_some(0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!v.iter().any(|x| *x == 42))`
 
-error: called `is_none()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some_fixable_none.rs:242:17
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable_none.rs:251:17
    |
-LL |         Foo.bar(v.iter().find(|x| **x == 42).is_none());
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| *x == 42)`
+LL |         let _ = s.find("world").is_none();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")`
 
-error: aborting due to 46 previous errors
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable_none.rs:252:17
+   |
+LL |         Foo.bar(s.find("world").is_none());
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")`
+
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable_none.rs:254:17
+   |
+LL |         let _ = s.find("world").is_none();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")`
+
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable_none.rs:255:17
+   |
+LL |         Foo.bar(s.find("world").is_none());
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")`
+
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable_none.rs:260:17
+   |
+LL |         let _ = s.find("world").is_none().then(computations);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))`
+
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable_none.rs:262:17
+   |
+LL |         let _ = s.find("world").is_none().then(computations);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))`
+
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable_none.rs:267:17
+   |
+LL |         let _ = s.find("world").is_none().then_some(0);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))`
+
+error: called `is_none()` after calling `find()` on a string
+  --> $DIR/search_is_some_fixable_none.rs:269:17
+   |
+LL |         let _ = s.find("world").is_none().then_some(0);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))`
+
+error: aborting due to 55 previous errors
 

From b89fa5364f3de5fe17e65f6b42865e5b95f1ad9a Mon Sep 17 00:00:00 2001
From: Yuxiang Qiu <yuxqiu@proton.me>
Date: Mon, 1 Apr 2024 16:59:46 -0400
Subject: [PATCH 10/47] fix: fix ci errors

---
 clippy_lints/src/methods/search_is_some.rs  |  2 +-
 tests/ui/search_is_some_fixable_none.stderr | 24 ++++++++++-----------
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/clippy_lints/src/methods/search_is_some.rs b/clippy_lints/src/methods/search_is_some.rs
index 1e1a8f9060b..f5f1e94bbf4 100644
--- a/clippy_lints/src/methods/search_is_some.rs
+++ b/clippy_lints/src/methods/search_is_some.rs
@@ -36,7 +36,7 @@ pub(super) fn check<'tcx>(
             // suggest `any(|..| *..)` instead of `any(|..| **..)` for `find(|..| **..).is_some()`
             let mut applicability = Applicability::MachineApplicable;
             let any_search_snippet = if search_method == "find"
-                && let hir::ExprKind::Closure(&hir::Closure { body, .. }) = search_arg.kind
+                && let ExprKind::Closure(&hir::Closure { body, .. }) = search_arg.kind
                 && let closure_body = cx.tcx.hir().body(body)
                 && let Some(closure_arg) = closure_body.params.first()
             {
diff --git a/tests/ui/search_is_some_fixable_none.stderr b/tests/ui/search_is_some_fixable_none.stderr
index a1d37daf825..2c858b9fb10 100644
--- a/tests/ui/search_is_some_fixable_none.stderr
+++ b/tests/ui/search_is_some_fixable_none.stderr
@@ -283,73 +283,73 @@ LL |         let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| test_u32_2(*fp.field))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some_fixable_none.rs:235:17
+  --> tests/ui/search_is_some_fixable_none.rs:235:17
    |
 LL |         let _ = v.iter().find(|x| **x == 42).is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| *x == 42)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some_fixable_none.rs:236:17
+  --> tests/ui/search_is_some_fixable_none.rs:236:17
    |
 LL |         Foo.bar(v.iter().find(|x| **x == 42).is_none());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| *x == 42)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some_fixable_none.rs:241:9
+  --> tests/ui/search_is_some_fixable_none.rs:241:9
    |
 LL |         v.iter().find(|x| **x == 42).is_none().then(computations);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!v.iter().any(|x| *x == 42))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> $DIR/search_is_some_fixable_none.rs:246:9
+  --> tests/ui/search_is_some_fixable_none.rs:246:9
    |
 LL |         v.iter().find(|x| **x == 42).is_none().then_some(0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!v.iter().any(|x| *x == 42))`
 
 error: called `is_none()` after calling `find()` on a string
-  --> $DIR/search_is_some_fixable_none.rs:251:17
+  --> tests/ui/search_is_some_fixable_none.rs:251:17
    |
 LL |         let _ = s.find("world").is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")`
 
 error: called `is_none()` after calling `find()` on a string
-  --> $DIR/search_is_some_fixable_none.rs:252:17
+  --> tests/ui/search_is_some_fixable_none.rs:252:17
    |
 LL |         Foo.bar(s.find("world").is_none());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")`
 
 error: called `is_none()` after calling `find()` on a string
-  --> $DIR/search_is_some_fixable_none.rs:254:17
+  --> tests/ui/search_is_some_fixable_none.rs:254:17
    |
 LL |         let _ = s.find("world").is_none();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")`
 
 error: called `is_none()` after calling `find()` on a string
-  --> $DIR/search_is_some_fixable_none.rs:255:17
+  --> tests/ui/search_is_some_fixable_none.rs:255:17
    |
 LL |         Foo.bar(s.find("world").is_none());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")`
 
 error: called `is_none()` after calling `find()` on a string
-  --> $DIR/search_is_some_fixable_none.rs:260:17
+  --> tests/ui/search_is_some_fixable_none.rs:260:17
    |
 LL |         let _ = s.find("world").is_none().then(computations);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))`
 
 error: called `is_none()` after calling `find()` on a string
-  --> $DIR/search_is_some_fixable_none.rs:262:17
+  --> tests/ui/search_is_some_fixable_none.rs:262:17
    |
 LL |         let _ = s.find("world").is_none().then(computations);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))`
 
 error: called `is_none()` after calling `find()` on a string
-  --> $DIR/search_is_some_fixable_none.rs:267:17
+  --> tests/ui/search_is_some_fixable_none.rs:267:17
    |
 LL |         let _ = s.find("world").is_none().then_some(0);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))`
 
 error: called `is_none()` after calling `find()` on a string
-  --> $DIR/search_is_some_fixable_none.rs:269:17
+  --> tests/ui/search_is_some_fixable_none.rs:269:17
    |
 LL |         let _ = s.find("world").is_none().then_some(0);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))`

From ac18c24fe80a59a4a2d093165230924e0abeed7d Mon Sep 17 00:00:00 2001
From: Aneesh Kadiyala <143342960+ARandomDev99@users.noreply.github.com>
Date: Tue, 2 Apr 2024 22:39:30 +0530
Subject: [PATCH 11/47] Use `IfLetOrMatch` to avoid repetition of code

---
 clippy_lints/src/manual_unwrap_or_default.rs | 102 ++++++++-----------
 1 file changed, 40 insertions(+), 62 deletions(-)

diff --git a/clippy_lints/src/manual_unwrap_or_default.rs b/clippy_lints/src/manual_unwrap_or_default.rs
index a4048e89926..84fb183e3f7 100644
--- a/clippy_lints/src/manual_unwrap_or_default.rs
+++ b/clippy_lints/src/manual_unwrap_or_default.rs
@@ -1,4 +1,3 @@
-use clippy_utils::sugg::Sugg;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatKind, QPath};
@@ -8,7 +7,8 @@ use rustc_session::declare_lint_pass;
 use rustc_span::sym;
 
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::higher::IfLetOrMatch;
+use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::{in_constant, is_default_equivalent, peel_blocks, span_contains_comment};
 
@@ -106,23 +106,39 @@ fn get_some_and_none_bodies<'tcx>(
     }
 }
 
-fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
-    let ExprKind::Match(match_expr, [arm1, arm2], MatchSource::Normal | MatchSource::ForLoopDesugar) = expr.kind else {
-        return false;
+#[allow(clippy::needless_pass_by_value)]
+fn handle<'tcx>(cx: &LateContext<'tcx>, if_let_or_match: IfLetOrMatch<'tcx>, expr: &'tcx Expr<'tcx>) {
+    // Get expr_name ("if let" or "match" depending on kind of expression),  the condition, the body for
+    // the some arm, the body for the none arm and the binding id of the some arm
+    let (expr_name, condition, body_some, body_none, binding_id) = match if_let_or_match {
+        IfLetOrMatch::Match(condition, [arm1, arm2], MatchSource::Normal | MatchSource::ForLoopDesugar)
+            // Make sure there are no guards to keep things simple
+            if arm1.guard.is_none()
+                && arm2.guard.is_none()
+                // Get the some and none bodies and the binding id of the some arm
+                && let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2) =>
+        {
+            ("match", condition, body_some, body_none, binding_id)
+        },
+        IfLetOrMatch::IfLet(condition, pat, if_expr, Some(else_expr), _)
+            if let Some(binding_id) = get_some(cx, pat) =>
+        {
+            ("if let", condition, if_expr, else_expr, binding_id)
+        },
+        _ => {
+            // All other cases (match with number of arms != 2, if let without else, etc.)
+            return;
+        },
     };
-    // We don't want conditions on the arms to simplify things.
-    if arm1.guard.is_none()
-        && arm2.guard.is_none()
-        // We check that the returned type implements the `Default` trait.
-        && let match_ty = cx.typeck_results().expr_ty(expr)
-        && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
-        && implements_trait(cx, match_ty, default_trait_id, &[])
-        // We now get the bodies for both the `Some` and `None` arms.
-        && let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2)
-        // We check that the initial expression also implies the `Default` trait.
-        && let Some(match_expr_ty) = cx.typeck_results().expr_ty(match_expr).walk().nth(1)
-        && let GenericArgKind::Type(match_expr_ty) = match_expr_ty.unpack()
-        && implements_trait(cx, match_expr_ty, default_trait_id, &[])
+
+    // We check if the return type of the expression implements Default.
+    let expr_type = cx.typeck_results().expr_ty(expr);
+    if let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
+        && implements_trait(cx, expr_type, default_trait_id, &[])
+        // We check if the initial condition implements Default.
+        && let Some(condition_ty) = cx.typeck_results().expr_ty(condition).walk().nth(1)
+        && let GenericArgKind::Type(condition_ty) = condition_ty.unpack()
+        && implements_trait(cx, condition_ty, default_trait_id, &[])
         // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
         && let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(body_some).kind
         && let Res::Local(local_id) = path.res
@@ -130,8 +146,9 @@ fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
         // We now check the `None` arm is calling a method equivalent to `Default::default`.
         && let body_none = peel_blocks(body_none)
         && is_default_equivalent(cx, body_none)
-        && let Some(receiver) = Sugg::hir_opt(cx, match_expr).map(Sugg::maybe_par)
+        && let Some(receiver) = Sugg::hir_opt(cx, condition).map(Sugg::maybe_par)
     {
+        // Machine applicable only if there are no comments present
         let applicability = if span_contains_comment(cx.sess().source_map(), expr.span) {
             Applicability::MaybeIncorrect
         } else {
@@ -141,52 +158,12 @@ fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
             cx,
             MANUAL_UNWRAP_OR_DEFAULT,
             expr.span,
-            "match can be simplified with `.unwrap_or_default()`",
+            format!("{expr_name} can be simplified with `.unwrap_or_default()`"),
             "replace it with",
             format!("{receiver}.unwrap_or_default()"),
             applicability,
         );
     }
-    true
-}
-
-fn handle_if_let<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-    if let ExprKind::If(cond, if_block, Some(else_expr)) = expr.kind
-        && let ExprKind::Let(let_) = cond.kind
-        && let ExprKind::Block(_, _) = else_expr.kind
-        // We check that the returned type implements the `Default` trait.
-        && let match_ty = cx.typeck_results().expr_ty(expr)
-        && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
-        && implements_trait(cx, match_ty, default_trait_id, &[])
-        && let Some(binding_id) = get_some(cx, let_.pat)
-        // We check that the initial expression also implies the `Default` trait.
-        && let Some(let_ty) = cx.typeck_results().expr_ty(let_.init).walk().nth(1)
-        && let GenericArgKind::Type(let_ty) = let_ty.unpack()
-        && implements_trait(cx, let_ty, default_trait_id, &[])
-        // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
-        && let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(if_block).kind
-        && let Res::Local(local_id) = path.res
-        && local_id == binding_id
-        // We now check the `None` arm is calling a method equivalent to `Default::default`.
-        && let body_else = peel_blocks(else_expr)
-        && is_default_equivalent(cx, body_else)
-        && let Some(if_let_expr_snippet) = snippet_opt(cx, let_.init.span)
-    {
-        let applicability = if span_contains_comment(cx.sess().source_map(), expr.span) {
-            Applicability::MaybeIncorrect
-        } else {
-            Applicability::MachineApplicable
-        };
-        span_lint_and_sugg(
-            cx,
-            MANUAL_UNWRAP_OR_DEFAULT,
-            expr.span,
-            "if let can be simplified with `.unwrap_or_default()`",
-            "replace it with",
-            format!("{if_let_expr_snippet}.unwrap_or_default()"),
-            applicability,
-        );
-    }
 }
 
 impl<'tcx> LateLintPass<'tcx> for ManualUnwrapOrDefault {
@@ -194,8 +171,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualUnwrapOrDefault {
         if expr.span.from_expansion() || in_constant(cx, expr.hir_id) {
             return;
         }
-        if !handle_match(cx, expr) {
-            handle_if_let(cx, expr);
+        // Call handle only if the expression is `if let` or `match`
+        if let Some(if_let_or_match) = IfLetOrMatch::parse(cx, expr) {
+            handle(cx, if_let_or_match, expr);
         }
     }
 }

From ac225a3b1f30953f3fd45f02d9a08a857943b5b4 Mon Sep 17 00:00:00 2001
From: Francisco Salgueiro <francisco.salgueiro@tecnico.ulisboa.pt>
Date: Wed, 3 Apr 2024 21:43:06 +0100
Subject: [PATCH 12/47] Fix #11738: allow `cast` lints in macros

Removed the `from_expansion` guard clause for cast lints, so that these warnings can be generated for internal macros.
---
 clippy_lints/src/casts/mod.rs | 11 ++++-----
 tests/ui/cast.rs              | 12 ++++++++++
 tests/ui/cast.stderr          | 45 ++++++++++++++++++++++++++++++++---
 3 files changed, 58 insertions(+), 10 deletions(-)

diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index 063aab28238..a87102b6bf4 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -754,13 +754,10 @@ impl_lint_pass!(Casts => [
 
 impl<'tcx> LateLintPass<'tcx> for Casts {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if !in_external_macro(cx.sess(), expr.span) {
-            ptr_as_ptr::check(cx, expr, &self.msrv);
-        }
-
-        if expr.span.from_expansion() {
+        if in_external_macro(cx.sess(), expr.span) {
             return;
         }
+        ptr_as_ptr::check(cx, expr, &self.msrv);
 
         if let ExprKind::Cast(cast_expr, cast_to_hir) = expr.kind {
             if is_hir_ty_cfg_dependant(cx, cast_to_hir) {
@@ -771,7 +768,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
                 cx.typeck_results().expr_ty(expr),
             );
 
-            if unnecessary_cast::check(cx, expr, cast_expr, cast_from, cast_to) {
+            if !expr.span.from_expansion() && unnecessary_cast::check(cx, expr, cast_expr, cast_from, cast_to) {
                 return;
             }
             cast_slice_from_raw_parts::check(cx, expr, cast_expr, cast_to, &self.msrv);
@@ -782,7 +779,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
             fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
             zero_ptr::check(cx, expr, cast_expr, cast_to_hir);
 
-            if cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) {
+            if cast_to.is_numeric() {
                 cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to, cast_to_hir.span);
                 if cast_from.is_numeric() {
                     cast_possible_wrap::check(cx, expr, cast_from, cast_to);
diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs
index ce76ad3d3ad..215c008902d 100644
--- a/tests/ui/cast.rs
+++ b/tests/ui/cast.rs
@@ -463,6 +463,18 @@ fn issue11642() {
     }
 }
 
+fn issue11738() {
+    macro_rules! m {
+        () => {
+            let _ = i32::MIN as u32; // cast_sign_loss
+            let _ = u32::MAX as u8; // cast_possible_truncation
+            let _ = std::f64::consts::PI as f32; // cast_possible_truncation
+            let _ = 0i8 as i32; // cast_lossless
+        };
+    }
+    m!();
+}
+
 fn issue12506() -> usize {
     let bar: Result<Option<i64>, u32> = Ok(Some(10));
     bar.unwrap().unwrap() as usize
diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr
index 3736e8aee0a..8b269c47176 100644
--- a/tests/ui/cast.stderr
+++ b/tests/ui/cast.stderr
@@ -650,8 +650,47 @@ error: casting `i32` to `u32` may lose the sign of the value
 LL |         (a.abs() * b.pow(2) / c.abs()) as u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: casting `i32` to `u32` may lose the sign of the value
+  --> tests/ui/cast.rs:469:21
+   |
+LL |             let _ = i32::MIN as u32; // cast_sign_loss
+   |                     ^^^^^^^^^^^^^^^
+...
+LL |     m!();
+   |     ---- in this macro invocation
+   |
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: casting `u32` to `u8` may truncate the value
+  --> tests/ui/cast.rs:470:21
+   |
+LL |             let _ = u32::MAX as u8; // cast_possible_truncation
+   |                     ^^^^^^^^^^^^^^
+...
+LL |     m!();
+   |     ---- in this macro invocation
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: ... or use `try_from` and handle the error accordingly
+   |
+LL |             let _ = u8::try_from(u32::MAX); // cast_possible_truncation
+   |                     ~~~~~~~~~~~~~~~~~~~~~~
+
+error: casting `f64` to `f32` may truncate the value
+  --> tests/ui/cast.rs:471:21
+   |
+LL |             let _ = std::f64::consts::PI as f32; // cast_possible_truncation
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     m!();
+   |     ---- in this macro invocation
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
 error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers
-  --> tests/ui/cast.rs:468:5
+  --> tests/ui/cast.rs:480:5
    |
 LL |     bar.unwrap().unwrap() as usize
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -663,10 +702,10 @@ LL |     usize::try_from(bar.unwrap().unwrap())
    |
 
 error: casting `i64` to `usize` may lose the sign of the value
-  --> tests/ui/cast.rs:468:5
+  --> tests/ui/cast.rs:480:5
    |
 LL |     bar.unwrap().unwrap() as usize
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 87 previous errors
+error: aborting due to 90 previous errors
 

From ca92c0a7a472e3d641bb5b38e69851317dc0986a Mon Sep 17 00:00:00 2001
From: Dan <hello@danielh.cc>
Date: Wed, 3 Apr 2024 19:03:12 -0400
Subject: [PATCH 13/47] update messages

---
 clippy_lints/src/misc.rs                    | 2 +-
 tests/ui-internal/custom_ice_message.stderr | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs
index ea6e662b4be..be1a35f8fb2 100644
--- a/clippy_lints/src/misc.rs
+++ b/clippy_lints/src/misc.rs
@@ -66,7 +66,7 @@ declare_clippy_lint! {
     ///
     /// ### Known problems
     /// The lint does not work properly with desugaring and
-    /// macro, it has been allowed in the mean time.
+    /// macro, it has been allowed in the meantime.
     ///
     /// ### Example
     /// ```no_run
diff --git a/tests/ui-internal/custom_ice_message.stderr b/tests/ui-internal/custom_ice_message.stderr
index b84f4e87e07..763ce59ba1d 100644
--- a/tests/ui-internal/custom_ice_message.stderr
+++ b/tests/ui-internal/custom_ice_message.stderr
@@ -4,7 +4,7 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 
 error: the compiler unexpectedly panicked. this is a bug.
 
-note: it seems that this compiler <version> is outdated, a newer nightly should have been released in the mean time
+note: it seems that this compiler <version> is outdated, a newer nightly should have been released in the meantime
   |
   = note: please consider running `rustup update nightly` to update the nightly channel and check if this problem still persists
   = note: if the problem still persists, we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml

From 38b8056fc652ed822c959d45486683147e24f103 Mon Sep 17 00:00:00 2001
From: Mariana Miranda <mariana.almeida.miranda@tecnico.ulisboa.pt>
Date: Thu, 4 Apr 2024 10:24:25 +0100
Subject: [PATCH 14/47] Fix: #12268: Correct parentheses for needless_borrow
 suggestion

Clippy no longer adds unnecessary parentheses in suggestion when the expression is a part of a tuple.
---
 clippy_lints/src/dereference.rs | 6 ++++++
 tests/ui/needless_borrow.fixed  | 7 +++++++
 tests/ui/needless_borrow.rs     | 7 +++++++
 tests/ui/needless_borrow.stderr | 8 +++++++-
 4 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs
index 560b2acc1c7..f63413bd575 100644
--- a/clippy_lints/src/dereference.rs
+++ b/clippy_lints/src/dereference.rs
@@ -1014,9 +1014,15 @@ fn report<'tcx>(
                         },
                         _ => (0, false),
                     };
+                    let is_in_tuple = match cx.tcx.parent_hir_node(data.first_expr.hir_id) {
+                        Node::Expr(e) => matches!(e.kind, ExprKind::Tup(_)),
+                        _ => false,
+                    };
+
                     let sugg = if !snip_is_macro
                         && (calls_field || expr.precedence().order() < precedence)
                         && !has_enclosing_paren(&snip)
+                        && !is_in_tuple
                     {
                         format!("({snip})")
                     } else {
diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed
index 998f5430fdf..adc92be0e1a 100644
--- a/tests/ui/needless_borrow.fixed
+++ b/tests/ui/needless_borrow.fixed
@@ -251,3 +251,10 @@ mod issue_10253 {
         (&S).f::<()>();
     }
 }
+
+fn issue_12268() {
+    let option = Some((&1,));
+    let x = (&1,);
+    // Lint here.
+    option.unwrap_or((x.0,));
+}
diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs
index acb2c74d849..b1f51a29978 100644
--- a/tests/ui/needless_borrow.rs
+++ b/tests/ui/needless_borrow.rs
@@ -251,3 +251,10 @@ mod issue_10253 {
         (&S).f::<()>();
     }
 }
+
+fn issue_12268() {
+    let option = Some((&1,));
+    let x = (&1,);
+    // Lint here.
+    option.unwrap_or((&x.0,));
+}
diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr
index 5f028338764..56fcf1268a1 100644
--- a/tests/ui/needless_borrow.stderr
+++ b/tests/ui/needless_borrow.stderr
@@ -163,5 +163,11 @@ error: this expression borrows a value the compiler would automatically borrow
 LL |         let _ = &mut (&mut { x.u }).x;
    |                      ^^^^^^^^^^^^^^ help: change this to: `{ x.u }`
 
-error: aborting due to 27 previous errors
+error: this expression creates a reference which is immediately dereferenced by the compiler
+  --> tests/ui/needless_borrow.rs:259:23
+   |
+LL |     option.unwrap_or((&x.0,));
+   |                       ^^^^ help: change this to: `x.0`
+
+error: aborting due to 28 previous errors
 

From a1e76af295e39b2cb012c70ef3649731663be8ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= <me@fmease.dev>
Date: Thu, 4 Apr 2024 19:03:32 +0200
Subject: [PATCH 15/47] Rename ModSep to PathSep

---
 clippy_lints/src/crate_in_macro_def.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clippy_lints/src/crate_in_macro_def.rs b/clippy_lints/src/crate_in_macro_def.rs
index b1aa472aa03..adf6f7c4737 100644
--- a/clippy_lints/src/crate_in_macro_def.rs
+++ b/clippy_lints/src/crate_in_macro_def.rs
@@ -88,7 +88,7 @@ fn contains_unhygienic_crate_reference(tts: &TokenStream) -> Option<Span> {
         if !prev_is_dollar
             && let Some(span) = is_crate_keyword(curr)
             && let Some(next) = cursor.look_ahead(0)
-            && is_token(next, &TokenKind::ModSep)
+            && is_token(next, &TokenKind::PathSep)
         {
             return Some(span);
         }

From 0ae4a048c6fa9c84d169e1bba8747661099b2111 Mon Sep 17 00:00:00 2001
From: Philipp Krones <hello@philkrones.com>
Date: Thu, 4 Apr 2024 19:52:55 +0200
Subject: [PATCH 16/47] Merge commit '9725c4a162502a02c1c67fdca6b797fe09b2b73c'
 into clippy-subtree-update

---
 .gitignore                                    |   3 +
 CHANGELOG.md                                  |   2 +
 Cargo.toml                                    |   1 -
 book/src/SUMMARY.md                           |   1 +
 book/src/development/defining_lints.md        |   9 +-
 book/src/development/lint_passes.md           |   2 +-
 book/src/development/the_team.md              | 130 +++++++
 book/src/lint_configuration.md                |   1 +
 clippy_config/src/conf.rs                     |   7 +-
 clippy_config/src/lib.rs                      |   8 +-
 clippy_config/src/msrvs.rs                    |   2 +-
 clippy_dev/src/lib.rs                         |   9 +-
 clippy_dev/src/lint.rs                        |   4 +
 clippy_dev/src/update_lints.rs                |   4 +-
 clippy_lints/src/approx_const.rs              |   2 +-
 clippy_lints/src/asm_syntax.rs                |   4 +-
 clippy_lints/src/assertions_on_constants.rs   |   6 +-
 clippy_lints/src/assigning_clones.rs          |  30 +-
 .../attrs/allow_attributes_without_reason.rs  |   2 +-
 .../src/attrs/duplicated_attributes.rs        |  11 +
 clippy_lints/src/attrs/inline_always.rs       |   2 +-
 clippy_lints/src/attrs/maybe_misused_cfg.rs   |   2 +-
 .../src/attrs/mixed_attributes_style.rs       |  85 ++++-
 clippy_lints/src/attrs/mod.rs                 |  20 +-
 .../src/attrs/unnecessary_clippy_cfg.rs       |   2 +-
 clippy_lints/src/await_holding_invalid.rs     |   2 +-
 clippy_lints/src/blocks_in_conditions.rs      |   4 +-
 clippy_lints/src/bool_assert_comparison.rs    |   2 +-
 clippy_lints/src/booleans.rs                  |   4 +-
 clippy_lints/src/box_default.rs               |  55 +--
 clippy_lints/src/cargo/common_metadata.rs     |   2 +-
 clippy_lints/src/cargo/feature_name.rs        |   4 +-
 .../src/cargo/lint_groups_priority.rs         |   2 +-
 clippy_lints/src/cargo/mod.rs                 |   4 +-
 .../src/cargo/multiple_crate_versions.rs      |   2 +-
 .../src/cargo/wildcard_dependencies.rs        |   2 +-
 clippy_lints/src/casts/as_ptr_cast_mut.rs     |   2 +-
 .../src/casts/cast_abs_to_unsigned.rs         |   2 +-
 clippy_lints/src/casts/cast_lossless.rs       |   2 +-
 clippy_lints/src/casts/cast_nan_to_int.rs     |   2 +-
 .../src/casts/cast_possible_truncation.rs     |   8 +-
 clippy_lints/src/casts/cast_possible_wrap.rs  |   2 +-
 clippy_lints/src/casts/cast_precision_loss.rs |   2 +-
 clippy_lints/src/casts/cast_ptr_alignment.rs  |   2 +-
 clippy_lints/src/casts/cast_sign_loss.rs      |   7 +-
 .../src/casts/cast_slice_different_sizes.rs   |   2 +-
 .../src/casts/cast_slice_from_raw_parts.rs    |   2 +-
 clippy_lints/src/casts/fn_to_numeric_cast.rs  |   2 +-
 .../src/casts/fn_to_numeric_cast_any.rs       |   2 +-
 .../fn_to_numeric_cast_with_truncation.rs     |   2 +-
 clippy_lints/src/casts/ptr_as_ptr.rs          |   2 +-
 clippy_lints/src/casts/ptr_cast_constness.rs  |   2 +-
 clippy_lints/src/casts/unnecessary_cast.rs    |   6 +-
 clippy_lints/src/cognitive_complexity.rs      |   2 +-
 clippy_lints/src/collection_is_never_read.rs  |   2 +-
 clippy_lints/src/declared_lints.rs            |   2 +
 clippy_lints/src/default.rs                   |   4 +-
 .../src/default_constructed_unit_structs.rs   |   2 +-
 .../src/default_instead_of_iter_empty.rs      |   4 +-
 .../src/default_union_representation.rs       |   2 +-
 clippy_lints/src/derivable_impls.rs           |   2 +-
 clippy_lints/src/derive.rs                    |   3 +-
 clippy_lints/src/disallowed_macros.rs         |   4 +-
 clippy_lints/src/disallowed_methods.rs        |   2 +-
 clippy_lints/src/disallowed_names.rs          |   2 +-
 clippy_lints/src/disallowed_script_idents.rs  |   2 +-
 clippy_lints/src/disallowed_types.rs          |   2 +-
 clippy_lints/src/drop_forget_ref.rs           |   4 +-
 clippy_lints/src/duplicate_mod.rs             |   2 +-
 clippy_lints/src/endian_bytes.rs              |   2 +-
 clippy_lints/src/entry.rs                     |   2 +-
 clippy_lints/src/escape.rs                    |   2 +-
 clippy_lints/src/eta_reduction.rs             |   8 +-
 clippy_lints/src/excessive_bools.rs           |   4 +-
 clippy_lints/src/exhaustive_items.rs          |   2 +-
 clippy_lints/src/explicit_write.rs            |   2 +-
 .../src/extra_unused_type_parameters.rs       |   8 +-
 clippy_lints/src/float_literal.rs             |   6 +-
 clippy_lints/src/floating_point_arithmetic.rs |   6 +-
 clippy_lints/src/format_args.rs               |   6 +-
 clippy_lints/src/format_impl.rs               |   4 +-
 clippy_lints/src/formatting.rs                |  17 +-
 clippy_lints/src/from_raw_with_void_ptr.rs    |   4 +-
 clippy_lints/src/functions/must_use.rs        |   6 +-
 clippy_lints/src/functions/result.rs          |   4 +-
 .../src/functions/too_many_arguments.rs       |   2 +-
 clippy_lints/src/functions/too_many_lines.rs  |   2 +-
 clippy_lints/src/if_then_some_else_none.rs    |   4 +-
 clippy_lints/src/implicit_hasher.rs           |   4 +-
 clippy_lints/src/implied_bounds_in_impls.rs   |   4 +-
 clippy_lints/src/incompatible_msrv.rs         |   4 +-
 clippy_lints/src/inherent_to_string.rs        |   8 +-
 clippy_lints/src/inline_fn_without_body.rs    |   2 +-
 clippy_lints/src/instant_subtraction.rs       |   4 +-
 .../src/integer_division_remainder_used.rs    |   2 +-
 .../src/invalid_upcast_comparisons.rs         |   4 +-
 clippy_lints/src/item_name_repetitions.rs     |   8 +-
 .../src/iter_not_returning_iterator.rs        |   2 +-
 clippy_lints/src/iter_without_into_iter.rs    |   4 +-
 clippy_lints/src/large_futures.rs             |   2 +-
 clippy_lints/src/large_include_file.rs        |   2 +-
 clippy_lints/src/large_stack_arrays.rs        |   4 +-
 clippy_lints/src/large_stack_frames.rs        | 106 ++++--
 clippy_lints/src/legacy_numeric_constants.rs  | 293 +++++++++++++++
 clippy_lints/src/len_zero.rs                  |  38 +-
 clippy_lints/src/lib.rs                       |  15 +-
 clippy_lints/src/lifetimes.rs                 |   2 +-
 clippy_lints/src/lines_filter_map_ok.rs       |   2 +-
 clippy_lints/src/literal_representation.rs    |   8 +-
 .../src/loops/explicit_counter_loop.rs        |   4 +-
 clippy_lints/src/loops/for_kv_map.rs          |   2 +-
 clippy_lints/src/loops/manual_flatten.rs      |   2 +-
 clippy_lints/src/loops/mut_range_bound.rs     |   4 +-
 clippy_lints/src/loops/needless_range_loop.rs |   6 +-
 clippy_lints/src/loops/never_loop.rs          |   9 +-
 clippy_lints/src/loops/same_item_push.rs      |   2 +-
 clippy_lints/src/loops/single_element_loop.rs |   6 +-
 clippy_lints/src/main_recursion.rs            |   2 +-
 clippy_lints/src/manual_assert.rs             |   5 +-
 clippy_lints/src/manual_bits.rs               |   2 +-
 clippy_lints/src/manual_clamp.rs              |  38 +-
 clippy_lints/src/manual_strip.rs              |   4 +-
 clippy_lints/src/manual_unwrap_or_default.rs  |  33 +-
 clippy_lints/src/map_unit_fn.rs               |   4 +-
 clippy_lints/src/match_result_ok.rs           |   2 +-
 clippy_lints/src/matches/collapsible_match.rs |   2 +-
 clippy_lints/src/matches/manual_unwrap_or.rs  |   2 +-
 clippy_lints/src/matches/match_as_ref.rs      |   2 +-
 .../src/matches/match_like_matches.rs         |   2 +-
 .../src/matches/match_str_case_mismatch.rs    |   2 +-
 .../src/matches/match_wild_err_arm.rs         |   2 +-
 clippy_lints/src/matches/mod.rs               |  32 +-
 .../src/matches/redundant_pattern_match.rs    |   8 +-
 clippy_lints/src/mem_replace.rs               |   2 +-
 .../src/methods/bind_instead_of_map.rs        |   6 +-
 clippy_lints/src/methods/bytes_nth.rs         |   4 +-
 clippy_lints/src/methods/chars_cmp.rs         |   2 +-
 .../src/methods/chars_cmp_with_unwrap.rs      |   2 +-
 clippy_lints/src/methods/clear_with_drain.rs  |   5 +-
 clippy_lints/src/methods/clone_on_copy.rs     |   2 +-
 clippy_lints/src/methods/drain_collect.rs     |   2 +-
 clippy_lints/src/methods/expect_fun_call.rs   |   4 +-
 clippy_lints/src/methods/filetype_is_file.rs  |   2 +-
 clippy_lints/src/methods/filter_map.rs        |  53 ++-
 .../src/methods/filter_map_identity.rs        |  18 +-
 clippy_lints/src/methods/get_first.rs         |   4 +-
 clippy_lints/src/methods/get_last_with_len.rs |   2 +-
 clippy_lints/src/methods/get_unwrap.rs        |   2 +-
 clippy_lints/src/methods/implicit_clone.rs    |   2 +-
 .../src/methods/inefficient_to_string.rs      |   2 +-
 clippy_lints/src/methods/into_iter_on_ref.rs  |   2 +-
 .../src/methods/is_digit_ascii_radix.rs       |   2 +-
 clippy_lints/src/methods/is_empty.rs          |   2 +-
 .../src/methods/iter_cloned_collect.rs        |   2 +-
 clippy_lints/src/methods/iter_count.rs        |   2 +-
 clippy_lints/src/methods/iter_filter.rs       |  14 +-
 clippy_lints/src/methods/iter_kv_map.rs       |   4 +-
 clippy_lints/src/methods/iter_nth.rs          |   2 +-
 .../iter_on_single_or_empty_collections.rs    |   4 +-
 .../src/methods/iter_overeager_cloned.rs      |   2 +-
 clippy_lints/src/methods/iter_with_drain.rs   |   2 +-
 .../methods/manual_saturating_arithmetic.rs   |   2 +-
 clippy_lints/src/methods/map_clone.rs         |   9 +-
 clippy_lints/src/methods/map_flatten.rs       |   4 +-
 clippy_lints/src/methods/map_identity.rs      |   2 +-
 clippy_lints/src/methods/mod.rs               |  51 ++-
 clippy_lints/src/methods/needless_collect.rs  |   2 +-
 clippy_lints/src/methods/open_options.rs      |   2 +-
 .../src/methods/option_as_ref_cloned.rs       |   2 +-
 .../src/methods/option_as_ref_deref.rs        |   4 +-
 .../src/methods/option_map_unwrap_or.rs       |   2 +-
 clippy_lints/src/methods/or_fun_call.rs       |   4 +-
 .../src/methods/range_zip_with_len.rs         |   2 +-
 clippy_lints/src/methods/search_is_some.rs    |  12 +-
 .../src/methods/stable_sort_primitive.rs      |   2 +-
 clippy_lints/src/methods/str_splitn.rs        |   4 +-
 clippy_lints/src/methods/suspicious_splitn.rs |   2 +-
 .../src/methods/suspicious_to_owned.rs        |   2 +-
 clippy_lints/src/methods/type_id_on_box.rs    |  62 +++-
 .../src/methods/unnecessary_filter_map.rs     |   2 +-
 .../src/methods/unnecessary_get_then_check.rs |   4 +-
 .../src/methods/unnecessary_iter_cloned.rs    |   2 +-
 .../src/methods/unnecessary_literal_unwrap.rs |   2 +-
 .../src/methods/unnecessary_to_owned.rs       |  19 +-
 .../src/methods/unwrap_expect_used.rs         |   2 +-
 clippy_lints/src/methods/useless_asref.rs     |   8 +-
 clippy_lints/src/methods/utils.rs             |  11 +-
 .../src/methods/verbose_file_reads.rs         |   2 +-
 .../src/methods/wrong_self_convention.rs      |   2 +-
 clippy_lints/src/min_ident_chars.rs           |   2 +-
 clippy_lints/src/misc.rs                      |   2 +-
 .../src/misc_early/builtin_type_shadow.rs     |   2 +-
 clippy_lints/src/misc_early/literal_suffix.rs |   4 +-
 clippy_lints/src/misc_early/mod.rs            |   2 +-
 .../src/misc_early/redundant_pattern.rs       |   2 +-
 .../src/misc_early/unneeded_field_pattern.rs  |   4 +-
 .../src/mismatching_type_param_order.rs       |   2 +-
 .../src/missing_asserts_for_indexing.rs       |   2 +-
 clippy_lints/src/missing_doc.rs               |   2 +-
 clippy_lints/src/missing_fields_in_debug.rs   |   2 +-
 clippy_lints/src/missing_inline.rs            |   2 +-
 clippy_lints/src/missing_trait_methods.rs     |   2 +-
 .../src/mixed_read_write_in_expression.rs     |   2 +-
 clippy_lints/src/module_style.rs              |   8 +-
 .../src/multiple_unsafe_ops_per_block.rs      |   2 +-
 clippy_lints/src/mut_reference.rs             |   7 +-
 clippy_lints/src/mutable_debug_assertion.rs   |   2 +-
 clippy_lints/src/mutex_atomic.rs              |   6 +-
 clippy_lints/src/needless_bool.rs             |  28 +-
 clippy_lints/src/needless_borrowed_ref.rs     |   2 +-
 .../src/needless_borrows_for_generic_args.rs  |   6 +-
 clippy_lints/src/needless_continue.rs         |   2 +-
 clippy_lints/src/needless_question_mark.rs    |   2 +-
 clippy_lints/src/new_without_default.rs       |   4 +-
 clippy_lints/src/no_effect.rs                 |   2 +-
 clippy_lints/src/non_copy_const.rs            |   4 +-
 clippy_lints/src/non_expressive_names.rs      |   2 +-
 .../src/non_send_fields_in_send_ty.rs         |   2 +-
 clippy_lints/src/nonstandard_macro_braces.rs  |   2 +-
 clippy_lints/src/octal_escapes.rs             |   2 +-
 .../operators/absurd_extreme_comparisons.rs   |   2 +-
 clippy_lints/src/operators/bit_mask.rs        |  16 +-
 .../src/operators/const_comparisons.rs        |   6 +-
 clippy_lints/src/operators/duration_subsec.rs |   2 +-
 clippy_lints/src/operators/eq_op.rs           |   4 +-
 .../src/operators/modulo_arithmetic.rs        |   2 +-
 clippy_lints/src/operators/ptr_eq.rs          |   2 +-
 clippy_lints/src/operators/self_assignment.rs |   2 +-
 clippy_lints/src/option_if_let_else.rs        |   2 +-
 clippy_lints/src/pass_by_ref_or_value.rs      |   4 +-
 clippy_lints/src/pattern_type_mismatch.rs     |   6 +-
 clippy_lints/src/ptr.rs                       |   6 +-
 clippy_lints/src/ptr_offset_with_cast.rs      |   4 +-
 clippy_lints/src/question_mark.rs             |  36 +-
 clippy_lints/src/ranges.rs                    |   4 +-
 clippy_lints/src/redundant_closure_call.rs    |  34 +-
 clippy_lints/src/redundant_locals.rs          |   4 +-
 clippy_lints/src/redundant_pub_crate.rs       |   2 +-
 .../src/redundant_static_lifetimes.rs         |   2 +-
 .../src/redundant_type_annotations.rs         |   2 +-
 clippy_lints/src/regex.rs                     |   6 +-
 clippy_lints/src/repeat_vec_with_capacity.rs  |   2 +-
 clippy_lints/src/returns.rs                   |   3 +-
 clippy_lints/src/self_named_constructors.rs   |   2 +-
 clippy_lints/src/serde_api.rs                 |   2 +-
 clippy_lints/src/shadow.rs                    |   2 +-
 clippy_lints/src/single_range_in_vec_init.rs  |   2 +-
 .../src/slow_vector_initialization.rs         |   2 +-
 clippy_lints/src/std_instead_of_core.rs       |   4 +-
 clippy_lints/src/strings.rs                   |   4 +-
 clippy_lints/src/suspicious_trait_impl.rs     |   2 +-
 clippy_lints/src/swap.rs                      | 182 +++++++++-
 ...ead_local_initializer_can_be_made_const.rs |   4 +-
 clippy_lints/src/trailing_empty_array.rs      |   2 +-
 clippy_lints/src/trait_bounds.rs              |   8 +-
 .../src/transmute/crosspointer_transmute.rs   |   4 +-
 .../missing_transmute_annotations.rs          |  87 +++++
 clippy_lints/src/transmute/mod.rs             |  34 ++
 .../src/transmute/transmute_float_to_int.rs   |   2 +-
 .../src/transmute/transmute_int_to_bool.rs    |   2 +-
 .../src/transmute/transmute_int_to_char.rs    |   2 +-
 .../src/transmute/transmute_int_to_float.rs   |   2 +-
 .../transmute/transmute_int_to_non_zero.rs    |   2 +-
 .../src/transmute/transmute_num_to_bytes.rs   |   2 +-
 .../src/transmute/transmute_ptr_to_ref.rs     |   2 +-
 .../src/transmute/transmute_ref_to_ref.rs     |   2 +-
 .../src/transmute/transmute_undefined_repr.rs |  10 +-
 .../transmutes_expressible_as_ptr_casts.rs    |   2 +-
 .../transmute/unsound_collection_transmute.rs |   2 +-
 .../src/transmute/useless_transmute.rs        |   2 +-
 clippy_lints/src/transmute/wrong_transmute.rs |   2 +-
 clippy_lints/src/types/box_collection.rs      |   4 +-
 .../src/types/redundant_allocation.rs         |   6 +-
 clippy_lints/src/unconditional_recursion.rs   |   2 +-
 .../src/undocumented_unsafe_blocks.rs         |  22 +-
 clippy_lints/src/unit_return_expecting_ord.rs |   4 +-
 clippy_lints/src/unit_types/let_unit_value.rs |  44 ++-
 clippy_lints/src/unit_types/unit_arg.rs       |   6 +-
 clippy_lints/src/unit_types/unit_cmp.rs       |   4 +-
 clippy_lints/src/unnecessary_box_returns.rs   |   2 +-
 .../src/unnecessary_map_on_constructor.rs     |   4 +-
 clippy_lints/src/unnecessary_wraps.rs         |   2 +-
 clippy_lints/src/unnested_or_patterns.rs      |   6 +-
 clippy_lints/src/unsafe_removed_from_name.rs  |   2 +-
 clippy_lints/src/unused_io_amount.rs          |  24 +-
 clippy_lints/src/unused_rounding.rs           |   4 +-
 clippy_lints/src/unwrap.rs                    |   4 +-
 clippy_lints/src/unwrap_in_result.rs          |   2 +-
 clippy_lints/src/upper_case_acronyms.rs       |   2 +-
 clippy_lints/src/use_self.rs                  |   4 +-
 clippy_lints/src/useless_conversion.rs        |  14 +-
 clippy_lints/src/utils/author.rs              |   4 +-
 .../almost_standard_lint_formulation.rs       |   2 +-
 .../utils/internal_lints/collapsible_calls.rs |   3 +-
 .../internal_lints/compiler_lint_functions.rs |   2 +-
 .../internal_lints/lint_without_lint_pass.rs  |   6 +-
 .../internal_lints/metadata_collector.rs      |  16 +-
 .../utils/internal_lints/msrv_attr_impl.rs    |   4 +-
 .../internal_lints/unnecessary_def_path.rs    |  13 +-
 clippy_lints/src/visibility.rs                |   2 +-
 clippy_lints/src/write.rs                     |   8 +-
 clippy_lints/src/zero_div_zero.rs             |   2 +-
 clippy_utils/src/ast_utils.rs                 |  20 +-
 clippy_utils/src/attrs.rs                     |  32 +-
 clippy_utils/src/check_proc_macro.rs          |  12 +-
 clippy_utils/src/consts.rs                    |  10 +-
 clippy_utils/src/diagnostics.rs               |  55 ++-
 clippy_utils/src/higher.rs                    |  54 +--
 clippy_utils/src/hir_utils.rs                 |   3 +-
 clippy_utils/src/lib.rs                       |  76 ++--
 clippy_utils/src/macros.rs                    |   2 +-
 clippy_utils/src/mir/mod.rs                   |   2 +-
 clippy_utils/src/sugg.rs                      |  79 +++--
 clippy_utils/src/ty.rs                        |  42 ++-
 clippy_utils/src/usage.rs                     |  18 +-
 clippy_utils/src/visitors.rs                  |  28 +-
 lintcheck/src/main.rs                         |  41 ++-
 rust-toolchain                                |   2 +-
 tests/compile-test.rs                         |   2 +
 .../ui-toml/absolute_paths/absolute_paths.rs  |   2 +-
 .../large_stack_frames/large_stack_frames.rs  |   2 +-
 .../large_stack_frames.stderr                 |  17 +-
 tests/ui/assigning_clones.fixed               |  13 +
 tests/ui/assigning_clones.rs                  |  13 +
 tests/ui/assigning_clones.stderr              |  12 +-
 tests/ui/author/issue_3849.rs                 |   2 +-
 tests/ui/auxiliary/macro_rules.rs             |   7 +
 tests/ui/blocks_in_conditions.fixed           |   7 +-
 tests/ui/blocks_in_conditions.rs              |   7 +-
 tests/ui/blocks_in_conditions.stderr          |   8 +-
 tests/ui/box_default.fixed                    |  85 +++--
 tests/ui/box_default.rs                       |  75 ++--
 tests/ui/box_default.stderr                   | 104 ++----
 tests/ui/cast.rs                              |  12 +-
 tests/ui/cast.stderr                          | 190 +++++-----
 tests/ui/checked_conversions.fixed            |   1 +
 tests/ui/checked_conversions.rs               |   1 +
 tests/ui/checked_conversions.stderr           |  34 +-
 tests/ui/crashes/ice-12616.fixed              |   7 +
 tests/ui/crashes/ice-12616.rs                 |   7 +
 tests/ui/crashes/ice-12616.stderr             |  19 +
 tests/ui/crashes/ice-1782.rs                  |   2 +-
 tests/ui/duplicated_attributes.rs             |  13 +-
 tests/ui/duplicated_attributes.stderr         |  94 +----
 tests/ui/eager_transmute.fixed                |   2 +-
 tests/ui/eager_transmute.rs                   |   2 +-
 tests/ui/filter_map_identity.fixed            |  86 ++++-
 tests/ui/filter_map_identity.rs               |  86 ++++-
 tests/ui/filter_map_identity.stderr           | 134 ++++++-
 tests/ui/large_stack_frames.rs                |  17 +-
 tests/ui/large_stack_frames.stderr            |  60 ++--
 tests/ui/legacy_numeric_constants.fixed       | 117 ++++++
 tests/ui/legacy_numeric_constants.rs          | 117 ++++++
 tests/ui/legacy_numeric_constants.stderr      | 184 ++++++++++
 .../ui/legacy_numeric_constants_unfixable.rs  |  78 ++++
 .../legacy_numeric_constants_unfixable.stderr |  83 +++++
 tests/ui/len_zero.fixed                       |  37 ++
 tests/ui/len_zero.rs                          |  37 ++
 tests/ui/len_zero.stderr                      |  20 +-
 tests/ui/let_and_return.fixed                 |   7 +
 tests/ui/let_and_return.rs                    |   7 +
 tests/ui/let_unit.fixed                       |  18 +
 tests/ui/let_unit.rs                          |  18 +
 tests/ui/let_unit.stderr                      |  21 +-
 tests/ui/manual_assert.edition2018.fixed      |   8 +
 tests/ui/manual_assert.edition2018.stderr     |  11 +-
 tests/ui/manual_assert.edition2021.fixed      |   8 +
 tests/ui/manual_assert.edition2021.stderr     |  11 +-
 tests/ui/manual_assert.rs                     |  10 +
 tests/ui/manual_clamp.fixed                   | 287 +++++++++++----
 tests/ui/manual_clamp.rs                      | 333 +++++++++++++-----
 tests/ui/manual_clamp.stderr                  | 188 +++++-----
 tests/ui/manual_saturating_arithmetic.fixed   |   2 +-
 tests/ui/manual_saturating_arithmetic.rs      |   2 +-
 tests/ui/manual_swap_auto_fix.fixed           |  57 +++
 tests/ui/manual_swap_auto_fix.rs              |  72 ++++
 tests/ui/manual_swap_auto_fix.stderr          |  88 +++++
 tests/ui/manual_unwrap_or_default.fixed       |  45 +++
 tests/ui/manual_unwrap_or_default.rs          |  48 +++
 tests/ui/manual_unwrap_or_default.stderr      |  12 +-
 tests/ui/map_clone.fixed                      |  24 ++
 tests/ui/map_clone.rs                         |  24 ++
 .../ui/missing_const_for_fn/could_be_const.rs |   2 +-
 tests/ui/missing_transmute_annotations.fixed  |  78 ++++
 tests/ui/missing_transmute_annotations.rs     |  78 ++++
 tests/ui/missing_transmute_annotations.stderr |  76 ++++
 tests/ui/mixed_attributes_style.rs            |  60 ++++
 tests/ui/mixed_attributes_style.stderr        |  41 ++-
 .../auxiliary/submodule.rs                    |   9 +
 .../ui/mixed_attributes_style/global_allow.rs |   7 +
 .../mixed_attributes_style/mod_declaration.rs |   3 +
 .../mod_declaration.stderr                    |  14 +
 tests/ui/ptr_cast_constness.fixed             |   7 +-
 tests/ui/ptr_cast_constness.rs                |   7 +-
 tests/ui/ptr_cast_constness.stderr            |  14 +-
 tests/ui/question_mark.fixed                  |  34 ++
 tests/ui/question_mark.rs                     |  36 ++
 tests/ui/question_mark.stderr                 |  10 +-
 tests/ui/suspicious_arithmetic_impl.rs        |   1 +
 tests/ui/suspicious_arithmetic_impl.stderr    |  18 +-
 tests/ui/suspicious_else_formatting.rs        |  28 ++
 tests/ui/transmute.rs                         |   7 +-
 tests/ui/transmute.stderr                     |  72 ++--
 tests/ui/transmute_collection.rs              |   1 +
 tests/ui/transmute_collection.stderr          |  36 +-
 tests/ui/transmute_float_to_int.fixed         |   1 +
 tests/ui/transmute_float_to_int.rs            |   1 +
 tests/ui/transmute_float_to_int.stderr        |  12 +-
 tests/ui/transmute_int_to_char.fixed          |   1 +
 tests/ui/transmute_int_to_char.rs             |   1 +
 tests/ui/transmute_int_to_char.stderr         |   4 +-
 tests/ui/transmute_int_to_char_no_std.fixed   |   1 +
 tests/ui/transmute_int_to_char_no_std.rs      |   1 +
 tests/ui/transmute_int_to_char_no_std.stderr  |   4 +-
 tests/ui/transmute_int_to_non_zero.fixed      |   1 +
 tests/ui/transmute_int_to_non_zero.rs         |   1 +
 tests/ui/transmute_int_to_non_zero.stderr     |  20 +-
 tests/ui/transmute_null_to_fn.rs              |   2 +-
 tests/ui/transmute_ptr_to_ptr.fixed           |   2 +-
 tests/ui/transmute_ptr_to_ptr.rs              |   2 +-
 tests/ui/transmute_ptr_to_ref.fixed           |   6 +-
 tests/ui/transmute_ptr_to_ref.rs              |   6 +-
 tests/ui/transmute_ptr_to_ref.stderr          |  44 +--
 tests/ui/transmute_ref_to_ref.rs              |   2 +-
 tests/ui/transmute_ref_to_ref_no_std.rs       |   2 +-
 tests/ui/transmute_undefined_repr.rs          |   7 +-
 tests/ui/transmute_undefined_repr.stderr      |  24 +-
 .../transmutes_expressible_as_ptr_casts.fixed |   2 +-
 .../ui/transmutes_expressible_as_ptr_casts.rs |   2 +-
 tests/ui/transmuting_null.rs                  |   2 +-
 tests/ui/type_id_on_box.fixed                 |  24 +-
 tests/ui/type_id_on_box.rs                    |  24 +-
 tests/ui/type_id_on_box.stderr                |  33 +-
 tests/ui/type_id_on_box_unfixable.rs          |  31 ++
 tests/ui/type_id_on_box_unfixable.stderr      |  22 ++
 tests/ui/uninhabited_references.rs            |   1 +
 tests/ui/uninhabited_references.stderr        |   8 +-
 tests/ui/use_self.fixed                       |   3 +-
 tests/ui/use_self.rs                          |   3 +-
 tests/ui/use_self.stderr                      |  86 ++---
 tests/ui/useless_asref.fixed                  |  18 +
 tests/ui/useless_asref.rs                     |  18 +
 tests/ui/useless_asref.stderr                 |  36 +-
 triagebot.toml                                |   2 +-
 444 files changed, 5289 insertions(+), 1934 deletions(-)
 create mode 100644 book/src/development/the_team.md
 create mode 100644 clippy_lints/src/legacy_numeric_constants.rs
 create mode 100644 clippy_lints/src/transmute/missing_transmute_annotations.rs
 create mode 100644 tests/ui/crashes/ice-12616.fixed
 create mode 100644 tests/ui/crashes/ice-12616.rs
 create mode 100644 tests/ui/crashes/ice-12616.stderr
 create mode 100644 tests/ui/legacy_numeric_constants.fixed
 create mode 100644 tests/ui/legacy_numeric_constants.rs
 create mode 100644 tests/ui/legacy_numeric_constants.stderr
 create mode 100644 tests/ui/legacy_numeric_constants_unfixable.rs
 create mode 100644 tests/ui/legacy_numeric_constants_unfixable.stderr
 create mode 100644 tests/ui/manual_swap_auto_fix.fixed
 create mode 100644 tests/ui/manual_swap_auto_fix.rs
 create mode 100644 tests/ui/manual_swap_auto_fix.stderr
 create mode 100644 tests/ui/missing_transmute_annotations.fixed
 create mode 100644 tests/ui/missing_transmute_annotations.rs
 create mode 100644 tests/ui/missing_transmute_annotations.stderr
 create mode 100644 tests/ui/mixed_attributes_style/auxiliary/submodule.rs
 create mode 100644 tests/ui/mixed_attributes_style/global_allow.rs
 create mode 100644 tests/ui/mixed_attributes_style/mod_declaration.rs
 create mode 100644 tests/ui/mixed_attributes_style/mod_declaration.stderr
 create mode 100644 tests/ui/type_id_on_box_unfixable.rs
 create mode 100644 tests/ui/type_id_on_box_unfixable.stderr

diff --git a/.gitignore b/.gitignore
index 503ae3c5090..181b71a658b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
+# Generated by ui-test
+rustc-ice-*
+
 # Used by CI to be able to push:
 /.github/deploy_key
 out
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 76ef84a48b8..f7e7ed86eed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5379,6 +5379,7 @@ Released 2018-09-13
 [`large_stack_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays
 [`large_stack_frames`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames
 [`large_types_passed_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value
+[`legacy_numeric_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants
 [`len_without_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_without_is_empty
 [`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
 [`let_and_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return
@@ -5481,6 +5482,7 @@ Released 2018-09-13
 [`missing_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc
 [`missing_spin_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_spin_loop
 [`missing_trait_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_trait_methods
+[`missing_transmute_annotations`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_transmute_annotations
 [`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes
 [`mixed_attributes_style`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_attributes_style
 [`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals
diff --git a/Cargo.toml b/Cargo.toml
index 2b37b54c004..43f20ecedc2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -31,7 +31,6 @@ anstream = "0.6.0"
 
 [dev-dependencies]
 ui_test = "0.22.2"
-tester = "0.9"
 regex = "1.5.5"
 toml = "0.7.3"
 walkdir = "2.3"
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index a048fbbd8ac..be13fcbe260 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -32,3 +32,4 @@
     - [Proposals](development/proposals/README.md)
         - [Roadmap 2021](development/proposals/roadmap-2021.md)
         - [Syntax Tree Patterns](development/proposals/syntax-tree-patterns.md)
+    - [The Team](development/the_team.md)
diff --git a/book/src/development/defining_lints.md b/book/src/development/defining_lints.md
index 54f77b00190..806ed0845f0 100644
--- a/book/src/development/defining_lints.md
+++ b/book/src/development/defining_lints.md
@@ -62,9 +62,8 @@ $ cargo dev new_lint --name=lint_name --pass=late --category=pedantic
 There are two things to note here:
 
 1. `--pass`: We set `--pass=late` in this command to do a late lint pass. The
-   alternative is an `early` lint pass. We will discuss this difference in a
-   later chapter.
-   <!-- FIXME: Link that "later chapter" when lint_passes.md is merged -->
+   alternative is an `early` lint pass. We will discuss this difference in the
+   [Lint Passes] chapter.
 2. `--category`: If not provided, the `category` of this new lint will default
    to `nursery`.
 
@@ -194,8 +193,7 @@ store.register_late_pass(|_| Box::new(foo_functions::FooFunctions));
 
 As you might have guessed, where there's something late, there is something
 early: in Clippy there is a `register_early_pass` method as well. More on early
-vs. late passes in a later chapter.
-<!-- FIXME: Link that "later chapter" when lint_passes.md is merged -->
+vs. late passes in the [Lint Passes] chapter.
 
 Without a call to one of `register_early_pass` or `register_late_pass`, the lint
 pass in question will not be run.
@@ -203,3 +201,4 @@ pass in question will not be run.
 
 [all_lints]: https://rust-lang.github.io/rust-clippy/master/
 [lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
+[Lint Passes]: lint_passes.md
diff --git a/book/src/development/lint_passes.md b/book/src/development/lint_passes.md
index 621fc20972e..dde9e1a273b 100644
--- a/book/src/development/lint_passes.md
+++ b/book/src/development/lint_passes.md
@@ -50,7 +50,7 @@ questions already, but the parser is okay with it. This is what we
 mean when we say `EarlyLintPass` deals with only syntax on the AST level.
 
 Alternatively, think of the `foo_functions` lint we mentioned in
-define new lints <!-- FIXME: add link --> chapter.
+the [Define New Lints](defining_lints.md) chapter.
 
 We want the `foo_functions` lint to detect functions with `foo` as their name.
 Writing a lint that only checks for the name of a function means that we only
diff --git a/book/src/development/the_team.md b/book/src/development/the_team.md
new file mode 100644
index 00000000000..10341791cec
--- /dev/null
+++ b/book/src/development/the_team.md
@@ -0,0 +1,130 @@
+# The team
+
+Everyone who contributes to Clippy makes the project what it is. Collaboration
+and discussions are the lifeblood of every open-source project. Clippy has a
+very flat hierarchy. The teams mainly have additional access rights to the repo.
+
+This document outlines the onboarding process, as well as duties, and access
+rights for members of a group.
+
+All regular events mentioned in this chapter are tracked in the [calendar repository].
+The calendar file is also available for download: [clippy.ics]
+
+## Everyone
+
+Everyone, including you, is welcome to join discussions and contribute in other
+ways, like PRs.
+
+You also have some triage rights, using `@rustbot` to add labels and claim
+issues. See [labeling with @rustbot].
+
+A rule for everyone should be to keep a healthy work-life balance. Take a break
+when you need one.
+
+## Clippy-Contributors
+
+This is a group of regular contributors to Clippy to help with triaging.
+
+### Duties
+
+This team exists to make contributing easier for regular members. It doesn't
+carry any duties that need to be done. However, we want to encourage members of
+this group to help with triaging, which can include:
+
+1. **Labeling issues**
+
+    For the `good-first-issue` label, it can still be good to use `@rustbot` to
+    subscribe to the issue and help interested parties, if they post questions
+    in the comments. 
+
+2. **Closing duplicate or resolved issues**
+
+    When you manually close an issue, it's often a good idea, to add a short
+    comment explaining the reason.
+
+3. **Ping people after two weeks of inactivity**
+
+    We try to keep issue assignments and PRs fairly up-to-date. After two weeks,
+    it can be good to send a friendly ping to the delaying party.
+
+    You might close a PR with the `I-inactive-closed` label if the author is
+    busy or wants to abandon it. If the reviewer is busy, the PR can be
+    reassigned to someone else.
+
+    Checkout: https://triage.rust-lang.org/triage/rust-lang/rust-clippy to
+    monitor PRs.
+
+While not part of their duties, contributors are encouraged to review PRs
+and help on Zulip. The team always appreciates help!
+
+### Membership
+
+If you have been contributing to Clippy for some time, we'll probably ask you if
+you want to join this team. Members of this team are also welcome to suggest
+people who they think would make a great addition to this group.
+
+For this group, there is no direct onboarding process. You're welcome to just
+continue what you've been doing. If you like, you can ask for someone to mentor
+you, either in the Clippy stream on Zulip or privately via a PM.
+
+If you have been inactive in Clippy for over three months, we'll probably move
+you to the alumni group. You're always welcome to come back.
+
+## The Clippy Team
+
+[The Clippy team](https://www.rust-lang.org/governance/teams/dev-tools#Clippy%20team)
+is responsible for maintaining Clippy.
+
+### Duties
+
+1. **Respond to PRs in a timely manner**
+
+    It's totally fine, if you don't have the time for reviews right now.
+    You can reassign the PR to a random member by commenting `r? clippy`.
+
+2. **Take a break when you need one**
+
+    You are valuable! Clippy wouldn't be what it is without you. So take a break
+    early and recharge some energy when you need to.
+
+3. **Be responsive on Zulip**
+
+    This means in a reasonable time frame, so responding within one or two days
+    is totally fine.
+
+    It's also good, if you answer threads on Zulip and take part in our Clippy
+    meetings, every two weeks. The meeting dates are tracked in the [calendar repository].
+    
+
+4. **Sync Clippy with the rust-lang/rust repo**
+
+    This is done every two weeks, usually by @flip1995.
+
+5. **Update the changelog**
+
+    This needs to be done for every release, every six weeks. This is usually
+    done by @xFrednet.
+
+### Membership
+
+If you have been active for some time, we'll probably reach out and ask
+if you want to help with reviews and eventually join the Clippy team.
+
+During the onboarding process, you'll be assigned pull requests to review.
+You'll also have an active team member as a mentor who'll stay in contact via
+Zulip DMs to provide advice and feedback. If you have questions, you're always
+welcome to ask, that is the best way to learn. Once you're done with the review,
+you can ping your mentor for a full review and to r+ the PR in both of your names.
+
+When your mentor is confident that you can handle reviews on your own, they'll
+start an informal vote among the active team members to officially add you to
+the team. This vote is usually accepted unanimously. Then you'll be added to
+the team once you've confirmed that you're still interested in joining. The
+onboarding phase typically takes a couple of weeks to a few months.
+
+If you have been inactive in Clippy for over three months, we'll probably move
+you to the alumni group. You're always welcome to come back.
+
+[calendar repository]: https://github.com/rust-lang/calendar/blob/main/clippy.toml
+[clippy.ics]: https://rust-lang.github.io/calendar/clippy.ics
+[labeling with @rustbot]: https://forge.rust-lang.org/triagebot/labeling.html
diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md
index a9234899746..4a2727c5197 100644
--- a/book/src/lint_configuration.md
+++ b/book/src/lint_configuration.md
@@ -616,6 +616,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
 * [`if_then_some_else_none`](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none)
 * [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
 * [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map)
+* [`legacy_numeric_constants`](https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants)
 * [`manual_bits`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits)
 * [`manual_c_str_literals`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals)
 * [`manual_clamp`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp)
diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs
index 3218fe7f456..53c10f7cee8 100644
--- a/clippy_config/src/conf.rs
+++ b/clippy_config/src/conf.rs
@@ -262,7 +262,7 @@ define_Conf! {
     ///
     /// Suppress lints whenever the suggested change would cause breakage for other crates.
     (avoid_breaking_exported_api: bool = true),
-    /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES.
+    /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES, LEGACY_NUMERIC_CONSTANTS.
     ///
     /// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
     #[default_text = ""]
@@ -856,11 +856,6 @@ mod tests {
             }
         }
 
-        assert!(
-            names.remove("allow-one-hash-in-raw-strings"),
-            "remove this when #11481 is fixed"
-        );
-
         assert!(
             names.is_empty(),
             "Configuration variable lacks test: {names:?}\nAdd a test to `tests/ui-toml`"
diff --git a/clippy_config/src/lib.rs b/clippy_config/src/lib.rs
index 01e2aa6e0a6..ff7fa7241cb 100644
--- a/clippy_config/src/lib.rs
+++ b/clippy_config/src/lib.rs
@@ -1,6 +1,12 @@
 #![feature(rustc_private, let_chains)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
-#![warn(rust_2018_idioms, unused_lifetimes)]
+#![warn(
+    trivial_casts,
+    trivial_numeric_casts,
+    rust_2018_idioms,
+    unused_lifetimes,
+    unused_qualifications
+)]
 #![allow(
     clippy::must_use_candidate,
     clippy::missing_panics_doc,
diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs
index 149c4776dc9..59dd5b334b8 100644
--- a/clippy_config/src/msrvs.rs
+++ b/clippy_config/src/msrvs.rs
@@ -36,7 +36,7 @@ msrv_aliases! {
     1,47,0 { TAU, IS_ASCII_DIGIT_CONST, ARRAY_IMPL_ANY_LEN }
     1,46,0 { CONST_IF_MATCH }
     1,45,0 { STR_STRIP_PREFIX }
-    1,43,0 { LOG2_10, LOG10_2 }
+    1,43,0 { LOG2_10, LOG10_2, NUMERIC_ASSOCIATED_CONSTANTS }
     1,42,0 { MATCHES_MACRO, SLICE_PATTERNS, PTR_SLICE_RAW_PARTS }
     1,41,0 { RE_REBALANCING_COHERENCE, RESULT_MAP_OR_ELSE }
     1,40,0 { MEM_TAKE, NON_EXHAUSTIVE, OPTION_AS_DEREF }
diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs
index c4ae4f0e2bd..bb62e902cd5 100644
--- a/clippy_dev/src/lib.rs
+++ b/clippy_dev/src/lib.rs
@@ -2,8 +2,13 @@
 #![feature(let_chains)]
 #![feature(rustc_private)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
-// warn on lints, that are included in `rust-lang/rust`s bootstrap
-#![warn(rust_2018_idioms, unused_lifetimes)]
+#![warn(
+    trivial_casts,
+    trivial_numeric_casts,
+    rust_2018_idioms,
+    unused_lifetimes,
+    unused_qualifications
+)]
 
 // The `rustc_driver` crate seems to be required in order to use the `rust_lexer` crate.
 #[allow(unused_extern_crates)]
diff --git a/clippy_dev/src/lint.rs b/clippy_dev/src/lint.rs
index 906a9727810..f308f5dfdfd 100644
--- a/clippy_dev/src/lint.rs
+++ b/clippy_dev/src/lint.rs
@@ -20,6 +20,8 @@ pub fn run<'a>(path: &str, args: impl Iterator<Item = &'a String>) {
                 .args(["--edition", "2021"])
                 .arg(path)
                 .args(args)
+                // Prevent rustc from creating `rustc-ice-*` files the console output is enough.
+                .env("RUSTC_ICE", "0")
                 .status(),
         );
     } else {
@@ -32,6 +34,8 @@ pub fn run<'a>(path: &str, args: impl Iterator<Item = &'a String>) {
         let status = Command::new(cargo_clippy_path())
             .arg("clippy")
             .args(args)
+            // Prevent rustc from creating `rustc-ice-*` files the console output is enough.
+            .env("RUSTC_ICE", "0")
             .current_dir(path)
             .status();
 
diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs
index 76ae26dddf4..625b1339591 100644
--- a/clippy_dev/src/update_lints.rs
+++ b/clippy_dev/src/update_lints.rs
@@ -992,7 +992,7 @@ fn replace_region_in_text<'a>(
 }
 
 fn try_rename_file(old_name: &Path, new_name: &Path) -> bool {
-    match fs::OpenOptions::new().create_new(true).write(true).open(new_name) {
+    match OpenOptions::new().create_new(true).write(true).open(new_name) {
         Ok(file) => drop(file),
         Err(e) if matches!(e.kind(), io::ErrorKind::AlreadyExists | io::ErrorKind::NotFound) => return false,
         Err(e) => panic_file(e, new_name, "create"),
@@ -1016,7 +1016,7 @@ fn panic_file(error: io::Error, name: &Path, action: &str) -> ! {
 }
 
 fn rewrite_file(path: &Path, f: impl FnOnce(&str) -> Option<String>) {
-    let mut file = fs::OpenOptions::new()
+    let mut file = OpenOptions::new()
         .write(true)
         .read(true)
         .open(path)
diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs
index 25606f4253e..ec28fd46111 100644
--- a/clippy_lints/src/approx_const.rs
+++ b/clippy_lints/src/approx_const.rs
@@ -95,7 +95,7 @@ impl ApproxConstant {
                         cx,
                         APPROX_CONSTANT,
                         e.span,
-                        &format!("approximate value of `{module}::consts::{}` found", &name),
+                        format!("approximate value of `{module}::consts::{}` found", &name),
                         None,
                         "consider using the constant directly",
                     );
diff --git a/clippy_lints/src/asm_syntax.rs b/clippy_lints/src/asm_syntax.rs
index c2fa56e1360..7c88bfc97ca 100644
--- a/clippy_lints/src/asm_syntax.rs
+++ b/clippy_lints/src/asm_syntax.rs
@@ -53,9 +53,9 @@ fn check_asm_syntax(
                 cx,
                 lint,
                 span,
-                &format!("{style} x86 assembly syntax used"),
+                format!("{style} x86 assembly syntax used"),
                 None,
-                &format!("use {} x86 assembly syntax", !style),
+                format!("use {} x86 assembly syntax", !style),
             );
         }
     }
diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs
index 9365fbfaed0..2003dd1fb0e 100644
--- a/clippy_lints/src/assertions_on_constants.rs
+++ b/clippy_lints/src/assertions_on_constants.rs
@@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants {
                 cx,
                 ASSERTIONS_ON_CONSTANTS,
                 macro_call.span,
-                &format!(
+                format!(
                     "`{}!(true)` will be optimized out by the compiler",
                     cx.tcx.item_name(macro_call.def_id)
                 ),
@@ -74,9 +74,9 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants {
                 cx,
                 ASSERTIONS_ON_CONSTANTS,
                 macro_call.span,
-                &format!("`assert!(false{assert_arg})` should probably be replaced"),
+                format!("`assert!(false{assert_arg})` should probably be replaced"),
                 None,
-                &format!("use `panic!({panic_arg})` or `unreachable!({panic_arg})`"),
+                format!("use `panic!({panic_arg})` or `unreachable!({panic_arg})`"),
             );
         }
     }
diff --git a/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs
index 8e27b3ccefd..dc7f44af2b7 100644
--- a/clippy_lints/src/assigning_clones.rs
+++ b/clippy_lints/src/assigning_clones.rs
@@ -65,7 +65,7 @@ impl AssigningClones {
 impl_lint_pass!(AssigningClones => [ASSIGNING_CLONES]);
 
 impl<'tcx> LateLintPass<'tcx> for AssigningClones {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, assign_expr: &'tcx hir::Expr<'_>) {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, assign_expr: &'tcx Expr<'_>) {
         // Do not fire the lint in macros
         let expn_data = assign_expr.span().ctxt().outer_expn_data();
         match expn_data.kind {
@@ -181,6 +181,23 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC
         return false;
     }
 
+    // If the call expression is inside an impl block that contains the method invoked by the
+    // call expression, we bail out to avoid suggesting something that could result in endless
+    // recursion.
+    if let Some(local_block_id) = impl_block.as_local()
+        && let Some(block) = cx.tcx.hir_node_by_def_id(local_block_id).as_owner()
+    {
+        let impl_block_owner = block.def_id();
+        if cx
+            .tcx
+            .hir()
+            .parent_id_iter(lhs.hir_id)
+            .any(|parent| parent.owner == impl_block_owner)
+        {
+            return false;
+        }
+    }
+
     // Find the function for which we want to check that it is implemented.
     let provided_fn = match call.target {
         TargetTrait::Clone => cx.tcx.get_diagnostic_item(sym::Clone).and_then(|clone| {
@@ -205,14 +222,9 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC
     implemented_fns.contains_key(&provided_fn.def_id)
 }
 
-fn suggest<'tcx>(
-    cx: &LateContext<'tcx>,
-    assign_expr: &hir::Expr<'tcx>,
-    lhs: &hir::Expr<'tcx>,
-    call: &CallCandidate<'tcx>,
-) {
+fn suggest<'tcx>(cx: &LateContext<'tcx>, assign_expr: &Expr<'tcx>, lhs: &Expr<'tcx>, call: &CallCandidate<'tcx>) {
     span_lint_and_then(cx, ASSIGNING_CLONES, assign_expr.span, call.message(), |diag| {
-        let mut applicability = Applicability::MachineApplicable;
+        let mut applicability = Applicability::Unspecified;
 
         diag.span_suggestion(
             assign_expr.span,
@@ -263,7 +275,7 @@ impl<'tcx> CallCandidate<'tcx> {
     fn suggested_replacement(
         &self,
         cx: &LateContext<'tcx>,
-        lhs: &hir::Expr<'tcx>,
+        lhs: &Expr<'tcx>,
         applicability: &mut Applicability,
     ) -> String {
         match self.target {
diff --git a/clippy_lints/src/attrs/allow_attributes_without_reason.rs b/clippy_lints/src/attrs/allow_attributes_without_reason.rs
index df00f23e37e..4a22e17463f 100644
--- a/clippy_lints/src/attrs/allow_attributes_without_reason.rs
+++ b/clippy_lints/src/attrs/allow_attributes_without_reason.rs
@@ -30,7 +30,7 @@ pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMet
         cx,
         ALLOW_ATTRIBUTES_WITHOUT_REASON,
         attr.span,
-        &format!("`{}` attribute without specifying a reason", name.as_str()),
+        format!("`{}` attribute without specifying a reason", name.as_str()),
         None,
         "try adding a reason at the end with `, reason = \"..\"`",
     );
diff --git a/clippy_lints/src/attrs/duplicated_attributes.rs b/clippy_lints/src/attrs/duplicated_attributes.rs
index 3c5ac597fd5..3a8844d0754 100644
--- a/clippy_lints/src/attrs/duplicated_attributes.rs
+++ b/clippy_lints/src/attrs/duplicated_attributes.rs
@@ -31,6 +31,9 @@ fn check_duplicated_attr(
     attr_paths: &mut FxHashMap<String, Span>,
     parent: &mut Vec<String>,
 ) {
+    if attr.span.from_expansion() {
+        return;
+    }
     let Some(ident) = attr.ident() else { return };
     let name = ident.name;
     if name == sym::doc || name == sym::cfg_attr {
@@ -38,6 +41,14 @@ fn check_duplicated_attr(
         // conditions are the same.
         return;
     }
+    if let Some(direct_parent) = parent.last()
+        && ["cfg", "cfg_attr"].contains(&direct_parent.as_str())
+        && [sym::all, sym::not, sym::any].contains(&name)
+    {
+        // FIXME: We don't correctly check `cfg`s for now, so if it's more complex than just a one
+        // level `cfg`, we leave.
+        return;
+    }
     if let Some(value) = attr.value_str() {
         emit_if_duplicated(cx, attr, attr_paths, format!("{}:{name}={value}", parent.join(":")));
     } else if let Some(sub_attrs) = attr.meta_item_list() {
diff --git a/clippy_lints/src/attrs/inline_always.rs b/clippy_lints/src/attrs/inline_always.rs
index cfcd2cc6a00..3b5b80ffefa 100644
--- a/clippy_lints/src/attrs/inline_always.rs
+++ b/clippy_lints/src/attrs/inline_always.rs
@@ -21,7 +21,7 @@ pub(super) fn check(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Att
                     cx,
                     INLINE_ALWAYS,
                     attr.span,
-                    &format!("you have declared `#[inline(always)]` on `{name}`. This is usually a bad idea"),
+                    format!("you have declared `#[inline(always)]` on `{name}`. This is usually a bad idea"),
                 );
             }
         }
diff --git a/clippy_lints/src/attrs/maybe_misused_cfg.rs b/clippy_lints/src/attrs/maybe_misused_cfg.rs
index 5a70866eda5..e6b2e835be8 100644
--- a/clippy_lints/src/attrs/maybe_misused_cfg.rs
+++ b/clippy_lints/src/attrs/maybe_misused_cfg.rs
@@ -40,7 +40,7 @@ fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
                     cx,
                     MAYBE_MISUSED_CFG,
                     meta.span,
-                    &format!("'test' may be misspelled as '{}'", ident.name.as_str()),
+                    format!("'test' may be misspelled as '{}'", ident.name.as_str()),
                     "did you mean",
                     "test".to_string(),
                     Applicability::MaybeIncorrect,
diff --git a/clippy_lints/src/attrs/mixed_attributes_style.rs b/clippy_lints/src/attrs/mixed_attributes_style.rs
index c2e21cfd330..75a3d7a9ac3 100644
--- a/clippy_lints/src/attrs/mixed_attributes_style.rs
+++ b/clippy_lints/src/attrs/mixed_attributes_style.rs
@@ -1,30 +1,85 @@
 use super::MIXED_ATTRIBUTES_STYLE;
 use clippy_utils::diagnostics::span_lint;
-use rustc_ast::AttrStyle;
-use rustc_lint::EarlyContext;
+use rustc_ast::{AttrKind, AttrStyle, Attribute};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_lint::{LateContext, LintContext};
+use rustc_span::source_map::SourceMap;
+use rustc_span::{SourceFile, Span, Symbol};
+use std::sync::Arc;
 
-pub(super) fn check(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
-    let mut has_outer = false;
-    let mut has_inner = false;
+#[derive(Hash, PartialEq, Eq)]
+enum SimpleAttrKind {
+    Doc,
+    /// A normal attribute, with its name symbols.
+    Normal(Vec<Symbol>),
+}
 
-    for attr in &item.attrs {
-        if attr.span.from_expansion() {
+impl From<&AttrKind> for SimpleAttrKind {
+    fn from(value: &AttrKind) -> Self {
+        match value {
+            AttrKind::Normal(attr) => {
+                let path_symbols = attr
+                    .item
+                    .path
+                    .segments
+                    .iter()
+                    .map(|seg| seg.ident.name)
+                    .collect::<Vec<_>>();
+                Self::Normal(path_symbols)
+            },
+            AttrKind::DocComment(..) => Self::Doc,
+        }
+    }
+}
+
+pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute]) {
+    let mut inner_attr_kind: FxHashSet<SimpleAttrKind> = FxHashSet::default();
+    let mut outer_attr_kind: FxHashSet<SimpleAttrKind> = FxHashSet::default();
+
+    let source_map = cx.sess().source_map();
+    let item_src = source_map.lookup_source_file(item_span.lo());
+
+    for attr in attrs {
+        if attr.span.from_expansion() || !attr_in_same_src_as_item(source_map, &item_src, attr.span) {
             continue;
         }
+
+        let kind: SimpleAttrKind = (&attr.kind).into();
         match attr.style {
-            AttrStyle::Inner => has_inner = true,
-            AttrStyle::Outer => has_outer = true,
-        }
+            AttrStyle::Inner => {
+                if outer_attr_kind.contains(&kind) {
+                    lint_mixed_attrs(cx, attrs);
+                    return;
+                }
+                inner_attr_kind.insert(kind);
+            },
+            AttrStyle::Outer => {
+                if inner_attr_kind.contains(&kind) {
+                    lint_mixed_attrs(cx, attrs);
+                    return;
+                }
+                outer_attr_kind.insert(kind);
+            },
+        };
     }
-    if !has_outer || !has_inner {
+}
+
+fn lint_mixed_attrs(cx: &LateContext<'_>, attrs: &[Attribute]) {
+    let mut attrs_iter = attrs.iter().filter(|attr| !attr.span.from_expansion());
+    let span = if let (Some(first), Some(last)) = (attrs_iter.next(), attrs_iter.last()) {
+        first.span.with_hi(last.span.hi())
+    } else {
         return;
-    }
-    let mut attrs_iter = item.attrs.iter().filter(|attr| !attr.span.from_expansion());
-    let span = attrs_iter.next().unwrap().span;
+    };
     span_lint(
         cx,
         MIXED_ATTRIBUTES_STYLE,
-        span.with_hi(attrs_iter.last().unwrap().span.hi()),
+        span,
         "item has both inner and outer attributes",
     );
 }
+
+fn attr_in_same_src_as_item(source_map: &SourceMap, item_src: &Arc<SourceFile>, attr_span: Span) -> bool {
+    let attr_src = source_map.lookup_source_file(attr_span.lo());
+    Arc::ptr_eq(item_src, &attr_src)
+}
diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs
index 675c428948f..684ad7de2f0 100644
--- a/clippy_lints/src/attrs/mod.rs
+++ b/clippy_lints/src/attrs/mod.rs
@@ -465,10 +465,20 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks that an item has only one kind of attributes.
+    /// Checks for items that have the same kind of attributes with mixed styles (inner/outer).
     ///
     /// ### Why is this bad?
-    /// Having both kinds of attributes makes it more complicated to read code.
+    /// Having both style of said attributes makes it more complicated to read code.
+    ///
+    /// ### Known problems
+    /// This lint currently has false-negatives when mixing same attributes
+    /// but they have different path symbols, for example:
+    /// ```ignore
+    /// #[custom_attribute]
+    /// pub fn foo() {
+    ///     #![my_crate::custom_attribute]
+    /// }
+    /// ```
     ///
     /// ### Example
     /// ```no_run
@@ -486,7 +496,7 @@ declare_clippy_lint! {
     /// ```
     #[clippy::version = "1.78.0"]
     pub MIXED_ATTRIBUTES_STYLE,
-    suspicious,
+    style,
     "item has both inner and outer attributes"
 }
 
@@ -523,6 +533,7 @@ declare_lint_pass!(Attributes => [
     USELESS_ATTRIBUTE,
     BLANKET_CLIPPY_RESTRICTION_LINTS,
     SHOULD_PANIC_WITHOUT_EXPECT,
+    MIXED_ATTRIBUTES_STYLE,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for Attributes {
@@ -566,6 +577,7 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
             ItemKind::ExternCrate(..) | ItemKind::Use(..) => useless_attribute::check(cx, item, attrs),
             _ => {},
         }
+        mixed_attributes_style::check(cx, item.span, attrs);
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
@@ -594,7 +606,6 @@ impl_lint_pass!(EarlyAttributes => [
     MAYBE_MISUSED_CFG,
     DEPRECATED_CLIPPY_CFG_ATTR,
     UNNECESSARY_CLIPPY_CFG,
-    MIXED_ATTRIBUTES_STYLE,
     DUPLICATED_ATTRIBUTES,
 ]);
 
@@ -605,7 +616,6 @@ impl EarlyLintPass for EarlyAttributes {
 
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
         empty_line_after::check(cx, item);
-        mixed_attributes_style::check(cx, item);
         duplicated_attributes::check(cx, &item.attrs);
     }
 
diff --git a/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs b/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs
index 05da69636c6..486e7c6ec4f 100644
--- a/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs
+++ b/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs
@@ -58,7 +58,7 @@ pub(super) fn check(
                 clippy_lints,
                 "no need to put clippy lints behind a `clippy` cfg",
                 None,
-                &format!(
+                format!(
                     "write instead: `#{}[{}({})]`",
                     if attr.style == AttrStyle::Inner { "!" } else { "" },
                     ident.name,
diff --git a/clippy_lints/src/await_holding_invalid.rs b/clippy_lints/src/await_holding_invalid.rs
index 765cc7c0a54..f25a474d9bb 100644
--- a/clippy_lints/src/await_holding_invalid.rs
+++ b/clippy_lints/src/await_holding_invalid.rs
@@ -267,7 +267,7 @@ fn emit_invalid_type(cx: &LateContext<'_>, span: Span, disallowed: &DisallowedPa
         cx,
         AWAIT_HOLDING_INVALID_TYPE,
         span,
-        &format!(
+        format!(
             "`{}` may not be held across an `await` point per `clippy.toml`",
             disallowed.path()
         ),
diff --git a/clippy_lints/src/blocks_in_conditions.rs b/clippy_lints/src/blocks_in_conditions.rs
index 2eb0dac9742..171f3031860 100644
--- a/clippy_lints/src/blocks_in_conditions.rs
+++ b/clippy_lints/src/blocks_in_conditions.rs
@@ -72,7 +72,7 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInConditions {
         else {
             return;
         };
-        let complex_block_message = &format!(
+        let complex_block_message = format!(
             "in {desc}, avoid complex blocks or closures with blocks; \
             instead, move the block or closure higher and bind it with a `let`",
         );
@@ -141,7 +141,7 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInConditions {
                     let ex = &body.value;
                     if let ExprKind::Block(block, _) = ex.kind {
                         if !body.value.span.from_expansion() && !block.stmts.is_empty() {
-                            span_lint(cx, BLOCKS_IN_CONDITIONS, ex.span, complex_block_message);
+                            span_lint(cx, BLOCKS_IN_CONDITIONS, ex.span, complex_block_message.clone());
                             return ControlFlow::Continue(Descend::No);
                         }
                     }
diff --git a/clippy_lints/src/bool_assert_comparison.rs b/clippy_lints/src/bool_assert_comparison.rs
index 74201e9cc30..58c1a2f2706 100644
--- a/clippy_lints/src/bool_assert_comparison.rs
+++ b/clippy_lints/src/bool_assert_comparison.rs
@@ -121,7 +121,7 @@ impl<'tcx> LateLintPass<'tcx> for BoolAssertComparison {
             cx,
             BOOL_ASSERT_COMPARISON,
             macro_call.span,
-            &format!("used `{macro_name}!` with a literal bool"),
+            format!("used `{macro_name}!` with a literal bool"),
             |diag| {
                 // assert_eq!(...)
                 // ^^^^^^^^^
diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs
index a474356608f..6edfebb5534 100644
--- a/clippy_lints/src/booleans.rs
+++ b/clippy_lints/src/booleans.rs
@@ -392,13 +392,13 @@ fn simple_negate(b: Bool) -> Bool {
         t @ Term(_) => Not(Box::new(t)),
         And(mut v) => {
             for el in &mut v {
-                *el = simple_negate(::std::mem::replace(el, True));
+                *el = simple_negate(std::mem::replace(el, True));
             }
             Or(v)
         },
         Or(mut v) => {
             for el in &mut v {
-                *el = simple_negate(::std::mem::replace(el, True));
+                *el = simple_negate(std::mem::replace(el, True));
             }
             And(v)
         },
diff --git a/clippy_lints/src/box_default.rs b/clippy_lints/src/box_default.rs
index 8683cb86e8a..4062212f408 100644
--- a/clippy_lints/src/box_default.rs
+++ b/clippy_lints/src/box_default.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::macros::macro_backtrace;
-use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::expr_sig;
 use clippy_utils::{is_default_equivalent, path_def_id};
 use rustc_errors::Applicability;
@@ -9,20 +8,16 @@ use rustc_hir::intravisit::{walk_ty, Visitor};
 use rustc_hir::{Block, Expr, ExprKind, LetStmt, Node, QPath, Ty, TyKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::print::with_forced_trimmed_paths;
-use rustc_middle::ty::IsSuggestable;
 use rustc_session::declare_lint_pass;
 use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
-    /// checks for `Box::new(T::default())`, which is better written as
-    /// `Box::<T>::default()`.
+    /// checks for `Box::new(Default::default())`, which can be written as
+    /// `Box::default()`.
     ///
     /// ### Why is this bad?
-    /// First, it's more complex, involving two calls instead of one.
-    /// Second, `Box::default()` can be faster
-    /// [in certain cases](https://nnethercote.github.io/perf-book/standard-library-types.html#box).
+    /// `Box::default()` is equivalent and more concise.
     ///
     /// ### Example
     /// ```no_run
@@ -34,7 +29,7 @@ declare_clippy_lint! {
     /// ```
     #[clippy::version = "1.66.0"]
     pub BOX_DEFAULT,
-    perf,
+    style,
     "Using Box::new(T::default()) instead of Box::default()"
 }
 
@@ -53,14 +48,14 @@ impl LateLintPass<'_> for BoxDefault {
             && path_def_id(cx, ty).map_or(false, |id| Some(id) == cx.tcx.lang_items().owned_box())
             // And the single argument to the call is another function call
             // This is the `T::default()` of `Box::new(T::default())`
-            && let ExprKind::Call(arg_path, inner_call_args) = arg.kind
+            && let ExprKind::Call(arg_path, _) = arg.kind
             // And we are not in a foreign crate's macro
             && !in_external_macro(cx.sess(), expr.span)
             // And the argument expression has the same context as the outer call expression
             // or that we are inside a `vec!` macro expansion
             && (expr.span.eq_ctxt(arg.span) || is_local_vec_expn(cx, arg, expr))
-            // And the argument is equivalent to `Default::default()`
-            && is_default_equivalent(cx, arg)
+            // And the argument is `Default::default()` or the type is specified
+            && (is_plain_default(cx, arg_path) || (given_type(cx, expr) && is_default_equivalent(cx, arg)))
         {
             span_lint_and_sugg(
                 cx,
@@ -68,25 +63,7 @@ impl LateLintPass<'_> for BoxDefault {
                 expr.span,
                 "`Box::new(_)` of default value",
                 "try",
-                if is_plain_default(cx, arg_path) || given_type(cx, expr) {
-                    "Box::default()".into()
-                } else if let Some(arg_ty) =
-                    cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true, None)
-                {
-                    // Check if we can copy from the source expression in the replacement.
-                    // We need the call to have no argument (see `explicit_default_type`).
-                    if inner_call_args.is_empty()
-                        && let Some(ty) = explicit_default_type(arg_path)
-                        && let Some(s) = snippet_opt(cx, ty.span)
-                    {
-                        format!("Box::<{s}>::default()")
-                    } else {
-                        // Otherwise, use the inferred type's formatting.
-                        with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()"))
-                    }
-                } else {
-                    return;
-                },
+                "Box::default()".into(),
                 Applicability::MachineApplicable,
             );
         }
@@ -105,20 +82,6 @@ fn is_plain_default(cx: &LateContext<'_>, arg_path: &Expr<'_>) -> bool {
     }
 }
 
-// Checks whether the call is of the form `A::B::f()`. Returns `A::B` if it is.
-//
-// In the event we have this kind of construct, it's easy to use `A::B` as a replacement in the
-// quickfix. `f` must however have no parameter. Should `f` have some, then some of the type of
-// `A::B` may be inferred from the arguments. This would be the case for `Vec::from([0; false])`,
-// where the argument to `from` allows inferring this is a `Vec<bool>`
-fn explicit_default_type<'a>(arg_path: &'a Expr<'_>) -> Option<&'a Ty<'a>> {
-    if let ExprKind::Path(QPath::TypeRelative(ty, _)) = &arg_path.kind {
-        Some(ty)
-    } else {
-        None
-    }
-}
-
 fn is_local_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>, ref_expr: &Expr<'_>) -> bool {
     macro_backtrace(expr.span).next().map_or(false, |call| {
         cx.tcx.is_diagnostic_item(sym::vec_macro, call.def_id) && call.span.eq_ctxt(ref_expr.span)
@@ -129,7 +92,7 @@ fn is_local_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>, ref_expr: &Expr<'_>)
 struct InferVisitor(bool);
 
 impl<'tcx> Visitor<'tcx> for InferVisitor {
-    fn visit_ty(&mut self, t: &rustc_hir::Ty<'_>) {
+    fn visit_ty(&mut self, t: &Ty<'_>) {
         self.0 |= matches!(t.kind, TyKind::Infer | TyKind::OpaqueDef(..) | TyKind::TraitObject(..));
         if !self.0 {
             walk_ty(self, t);
diff --git a/clippy_lints/src/cargo/common_metadata.rs b/clippy_lints/src/cargo/common_metadata.rs
index 99fe6c1e790..3af2d8c0256 100644
--- a/clippy_lints/src/cargo/common_metadata.rs
+++ b/clippy_lints/src/cargo/common_metadata.rs
@@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata, ignore_publish: b
 
 fn missing_warning(cx: &LateContext<'_>, package: &cargo_metadata::Package, field: &str) {
     let message = format!("package `{}` is missing `{field}` metadata", package.name);
-    span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, &message);
+    span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, message);
 }
 
 fn is_empty_str<T: AsRef<std::ffi::OsStr>>(value: &Option<T>) -> bool {
diff --git a/clippy_lints/src/cargo/feature_name.rs b/clippy_lints/src/cargo/feature_name.rs
index 9e69919c727..6982b96dd3b 100644
--- a/clippy_lints/src/cargo/feature_name.rs
+++ b/clippy_lints/src/cargo/feature_name.rs
@@ -56,13 +56,13 @@ fn lint(cx: &LateContext<'_>, feature: &str, substring: &str, is_prefix: bool) {
             REDUNDANT_FEATURE_NAMES
         },
         DUMMY_SP,
-        &format!(
+        format!(
             "the \"{substring}\" {} in the feature name \"{feature}\" is {}",
             if is_prefix { "prefix" } else { "suffix" },
             if is_negative { "negative" } else { "redundant" }
         ),
         None,
-        &format!(
+        format!(
             "consider renaming the feature to \"{}\"{}",
             if is_prefix {
                 feature.strip_prefix(substring)
diff --git a/clippy_lints/src/cargo/lint_groups_priority.rs b/clippy_lints/src/cargo/lint_groups_priority.rs
index a39b972b56a..a3291c9da10 100644
--- a/clippy_lints/src/cargo/lint_groups_priority.rs
+++ b/clippy_lints/src/cargo/lint_groups_priority.rs
@@ -102,7 +102,7 @@ fn check_table(cx: &LateContext<'_>, table: LintTable, groups: &FxHashSet<&str>,
                 cx,
                 LINT_GROUPS_PRIORITY,
                 toml_span(group.span(), file),
-                &format!(
+                format!(
                     "lint group `{}` has the same priority ({priority}) as a lint",
                     group.as_ref()
                 ),
diff --git a/clippy_lints/src/cargo/mod.rs b/clippy_lints/src/cargo/mod.rs
index 95d5449781b..ca7fa4e5a41 100644
--- a/clippy_lints/src/cargo/mod.rs
+++ b/clippy_lints/src/cargo/mod.rs
@@ -241,7 +241,7 @@ impl LateLintPass<'_> for Cargo {
                 },
                 Err(e) => {
                     for lint in NO_DEPS_LINTS {
-                        span_lint(cx, lint, DUMMY_SP, &format!("could not read cargo metadata: {e}"));
+                        span_lint(cx, lint, DUMMY_SP, format!("could not read cargo metadata: {e}"));
                     }
                 },
             }
@@ -257,7 +257,7 @@ impl LateLintPass<'_> for Cargo {
                 },
                 Err(e) => {
                     for lint in WITH_DEPS_LINTS {
-                        span_lint(cx, lint, DUMMY_SP, &format!("could not read cargo metadata: {e}"));
+                        span_lint(cx, lint, DUMMY_SP, format!("could not read cargo metadata: {e}"));
                     }
                 },
             }
diff --git a/clippy_lints/src/cargo/multiple_crate_versions.rs b/clippy_lints/src/cargo/multiple_crate_versions.rs
index 3f30a77fcfe..2769463c8a5 100644
--- a/clippy_lints/src/cargo/multiple_crate_versions.rs
+++ b/clippy_lints/src/cargo/multiple_crate_versions.rs
@@ -52,7 +52,7 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata, allowed_duplicate
                     cx,
                     MULTIPLE_CRATE_VERSIONS,
                     DUMMY_SP,
-                    &format!("multiple versions for dependency `{name}`: {versions}"),
+                    format!("multiple versions for dependency `{name}`: {versions}"),
                 );
             }
         }
diff --git a/clippy_lints/src/cargo/wildcard_dependencies.rs b/clippy_lints/src/cargo/wildcard_dependencies.rs
index 244e98eb666..0cf687d0192 100644
--- a/clippy_lints/src/cargo/wildcard_dependencies.rs
+++ b/clippy_lints/src/cargo/wildcard_dependencies.rs
@@ -17,7 +17,7 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) {
                 cx,
                 WILDCARD_DEPENDENCIES,
                 DUMMY_SP,
-                &format!("wildcard dependency for `{}`", dep.name),
+                format!("wildcard dependency for `{}`", dep.name),
             );
         }
     }
diff --git a/clippy_lints/src/casts/as_ptr_cast_mut.rs b/clippy_lints/src/casts/as_ptr_cast_mut.rs
index a667ea04af0..f05fd3fcde5 100644
--- a/clippy_lints/src/casts/as_ptr_cast_mut.rs
+++ b/clippy_lints/src/casts/as_ptr_cast_mut.rs
@@ -28,7 +28,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
             cx,
             AS_PTR_CAST_MUT,
             expr.span,
-            &format!("casting the result of `as_ptr` to *mut {ptrty}"),
+            format!("casting the result of `as_ptr` to *mut {ptrty}"),
             "replace with",
             format!("{recv}.as_mut_ptr()"),
             applicability,
diff --git a/clippy_lints/src/casts/cast_abs_to_unsigned.rs b/clippy_lints/src/casts/cast_abs_to_unsigned.rs
index c1663348321..d4d5ee37bcc 100644
--- a/clippy_lints/src/casts/cast_abs_to_unsigned.rs
+++ b/clippy_lints/src/casts/cast_abs_to_unsigned.rs
@@ -34,7 +34,7 @@ pub(super) fn check(
             cx,
             CAST_ABS_TO_UNSIGNED,
             span,
-            &format!("casting the result of `{cast_from}::abs()` to {cast_to}"),
+            format!("casting the result of `{cast_from}::abs()` to {cast_to}"),
             "replace with",
             format!("{}.unsigned_abs()", Sugg::hir(cx, receiver, "..").maybe_par()),
             Applicability::MachineApplicable,
diff --git a/clippy_lints/src/casts/cast_lossless.rs b/clippy_lints/src/casts/cast_lossless.rs
index 86f4332d05a..d52ad1c6f23 100644
--- a/clippy_lints/src/casts/cast_lossless.rs
+++ b/clippy_lints/src/casts/cast_lossless.rs
@@ -68,7 +68,7 @@ pub(super) fn check(
         cx,
         CAST_LOSSLESS,
         expr.span,
-        &message,
+        message,
         "try",
         format!("{cast_to_fmt}::from({sugg})"),
         app,
diff --git a/clippy_lints/src/casts/cast_nan_to_int.rs b/clippy_lints/src/casts/cast_nan_to_int.rs
index da756129db3..1743ce71add 100644
--- a/clippy_lints/src/casts/cast_nan_to_int.rs
+++ b/clippy_lints/src/casts/cast_nan_to_int.rs
@@ -12,7 +12,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
             cx,
             CAST_NAN_TO_INT,
             expr.span,
-            &format!("casting a known NaN to {to_ty}"),
+            format!("casting a known NaN to {to_ty}"),
             None,
             "this always evaluates to 0",
         );
diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs
index 2c0a3d48296..dbfa8e1ee91 100644
--- a/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -41,7 +41,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
                 })
             },
             BinOpKind::Rem | BinOpKind::BitAnd => get_constant_bits(cx, right)
-                .unwrap_or(u64::max_value())
+                .unwrap_or(u64::MAX)
                 .min(apply_reductions(cx, nbits, left, signed)),
             BinOpKind::Shr => apply_reductions(cx, nbits, left, signed)
                 .saturating_sub(constant_int(cx, right).map_or(0, |s| u64::try_from(s).unwrap_or_default())),
@@ -56,7 +56,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
             } else {
                 None
             };
-            apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::max_value()))
+            apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::MAX))
         },
         ExprKind::MethodCall(method, _, [lo, hi], _) => {
             if method.ident.as_str() == "clamp" {
@@ -142,7 +142,7 @@ pub(super) fn check(
                     cx,
                     CAST_ENUM_TRUNCATION,
                     expr.span,
-                    &format!(
+                    format!(
                         "casting `{cast_from}::{}` to `{cast_to}` will truncate the value{suffix}",
                         variant.name,
                     ),
@@ -163,7 +163,7 @@ pub(super) fn check(
         _ => return,
     };
 
-    span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg, |diag| {
+    span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, msg, |diag| {
         diag.help("if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...");
         if !cast_from.is_floating_point() {
             offer_suggestion(cx, expr, cast_expr, cast_to_span, diag);
diff --git a/clippy_lints/src/casts/cast_possible_wrap.rs b/clippy_lints/src/casts/cast_possible_wrap.rs
index 2ddb0f00ecd..11274383595 100644
--- a/clippy_lints/src/casts/cast_possible_wrap.rs
+++ b/clippy_lints/src/casts/cast_possible_wrap.rs
@@ -79,7 +79,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca
         ),
     };
 
-    span_lint_and_then(cx, CAST_POSSIBLE_WRAP, expr.span, &message, |diag| {
+    span_lint_and_then(cx, CAST_POSSIBLE_WRAP, expr.span, message, |diag| {
         if let EmitState::LintOnPtrSize(16) = should_lint {
             diag
                 .note("`usize` and `isize` may be as small as 16 bits on some platforms")
diff --git a/clippy_lints/src/casts/cast_precision_loss.rs b/clippy_lints/src/casts/cast_precision_loss.rs
index 334e1646cd4..035666e4d4c 100644
--- a/clippy_lints/src/casts/cast_precision_loss.rs
+++ b/clippy_lints/src/casts/cast_precision_loss.rs
@@ -38,7 +38,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca
         cx,
         CAST_PRECISION_LOSS,
         expr.span,
-        &format!(
+        format!(
             "casting `{0}` to `{1}` causes a loss of precision {2}(`{0}` is {3} bits wide, \
              but `{1}`'s mantissa is only {4} bits wide)",
             cast_from,
diff --git a/clippy_lints/src/casts/cast_ptr_alignment.rs b/clippy_lints/src/casts/cast_ptr_alignment.rs
index 4d1a0f678f4..960c81045e3 100644
--- a/clippy_lints/src/casts/cast_ptr_alignment.rs
+++ b/clippy_lints/src/casts/cast_ptr_alignment.rs
@@ -48,7 +48,7 @@ fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, cast_f
             cx,
             CAST_PTR_ALIGNMENT,
             expr.span,
-            &format!(
+            format!(
                 "casting from `{cast_from}` to a more-strictly-aligned pointer (`{cast_to}`) ({} < {} bytes)",
                 from_layout.align.abi.bytes(),
                 to_layout.align.abi.bytes(),
diff --git a/clippy_lints/src/casts/cast_sign_loss.rs b/clippy_lints/src/casts/cast_sign_loss.rs
index 8fd95d9654c..2b6e17dc103 100644
--- a/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/clippy_lints/src/casts/cast_sign_loss.rs
@@ -47,7 +47,7 @@ pub(super) fn check<'cx>(
             cx,
             CAST_SIGN_LOSS,
             expr.span,
-            &format!("casting `{cast_from}` to `{cast_to}` may lose the sign of the value"),
+            format!("casting `{cast_from}` to `{cast_to}` may lose the sign of the value"),
         );
     }
 }
@@ -118,7 +118,7 @@ enum Sign {
     Uncertain,
 }
 
-fn expr_sign<'cx>(cx: &LateContext<'cx>, expr: &Expr<'_>, ty: impl Into<Option<Ty<'cx>>>) -> Sign {
+fn expr_sign<'cx, 'tcx>(cx: &LateContext<'cx>, mut expr: &'tcx Expr<'tcx>, ty: impl Into<Option<Ty<'cx>>>) -> Sign {
     // Try evaluate this expr first to see if it's positive
     if let Some(val) = get_const_signed_int_eval(cx, expr, ty) {
         return if val >= 0 { Sign::ZeroOrPositive } else { Sign::Negative };
@@ -134,11 +134,12 @@ fn expr_sign<'cx>(cx: &LateContext<'cx>, expr: &Expr<'_>, ty: impl Into<Option<T
         // Peel unwrap(), expect(), etc.
         while let Some(&found_name) = METHODS_UNWRAP.iter().find(|&name| &method_name == name)
             && let Some(arglist) = method_chain_args(expr, &[found_name])
-            && let ExprKind::MethodCall(inner_path, ..) = &arglist[0].0.kind
+            && let ExprKind::MethodCall(inner_path, recv, ..) = &arglist[0].0.kind
         {
             // The original type has changed, but we can't use `ty` here anyway, because it has been
             // moved.
             method_name = inner_path.ident.name.as_str();
+            expr = recv;
         }
 
         if METHODS_POW.iter().any(|&name| method_name == name)
diff --git a/clippy_lints/src/casts/cast_slice_different_sizes.rs b/clippy_lints/src/casts/cast_slice_different_sizes.rs
index 76d5c329179..285f0357112 100644
--- a/clippy_lints/src/casts/cast_slice_different_sizes.rs
+++ b/clippy_lints/src/casts/cast_slice_different_sizes.rs
@@ -35,7 +35,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv
                     cx,
                     CAST_SLICE_DIFFERENT_SIZES,
                     expr.span,
-                    &format!(
+                    format!(
                         "casting between raw pointers to `[{}]` (element size {from_size}) and `[{}]` (element size {to_size}) does not adjust the count",
                         start_ty.ty, end_ty.ty,
                     ),
diff --git a/clippy_lints/src/casts/cast_slice_from_raw_parts.rs b/clippy_lints/src/casts/cast_slice_from_raw_parts.rs
index 48629b6c5cc..1d89f6c75e1 100644
--- a/clippy_lints/src/casts/cast_slice_from_raw_parts.rs
+++ b/clippy_lints/src/casts/cast_slice_from_raw_parts.rs
@@ -46,7 +46,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
             cx,
             CAST_SLICE_FROM_RAW_PARTS,
             span,
-            &format!("casting the result of `{func}` to {cast_to}"),
+            format!("casting the result of `{func}` to {cast_to}"),
             "replace with",
             format!("core::ptr::slice_{func}({ptr}, {len})"),
             applicability,
diff --git a/clippy_lints/src/casts/fn_to_numeric_cast.rs b/clippy_lints/src/casts/fn_to_numeric_cast.rs
index a26bfab4e7c..f263bec1576 100644
--- a/clippy_lints/src/casts/fn_to_numeric_cast.rs
+++ b/clippy_lints/src/casts/fn_to_numeric_cast.rs
@@ -25,7 +25,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
                     cx,
                     FN_TO_NUMERIC_CAST,
                     expr.span,
-                    &format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
+                    format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
                     "try",
                     format!("{from_snippet} as usize"),
                     applicability,
diff --git a/clippy_lints/src/casts/fn_to_numeric_cast_any.rs b/clippy_lints/src/casts/fn_to_numeric_cast_any.rs
index 75654129408..826589bf303 100644
--- a/clippy_lints/src/casts/fn_to_numeric_cast_any.rs
+++ b/clippy_lints/src/casts/fn_to_numeric_cast_any.rs
@@ -23,7 +23,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
                 cx,
                 FN_TO_NUMERIC_CAST_ANY,
                 expr.span,
-                &format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
+                format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
                 "did you mean to invoke the function?",
                 format!("{from_snippet}() as {cast_to}"),
                 applicability,
diff --git a/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs b/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs
index 556be1d1506..0e11bcfb8ec 100644
--- a/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs
+++ b/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs
@@ -24,7 +24,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
                     cx,
                     FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
                     expr.span,
-                    &format!("casting function pointer `{from_snippet}` to `{cast_to}`, which truncates the value"),
+                    format!("casting function pointer `{from_snippet}` to `{cast_to}`, which truncates the value"),
                     "try",
                     format!("{from_snippet} as usize"),
                     applicability,
diff --git a/clippy_lints/src/casts/ptr_as_ptr.rs b/clippy_lints/src/casts/ptr_as_ptr.rs
index 5a121e6a7eb..68841076f77 100644
--- a/clippy_lints/src/casts/ptr_as_ptr.rs
+++ b/clippy_lints/src/casts/ptr_as_ptr.rs
@@ -62,8 +62,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
         // we omit following `cast`:
         let omit_cast = if let ExprKind::Call(func, []) = cast_expr.kind
             && let ExprKind::Path(ref qpath @ QPath::Resolved(None, path)) = func.kind
+            && let Some(method_defid) = path.res.opt_def_id()
         {
-            let method_defid = path.res.def_id();
             if cx.tcx.is_diagnostic_item(sym::ptr_null, method_defid) {
                 OmitFollowedCastReason::Null(qpath)
             } else if cx.tcx.is_diagnostic_item(sym::ptr_null_mut, method_defid) {
diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs
index e88146331ca..921693567fc 100644
--- a/clippy_lints/src/casts/ptr_cast_constness.rs
+++ b/clippy_lints/src/casts/ptr_cast_constness.rs
@@ -36,7 +36,7 @@ pub(super) fn check<'tcx>(
             PTR_CAST_CONSTNESS,
             expr.span,
             "`as` casting between raw pointers while changing only its constness",
-            &format!("try `pointer::cast_{constness}`, a safer alternative"),
+            format!("try `pointer::cast_{constness}`, a safer alternative"),
             format!("{}.cast_{constness}()", sugg.maybe_par()),
             Applicability::MachineApplicable,
         );
diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs
index 148d52cb5dd..a7f7bf7854e 100644
--- a/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/clippy_lints/src/casts/unnecessary_cast.rs
@@ -51,7 +51,7 @@ pub(super) fn check<'tcx>(
             cx,
             UNNECESSARY_CAST,
             expr.span,
-            &format!(
+            format!(
                 "casting raw pointers to the same type and constness is unnecessary (`{cast_from}` -> `{cast_to}`)"
             ),
             "try",
@@ -166,7 +166,7 @@ pub(super) fn check<'tcx>(
             cx,
             UNNECESSARY_CAST,
             expr.span,
-            &format!("casting to the same type is unnecessary (`{cast_from}` -> `{cast_to}`)"),
+            format!("casting to the same type is unnecessary (`{cast_from}` -> `{cast_to}`)"),
             "try",
             if needs_block {
                 format!("{{ {cast_str} }}")
@@ -209,7 +209,7 @@ fn lint_unnecessary_cast(
         cx,
         UNNECESSARY_CAST,
         expr.span,
-        &format!("casting {literal_kind_name} literal to `{cast_to}` is unnecessary"),
+        format!("casting {literal_kind_name} literal to `{cast_to}` is unnecessary"),
         "try",
         sugg,
         Applicability::MachineApplicable,
diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs
index 7dac3c5d9da..ee1bb63b50d 100644
--- a/clippy_lints/src/cognitive_complexity.rs
+++ b/clippy_lints/src/cognitive_complexity.rs
@@ -121,7 +121,7 @@ impl CognitiveComplexity {
                 cx,
                 COGNITIVE_COMPLEXITY,
                 fn_span,
-                &format!(
+                format!(
                     "the function has a cognitive complexity of ({cc}/{})",
                     self.limit.limit()
                 ),
diff --git a/clippy_lints/src/collection_is_never_read.rs b/clippy_lints/src/collection_is_never_read.rs
index e921b9b46a6..6942ca53640 100644
--- a/clippy_lints/src/collection_is_never_read.rs
+++ b/clippy_lints/src/collection_is_never_read.rs
@@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead {
     }
 }
 
-fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>, collections: &[rustc_span::Symbol]) -> bool {
+fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>, collections: &[Symbol]) -> bool {
     let ty = cx.typeck_results().pat_ty(local.pat);
     collections.iter().any(|&sym| is_type_diagnostic_item(cx, ty, sym))
     // String type is a lang item but not a diagnostic item for now so we need a separate check
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index c8e148598a2..5ff7d8e5134 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -254,6 +254,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::large_include_file::LARGE_INCLUDE_FILE_INFO,
     crate::large_stack_arrays::LARGE_STACK_ARRAYS_INFO,
     crate::large_stack_frames::LARGE_STACK_FRAMES_INFO,
+    crate::legacy_numeric_constants::LEGACY_NUMERIC_CONSTANTS_INFO,
     crate::len_zero::COMPARISON_TO_EMPTY_INFO,
     crate::len_zero::LEN_WITHOUT_IS_EMPTY_INFO,
     crate::len_zero::LEN_ZERO_INFO,
@@ -678,6 +679,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::trait_bounds::TYPE_REPETITION_IN_BOUNDS_INFO,
     crate::transmute::CROSSPOINTER_TRANSMUTE_INFO,
     crate::transmute::EAGER_TRANSMUTE_INFO,
+    crate::transmute::MISSING_TRANSMUTE_ANNOTATIONS_INFO,
     crate::transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS_INFO,
     crate::transmute::TRANSMUTE_BYTES_TO_STR_INFO,
     crate::transmute::TRANSMUTE_FLOAT_TO_INT_INFO,
diff --git a/clippy_lints/src/default.rs b/clippy_lints/src/default.rs
index 98a6d9370c3..2b3f4854255 100644
--- a/clippy_lints/src/default.rs
+++ b/clippy_lints/src/default.rs
@@ -100,7 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
                 cx,
                 DEFAULT_TRAIT_ACCESS,
                 expr.span,
-                &format!("calling `{replacement}` is more clear than this expression"),
+                format!("calling `{replacement}` is more clear than this expression"),
                 "try",
                 replacement,
                 Applicability::Unspecified, // First resolve the TODO above
@@ -243,7 +243,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
                     first_assign.unwrap().span,
                     "field assignment outside of initializer for an instance created with Default::default()",
                     Some(local.span),
-                    &format!("consider initializing the variable with `{sugg}` and removing relevant reassignments"),
+                    format!("consider initializing the variable with `{sugg}` and removing relevant reassignments"),
                 );
                 self.reassigned_linted.insert(span);
             }
diff --git a/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs
index 71e1a25c2bc..13778175496 100644
--- a/clippy_lints/src/default_constructed_unit_structs.rs
+++ b/clippy_lints/src/default_constructed_unit_structs.rs
@@ -56,7 +56,7 @@ fn is_alias(ty: hir::Ty<'_>) -> bool {
 
 impl LateLintPass<'_> for DefaultConstructedUnitStructs {
     fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
-        if let hir::ExprKind::Call(fn_expr, &[]) = expr.kind
+        if let ExprKind::Call(fn_expr, &[]) = expr.kind
             // make sure we have a call to `Default::default`
             && let ExprKind::Path(ref qpath @ hir::QPath::TypeRelative(base, _)) = fn_expr.kind
             // make sure this isn't a type alias:
diff --git a/clippy_lints/src/default_instead_of_iter_empty.rs b/clippy_lints/src/default_instead_of_iter_empty.rs
index e617c19eff0..ac49e6f1a48 100644
--- a/clippy_lints/src/default_instead_of_iter_empty.rs
+++ b/clippy_lints/src/default_instead_of_iter_empty.rs
@@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultIterEmpty {
                 cx,
                 DEFAULT_INSTEAD_OF_ITER_EMPTY,
                 expr.span,
-                &format!("`{path}()` is the more idiomatic way"),
+                format!("`{path}()` is the more idiomatic way"),
                 "try",
                 sugg,
                 applicability,
@@ -60,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultIterEmpty {
 
 fn make_sugg(
     cx: &LateContext<'_>,
-    ty_path: &rustc_hir::QPath<'_>,
+    ty_path: &QPath<'_>,
     ctxt: SyntaxContext,
     applicability: &mut Applicability,
     path: &str,
diff --git a/clippy_lints/src/default_union_representation.rs b/clippy_lints/src/default_union_representation.rs
index bfd89bfd2c7..3f87ed8df2b 100644
--- a/clippy_lints/src/default_union_representation.rs
+++ b/clippy_lints/src/default_union_representation.rs
@@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation {
                 item.span,
                 "this union has the default representation",
                 None,
-                &format!(
+                format!(
                     "consider annotating `{}` with `#[repr(C)]` to explicitly specify memory layout",
                     cx.tcx.def_path_str(item.owner_id)
                 ),
diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs
index b0f46f5c646..80327586fed 100644
--- a/clippy_lints/src/derivable_impls.rs
+++ b/clippy_lints/src/derivable_impls.rs
@@ -79,7 +79,7 @@ fn is_path_self(e: &Expr<'_>) -> bool {
 fn contains_trait_object(ty: Ty<'_>) -> bool {
     match ty.kind() {
         ty::Ref(_, ty, _) => contains_trait_object(*ty),
-        ty::Adt(def, args) => def.is_box() && args[0].as_type().map_or(false, contains_trait_object),
+        Adt(def, args) => def.is_box() && args[0].as_type().map_or(false, contains_trait_object),
         ty::Dynamic(..) => true,
         _ => false,
     }
diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs
index c554edc8fce..5f9700b76d9 100644
--- a/clippy_lints/src/derive.rs
+++ b/clippy_lints/src/derive.rs
@@ -11,8 +11,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::traits::Reveal;
 use rustc_middle::ty::{
-    self, ClauseKind, GenericArgKind, GenericParamDefKind, ParamEnv, ToPredicate, TraitPredicate, Ty,
-    TyCtxt,
+    self, ClauseKind, GenericArgKind, GenericParamDefKind, ParamEnv, ToPredicate, TraitPredicate, Ty, TyCtxt,
 };
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
diff --git a/clippy_lints/src/disallowed_macros.rs b/clippy_lints/src/disallowed_macros.rs
index 4a617ba34d5..871f529da6c 100644
--- a/clippy_lints/src/disallowed_macros.rs
+++ b/clippy_lints/src/disallowed_macros.rs
@@ -102,11 +102,11 @@ impl DisallowedMacros {
                         DISALLOWED_MACROS,
                         cx.tcx.local_def_id_to_hir_id(derive_src.def_id),
                         mac.span,
-                        &msg,
+                        msg,
                         add_note,
                     );
                 } else {
-                    span_lint_and_then(cx, DISALLOWED_MACROS, mac.span, &msg, add_note);
+                    span_lint_and_then(cx, DISALLOWED_MACROS, mac.span, msg, add_note);
                 }
             }
         }
diff --git a/clippy_lints/src/disallowed_methods.rs b/clippy_lints/src/disallowed_methods.rs
index 1868d3cd391..9de879604e2 100644
--- a/clippy_lints/src/disallowed_methods.rs
+++ b/clippy_lints/src/disallowed_methods.rs
@@ -99,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedMethods {
             None => return,
         };
         let msg = format!("use of a disallowed method `{}`", conf.path());
-        span_lint_and_then(cx, DISALLOWED_METHODS, expr.span, &msg, |diag| {
+        span_lint_and_then(cx, DISALLOWED_METHODS, expr.span, msg, |diag| {
             if let Some(reason) = conf.reason() {
                 diag.note(reason);
             }
diff --git a/clippy_lints/src/disallowed_names.rs b/clippy_lints/src/disallowed_names.rs
index 09dad5554ad..2afbf184117 100644
--- a/clippy_lints/src/disallowed_names.rs
+++ b/clippy_lints/src/disallowed_names.rs
@@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedNames {
                     cx,
                     DISALLOWED_NAMES,
                     ident.span,
-                    &format!("use of a disallowed/placeholder name `{}`", ident.name),
+                    format!("use of a disallowed/placeholder name `{}`", ident.name),
                 );
             }
         }
diff --git a/clippy_lints/src/disallowed_script_idents.rs b/clippy_lints/src/disallowed_script_idents.rs
index 0c1bb2da7e8..def4b5932b4 100644
--- a/clippy_lints/src/disallowed_script_idents.rs
+++ b/clippy_lints/src/disallowed_script_idents.rs
@@ -98,7 +98,7 @@ impl EarlyLintPass for DisallowedScriptIdents {
                         cx,
                         DISALLOWED_SCRIPT_IDENTS,
                         span,
-                        &format!(
+                        format!(
                             "identifier `{symbol_str}` has a Unicode script that is not allowed by configuration: {}",
                             script.full_name()
                         ),
diff --git a/clippy_lints/src/disallowed_types.rs b/clippy_lints/src/disallowed_types.rs
index 130f56b698f..4196309a22a 100644
--- a/clippy_lints/src/disallowed_types.rs
+++ b/clippy_lints/src/disallowed_types.rs
@@ -127,7 +127,7 @@ fn emit(cx: &LateContext<'_>, name: &str, span: Span, conf: &DisallowedPath) {
         cx,
         DISALLOWED_TYPES,
         span,
-        &format!("`{name}` is not allowed according to config"),
+        format!("`{name}` is not allowed according to config"),
         |diag| {
             if let Some(reason) = conf.reason() {
                 diag.note(reason);
diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs
index bf6f54c1e72..119473c2454 100644
--- a/clippy_lints/src/drop_forget_ref.rs
+++ b/clippy_lints/src/drop_forget_ref.rs
@@ -129,9 +129,9 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
                 cx,
                 lint,
                 expr.span,
-                &msg,
+                msg,
                 note_span,
-                &format!("argument has type `{arg_ty}`"),
+                format!("argument has type `{arg_ty}`"),
             );
         }
     }
diff --git a/clippy_lints/src/duplicate_mod.rs b/clippy_lints/src/duplicate_mod.rs
index 471335c098f..ed27e38ef2d 100644
--- a/clippy_lints/src/duplicate_mod.rs
+++ b/clippy_lints/src/duplicate_mod.rs
@@ -119,7 +119,7 @@ impl EarlyLintPass for DuplicateMod {
                 cx,
                 DUPLICATE_MOD,
                 multi_span,
-                &format!("file is loaded as a module multiple times: `{}`", local_path.display()),
+                format!("file is loaded as a module multiple times: `{}`", local_path.display()),
                 None,
                 "replace all but one `mod` item with `use` items",
             );
diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs
index b8a817e21b1..dd03df797de 100644
--- a/clippy_lints/src/endian_bytes.rs
+++ b/clippy_lints/src/endian_bytes.rs
@@ -197,7 +197,7 @@ fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: Prefix
         cx,
         lint.as_lint(),
         expr.span,
-        &format!(
+        format!(
             "usage of the {}`{ty}::{}`{}",
             if prefix == Prefix::From { "function " } else { "" },
             lint.as_name(prefix),
diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs
index dafbf6c8846..b7c9d3d0385 100644
--- a/clippy_lints/src/entry.rs
+++ b/clippy_lints/src/entry.rs
@@ -186,7 +186,7 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
             cx,
             MAP_ENTRY,
             expr.span,
-            &format!("usage of `contains_key` followed by `insert` on a `{}`", map_ty.name()),
+            format!("usage of `contains_key` followed by `insert` on a `{}`", map_ty.name()),
             "try",
             sugg,
             app,
diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs
index ad589dad350..386d4c3c317 100644
--- a/clippy_lints/src/escape.rs
+++ b/clippy_lints/src/escape.rs
@@ -177,7 +177,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
         }
     }
 
-    fn fake_read(&mut self, _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+    fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
 }
 
 impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {
diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs
index eccfc31fdd3..850a4f0eec8 100644
--- a/clippy_lints/src/eta_reduction.rs
+++ b/clippy_lints/src/eta_reduction.rs
@@ -3,14 +3,14 @@ use clippy_utils::higher::VecArgs;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::type_diagnostic_name;
 use clippy_utils::usage::{local_used_after_expr, local_used_in};
-use clippy_utils::{get_path_from_caller_to_method_type, higher, is_adjusted, path_to_local, path_to_local_id};
+use clippy_utils::{get_path_from_caller_to_method_type, is_adjusted, path_to_local, path_to_local_id};
 use rustc_errors::Applicability;
 use rustc_hir::{BindingAnnotation, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, TyKind, Unsafety};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{
-    self, Binder, ClosureArgs, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, RegionKind,
-    Ty, TypeVisitableExt, TypeckResults,
+    self, Binder, ClosureArgs, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, RegionKind, Ty,
+    TypeVisitableExt, TypeckResults,
 };
 use rustc_session::declare_lint_pass;
 use rustc_span::symbol::sym;
@@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
 
         if body.value.span.from_expansion() {
             if body.params.is_empty() {
-                if let Some(VecArgs::Vec(&[])) = higher::VecArgs::hir(cx, body.value) {
+                if let Some(VecArgs::Vec(&[])) = VecArgs::hir(cx, body.value) {
                     // replace `|| vec![]` with `Vec::new`
                     span_lint_and_sugg(
                         cx,
diff --git a/clippy_lints/src/excessive_bools.rs b/clippy_lints/src/excessive_bools.rs
index c5f7212c4c0..62d5ce24d40 100644
--- a/clippy_lints/src/excessive_bools.rs
+++ b/clippy_lints/src/excessive_bools.rs
@@ -120,7 +120,7 @@ impl ExcessiveBools {
                 cx,
                 FN_PARAMS_EXCESSIVE_BOOLS,
                 span,
-                &format!("more than {} bools in function parameters", self.max_fn_params_bools),
+                format!("more than {} bools in function parameters", self.max_fn_params_bools),
                 None,
                 "consider refactoring bools into two-variant enums",
             );
@@ -145,7 +145,7 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
                     cx,
                     STRUCT_EXCESSIVE_BOOLS,
                     item.span,
-                    &format!("more than {} bools in a struct", self.max_struct_bools),
+                    format!("more than {} bools in a struct", self.max_struct_bools),
                     None,
                     "consider using a state machine or refactoring bools into two-variant enums",
                 );
diff --git a/clippy_lints/src/exhaustive_items.rs b/clippy_lints/src/exhaustive_items.rs
index 3a621d967f4..9ffda645742 100644
--- a/clippy_lints/src/exhaustive_items.rs
+++ b/clippy_lints/src/exhaustive_items.rs
@@ -38,7 +38,7 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Warns on any exported `structs`s that are not tagged `#[non_exhaustive]`
+    /// Warns on any exported `struct`s that are not tagged `#[non_exhaustive]`
     ///
     /// ### Why is this bad?
     /// Exhaustive structs are typically fine, but a project which does
diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs
index 2e9bec6a7b0..33bd5a5a9d3 100644
--- a/clippy_lints/src/explicit_write.rs
+++ b/clippy_lints/src/explicit_write.rs
@@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
                 cx,
                 EXPLICIT_WRITE,
                 expr.span,
-                &format!("use of `{used}.unwrap()`"),
+                format!("use of `{used}.unwrap()`"),
                 "try",
                 format!("{prefix}{sugg_mac}!({inputs_snippet})"),
                 applicability,
diff --git a/clippy_lints/src/extra_unused_type_parameters.rs b/clippy_lints/src/extra_unused_type_parameters.rs
index 538d29eb43d..7484f772e08 100644
--- a/clippy_lints/src/extra_unused_type_parameters.rs
+++ b/clippy_lints/src/extra_unused_type_parameters.rs
@@ -110,11 +110,11 @@ impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> {
             .map_or(param.span, |bound_span| param.span.with_hi(bound_span.hi()))
     }
 
-    fn emit_help(&self, spans: Vec<Span>, msg: &str, help: &'static str) {
+    fn emit_help(&self, spans: Vec<Span>, msg: String, help: &'static str) {
         span_lint_and_help(self.cx, EXTRA_UNUSED_TYPE_PARAMETERS, spans, msg, None, help);
     }
 
-    fn emit_sugg(&self, spans: Vec<Span>, msg: &str, help: &'static str) {
+    fn emit_sugg(&self, spans: Vec<Span>, msg: String, help: &'static str) {
         let suggestions: Vec<(Span, String)> = spans.iter().copied().zip(std::iter::repeat(String::new())).collect();
         span_lint_and_then(self.cx, EXTRA_UNUSED_TYPE_PARAMETERS, spans, msg, |diag| {
             diag.multipart_suggestion(help, suggestions, Applicability::MachineApplicable);
@@ -167,7 +167,7 @@ impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> {
                 .iter()
                 .map(|(_, param)| self.get_bound_span(param))
                 .collect::<Vec<_>>();
-            self.emit_help(spans, &msg, help);
+            self.emit_help(spans, msg, help);
         } else {
             let spans = if explicit_params.len() == extra_params.len() {
                 vec![self.generics.span] // Remove the entire list of generics
@@ -196,7 +196,7 @@ impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> {
                     })
                     .collect()
             };
-            self.emit_sugg(spans, &msg, help);
+            self.emit_sugg(spans, msg, help);
         };
     }
 }
diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs
index 981a76d683d..2cd4e9e99a5 100644
--- a/clippy_lints/src/float_literal.rs
+++ b/clippy_lints/src/float_literal.rs
@@ -83,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
                 LitFloatType::Unsuffixed => None,
             };
             let (is_whole, is_inf, mut float_str) = match fty {
-                FloatTy::F16 => {
+                FloatTy::F16 | FloatTy::F128 => {
                     // FIXME(f16_f128): do a check like the others when parsing is available
                     return;
                 },
@@ -97,10 +97,6 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
 
                     (value.fract() == 0.0, value.is_infinite(), formatter.format(value))
                 },
-                FloatTy::F128 => {
-                    // FIXME(f16_f128): do a check like the others when parsing is available
-                    return;
-                },
             };
 
             if is_inf {
diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs
index c8b87e510ed..46d47e217b0 100644
--- a/clippy_lints/src/floating_point_arithmetic.rs
+++ b/clippy_lints/src/floating_point_arithmetic.rs
@@ -552,9 +552,9 @@ fn is_testing_negative(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) -
 /// Returns true iff expr is some zero literal
 fn is_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     match constant_simple(cx, cx.typeck_results(), expr) {
-        Some(Constant::Int(i)) => i == 0,
-        Some(Constant::F32(f)) => f == 0.0,
-        Some(Constant::F64(f)) => f == 0.0,
+        Some(Int(i)) => i == 0,
+        Some(F32(f)) => f == 0.0,
+        Some(F64(f)) => f == 0.0,
         _ => false,
     }
 }
diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs
index 61f550ce0be..80db617c639 100644
--- a/clippy_lints/src/format_args.rs
+++ b/clippy_lints/src/format_args.rs
@@ -401,7 +401,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> {
             self.cx,
             FORMAT_IN_FORMAT_ARGS,
             self.macro_call.span,
-            &format!("`format!` in `{name}!` args"),
+            format!("`format!` in `{name}!` args"),
             |diag| {
                 diag.help(format!(
                     "combine the `format!(..)` arguments with the outer `{name}!(..)` call"
@@ -431,7 +431,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> {
                     cx,
                     TO_STRING_IN_FORMAT_ARGS,
                     to_string_span.with_lo(receiver.span.hi()),
-                    &format!("`to_string` applied to a type that implements `Display` in `{name}!` args"),
+                    format!("`to_string` applied to a type that implements `Display` in `{name}!` args"),
                     "remove this",
                     String::new(),
                     Applicability::MachineApplicable,
@@ -441,7 +441,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> {
                     cx,
                     TO_STRING_IN_FORMAT_ARGS,
                     value.span,
-                    &format!("`to_string` applied to a type that implements `Display` in `{name}!` args"),
+                    format!("`to_string` applied to a type that implements `Display` in `{name}!` args"),
                     "use this",
                     format!(
                         "{}{:*>n_needed_derefs$}{receiver_snippet}",
diff --git a/clippy_lints/src/format_impl.rs b/clippy_lints/src/format_impl.rs
index 93517076cda..0a52347940a 100644
--- a/clippy_lints/src/format_impl.rs
+++ b/clippy_lints/src/format_impl.rs
@@ -214,7 +214,7 @@ impl<'a, 'tcx> FormatImplExpr<'a, 'tcx> {
                 self.cx,
                 RECURSIVE_FORMAT_IMPL,
                 self.expr.span,
-                &format!("using `self` as `{name}` in `impl {name}` will cause infinite recursion"),
+                format!("using `self` as `{name}` in `impl {name}` will cause infinite recursion"),
             );
         }
     }
@@ -235,7 +235,7 @@ impl<'a, 'tcx> FormatImplExpr<'a, 'tcx> {
                 self.cx,
                 PRINT_IN_FORMAT_IMPL,
                 macro_call.span,
-                &format!("use of `{name}!` in `{}` impl", self.format_trait_impl.name),
+                format!("use of `{name}!` in `{}` impl", self.format_trait_impl.name),
                 "replace with",
                 if let Some(formatter_name) = self.format_trait_impl.formatter_name {
                     format!("{replacement}!({formatter_name}, ..)")
diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs
index c3ef6f180c9..34e93bdb9b9 100644
--- a/clippy_lints/src/formatting.rs
+++ b/clippy_lints/src/formatting.rs
@@ -151,12 +151,12 @@ fn check_assign(cx: &EarlyContext<'_>, expr: &Expr) {
                             cx,
                             SUSPICIOUS_ASSIGNMENT_FORMATTING,
                             eqop_span,
-                            &format!(
+                            format!(
                                 "this looks like you are trying to use `.. {op}= ..`, but you \
                                  really are doing `.. = ({op} ..)`"
                             ),
                             None,
-                            &format!("to remove this lint, use either `{op}=` or `= {op}`"),
+                            format!("to remove this lint, use either `{op}=` or `= {op}`"),
                         );
                     }
                 }
@@ -187,12 +187,12 @@ fn check_unop(cx: &EarlyContext<'_>, expr: &Expr) {
             cx,
             SUSPICIOUS_UNARY_OP_FORMATTING,
             eqop_span,
-            &format!(
+            format!(
                 "by not having a space between `{binop_str}` and `{unop_str}` it looks like \
                  `{binop_str}{unop_str}` is a single operator"
             ),
             None,
-            &format!("put a space between `{binop_str}` and `{unop_str}` and remove the space after `{unop_str}`"),
+            format!("put a space between `{binop_str}` and `{unop_str}` and remove the space after `{unop_str}`"),
         );
     }
 }
@@ -215,6 +215,7 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) {
         // it’s bad when there is a ‘\n’ after the “else”
         && let Some(else_snippet) = snippet_opt(cx, else_span)
         && let Some((pre_else, post_else)) = else_snippet.split_once("else")
+        && !else_snippet.contains('/')
         && let Some((_, post_else_post_eol)) = post_else.split_once('\n')
     {
         // Allow allman style braces `} \n else \n {`
@@ -238,9 +239,9 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) {
             cx,
             SUSPICIOUS_ELSE_FORMATTING,
             else_span,
-            &format!("this is an `else {else_desc}` but the formatting might hide it"),
+            format!("this is an `else {else_desc}` but the formatting might hide it"),
             None,
-            &format!(
+            format!(
                 "to remove this lint, remove the `else` or remove the new line between \
                  `else` and `{else_desc}`",
             ),
@@ -308,9 +309,9 @@ fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) {
             cx,
             SUSPICIOUS_ELSE_FORMATTING,
             else_span,
-            &format!("this looks like {looks_like} but the `else` is missing"),
+            format!("this looks like {looks_like} but the `else` is missing"),
             None,
-            &format!("to remove this lint, add the missing `else` or add a new line before {next_thing}",),
+            format!("to remove this lint, add the missing `else` or add a new line before {next_thing}",),
         );
     }
 }
diff --git a/clippy_lints/src/from_raw_with_void_ptr.rs b/clippy_lints/src/from_raw_with_void_ptr.rs
index 286ba2306c9..ba2495c17a2 100644
--- a/clippy_lints/src/from_raw_with_void_ptr.rs
+++ b/clippy_lints/src/from_raw_with_void_ptr.rs
@@ -4,7 +4,7 @@ use clippy_utils::ty::is_c_void;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{RawPtr};
+use rustc_middle::ty::RawPtr;
 use rustc_session::declare_lint_pass;
 use rustc_span::sym;
 
@@ -52,7 +52,7 @@ impl LateLintPass<'_> for FromRawWithVoidPtr {
                 cx,
                 FROM_RAW_WITH_VOID_PTR,
                 expr.span,
-                &msg,
+                msg,
                 Some(arg.span),
                 "cast this to a pointer of the appropriate type",
             );
diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs
index d752d010f9f..d0c66900c00 100644
--- a/clippy_lints/src/functions/must_use.rs
+++ b/clippy_lints/src/functions/must_use.rs
@@ -142,7 +142,7 @@ fn check_must_use_candidate<'tcx>(
     item_span: Span,
     item_id: hir::OwnerId,
     fn_span: Span,
-    msg: &str,
+    msg: &'static str,
 ) {
     if has_mutable_arg(cx, body)
         || mutates_static(cx, body)
@@ -207,9 +207,7 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, tys: &mut DefIdSet)
         },
         ty::Tuple(args) => args.iter().any(|ty| is_mutable_ty(cx, ty, tys)),
         ty::Array(ty, _) | ty::Slice(ty) => is_mutable_ty(cx, ty, tys),
-        ty::RawPtr(ty, mutbl) | ty::Ref(_, ty, mutbl) => {
-            mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, tys)
-        },
+        ty::RawPtr(ty, mutbl) | ty::Ref(_, ty, mutbl) => mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, tys),
         // calling something constitutes a side effect, so return true on all callables
         // also never calls need not be used, so return true for them, too
         _ => true,
diff --git a/clippy_lints/src/functions/result.rs b/clippy_lints/src/functions/result.rs
index 37fbf2c7d59..93f088d3e33 100644
--- a/clippy_lints/src/functions/result.rs
+++ b/clippy_lints/src/functions/result.rs
@@ -2,7 +2,7 @@ use rustc_errors::Diag;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{self, Adt, Ty};
+use rustc_middle::ty::{Adt, Ty};
 use rustc_span::{sym, Span};
 
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
@@ -25,7 +25,7 @@ fn result_err_ty<'tcx>(
             .tcx
             .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(id).instantiate_identity().output())
         && is_type_diagnostic_item(cx, ty, sym::Result)
-        && let ty::Adt(_, args) = ty.kind()
+        && let Adt(_, args) = ty.kind()
     {
         let err_ty = args.type_at(1);
         Some((hir_ty, err_ty))
diff --git a/clippy_lints/src/functions/too_many_arguments.rs b/clippy_lints/src/functions/too_many_arguments.rs
index 1e08922a616..e72a2ad49d8 100644
--- a/clippy_lints/src/functions/too_many_arguments.rs
+++ b/clippy_lints/src/functions/too_many_arguments.rs
@@ -59,7 +59,7 @@ fn check_arg_number(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, fn_span: Span,
             cx,
             TOO_MANY_ARGUMENTS,
             fn_span,
-            &format!("this function has too many arguments ({args}/{too_many_arguments_threshold})"),
+            format!("this function has too many arguments ({args}/{too_many_arguments_threshold})"),
         );
     }
 }
diff --git a/clippy_lints/src/functions/too_many_lines.rs b/clippy_lints/src/functions/too_many_lines.rs
index 34f1bf3b2b1..586ca58d60d 100644
--- a/clippy_lints/src/functions/too_many_lines.rs
+++ b/clippy_lints/src/functions/too_many_lines.rs
@@ -77,7 +77,7 @@ pub(super) fn check_fn(
             cx,
             TOO_MANY_LINES,
             span,
-            &format!("this function has too many lines ({line_count}/{too_many_lines_threshold})"),
+            format!("this function has too many lines ({line_count}/{too_many_lines_threshold})"),
         );
     }
 }
diff --git a/clippy_lints/src/if_then_some_else_none.rs b/clippy_lints/src/if_then_some_else_none.rs
index 8f48941c4a9..f5ba62ae432 100644
--- a/clippy_lints/src/if_then_some_else_none.rs
+++ b/clippy_lints/src/if_then_some_else_none.rs
@@ -117,9 +117,9 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
                 cx,
                 IF_THEN_SOME_ELSE_NONE,
                 expr.span,
-                &format!("this could be simplified with `bool::{method_name}`"),
+                format!("this could be simplified with `bool::{method_name}`"),
                 None,
-                &help,
+                help,
             );
         }
     }
diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs
index 8acb138332c..a46aae36d5c 100644
--- a/clippy_lints/src/implicit_hasher.rs
+++ b/clippy_lints/src/implicit_hasher.rs
@@ -141,7 +141,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
                         cx,
                         IMPLICIT_HASHER,
                         target.span(),
-                        &format!(
+                        format!(
                             "impl for `{}` should be generalized over different hashers",
                             target.type_name()
                         ),
@@ -187,7 +187,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
                             cx,
                             IMPLICIT_HASHER,
                             target.span(),
-                            &format!(
+                            format!(
                                 "parameter of type `{}` should be generalized over different hashers",
                                 target.type_name()
                             ),
diff --git a/clippy_lints/src/implied_bounds_in_impls.rs b/clippy_lints/src/implied_bounds_in_impls.rs
index 9f4d7b51271..7b97fc15caa 100644
--- a/clippy_lints/src/implied_bounds_in_impls.rs
+++ b/clippy_lints/src/implied_bounds_in_impls.rs
@@ -56,7 +56,7 @@ fn emit_lint(
     index: usize,
     // The bindings that were implied, used for suggestion purposes since removing a bound with associated types
     // means we might need to then move it to a different bound
-    implied_bindings: &[rustc_hir::TypeBinding<'_>],
+    implied_bindings: &[TypeBinding<'_>],
     bound: &ImplTraitBound<'_>,
 ) {
     let implied_by = snippet(cx, bound.span, "..");
@@ -65,7 +65,7 @@ fn emit_lint(
         cx,
         IMPLIED_BOUNDS_IN_IMPLS,
         poly_trait.span,
-        &format!("this bound is already specified as the supertrait of `{implied_by}`"),
+        format!("this bound is already specified as the supertrait of `{implied_by}`"),
         |diag| {
             // If we suggest removing a bound, we may also need to extend the span
             // to include the `+` token that is ahead or behind,
diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs
index cd000fcd184..35b4481bfee 100644
--- a/clippy_lints/src/incompatible_msrv.rs
+++ b/clippy_lints/src/incompatible_msrv.rs
@@ -33,7 +33,7 @@ declare_clippy_lint! {
     ///
     /// To fix this problem, either increase your MSRV or use another item
     /// available in your current MSRV.
-    #[clippy::version = "1.77.0"]
+    #[clippy::version = "1.78.0"]
     pub INCOMPATIBLE_MSRV,
     suspicious,
     "ensures that all items used in the crate are available for the current MSRV"
@@ -104,7 +104,7 @@ impl IncompatibleMsrv {
             cx,
             INCOMPATIBLE_MSRV,
             span,
-            &format!(
+            format!(
                 "current MSRV (Minimum Supported Rust Version) is `{}` but this item is stable since `{version}`",
                 self.msrv
             ),
diff --git a/clippy_lints/src/inherent_to_string.rs b/clippy_lints/src/inherent_to_string.rs
index ca2ac60306b..157f6105984 100644
--- a/clippy_lints/src/inherent_to_string.rs
+++ b/clippy_lints/src/inherent_to_string.rs
@@ -132,20 +132,20 @@ fn show_lint(cx: &LateContext<'_>, item: &ImplItem<'_>) {
             cx,
             INHERENT_TO_STRING_SHADOW_DISPLAY,
             item.span,
-            &format!(
+            format!(
                 "type `{self_type}` implements inherent method `to_string(&self) -> String` which shadows the implementation of `Display`"
             ),
             None,
-            &format!("remove the inherent method from type `{self_type}`"),
+            format!("remove the inherent method from type `{self_type}`"),
         );
     } else {
         span_lint_and_help(
             cx,
             INHERENT_TO_STRING,
             item.span,
-            &format!("implementation of inherent method `to_string(&self) -> String` for type `{self_type}`"),
+            format!("implementation of inherent method `to_string(&self) -> String` for type `{self_type}`"),
             None,
-            &format!("implement trait `Display` for type `{self_type}` instead"),
+            format!("implement trait `Display` for type `{self_type}` instead"),
         );
     }
 }
diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs
index 83ecaeef982..860258fd030 100644
--- a/clippy_lints/src/inline_fn_without_body.rs
+++ b/clippy_lints/src/inline_fn_without_body.rs
@@ -51,7 +51,7 @@ fn check_attrs(cx: &LateContext<'_>, name: Symbol, attrs: &[Attribute]) {
             cx,
             INLINE_FN_WITHOUT_BODY,
             attr.span,
-            &format!("use of `#[inline]` on trait method `{name}` which has no body"),
+            format!("use of `#[inline]` on trait method `{name}` which has no body"),
             |diag| {
                 diag.suggest_remove_item(cx, attr.span, "remove", Applicability::MachineApplicable);
             },
diff --git a/clippy_lints/src/instant_subtraction.rs b/clippy_lints/src/instant_subtraction.rs
index 17b6256f982..10b00f632bb 100644
--- a/clippy_lints/src/instant_subtraction.rs
+++ b/clippy_lints/src/instant_subtraction.rs
@@ -1,5 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
-use clippy_utils::diagnostics::{self, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty;
@@ -149,7 +149,7 @@ fn print_unchecked_duration_subtraction_sugg(
     let left_expr = snippet_with_context(cx, left_expr.span, ctxt, "<instant>", &mut applicability).0;
     let right_expr = snippet_with_context(cx, right_expr.span, ctxt, "<duration>", &mut applicability).0;
 
-    diagnostics::span_lint_and_sugg(
+    span_lint_and_sugg(
         cx,
         UNCHECKED_DURATION_SUBTRACTION,
         expr.span,
diff --git a/clippy_lints/src/integer_division_remainder_used.rs b/clippy_lints/src/integer_division_remainder_used.rs
index 36dc45ca788..a3577b765c0 100644
--- a/clippy_lints/src/integer_division_remainder_used.rs
+++ b/clippy_lints/src/integer_division_remainder_used.rs
@@ -43,7 +43,7 @@ impl LateLintPass<'_> for IntegerDivisionRemainderUsed {
                 cx,
                 INTEGER_DIVISION_REMAINDER_USED,
                 expr.span.source_callsite(),
-                &format!("use of {} has been disallowed in this context", op.node.as_str()),
+                format!("use of {} has been disallowed in this context", op.node.as_str()),
             );
         }
     }
diff --git a/clippy_lints/src/invalid_upcast_comparisons.rs b/clippy_lints/src/invalid_upcast_comparisons.rs
index 8bcd9b532bd..30f2285bdd2 100644
--- a/clippy_lints/src/invalid_upcast_comparisons.rs
+++ b/clippy_lints/src/invalid_upcast_comparisons.rs
@@ -76,7 +76,7 @@ fn err_upcast_comparison(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, alwa
             cx,
             INVALID_UPCAST_COMPARISONS,
             span,
-            &format!(
+            format!(
                 "because of the numeric bounds on `{}` prior to casting, this expression is always {}",
                 snippet(cx, cast_val.span, "the expression"),
                 if always { "true" } else { "false" },
@@ -88,7 +88,7 @@ fn err_upcast_comparison(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, alwa
 fn upcast_comparison_bounds_err<'tcx>(
     cx: &LateContext<'tcx>,
     span: Span,
-    rel: comparisons::Rel,
+    rel: Rel,
     lhs_bounds: Option<(FullInt, FullInt)>,
     lhs: &'tcx Expr<'_>,
     rhs: &'tcx Expr<'_>,
diff --git a/clippy_lints/src/item_name_repetitions.rs b/clippy_lints/src/item_name_repetitions.rs
index 0b4c416d94d..6615122567d 100644
--- a/clippy_lints/src/item_name_repetitions.rs
+++ b/clippy_lints/src/item_name_repetitions.rs
@@ -240,9 +240,9 @@ fn check_fields(cx: &LateContext<'_>, threshold: u64, item: &Item<'_>, fields: &
             cx,
             STRUCT_FIELD_NAMES,
             item.span,
-            &format!("all fields have the same {what}fix: `{value}`"),
+            format!("all fields have the same {what}fix: `{value}`"),
             None,
-            &format!("remove the {what}fixes"),
+            format!("remove the {what}fixes"),
         );
     }
 }
@@ -370,9 +370,9 @@ fn check_variant(cx: &LateContext<'_>, threshold: u64, def: &EnumDef<'_>, item_n
         cx,
         ENUM_VARIANT_NAMES,
         span,
-        &format!("all variants have the same {what}fix: `{value}`"),
+        format!("all variants have the same {what}fix: `{value}`"),
         None,
-        &format!(
+        format!(
             "remove the {what}fixes and use full paths to \
              the variants instead of glob imports"
         ),
diff --git a/clippy_lints/src/iter_not_returning_iterator.rs b/clippy_lints/src/iter_not_returning_iterator.rs
index 32ae6be5687..1b5f1b49947 100644
--- a/clippy_lints/src/iter_not_returning_iterator.rs
+++ b/clippy_lints/src/iter_not_returning_iterator.rs
@@ -84,7 +84,7 @@ fn check_sig(cx: &LateContext<'_>, name: &str, sig: &FnSig<'_>, fn_id: LocalDefI
                 cx,
                 ITER_NOT_RETURNING_ITERATOR,
                 sig.span,
-                &format!("this method is named `{name}` but its return type does not implement `Iterator`"),
+                format!("this method is named `{name}` but its return type does not implement `Iterator`"),
             );
         }
     }
diff --git a/clippy_lints/src/iter_without_into_iter.rs b/clippy_lints/src/iter_without_into_iter.rs
index cf0ab88032c..c749a712330 100644
--- a/clippy_lints/src/iter_without_into_iter.rs
+++ b/clippy_lints/src/iter_without_into_iter.rs
@@ -182,7 +182,7 @@ impl LateLintPass<'_> for IterWithoutIntoIter {
                 cx,
                 INTO_ITER_WITHOUT_ITER,
                 item.span,
-                &format!("`IntoIterator` implemented for a reference type without an `{expected_method_name}` method"),
+                format!("`IntoIterator` implemented for a reference type without an `{expected_method_name}` method"),
                 |diag| {
                     // The suggestion forwards to the `IntoIterator` impl and uses a form of UFCS
                     // to avoid name ambiguities, as there might be an inherent into_iter method
@@ -258,7 +258,7 @@ impl {self_ty_without_ref} {{
                 cx,
                 ITER_WITHOUT_INTO_ITER,
                 item.span,
-                &format!(
+                format!(
                     "`{}` method without an `IntoIterator` impl for `{self_ty_snippet}`",
                     item.ident
                 ),
diff --git a/clippy_lints/src/large_futures.rs b/clippy_lints/src/large_futures.rs
index eb7570e9b44..07488a512a3 100644
--- a/clippy_lints/src/large_futures.rs
+++ b/clippy_lints/src/large_futures.rs
@@ -71,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeFuture {
                     cx,
                     LARGE_FUTURES,
                     expr.span,
-                    &format!("large future with a size of {} bytes", size.bytes()),
+                    format!("large future with a size of {} bytes", size.bytes()),
                     "consider `Box::pin` on it",
                     format!("Box::pin({})", snippet(cx, expr.span, "..")),
                     Applicability::Unspecified,
diff --git a/clippy_lints/src/large_include_file.rs b/clippy_lints/src/large_include_file.rs
index 1b5981ecc28..0599afca09f 100644
--- a/clippy_lints/src/large_include_file.rs
+++ b/clippy_lints/src/large_include_file.rs
@@ -74,7 +74,7 @@ impl LateLintPass<'_> for LargeIncludeFile {
                 expr.span,
                 "attempted to include a large file",
                 None,
-                &format!(
+                format!(
                     "the configuration allows a maximum size of {} bytes",
                     self.max_file_size
                 ),
diff --git a/clippy_lints/src/large_stack_arrays.rs b/clippy_lints/src/large_stack_arrays.rs
index fd33ba91bfd..afcb6745947 100644
--- a/clippy_lints/src/large_stack_arrays.rs
+++ b/clippy_lints/src/large_stack_arrays.rs
@@ -58,12 +58,12 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
                 cx,
                 LARGE_STACK_ARRAYS,
                 expr.span,
-                &format!(
+                format!(
                     "allocating a local array larger than {} bytes",
                     self.maximum_allowed_size
                 ),
                 None,
-                &format!(
+                format!(
                     "consider allocating on the heap with `vec!{}.into_boxed_slice()`",
                     snippet(cx, expr.span, "[...]")
                 ),
diff --git a/clippy_lints/src/large_stack_frames.rs b/clippy_lints/src/large_stack_frames.rs
index b397180a69c..49408d7e243 100644
--- a/clippy_lints/src/large_stack_frames.rs
+++ b/clippy_lints/src/large_stack_frames.rs
@@ -1,10 +1,12 @@
-use std::ops::AddAssign;
+use std::{fmt, ops};
 
-use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::fn_has_unsatisfiable_preds;
+use clippy_utils::source::snippet_opt;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, FnDecl};
+use rustc_lexer::is_ident;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
 use rustc_span::Span;
@@ -108,13 +110,25 @@ impl Space {
     }
 }
 
-impl AddAssign<u64> for Space {
-    fn add_assign(&mut self, rhs: u64) {
-        if let Self::Used(lhs) = self {
-            match lhs.checked_add(rhs) {
-                Some(sum) => *self = Self::Used(sum),
-                None => *self = Self::Overflow,
-            }
+impl fmt::Display for Space {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Space::Used(1) => write!(f, "1 byte"),
+            Space::Used(n) => write!(f, "{n} bytes"),
+            Space::Overflow => write!(f, "over 2⁶⁴-1 bytes"),
+        }
+    }
+}
+
+impl ops::Add<u64> for Space {
+    type Output = Self;
+    fn add(self, rhs: u64) -> Self {
+        match self {
+            Self::Used(lhs) => match lhs.checked_add(rhs) {
+                Some(sum) => Self::Used(sum),
+                None => Self::Overflow,
+            },
+            Self::Overflow => self,
         }
     }
 }
@@ -123,10 +137,10 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames {
     fn check_fn(
         &mut self,
         cx: &LateContext<'tcx>,
-        _: FnKind<'tcx>,
+        fn_kind: FnKind<'tcx>,
         _: &'tcx FnDecl<'tcx>,
         _: &'tcx Body<'tcx>,
-        span: Span,
+        entire_fn_span: Span,
         local_def_id: LocalDefId,
     ) {
         let def_id = local_def_id.to_def_id();
@@ -138,22 +152,68 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames {
         let mir = cx.tcx.optimized_mir(def_id);
         let param_env = cx.tcx.param_env(def_id);
 
-        let mut frame_size = Space::Used(0);
+        let sizes_of_locals = || {
+            mir.local_decls.iter().filter_map(|local| {
+                let layout = cx.tcx.layout_of(param_env.and(local.ty)).ok()?;
+                Some((local, layout.size.bytes()))
+            })
+        };
 
-        for local in &mir.local_decls {
-            if let Ok(layout) = cx.tcx.layout_of(param_env.and(local.ty)) {
-                frame_size += layout.size.bytes();
-            }
-        }
+        let frame_size = sizes_of_locals().fold(Space::Used(0), |sum, (_, size)| sum + size);
 
-        if frame_size.exceeds_limit(self.maximum_allowed_size) {
-            span_lint_and_note(
+        let limit = self.maximum_allowed_size;
+        if frame_size.exceeds_limit(limit) {
+            // Point at just the function name if possible, because lints that span
+            // the entire body and don't have to are less legible.
+            let fn_span = match fn_kind {
+                FnKind::ItemFn(ident, _, _) | FnKind::Method(ident, _) => ident.span,
+                FnKind::Closure => entire_fn_span,
+            };
+
+            span_lint_and_then(
                 cx,
                 LARGE_STACK_FRAMES,
-                span,
-                "this function allocates a large amount of stack space",
-                None,
-                "allocating large amounts of stack space can overflow the stack",
+                fn_span,
+                format!("this function may allocate {frame_size} on the stack"),
+                |diag| {
+                    // Point out the largest individual contribution to this size, because
+                    // it is the most likely to be unintentionally large.
+                    if let Some((local, size)) = sizes_of_locals().max_by_key(|&(_, size)| size) {
+                        let local_span: Span = local.source_info.span;
+                        let size = Space::Used(size); // pluralizes for us
+                        let ty = local.ty;
+
+                        // TODO: Is there a cleaner, robust way to ask this question?
+                        // The obvious `LocalDecl::is_user_variable()` panics on "unwrapping cross-crate data",
+                        // and that doesn't get us the true name in scope rather than the span text either.
+                        if let Some(name) = snippet_opt(cx, local_span)
+                            && is_ident(&name)
+                        {
+                            // If the local is an ordinary named variable,
+                            // print its name rather than relying solely on the span.
+                            diag.span_label(
+                                local_span,
+                                format!("`{name}` is the largest part, at {size} for type `{ty}`"),
+                            );
+                        } else {
+                            diag.span_label(
+                                local_span,
+                                format!("this is the largest part, at {size} for type `{ty}`"),
+                            );
+                        }
+                    }
+
+                    // Explain why we are linting this and not other functions.
+                    diag.note(format!(
+                        "{frame_size} is larger than Clippy's configured `stack-size-threshold` of {limit}"
+                    ));
+
+                    // Explain why the user should care, briefly.
+                    diag.note_once(
+                        "allocating large amounts of stack space can overflow the stack \
+                        and cause the program to abort",
+                    );
+                },
             );
         }
     }
diff --git a/clippy_lints/src/legacy_numeric_constants.rs b/clippy_lints/src/legacy_numeric_constants.rs
new file mode 100644
index 00000000000..c5f1afe68c3
--- /dev/null
+++ b/clippy_lints/src/legacy_numeric_constants.rs
@@ -0,0 +1,293 @@
+use clippy_config::msrvs::{Msrv, NUMERIC_ASSOCIATED_CONSTANTS};
+use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
+use clippy_utils::{get_parent_expr, is_from_proc_macro};
+use hir::def_id::DefId;
+use rustc_errors::{Applicability, SuggestionStyle};
+use rustc_hir as hir;
+use rustc_hir::{ExprKind, Item, ItemKind, QPath, UseKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::impl_lint_pass;
+use rustc_span::symbol::kw;
+use rustc_span::{sym, Symbol};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for usage of `<integer>::max_value()`, `std::<integer>::MAX`,
+    /// `std::<float>::EPSILON`, etc.
+    ///
+    /// ### Why is this bad?
+    /// All of these have been superceded by the associated constants on their respective types,
+    /// such as `i128::MAX`. These legacy items may be deprecated in a future version of rust.
+    ///
+    /// ### Example
+    /// ```rust
+    /// let eps = std::f32::EPSILON;
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let eps = f32::EPSILON;
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub LEGACY_NUMERIC_CONSTANTS,
+    style,
+    "checks for usage of legacy std numeric constants and methods"
+}
+pub struct LegacyNumericConstants {
+    msrv: Msrv,
+}
+
+impl LegacyNumericConstants {
+    #[must_use]
+    pub fn new(msrv: Msrv) -> Self {
+        Self { msrv }
+    }
+}
+
+impl_lint_pass!(LegacyNumericConstants => [LEGACY_NUMERIC_CONSTANTS]);
+
+impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+        let Self { msrv } = self;
+
+        if !msrv.meets(NUMERIC_ASSOCIATED_CONSTANTS) || in_external_macro(cx.sess(), item.span) {
+            return;
+        }
+
+        // Integer modules are "TBD" deprecated, and the contents are too,
+        // so lint on the `use` statement directly.
+        if let ItemKind::Use(path, kind @ (UseKind::Single | UseKind::Glob)) = item.kind
+            && let Some(def_id) = path.res[0].opt_def_id()
+        {
+            let module = if is_integer_module(cx, def_id) {
+                true
+            } else if is_numeric_const(cx, def_id) {
+                false
+            } else {
+                return;
+            };
+
+            span_lint_and_then(
+                cx,
+                LEGACY_NUMERIC_CONSTANTS,
+                path.span,
+                if module {
+                    "importing legacy numeric constants"
+                } else {
+                    "importing a legacy numeric constant"
+                },
+                |diag| {
+                    if item.ident.name == kw::Underscore {
+                        diag.help("remove this import");
+                        return;
+                    }
+
+                    let def_path = cx.get_def_path(def_id);
+
+                    if module && let [.., module_name] = &*def_path {
+                        if kind == UseKind::Glob {
+                            diag.help(format!("remove this import and use associated constants `{module_name}::<CONST>` from the primitive type instead"));
+                        } else {
+                            diag.help("remove this import").note(format!(
+                                "then `{module_name}::<CONST>` will resolve to the respective associated constant"
+                            ));
+                        }
+                    } else if let [.., module_name, name] = &*def_path {
+                        diag.help(
+                            format!("remove this import and use the associated constant `{module_name}::{name}` from the primitive type instead")
+                        );
+                    }
+                },
+            );
+        }
+    }
+
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
+        let Self { msrv } = self;
+
+        if !msrv.meets(NUMERIC_ASSOCIATED_CONSTANTS) || in_external_macro(cx.sess(), expr.span) {
+            return;
+        }
+        let ExprKind::Path(qpath) = expr.kind else {
+            return;
+        };
+
+        // `std::<integer>::<CONST>` check
+        let (span, sugg, msg) = if let QPath::Resolved(None, path) = qpath
+            && let Some(def_id) = path.res.opt_def_id()
+            && is_numeric_const(cx, def_id)
+            && let def_path = cx.get_def_path(def_id)
+            && let [.., mod_name, name] = &*def_path
+            // Skip linting if this usage looks identical to the associated constant,
+            // since this would only require removing a `use` import (which is already linted).
+            && !is_numeric_const_path_canonical(path, [*mod_name, *name])
+        {
+            (
+                expr.span,
+                format!("{mod_name}::{name}"),
+                "usage of a legacy numeric constant",
+            )
+        // `<integer>::xxx_value` check
+        } else if let QPath::TypeRelative(_, last_segment) = qpath
+            && let Some(def_id) = cx.qpath_res(&qpath, expr.hir_id).opt_def_id()
+            && is_integer_method(cx, def_id)
+            && let Some(par_expr) = get_parent_expr(cx, expr)
+            && let ExprKind::Call(_, _) = par_expr.kind
+        {
+            let name = last_segment.ident.name.as_str();
+
+            (
+                last_segment.ident.span.with_hi(par_expr.span.hi()),
+                name[..=2].to_ascii_uppercase(),
+                "usage of a legacy numeric method",
+            )
+        } else {
+            return;
+        };
+
+        if is_from_proc_macro(cx, expr) {
+            return;
+        }
+
+        span_lint_hir_and_then(cx, LEGACY_NUMERIC_CONSTANTS, expr.hir_id, span, msg, |diag| {
+            diag.span_suggestion_with_style(
+                span,
+                "use the associated constant instead",
+                sugg,
+                Applicability::MaybeIncorrect,
+                SuggestionStyle::ShowAlways,
+            );
+        });
+    }
+
+    extract_msrv_attr!(LateContext);
+}
+
+fn is_integer_module(cx: &LateContext<'_>, did: DefId) -> bool {
+    matches!(
+        cx.tcx.get_diagnostic_name(did),
+        Some(
+            sym::isize_legacy_mod
+                | sym::i128_legacy_mod
+                | sym::i64_legacy_mod
+                | sym::i32_legacy_mod
+                | sym::i16_legacy_mod
+                | sym::i8_legacy_mod
+                | sym::usize_legacy_mod
+                | sym::u128_legacy_mod
+                | sym::u64_legacy_mod
+                | sym::u32_legacy_mod
+                | sym::u16_legacy_mod
+                | sym::u8_legacy_mod
+        )
+    )
+}
+
+fn is_numeric_const(cx: &LateContext<'_>, did: DefId) -> bool {
+    matches!(
+        cx.tcx.get_diagnostic_name(did),
+        Some(
+            sym::isize_legacy_const_max
+                | sym::isize_legacy_const_min
+                | sym::i128_legacy_const_max
+                | sym::i128_legacy_const_min
+                | sym::i16_legacy_const_max
+                | sym::i16_legacy_const_min
+                | sym::i32_legacy_const_max
+                | sym::i32_legacy_const_min
+                | sym::i64_legacy_const_max
+                | sym::i64_legacy_const_min
+                | sym::i8_legacy_const_max
+                | sym::i8_legacy_const_min
+                | sym::usize_legacy_const_max
+                | sym::usize_legacy_const_min
+                | sym::u128_legacy_const_max
+                | sym::u128_legacy_const_min
+                | sym::u16_legacy_const_max
+                | sym::u16_legacy_const_min
+                | sym::u32_legacy_const_max
+                | sym::u32_legacy_const_min
+                | sym::u64_legacy_const_max
+                | sym::u64_legacy_const_min
+                | sym::u8_legacy_const_max
+                | sym::u8_legacy_const_min
+                | sym::f32_legacy_const_digits
+                | sym::f32_legacy_const_epsilon
+                | sym::f32_legacy_const_infinity
+                | sym::f32_legacy_const_mantissa_dig
+                | sym::f32_legacy_const_max
+                | sym::f32_legacy_const_max_10_exp
+                | sym::f32_legacy_const_max_exp
+                | sym::f32_legacy_const_min
+                | sym::f32_legacy_const_min_10_exp
+                | sym::f32_legacy_const_min_exp
+                | sym::f32_legacy_const_min_positive
+                | sym::f32_legacy_const_nan
+                | sym::f32_legacy_const_neg_infinity
+                | sym::f32_legacy_const_radix
+                | sym::f64_legacy_const_digits
+                | sym::f64_legacy_const_epsilon
+                | sym::f64_legacy_const_infinity
+                | sym::f64_legacy_const_mantissa_dig
+                | sym::f64_legacy_const_max
+                | sym::f64_legacy_const_max_10_exp
+                | sym::f64_legacy_const_max_exp
+                | sym::f64_legacy_const_min
+                | sym::f64_legacy_const_min_10_exp
+                | sym::f64_legacy_const_min_exp
+                | sym::f64_legacy_const_min_positive
+                | sym::f64_legacy_const_nan
+                | sym::f64_legacy_const_neg_infinity
+                | sym::f64_legacy_const_radix
+        )
+    )
+}
+
+// Whether path expression looks like `i32::MAX`
+fn is_numeric_const_path_canonical(expr_path: &hir::Path<'_>, [mod_name, name]: [Symbol; 2]) -> bool {
+    let [
+        hir::PathSegment {
+            ident: one, args: None, ..
+        },
+        hir::PathSegment {
+            ident: two, args: None, ..
+        },
+    ] = expr_path.segments
+    else {
+        return false;
+    };
+
+    one.name == mod_name && two.name == name
+}
+
+fn is_integer_method(cx: &LateContext<'_>, did: DefId) -> bool {
+    matches!(
+        cx.tcx.get_diagnostic_name(did),
+        Some(
+            sym::isize_legacy_fn_max_value
+                | sym::isize_legacy_fn_min_value
+                | sym::i128_legacy_fn_max_value
+                | sym::i128_legacy_fn_min_value
+                | sym::i16_legacy_fn_max_value
+                | sym::i16_legacy_fn_min_value
+                | sym::i32_legacy_fn_max_value
+                | sym::i32_legacy_fn_min_value
+                | sym::i64_legacy_fn_max_value
+                | sym::i64_legacy_fn_min_value
+                | sym::i8_legacy_fn_max_value
+                | sym::i8_legacy_fn_min_value
+                | sym::usize_legacy_fn_max_value
+                | sym::usize_legacy_fn_min_value
+                | sym::u128_legacy_fn_max_value
+                | sym::u128_legacy_fn_min_value
+                | sym::u16_legacy_fn_max_value
+                | sym::u16_legacy_fn_min_value
+                | sym::u32_legacy_fn_max_value
+                | sym::u32_legacy_fn_min_value
+                | sym::u64_legacy_fn_max_value
+                | sym::u64_legacy_fn_min_value
+                | sym::u8_legacy_fn_max_value
+                | sym::u8_legacy_fn_min_value
+        )
+    )
+}
diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs
index cae9ada5a33..97a245b76d4 100644
--- a/clippy_lints/src/len_zero.rs
+++ b/clippy_lints/src/len_zero.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::source::snippet_with_context;
-use clippy_utils::sugg::Sugg;
+use clippy_utils::source::{snippet_opt, snippet_with_context};
+use clippy_utils::sugg::{has_enclosing_paren, Sugg};
 use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators};
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
@@ -192,7 +192,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
 
         if let ExprKind::Binary(Spanned { node: cmp, .. }, left, right) = expr.kind {
             // expr.span might contains parenthesis, see issue #10529
-            let actual_span = left.span.with_hi(right.span.hi());
+            let actual_span = span_without_enclosing_paren(cx, expr.span);
             match cmp {
                 BinOpKind::Eq => {
                     check_cmp(cx, actual_span, left, right, "", 0); // len == 0
@@ -218,6 +218,20 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
     }
 }
 
+fn span_without_enclosing_paren(cx: &LateContext<'_>, span: Span) -> Span {
+    let Some(snippet) = snippet_opt(cx, span) else {
+        return span;
+    };
+    if has_enclosing_paren(snippet) {
+        let source_map = cx.tcx.sess.source_map();
+        let left_paren = source_map.start_point(span);
+        let right_parent = source_map.end_point(span);
+        left_paren.between(right_parent)
+    } else {
+        span
+    }
+}
+
 fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items: &[TraitItemRef]) {
     fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: Symbol) -> bool {
         item.ident.name == name
@@ -256,7 +270,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
             .items()
             .flat_map(|&i| cx.tcx.associated_items(i).filter_by_name_unhygienic(is_empty))
             .any(|i| {
-                i.kind == ty::AssocKind::Fn
+                i.kind == AssocKind::Fn
                     && i.fn_has_self_parameter
                     && cx.tcx.fn_sig(i.def_id).skip_binder().inputs().skip_binder().len() == 1
             });
@@ -266,7 +280,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
                 cx,
                 LEN_WITHOUT_IS_EMPTY,
                 visited_trait.span,
-                &format!(
+                format!(
                     "trait `{}` has a `len` method but no (possibly inherited) `is_empty` method",
                     visited_trait.ident.name
                 ),
@@ -484,7 +498,7 @@ fn check_for_is_empty(
         Some(_) => return,
     };
 
-    span_lint_and_then(cx, LEN_WITHOUT_IS_EMPTY, span, &msg, |db| {
+    span_lint_and_then(cx, LEN_WITHOUT_IS_EMPTY, span, msg, |db| {
         if let Some(span) = is_empty_span {
             db.span_note(span, "`is_empty` defined here");
         }
@@ -495,6 +509,10 @@ fn check_for_is_empty(
 }
 
 fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) {
+    if method.span.from_expansion() {
+        return;
+    }
+
     if let (&ExprKind::MethodCall(method_path, receiver, args, _), ExprKind::Lit(lit)) = (&method.kind, &lit.kind) {
         // check if we are in an is_empty() method
         if let Some(name) = get_item_name(cx, method) {
@@ -542,8 +560,8 @@ fn check_len(
                 cx,
                 LEN_ZERO,
                 span,
-                &format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }),
-                &format!("using `{op}is_empty` is clearer and more explicit"),
+                format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }),
+                format!("using `{op}is_empty` is clearer and more explicit"),
                 format!(
                     "{op}{}.is_empty()",
                     snippet_with_context(cx, receiver.span, span.ctxt(), "_", &mut applicability).0,
@@ -566,7 +584,7 @@ fn check_empty_expr(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Ex
             COMPARISON_TO_EMPTY,
             span,
             "comparison to empty slice",
-            &format!("using `{op}is_empty` is clearer and more explicit"),
+            format!("using `{op}is_empty` is clearer and more explicit"),
             format!("{op}{lit_str}.is_empty()"),
             applicability,
         );
@@ -594,7 +612,7 @@ fn is_empty_array(expr: &Expr<'_>) -> bool {
 fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     /// Gets an `AssocItem` and return true if it matches `is_empty(self)`.
     fn is_is_empty(cx: &LateContext<'_>, item: &ty::AssocItem) -> bool {
-        if item.kind == ty::AssocKind::Fn {
+        if item.kind == AssocKind::Fn {
             let sig = cx.tcx.fn_sig(item.def_id).skip_binder();
             let ty = sig.skip_binder();
             ty.inputs().len() == 1
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 57fac351042..b92364a9d14 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -16,11 +16,14 @@
     rustc::diagnostic_outside_of_impl,
     rustc::untranslatable_diagnostic
 )]
-#![warn(trivial_casts, trivial_numeric_casts)]
-// warn on lints, that are included in `rust-lang/rust`s bootstrap
-#![warn(rust_2018_idioms, unused_lifetimes)]
-// warn on rustc internal lints
-#![warn(rustc::internal)]
+#![warn(
+    trivial_casts,
+    trivial_numeric_casts,
+    rust_2018_idioms,
+    unused_lifetimes,
+    unused_qualifications,
+    rustc::internal
+)]
 // Disable this rustc lint for now, as it was also done in rustc
 #![allow(rustc::potential_query_instability)]
 
@@ -186,6 +189,7 @@ mod large_futures;
 mod large_include_file;
 mod large_stack_arrays;
 mod large_stack_frames;
+mod legacy_numeric_constants;
 mod len_zero;
 mod let_if_seq;
 mod let_underscore;
@@ -1080,6 +1084,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
             allow_one_hash_in_raw_strings,
         })
     });
+    store.register_late_pass(move |_| Box::new(legacy_numeric_constants::LegacyNumericConstants::new(msrv())));
     store.register_late_pass(|_| Box::new(manual_range_patterns::ManualRangePatterns));
     store.register_early_pass(|| Box::new(visibility::Visibility));
     store.register_late_pass(move |_| Box::new(tuple_array_conversions::TupleArrayConversions { msrv: msrv() }));
diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs
index 2b73663d229..a60a40a2a47 100644
--- a/clippy_lints/src/lifetimes.rs
+++ b/clippy_lints/src/lifetimes.rs
@@ -216,7 +216,7 @@ fn check_fn_inner<'tcx>(
                     None
                 }))
                 .collect_vec(),
-            &format!("the following explicit lifetimes could be elided: {lts}"),
+            format!("the following explicit lifetimes could be elided: {lts}"),
             |diag| {
                 if sig.header.is_async() {
                     // async functions have usages whose spans point at the lifetime declaration which messes up
diff --git a/clippy_lints/src/lines_filter_map_ok.rs b/clippy_lints/src/lines_filter_map_ok.rs
index 29957e423b0..3d1c666dfea 100644
--- a/clippy_lints/src/lines_filter_map_ok.rs
+++ b/clippy_lints/src/lines_filter_map_ok.rs
@@ -70,7 +70,7 @@ impl LateLintPass<'_> for LinesFilterMapOk {
                 cx,
                 LINES_FILTER_MAP_OK,
                 fm_span,
-                &format!("`{fm_method_str}()` will run forever if the iterator repeatedly produces an `Err`",),
+                format!("`{fm_method_str}()` will run forever if the iterator repeatedly produces an `Err`",),
                 |diag| {
                     diag.span_note(
                         fm_receiver.span,
diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs
index f33151cf4c5..2348dd18220 100644
--- a/clippy_lints/src/literal_representation.rs
+++ b/clippy_lints/src/literal_representation.rs
@@ -158,7 +158,7 @@ enum WarningType {
 }
 
 impl WarningType {
-    fn display(&self, suggested_format: String, cx: &EarlyContext<'_>, span: rustc_span::Span) {
+    fn display(&self, suggested_format: String, cx: &EarlyContext<'_>, span: Span) {
         match self {
             Self::MistypedLiteralSuffix => span_lint_and_sugg(
                 cx,
@@ -302,11 +302,7 @@ impl LiteralDigitGrouping {
     }
 
     // Returns `false` if the check fails
-    fn check_for_mistyped_suffix(
-        cx: &EarlyContext<'_>,
-        span: rustc_span::Span,
-        num_lit: &mut NumericLiteral<'_>,
-    ) -> bool {
+    fn check_for_mistyped_suffix(cx: &EarlyContext<'_>, span: Span, num_lit: &mut NumericLiteral<'_>) -> bool {
         if num_lit.suffix.is_some() {
             return true;
         }
diff --git a/clippy_lints/src/loops/explicit_counter_loop.rs b/clippy_lints/src/loops/explicit_counter_loop.rs
index 277062a8490..f0ee64d714e 100644
--- a/clippy_lints/src/loops/explicit_counter_loop.rs
+++ b/clippy_lints/src/loops/explicit_counter_loop.rs
@@ -42,7 +42,7 @@ pub(super) fn check<'tcx>(
                             cx,
                             EXPLICIT_COUNTER_LOOP,
                             span,
-                            &format!("the variable `{name}` is used as a loop counter"),
+                            format!("the variable `{name}` is used as a loop counter"),
                             "consider using",
                             format!(
                                 "for ({name}, {}) in {}.enumerate()",
@@ -62,7 +62,7 @@ pub(super) fn check<'tcx>(
                     cx,
                     EXPLICIT_COUNTER_LOOP,
                     span,
-                    &format!("the variable `{name}` is used as a loop counter"),
+                    format!("the variable `{name}` is used as a loop counter"),
                     |diag| {
                         diag.span_suggestion(
                             span,
diff --git a/clippy_lints/src/loops/for_kv_map.rs b/clippy_lints/src/loops/for_kv_map.rs
index 94c951fc10a..6922533fbe9 100644
--- a/clippy_lints/src/loops/for_kv_map.rs
+++ b/clippy_lints/src/loops/for_kv_map.rs
@@ -37,7 +37,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx
                     cx,
                     FOR_KV_MAP,
                     arg_span,
-                    &format!("you seem to want to iterate on a map's {kind}s"),
+                    format!("you seem to want to iterate on a map's {kind}s"),
                     |diag| {
                         let map = sugg::Sugg::hir(cx, arg, "map");
                         multispan_sugg(
diff --git a/clippy_lints/src/loops/manual_flatten.rs b/clippy_lints/src/loops/manual_flatten.rs
index 36de9021f49..dbc094a6d73 100644
--- a/clippy_lints/src/loops/manual_flatten.rs
+++ b/clippy_lints/src/loops/manual_flatten.rs
@@ -62,7 +62,7 @@ pub(super) fn check<'tcx>(
             "...and remove the `if let` statement in the for loop"
         };
 
-        span_lint_and_then(cx, MANUAL_FLATTEN, span, &msg, |diag| {
+        span_lint_and_then(cx, MANUAL_FLATTEN, span, msg, |diag| {
             diag.span_suggestion(arg.span, "try", sugg, applicability);
             diag.span_help(inner_expr.span, help_msg);
         });
diff --git a/clippy_lints/src/loops/mut_range_bound.rs b/clippy_lints/src/loops/mut_range_bound.rs
index c4e60e98ad4..94330001e4f 100644
--- a/clippy_lints/src/loops/mut_range_bound.rs
+++ b/clippy_lints/src/loops/mut_range_bound.rs
@@ -109,7 +109,7 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
         }
     }
 
-    fn fake_read(&mut self, _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+    fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
 }
 
 impl MutatePairDelegate<'_, '_> {
@@ -141,7 +141,7 @@ impl BreakAfterExprVisitor {
     }
 }
 
-impl<'tcx> intravisit::Visitor<'tcx> for BreakAfterExprVisitor {
+impl<'tcx> Visitor<'tcx> for BreakAfterExprVisitor {
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
         if self.past_candidate {
             return;
diff --git a/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs
index cf34c904dfe..de7ec81bc01 100644
--- a/clippy_lints/src/loops/needless_range_loop.rs
+++ b/clippy_lints/src/loops/needless_range_loop.rs
@@ -143,7 +143,7 @@ pub(super) fn check<'tcx>(
                         cx,
                         NEEDLESS_RANGE_LOOP,
                         arg.span,
-                        &format!("the loop variable `{}` is used to index `{indexed}`", ident.name),
+                        format!("the loop variable `{}` is used to index `{indexed}`", ident.name),
                         |diag| {
                             multispan_sugg(
                                 diag,
@@ -169,7 +169,7 @@ pub(super) fn check<'tcx>(
                         cx,
                         NEEDLESS_RANGE_LOOP,
                         arg.span,
-                        &format!("the loop variable `{}` is only used to index `{indexed}`", ident.name),
+                        format!("the loop variable `{}` is only used to index `{indexed}`", ident.name),
                         |diag| {
                             multispan_sugg(
                                 diag,
@@ -357,7 +357,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
                 let def_id = self.cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
                 for (ty, expr) in iter::zip(
                     self.cx.tcx.fn_sig(def_id).instantiate_identity().inputs().skip_binder(),
-                    std::iter::once(receiver).chain(args.iter()),
+                    iter::once(receiver).chain(args.iter()),
                 ) {
                     self.prefer_mutable = false;
                     if let ty::Ref(_, _, mutbl) = *ty.kind() {
diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs
index 8aae7be4593..313a5bfefbc 100644
--- a/clippy_lints/src/loops/never_loop.rs
+++ b/clippy_lints/src/loops/never_loop.rs
@@ -159,12 +159,9 @@ fn never_loop_expr<'tcx>(
         | ExprKind::DropTemps(e) => never_loop_expr(cx, e, local_labels, main_loop_id),
         ExprKind::Let(let_expr) => never_loop_expr(cx, let_expr.init, local_labels, main_loop_id),
         ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(cx, es.iter(), local_labels, main_loop_id),
-        ExprKind::MethodCall(_, receiver, es, _) => never_loop_expr_all(
-            cx,
-            std::iter::once(receiver).chain(es.iter()),
-            local_labels,
-            main_loop_id,
-        ),
+        ExprKind::MethodCall(_, receiver, es, _) => {
+            never_loop_expr_all(cx, once(receiver).chain(es.iter()), local_labels, main_loop_id)
+        },
         ExprKind::Struct(_, fields, base) => {
             let fields = never_loop_expr_all(cx, fields.iter().map(|f| f.expr), local_labels, main_loop_id);
             if let Some(base) = base {
diff --git a/clippy_lints/src/loops/same_item_push.rs b/clippy_lints/src/loops/same_item_push.rs
index 670a78d58c3..1d90d4a58f5 100644
--- a/clippy_lints/src/loops/same_item_push.rs
+++ b/clippy_lints/src/loops/same_item_push.rs
@@ -31,7 +31,7 @@ pub(super) fn check<'tcx>(
             vec.span,
             "it looks like the same item is being pushed into this Vec",
             None,
-            &format!("consider using vec![{item_str};SIZE] or {vec_str}.resize(NEW_SIZE, {item_str})"),
+            format!("consider using vec![{item_str};SIZE] or {vec_str}.resize(NEW_SIZE, {item_str})"),
         );
     }
 
diff --git a/clippy_lints/src/loops/single_element_loop.rs b/clippy_lints/src/loops/single_element_loop.rs
index 4773a1454b7..108fdb69775 100644
--- a/clippy_lints/src/loops/single_element_loop.rs
+++ b/clippy_lints/src/loops/single_element_loop.rs
@@ -42,7 +42,7 @@ pub(super) fn check<'tcx>(
             },
             [],
             _,
-        ) if method.ident.name == rustc_span::sym::iter => (arg, "&"),
+        ) if method.ident.name == sym::iter => (arg, "&"),
         ExprKind::MethodCall(
             method,
             Expr {
@@ -60,7 +60,7 @@ pub(super) fn check<'tcx>(
             },
             [],
             _,
-        ) if method.ident.name == rustc_span::sym::into_iter => (arg, ""),
+        ) if method.ident.name == sym::into_iter => (arg, ""),
         // Only check for arrays edition 2021 or later, as this case will trigger a compiler error otherwise.
         ExprKind::Array([arg]) if cx.tcx.sess.edition() >= Edition::Edition2021 => (arg, ""),
         _ => return,
@@ -95,7 +95,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 SINGLE_ELEMENT_LOOP,
                 arg.span,
-                format!("this loops only once with `{pat_snip}` being `{range_expr}`").as_str(),
+                format!("this loops only once with `{pat_snip}` being `{range_expr}`"),
                 "did you mean to iterate over the range instead?",
                 sugg.to_string(),
                 Applicability::Unspecified,
diff --git a/clippy_lints/src/main_recursion.rs b/clippy_lints/src/main_recursion.rs
index a381b35cf2e..72807b4b284 100644
--- a/clippy_lints/src/main_recursion.rs
+++ b/clippy_lints/src/main_recursion.rs
@@ -51,7 +51,7 @@ impl LateLintPass<'_> for MainRecursion {
                 cx,
                 MAIN_RECURSION,
                 func.span,
-                &format!("recursing into entrypoint `{}`", snippet(cx, func.span, "main")),
+                format!("recursing into entrypoint `{}`", snippet(cx, func.span, "main")),
                 None,
                 "consider using another function for this recursion",
             );
diff --git a/clippy_lints/src/manual_assert.rs b/clippy_lints/src/manual_assert.rs
index 4f6a2cf017c..76edbe8b755 100644
--- a/clippy_lints/src/manual_assert.rs
+++ b/clippy_lints/src/manual_assert.rs
@@ -1,7 +1,7 @@
 use crate::rustc_lint::LintContext;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::root_macro_call;
-use clippy_utils::{is_else_clause, peel_blocks_with_stmt, span_extract_comment, sugg};
+use clippy_utils::{is_else_clause, is_parent_stmt, peel_blocks_with_stmt, span_extract_comment, sugg};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
@@ -63,7 +63,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualAssert {
                 _ => (cond, "!"),
             };
             let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par();
-            let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip});");
+            let semicolon = if is_parent_stmt(cx, expr.hir_id) { ";" } else { "" };
+            let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip}){semicolon}");
             // we show to the user the suggestion without the comments, but when applying the fix, include the
             // comments in the block
             span_lint_and_then(
diff --git a/clippy_lints/src/manual_bits.rs b/clippy_lints/src/manual_bits.rs
index aa02e4e7a43..24fc2b4faea 100644
--- a/clippy_lints/src/manual_bits.rs
+++ b/clippy_lints/src/manual_bits.rs
@@ -139,7 +139,7 @@ fn is_ty_conversion(expr: &Expr<'_>) -> bool {
     if let ExprKind::Cast(..) = expr.kind {
         true
     } else if let ExprKind::MethodCall(path, _, [], _) = expr.kind
-        && path.ident.name == rustc_span::sym::try_into
+        && path.ident.name == sym::try_into
     {
         // This is only called for `usize` which implements `TryInto`. Therefore,
         // we don't have to check here if `self` implements the `TryInto` trait.
diff --git a/clippy_lints/src/manual_clamp.rs b/clippy_lints/src/manual_clamp.rs
index 830af77968c..1eadc200bed 100644
--- a/clippy_lints/src/manual_clamp.rs
+++ b/clippy_lints/src/manual_clamp.rs
@@ -1,4 +1,5 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
 use clippy_utils::higher::If;
 use clippy_utils::sugg::Sugg;
@@ -17,6 +18,7 @@ use rustc_middle::ty::Ty;
 use rustc_session::impl_lint_pass;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
+use std::cmp::Ordering;
 use std::ops::Deref;
 
 declare_clippy_lint! {
@@ -26,6 +28,11 @@ declare_clippy_lint! {
     /// ### Why is this bad?
     /// clamp is much shorter, easier to read, and doesn't use any control flow.
     ///
+    /// ### Limitations
+    ///
+    /// This lint will only trigger if max and min are known at compile time, and max is
+    /// greater than min.
+    ///
     /// ### Known issue(s)
     /// If the clamped variable is NaN this suggestion will cause the code to propagate NaN
     /// rather than returning either `max` or `min`.
@@ -80,7 +87,7 @@ declare_clippy_lint! {
     /// ```
     #[clippy::version = "1.66.0"]
     pub MANUAL_CLAMP,
-    nursery,
+    complexity,
     "using a clamp pattern instead of the clamp function"
 }
 impl_lint_pass!(ManualClamp => [MANUAL_CLAMP]);
@@ -103,6 +110,26 @@ struct ClampSuggestion<'tcx> {
     hir_with_ignore_attr: Option<HirId>,
 }
 
+impl<'tcx> ClampSuggestion<'tcx> {
+    /// This function will return true if and only if you can demonstrate at compile time that min
+    /// is less than max.
+    fn min_less_than_max(&self, cx: &LateContext<'tcx>) -> bool {
+        let max_type = cx.typeck_results().expr_ty(self.params.max);
+        let min_type = cx.typeck_results().expr_ty(self.params.min);
+        if max_type != min_type {
+            return false;
+        }
+        if let Some(max) = constant(cx, cx.typeck_results(), self.params.max)
+            && let Some(min) = constant(cx, cx.typeck_results(), self.params.min)
+            && let Some(ord) = Constant::partial_cmp(cx.tcx, max_type, &min, &max)
+        {
+            ord != Ordering::Greater
+        } else {
+            false
+        }
+    }
+}
+
 #[derive(Debug)]
 struct InputMinMax<'tcx> {
     input: &'tcx Expr<'tcx>,
@@ -123,7 +150,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualClamp {
                 .or_else(|| is_match_pattern(cx, expr))
                 .or_else(|| is_if_elseif_pattern(cx, expr));
             if let Some(suggestion) = suggestion {
-                emit_suggestion(cx, &suggestion);
+                maybe_emit_suggestion(cx, &suggestion);
             }
         }
     }
@@ -133,13 +160,16 @@ impl<'tcx> LateLintPass<'tcx> for ManualClamp {
             return;
         }
         for suggestion in is_two_if_pattern(cx, block) {
-            emit_suggestion(cx, &suggestion);
+            maybe_emit_suggestion(cx, &suggestion);
         }
     }
     extract_msrv_attr!(LateContext);
 }
 
-fn emit_suggestion<'tcx>(cx: &LateContext<'tcx>, suggestion: &ClampSuggestion<'tcx>) {
+fn maybe_emit_suggestion<'tcx>(cx: &LateContext<'tcx>, suggestion: &ClampSuggestion<'tcx>) {
+    if !suggestion.min_less_than_max(cx) {
+        return;
+    }
     let ClampSuggestion {
         params: InputMinMax {
             input,
diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs
index bcd02436002..45af9f07718 100644
--- a/clippy_lints/src/manual_strip.rs
+++ b/clippy_lints/src/manual_strip.rs
@@ -106,12 +106,12 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
                     cx,
                     MANUAL_STRIP,
                     strippings[0],
-                    &format!("stripping a {kind_word} manually"),
+                    format!("stripping a {kind_word} manually"),
                     |diag| {
                         diag.span_note(test_span, format!("the {kind_word} was tested here"));
                         multispan_sugg(
                             diag,
-                            &format!("try using the `strip_{kind_word}` method"),
+                            format!("try using the `strip_{kind_word}` method"),
                             vec![(
                                 test_span,
                                 format!(
diff --git a/clippy_lints/src/manual_unwrap_or_default.rs b/clippy_lints/src/manual_unwrap_or_default.rs
index ddaf97c463a..c562ceb5bce 100644
--- a/clippy_lints/src/manual_unwrap_or_default.rs
+++ b/clippy_lints/src/manual_unwrap_or_default.rs
@@ -1,14 +1,15 @@
+use clippy_utils::sugg::Sugg;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatKind, QPath};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::declare_lint_pass;
 use rustc_span::sym;
 
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::is_default_equivalent;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::implements_trait;
+use clippy_utils::{in_constant, is_default_equivalent, peel_blocks, span_contains_comment};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -118,22 +119,27 @@ fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
         // We now get the bodies for both the `Some` and `None` arms.
         && let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2)
         // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
-        && let ExprKind::Path(QPath::Resolved(_, path)) = body_some.peel_blocks().kind
+        && let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(body_some).kind
         && let Res::Local(local_id) = path.res
         && local_id == binding_id
         // We now check the `None` arm is calling a method equivalent to `Default::default`.
-        && let body_none = body_none.peel_blocks()
+        && let body_none = peel_blocks(body_none)
         && is_default_equivalent(cx, body_none)
-        && let Some(match_expr_snippet) = snippet_opt(cx, match_expr.span)
+        && let Some(receiver) = Sugg::hir_opt(cx, match_expr).map(Sugg::maybe_par)
     {
+        let applicability = if span_contains_comment(cx.sess().source_map(), expr.span) {
+            Applicability::MaybeIncorrect
+        } else {
+            Applicability::MachineApplicable
+        };
         span_lint_and_sugg(
             cx,
             MANUAL_UNWRAP_OR_DEFAULT,
             expr.span,
             "match can be simplified with `.unwrap_or_default()`",
             "replace it with",
-            format!("{match_expr_snippet}.unwrap_or_default()"),
-            Applicability::MachineApplicable,
+            format!("{receiver}.unwrap_or_default()"),
+            applicability,
         );
     }
     true
@@ -149,14 +155,19 @@ fn handle_if_let<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         && implements_trait(cx, match_ty, default_trait_id, &[])
         && let Some(binding_id) = get_some(cx, let_.pat)
         // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
-        && let ExprKind::Path(QPath::Resolved(_, path)) = if_block.peel_blocks().kind
+        && let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(if_block).kind
         && let Res::Local(local_id) = path.res
         && local_id == binding_id
         // We now check the `None` arm is calling a method equivalent to `Default::default`.
-        && let body_else = else_expr.peel_blocks()
+        && let body_else = peel_blocks(else_expr)
         && is_default_equivalent(cx, body_else)
         && let Some(if_let_expr_snippet) = snippet_opt(cx, let_.init.span)
     {
+        let applicability = if span_contains_comment(cx.sess().source_map(), expr.span) {
+            Applicability::MaybeIncorrect
+        } else {
+            Applicability::MachineApplicable
+        };
         span_lint_and_sugg(
             cx,
             MANUAL_UNWRAP_OR_DEFAULT,
@@ -164,14 +175,14 @@ fn handle_if_let<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
             "if let can be simplified with `.unwrap_or_default()`",
             "replace it with",
             format!("{if_let_expr_snippet}.unwrap_or_default()"),
-            Applicability::MachineApplicable,
+            applicability,
         );
     }
 }
 
 impl<'tcx> LateLintPass<'tcx> for ManualUnwrapOrDefault {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if expr.span.from_expansion() {
+        if expr.span.from_expansion() || in_constant(cx, expr.hir_id) {
             return;
         }
         if !handle_match(cx, expr) {
diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs
index c9eab7109eb..9db04b615be 100644
--- a/clippy_lints/src/map_unit_fn.rs
+++ b/clippy_lints/src/map_unit_fn.rs
@@ -221,13 +221,13 @@ fn lint_map_unit_fn(
             binding = let_binding_name(cx, var_arg)
         );
 
-        span_lint_and_then(cx, lint, expr.span, &msg, |diag| {
+        span_lint_and_then(cx, lint, expr.span, msg, |diag| {
             diag.span_suggestion(stmt.span, "try", suggestion, applicability);
         });
     } else if let Some((binding, closure_expr)) = unit_closure(cx, fn_arg) {
         let msg = suggestion_msg("closure", map_type);
 
-        span_lint_and_then(cx, lint, expr.span, &msg, |diag| {
+        span_lint_and_then(cx, lint, expr.span, msg, |diag| {
             if let Some(reduced_expr_span) = reduce_unit_expression(cx, closure_expr) {
                 let mut applicability = Applicability::MachineApplicable;
                 let suggestion = format!(
diff --git a/clippy_lints/src/match_result_ok.rs b/clippy_lints/src/match_result_ok.rs
index 62cedc8847b..2a5fc8b6609 100644
--- a/clippy_lints/src/match_result_ok.rs
+++ b/clippy_lints/src/match_result_ok.rs
@@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchResultOk {
                 MATCH_RESULT_OK,
                 expr.span.with_hi(let_expr.span.hi()),
                 "matching on `Some` with `ok()` is redundant",
-                &format!("consider matching on `Ok({some_expr_string})` and removing the call to `ok` instead"),
+                format!("consider matching on `Ok({some_expr_string})` and removing the call to `ok` instead"),
                 sugg,
                 applicability,
             );
diff --git a/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs
index 5fef5930fab..6746920edc5 100644
--- a/clippy_lints/src/matches/collapsible_match.rs
+++ b/clippy_lints/src/matches/collapsible_match.rs
@@ -97,7 +97,7 @@ fn check_arm<'tcx>(
         } else {
             String::new()
         };
-        span_lint_and_then(cx, COLLAPSIBLE_MATCH, inner_expr.span, &msg, |diag| {
+        span_lint_and_then(cx, COLLAPSIBLE_MATCH, inner_expr.span, msg, |diag| {
             let mut help_span = MultiSpan::from_spans(vec![binding_span, inner_then_pat.span]);
             help_span.push_span_label(binding_span, "replace this binding");
             help_span.push_span_label(inner_then_pat.span, format!("with this pattern{replace_msg}"));
diff --git a/clippy_lints/src/matches/manual_unwrap_or.rs b/clippy_lints/src/matches/manual_unwrap_or.rs
index 3e79cabd795..9edd6c95404 100644
--- a/clippy_lints/src/matches/manual_unwrap_or.rs
+++ b/clippy_lints/src/matches/manual_unwrap_or.rs
@@ -34,7 +34,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, scrutinee:
             cx,
             MANUAL_UNWRAP_OR,
             expr.span,
-            &format!("this pattern reimplements `{ty_name}::unwrap_or`"),
+            format!("this pattern reimplements `{ty_name}::unwrap_or`"),
             "replace with",
             format!("{suggestion}.unwrap_or({reindented_or_body})",),
             app,
diff --git a/clippy_lints/src/matches/match_as_ref.rs b/clippy_lints/src/matches/match_as_ref.rs
index 6b484ff2749..f5da8ec6187 100644
--- a/clippy_lints/src/matches/match_as_ref.rs
+++ b/clippy_lints/src/matches/match_as_ref.rs
@@ -43,7 +43,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
                 cx,
                 MATCH_AS_REF,
                 expr.span,
-                &format!("use `{suggestion}()` instead"),
+                format!("use `{suggestion}()` instead"),
                 "try",
                 format!(
                     "{}.{suggestion}(){cast}",
diff --git a/clippy_lints/src/matches/match_like_matches.rs b/clippy_lints/src/matches/match_like_matches.rs
index b062e81cefd..64cb7a06ce9 100644
--- a/clippy_lints/src/matches/match_like_matches.rs
+++ b/clippy_lints/src/matches/match_like_matches.rs
@@ -122,7 +122,7 @@ where
             cx,
             MATCH_LIKE_MATCHES_MACRO,
             expr.span,
-            &format!(
+            format!(
                 "{} expression looks like `matches!` macro",
                 if is_if_let { "if let .. else" } else { "match" }
             ),
diff --git a/clippy_lints/src/matches/match_str_case_mismatch.rs b/clippy_lints/src/matches/match_str_case_mismatch.rs
index bd38648bcf1..322e9c3ebe5 100644
--- a/clippy_lints/src/matches/match_str_case_mismatch.rs
+++ b/clippy_lints/src/matches/match_str_case_mismatch.rs
@@ -111,7 +111,7 @@ fn lint(cx: &LateContext<'_>, case_method: &CaseMethod, bad_case_span: Span, bad
         MATCH_STR_CASE_MISMATCH,
         bad_case_span,
         "this `match` arm has a differing case than its expression",
-        &format!("consider changing the case of this arm to respect `{method_str}`"),
+        format!("consider changing the case of this arm to respect `{method_str}`"),
         format!("\"{suggestion}\""),
         Applicability::MachineApplicable,
     );
diff --git a/clippy_lints/src/matches/match_wild_err_arm.rs b/clippy_lints/src/matches/match_wild_err_arm.rs
index 8a4c0ab9062..d1f637ec78c 100644
--- a/clippy_lints/src/matches/match_wild_err_arm.rs
+++ b/clippy_lints/src/matches/match_wild_err_arm.rs
@@ -43,7 +43,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'
                             cx,
                             MATCH_WILD_ERR_ARM,
                             arm.pat.span,
-                            &format!("`Err({ident_bind_name})` matches all errors"),
+                            format!("`Err({ident_bind_name})` matches all errors"),
                             None,
                             "match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable",
                         );
diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs
index 580d4a64296..fae2c4e4af9 100644
--- a/clippy_lints/src/matches/mod.rs
+++ b/clippy_lints/src/matches/mod.rs
@@ -25,14 +25,13 @@ mod try_err;
 mod wild_in_or_pats;
 
 use clippy_config::msrvs::{self, Msrv};
-use clippy_utils::source::{snippet_opt, walk_span_to_context};
-use clippy_utils::{higher, in_constant, is_direct_expn_of, is_span_match, tokenize_with_text};
+use clippy_utils::source::walk_span_to_context;
+use clippy_utils::{higher, in_constant, is_direct_expn_of, is_span_match, span_contains_cfg};
 use rustc_hir::{Arm, Expr, ExprKind, LetStmt, MatchSource, Pat};
-use rustc_lexer::TokenKind;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::impl_lint_pass;
-use rustc_span::{Span, SpanData, SyntaxContext};
+use rustc_span::{SpanData, SyntaxContext};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -1196,28 +1195,3 @@ fn contains_cfg_arm(cx: &LateContext<'_>, e: &Expr<'_>, scrutinee: &Expr<'_>, ar
         Err(()) => true,
     }
 }
-
-/// Checks if the given span contains a `#[cfg(..)]` attribute
-fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool {
-    let Some(snip) = snippet_opt(cx, s) else {
-        // Assume true. This would require either an invalid span, or one which crosses file boundaries.
-        return true;
-    };
-    let mut iter = tokenize_with_text(&snip);
-
-    // Search for the token sequence [`#`, `[`, `cfg`]
-    while iter.any(|(t, _)| matches!(t, TokenKind::Pound)) {
-        let mut iter = iter.by_ref().skip_while(|(t, _)| {
-            matches!(
-                t,
-                TokenKind::Whitespace | TokenKind::LineComment { .. } | TokenKind::BlockComment { .. }
-            )
-        });
-        if matches!(iter.next(), Some((TokenKind::OpenBracket, _)))
-            && matches!(iter.next(), Some((TokenKind::Ident, "cfg")))
-        {
-            return true;
-        }
-    }
-    false
-}
diff --git a/clippy_lints/src/matches/redundant_pattern_match.rs b/clippy_lints/src/matches/redundant_pattern_match.rs
index b5870d94d99..78973984fb0 100644
--- a/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/clippy_lints/src/matches/redundant_pattern_match.rs
@@ -72,7 +72,7 @@ fn find_match_true<'tcx>(
     pat: &'tcx Pat<'_>,
     scrutinee: &'tcx Expr<'_>,
     span: Span,
-    message: &str,
+    message: &'static str,
 ) {
     if let PatKind::Lit(lit) = pat.kind
         && let ExprKind::Lit(lit) = lit.kind
@@ -98,7 +98,7 @@ fn find_match_true<'tcx>(
             span,
             message,
             "consider using the condition directly",
-            sugg.to_string(),
+            sugg.into_string(),
             applicability,
         );
     }
@@ -227,7 +227,7 @@ fn find_method_sugg_for_if_let<'tcx>(
         cx,
         REDUNDANT_PATTERN_MATCHING,
         let_pat.span,
-        &format!("redundant pattern matching, consider using `{good_method}`"),
+        format!("redundant pattern matching, consider using `{good_method}`"),
         |diag| {
             // if/while let ... = ... { ... }
             // ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -304,7 +304,7 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
                 cx,
                 REDUNDANT_PATTERN_MATCHING,
                 span,
-                &format!("redundant pattern matching, consider using `{good_method}`"),
+                format!("redundant pattern matching, consider using `{good_method}`"),
                 "try",
                 sugg,
                 Applicability::MachineApplicable,
diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs
index 1cdb7921f81..578aa7989e7 100644
--- a/clippy_lints/src/mem_replace.rs
+++ b/clippy_lints/src/mem_replace.rs
@@ -193,7 +193,7 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<
             cx,
             MEM_REPLACE_WITH_DEFAULT,
             expr_span,
-            &format!(
+            format!(
                 "replacing a value of type `T` with `T::default()` is better expressed using `{top_crate}::mem::take`"
             ),
             |diag| {
diff --git a/clippy_lints/src/methods/bind_instead_of_map.rs b/clippy_lints/src/methods/bind_instead_of_map.rs
index 08bfa2e009b..fb440ce656e 100644
--- a/clippy_lints/src/methods/bind_instead_of_map.rs
+++ b/clippy_lints/src/methods/bind_instead_of_map.rs
@@ -84,7 +84,7 @@ pub(crate) trait BindInsteadOfMap {
                 "{option_snip}.{}({closure_args_snip} {some_inner_snip})",
                 Self::GOOD_METHOD_NAME
             );
-            span_lint_and_sugg(cx, BIND_INSTEAD_OF_MAP, expr.span, &msg, "try", note, app);
+            span_lint_and_sugg(cx, BIND_INSTEAD_OF_MAP, expr.span, msg, "try", note, app);
             true
         } else {
             false
@@ -114,7 +114,7 @@ pub(crate) trait BindInsteadOfMap {
         } else {
             return false;
         };
-        span_lint_and_then(cx, BIND_INSTEAD_OF_MAP, expr.span, &msg, |diag| {
+        span_lint_and_then(cx, BIND_INSTEAD_OF_MAP, expr.span, msg, |diag| {
             multispan_sugg_with_applicability(
                 diag,
                 "try",
@@ -157,7 +157,7 @@ pub(crate) trait BindInsteadOfMap {
                         cx,
                         BIND_INSTEAD_OF_MAP,
                         expr.span,
-                        &msg,
+                        msg,
                         "use the expression directly",
                         snippet(cx, recv.span, "..").into(),
                         Applicability::MachineApplicable,
diff --git a/clippy_lints/src/methods/bytes_nth.rs b/clippy_lints/src/methods/bytes_nth.rs
index baafb7030aa..a82abc79f2a 100644
--- a/clippy_lints/src/methods/bytes_nth.rs
+++ b/clippy_lints/src/methods/bytes_nth.rs
@@ -31,7 +31,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E
             cx,
             BYTES_NTH,
             parent.span,
-            &format!("called `.bytes().nth().unwrap()` on a `{caller_type}`"),
+            format!("called `.bytes().nth().unwrap()` on a `{caller_type}`"),
             "try",
             format!("{receiver}.as_bytes()[{n}]",),
             applicability,
@@ -41,7 +41,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E
             cx,
             BYTES_NTH,
             expr.span,
-            &format!("called `.bytes().nth()` on a `{caller_type}`"),
+            format!("called `.bytes().nth()` on a `{caller_type}`"),
             "try",
             format!("{receiver}.as_bytes().get({n}).copied()"),
             applicability,
diff --git a/clippy_lints/src/methods/chars_cmp.rs b/clippy_lints/src/methods/chars_cmp.rs
index c99cec067bf..4ae0aeea2d1 100644
--- a/clippy_lints/src/methods/chars_cmp.rs
+++ b/clippy_lints/src/methods/chars_cmp.rs
@@ -30,7 +30,7 @@ pub(super) fn check(
             cx,
             lint,
             info.expr.span,
-            &format!("you should use the `{suggest}` method"),
+            format!("you should use the `{suggest}` method"),
             "like this",
             format!(
                 "{}{}.{suggest}({})",
diff --git a/clippy_lints/src/methods/chars_cmp_with_unwrap.rs b/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
index d07e45434a7..9c45ec2e56c 100644
--- a/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
+++ b/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
@@ -23,7 +23,7 @@ pub(super) fn check(
             cx,
             lint,
             info.expr.span,
-            &format!("you should use the `{suggest}` method"),
+            format!("you should use the `{suggest}` method"),
             "like this",
             format!(
                 "{}{}.{suggest}('{}')",
diff --git a/clippy_lints/src/methods/clear_with_drain.rs b/clippy_lints/src/methods/clear_with_drain.rs
index 67ad58d5a8c..5389861245a 100644
--- a/clippy_lints/src/methods/clear_with_drain.rs
+++ b/clippy_lints/src/methods/clear_with_drain.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_range_full;
 use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
 use rustc_errors::Applicability;
-use rustc_hir as hir;
 use rustc_hir::{Expr, ExprKind, LangItem, QPath};
 use rustc_lint::LateContext;
 use rustc_span::symbol::sym;
@@ -28,7 +27,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span
     }
 }
 
-fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, types: &[rustc_span::Symbol]) -> bool {
+fn match_acceptable_type(cx: &LateContext<'_>, expr: &Expr<'_>, types: &[rustc_span::Symbol]) -> bool {
     let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs();
     types.iter().any(|&ty| is_type_diagnostic_item(cx, expr_ty, ty))
     // String type is a lang item but not a diagnostic item for now so we need a separate check
@@ -44,7 +43,7 @@ fn suggest(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span) {
             cx,
             CLEAR_WITH_DRAIN,
             span.with_hi(expr.span.hi()),
-            &format!("`drain` used to clear a `{ty_name}`"),
+            format!("`drain` used to clear a `{ty_name}`"),
             "try",
             "clear()".to_string(),
             Applicability::MachineApplicable,
diff --git a/clippy_lints/src/methods/clone_on_copy.rs b/clippy_lints/src/methods/clone_on_copy.rs
index 3e099004c47..4e6823e8220 100644
--- a/clippy_lints/src/methods/clone_on_copy.rs
+++ b/clippy_lints/src/methods/clone_on_copy.rs
@@ -94,7 +94,7 @@ pub(super) fn check(
             cx,
             CLONE_ON_COPY,
             expr.span,
-            &with_forced_trimmed_paths!(format!(
+            with_forced_trimmed_paths!(format!(
                 "using `clone` on type `{ty}` which implements the `Copy` trait"
             )),
             help,
diff --git a/clippy_lints/src/methods/drain_collect.rs b/clippy_lints/src/methods/drain_collect.rs
index 3a8ca37610a..56171a13452 100644
--- a/clippy_lints/src/methods/drain_collect.rs
+++ b/clippy_lints/src/methods/drain_collect.rs
@@ -70,7 +70,7 @@ pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], expr: &Expr<'_>, re
             cx,
             DRAIN_COLLECT,
             expr.span,
-            &format!("you seem to be trying to move all elements into a new `{typename}`"),
+            format!("you seem to be trying to move all elements into a new `{typename}`"),
             "consider using `mem::take`",
             sugg,
             Applicability::MachineApplicable,
diff --git a/clippy_lints/src/methods/expect_fun_call.rs b/clippy_lints/src/methods/expect_fun_call.rs
index 4d8fb217f7f..fba76852344 100644
--- a/clippy_lints/src/methods/expect_fun_call.rs
+++ b/clippy_lints/src/methods/expect_fun_call.rs
@@ -142,7 +142,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 EXPECT_FUN_CALL,
                 span_replace_word,
-                &format!("use of `{name}` followed by a function call"),
+                format!("use of `{name}` followed by a function call"),
                 "try",
                 format!("unwrap_or_else({closure_args} panic!({sugg}))"),
                 applicability,
@@ -160,7 +160,7 @@ pub(super) fn check<'tcx>(
         cx,
         EXPECT_FUN_CALL,
         span_replace_word,
-        &format!("use of `{name}` followed by a function call"),
+        format!("use of `{name}` followed by a function call"),
         "try",
         format!("unwrap_or_else({closure_args} {{ panic!(\"{{}}\", {arg_root_snippet}) }})"),
         applicability,
diff --git a/clippy_lints/src/methods/filetype_is_file.rs b/clippy_lints/src/methods/filetype_is_file.rs
index b05361ab212..eab536b88a5 100644
--- a/clippy_lints/src/methods/filetype_is_file.rs
+++ b/clippy_lints/src/methods/filetype_is_file.rs
@@ -34,5 +34,5 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
     }
     let lint_msg = format!("`{lint_unary}FileType::is_file()` only {verb} regular files");
     let help_msg = format!("use `{help_unary}FileType::is_dir()` instead");
-    span_lint_and_help(cx, FILETYPE_IS_FILE, span, &lint_msg, None, &help_msg);
+    span_lint_and_help(cx, FILETYPE_IS_FILE, span, lint_msg, None, help_msg);
 }
diff --git a/clippy_lints/src/methods/filter_map.rs b/clippy_lints/src/methods/filter_map.rs
index 9b656531957..581e3b308c3 100644
--- a/clippy_lints/src/methods/filter_map.rs
+++ b/clippy_lints/src/methods/filter_map.rs
@@ -16,20 +16,18 @@ use std::borrow::Cow;
 
 use super::{MANUAL_FILTER_MAP, MANUAL_FIND_MAP, OPTION_FILTER_MAP, RESULT_FILTER_MAP};
 
-fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) -> bool {
+fn is_method(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol) -> bool {
     match &expr.kind {
-        hir::ExprKind::Path(QPath::TypeRelative(_, mname)) => mname.ident.name == method_name,
-        hir::ExprKind::Path(QPath::Resolved(_, segments)) => {
-            segments.segments.last().unwrap().ident.name == method_name
-        },
-        hir::ExprKind::MethodCall(segment, _, _, _) => segment.ident.name == method_name,
-        hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
+        ExprKind::Path(QPath::TypeRelative(_, mname)) => mname.ident.name == method_name,
+        ExprKind::Path(QPath::Resolved(_, segments)) => segments.segments.last().unwrap().ident.name == method_name,
+        ExprKind::MethodCall(segment, _, _, _) => segment.ident.name == method_name,
+        ExprKind::Closure(&Closure { body, .. }) => {
             let body = cx.tcx.hir().body(body);
             let closure_expr = peel_blocks(body.value);
             match closure_expr.kind {
-                hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, receiver, ..) => {
+                ExprKind::MethodCall(PathSegment { ident, .. }, receiver, ..) => {
                     if ident.name == method_name
-                        && let hir::ExprKind::Path(path) = &receiver.kind
+                        && let ExprKind::Path(path) = &receiver.kind
                         && let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id)
                         && !body.params.is_empty()
                     {
@@ -45,10 +43,10 @@ fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) ->
     }
 }
 
-fn is_option_filter_map(cx: &LateContext<'_>, filter_arg: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) -> bool {
+fn is_option_filter_map(cx: &LateContext<'_>, filter_arg: &Expr<'_>, map_arg: &Expr<'_>) -> bool {
     is_method(cx, map_arg, sym::unwrap) && is_method(cx, filter_arg, sym!(is_some))
 }
-fn is_ok_filter_map(cx: &LateContext<'_>, filter_arg: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) -> bool {
+fn is_ok_filter_map(cx: &LateContext<'_>, filter_arg: &Expr<'_>, map_arg: &Expr<'_>) -> bool {
     is_method(cx, map_arg, sym::unwrap) && is_method(cx, filter_arg, sym!(is_ok))
 }
 
@@ -267,10 +265,10 @@ impl<'tcx> OffendingFilterExpr<'tcx> {
 /// is `filter(|x| x.is_some()).map(|x| x.unwrap())`
 fn is_filter_some_map_unwrap(
     cx: &LateContext<'_>,
-    expr: &hir::Expr<'_>,
-    filter_recv: &hir::Expr<'_>,
-    filter_arg: &hir::Expr<'_>,
-    map_arg: &hir::Expr<'_>,
+    expr: &Expr<'_>,
+    filter_recv: &Expr<'_>,
+    filter_arg: &Expr<'_>,
+    map_arg: &Expr<'_>,
 ) -> bool {
     let iterator = is_trait_method(cx, expr, sym::Iterator);
     let option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(filter_recv), sym::Option);
@@ -279,12 +277,7 @@ fn is_filter_some_map_unwrap(
 }
 
 /// is `filter(|x| x.is_ok()).map(|x| x.unwrap())`
-fn is_filter_ok_map_unwrap(
-    cx: &LateContext<'_>,
-    expr: &hir::Expr<'_>,
-    filter_arg: &hir::Expr<'_>,
-    map_arg: &hir::Expr<'_>,
-) -> bool {
+fn is_filter_ok_map_unwrap(cx: &LateContext<'_>, expr: &Expr<'_>, filter_arg: &Expr<'_>, map_arg: &Expr<'_>) -> bool {
     // result has no filter, so we only check for iterators
     let iterator = is_trait_method(cx, expr, sym::Iterator);
     iterator && is_ok_filter_map(cx, filter_arg, map_arg)
@@ -294,12 +287,12 @@ fn is_filter_ok_map_unwrap(
 #[allow(clippy::too_many_arguments)]
 pub(super) fn check(
     cx: &LateContext<'_>,
-    expr: &hir::Expr<'_>,
-    filter_recv: &hir::Expr<'_>,
-    filter_arg: &hir::Expr<'_>,
+    expr: &Expr<'_>,
+    filter_recv: &Expr<'_>,
+    filter_arg: &Expr<'_>,
     filter_span: Span,
-    map_recv: &hir::Expr<'_>,
-    map_arg: &hir::Expr<'_>,
+    map_recv: &Expr<'_>,
+    map_arg: &Expr<'_>,
     map_span: Span,
     is_find: bool,
 ) {
@@ -393,7 +386,7 @@ pub(super) fn check(
                 )
             },
         };
-        span_lint_and_then(cx, lint, span, &msg, |diag| {
+        span_lint_and_then(cx, lint, span, msg, |diag| {
             diag.span_suggestion(span, "try", sugg, applicability);
 
             if let Some((note, span)) = note_and_span {
@@ -405,9 +398,9 @@ pub(super) fn check(
 
 fn is_find_or_filter<'a>(
     cx: &LateContext<'a>,
-    map_recv: &hir::Expr<'_>,
-    filter_arg: &hir::Expr<'_>,
-    map_arg: &hir::Expr<'_>,
+    map_recv: &Expr<'_>,
+    filter_arg: &Expr<'_>,
+    map_arg: &Expr<'_>,
 ) -> Option<(Ident, CheckResult<'a>)> {
     if is_trait_method(cx, map_recv, sym::Iterator)
         // filter(|x| ...is_some())...
diff --git a/clippy_lints/src/methods/filter_map_identity.rs b/clippy_lints/src/methods/filter_map_identity.rs
index 8291c373f37..999df875c75 100644
--- a/clippy_lints/src/methods/filter_map_identity.rs
+++ b/clippy_lints/src/methods/filter_map_identity.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::{is_expr_untyped_identity_function, is_trait_method};
+use clippy_utils::{is_expr_identity_function, is_expr_untyped_identity_function, is_trait_method};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -7,8 +7,20 @@ use rustc_span::{sym, Span};
 
 use super::FILTER_MAP_IDENTITY;
 
+fn is_identity(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Applicability> {
+    if is_expr_untyped_identity_function(cx, expr) {
+        return Some(Applicability::MachineApplicable);
+    }
+    if is_expr_identity_function(cx, expr) {
+        return Some(Applicability::Unspecified);
+    }
+    None
+}
+
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, filter_map_arg: &hir::Expr<'_>, filter_map_span: Span) {
-    if is_trait_method(cx, expr, sym::Iterator) && is_expr_untyped_identity_function(cx, filter_map_arg) {
+    if is_trait_method(cx, expr, sym::Iterator)
+        && let Some(applicability) = is_identity(cx, filter_map_arg)
+    {
         span_lint_and_sugg(
             cx,
             FILTER_MAP_IDENTITY,
@@ -16,7 +28,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, filter_map_arg:
             "use of `filter_map` with an identity function",
             "try",
             "flatten()".to_string(),
-            Applicability::MachineApplicable,
+            applicability,
         );
     }
 }
diff --git a/clippy_lints/src/methods/get_first.rs b/clippy_lints/src/methods/get_first.rs
index 55fcf372894..f4465e654c2 100644
--- a/clippy_lints/src/methods/get_first.rs
+++ b/clippy_lints/src/methods/get_first.rs
@@ -32,7 +32,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 GET_FIRST,
                 expr.span,
-                &format!("accessing first element with `{slice_name}.get(0)`"),
+                format!("accessing first element with `{slice_name}.get(0)`"),
                 "try",
                 format!("{slice_name}.first()"),
                 app,
@@ -44,7 +44,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 GET_FIRST,
                 expr.span,
-                &format!("accessing first element with `{slice_name}.get(0)`"),
+                format!("accessing first element with `{slice_name}.get(0)`"),
                 "try",
                 format!("{slice_name}.front()"),
                 app,
diff --git a/clippy_lints/src/methods/get_last_with_len.rs b/clippy_lints/src/methods/get_last_with_len.rs
index 3bdc154df04..62037651134 100644
--- a/clippy_lints/src/methods/get_last_with_len.rs
+++ b/clippy_lints/src/methods/get_last_with_len.rs
@@ -44,7 +44,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg:
             cx,
             GET_LAST_WITH_LEN,
             expr.span,
-            &format!("accessing last element with `{recv_snippet}.get({recv_snippet}.len() - 1)`"),
+            format!("accessing last element with `{recv_snippet}.get({recv_snippet}.len() - 1)`"),
             "try",
             format!("{recv_snippet}.{method}()"),
             applicability,
diff --git a/clippy_lints/src/methods/get_unwrap.rs b/clippy_lints/src/methods/get_unwrap.rs
index afdcb3b6549..455274a4428 100644
--- a/clippy_lints/src/methods/get_unwrap.rs
+++ b/clippy_lints/src/methods/get_unwrap.rs
@@ -70,7 +70,7 @@ pub(super) fn check<'tcx>(
         cx,
         GET_UNWRAP,
         span,
-        &format!("called `.get{mut_str}().unwrap()` on a {caller_type}. Using `[]` is more clear and more concise"),
+        format!("called `.get{mut_str}().unwrap()` on a {caller_type}. Using `[]` is more clear and more concise"),
         "try",
         format!(
             "{borrow_str}{}[{get_args_str}]",
diff --git a/clippy_lints/src/methods/implicit_clone.rs b/clippy_lints/src/methods/implicit_clone.rs
index 78a553eb8c0..c510cd915d0 100644
--- a/clippy_lints/src/methods/implicit_clone.rs
+++ b/clippy_lints/src/methods/implicit_clone.rs
@@ -27,7 +27,7 @@ pub fn check(cx: &LateContext<'_>, method_name: &str, expr: &hir::Expr<'_>, recv
             cx,
             IMPLICIT_CLONE,
             expr.span,
-            &format!("implicitly cloning a `{ty_name}` by calling `{method_name}` on its dereferenced type"),
+            format!("implicitly cloning a `{ty_name}` by calling `{method_name}` on its dereferenced type"),
             "consider using",
             if ref_count > 1 {
                 format!("({}{recv_snip}).clone()", "*".repeat(ref_count - 1))
diff --git a/clippy_lints/src/methods/inefficient_to_string.rs b/clippy_lints/src/methods/inefficient_to_string.rs
index efc3ddd20b4..230a8eb2ec4 100644
--- a/clippy_lints/src/methods/inefficient_to_string.rs
+++ b/clippy_lints/src/methods/inefficient_to_string.rs
@@ -32,7 +32,7 @@ pub fn check(
             cx,
             INEFFICIENT_TO_STRING,
             expr.span,
-            &format!("calling `to_string` on `{arg_ty}`"),
+            format!("calling `to_string` on `{arg_ty}`"),
             |diag| {
                 diag.help(format!(
                     "`{self_ty}` implements `ToString` through a slower blanket impl, but `{deref_self_ty}` has a fast specialization of `ToString`"
diff --git a/clippy_lints/src/methods/into_iter_on_ref.rs b/clippy_lints/src/methods/into_iter_on_ref.rs
index 80160d17c82..bbc7ce8d78a 100644
--- a/clippy_lints/src/methods/into_iter_on_ref.rs
+++ b/clippy_lints/src/methods/into_iter_on_ref.rs
@@ -27,7 +27,7 @@ pub(super) fn check(
             cx,
             INTO_ITER_ON_REF,
             method_span,
-            &format!("this `.into_iter()` call is equivalent to `.{method_name}()` and will not consume the `{kind}`",),
+            format!("this `.into_iter()` call is equivalent to `.{method_name}()` and will not consume the `{kind}`",),
             "call directly",
             method_name.to_string(),
             Applicability::MachineApplicable,
diff --git a/clippy_lints/src/methods/is_digit_ascii_radix.rs b/clippy_lints/src/methods/is_digit_ascii_radix.rs
index e963950960a..210e4ae0a7b 100644
--- a/clippy_lints/src/methods/is_digit_ascii_radix.rs
+++ b/clippy_lints/src/methods/is_digit_ascii_radix.rs
@@ -36,7 +36,7 @@ pub(super) fn check<'tcx>(
             cx,
             IS_DIGIT_ASCII_RADIX,
             expr.span,
-            &format!("use of `char::is_digit` with literal radix of {num}"),
+            format!("use of `char::is_digit` with literal radix of {num}"),
             "try",
             format!(
                 "{}.{replacement}()",
diff --git a/clippy_lints/src/methods/is_empty.rs b/clippy_lints/src/methods/is_empty.rs
index 7fe66062251..d921b7ea14f 100644
--- a/clippy_lints/src/methods/is_empty.rs
+++ b/clippy_lints/src/methods/is_empty.rs
@@ -23,7 +23,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_
             cx,
             CONST_IS_EMPTY,
             expr.span,
-            &format!("this expression always evaluates to {init_is_empty:?}"),
+            format!("this expression always evaluates to {init_is_empty:?}"),
         );
     }
 }
diff --git a/clippy_lints/src/methods/iter_cloned_collect.rs b/clippy_lints/src/methods/iter_cloned_collect.rs
index dd741cd43f9..49de83885a1 100644
--- a/clippy_lints/src/methods/iter_cloned_collect.rs
+++ b/clippy_lints/src/methods/iter_cloned_collect.rs
@@ -17,7 +17,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, method_name: &str, expr: &hir:
             cx,
             ITER_CLONED_COLLECT,
             to_replace,
-            &format!(
+            format!(
                 "called `iter().{method_name}().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \
             more readable"
             ),
diff --git a/clippy_lints/src/methods/iter_count.rs b/clippy_lints/src/methods/iter_count.rs
index bcddc7c786a..209cf2fcc0a 100644
--- a/clippy_lints/src/methods/iter_count.rs
+++ b/clippy_lints/src/methods/iter_count.rs
@@ -37,7 +37,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E
         cx,
         ITER_COUNT,
         expr.span,
-        &format!("called `.{iter_method}().count()` on a `{caller_type}`"),
+        format!("called `.{iter_method}().count()` on a `{caller_type}`"),
         "try",
         format!(
             "{}.len()",
diff --git a/clippy_lints/src/methods/iter_filter.rs b/clippy_lints/src/methods/iter_filter.rs
index 9f84321ced4..12647ea1ffc 100644
--- a/clippy_lints/src/methods/iter_filter.rs
+++ b/clippy_lints/src/methods/iter_filter.rs
@@ -55,7 +55,7 @@ fn is_method(
         }
     }
     match expr.kind {
-        hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, recv, ..) => {
+        ExprKind::MethodCall(hir::PathSegment { ident, .. }, recv, ..) => {
             // compare the identifier of the receiver to the parameter
             // we are in a filter => closure has a single parameter and a single, non-block
             // expression, this means that the parameter shadows all outside variables with
@@ -73,7 +73,7 @@ fn is_method(
         // This is used to check for complete paths via `|a| std::option::Option::is_some(a)`
         // this then unwraps to a path with `QPath::TypeRelative`
         // we pass the params as they've been passed to the current call through the closure
-        hir::ExprKind::Call(expr, [param]) => {
+        ExprKind::Call(expr, [param]) => {
             // this will hit the `QPath::TypeRelative` case and check that the method name is correct
             if is_method(cx, expr, type_symbol, method_name, params)
                 // we then check that this is indeed passing the parameter of the closure
@@ -85,7 +85,7 @@ fn is_method(
             }
             false
         },
-        hir::ExprKind::Path(QPath::TypeRelative(ty, mname)) => {
+        ExprKind::Path(QPath::TypeRelative(ty, mname)) => {
             let ty = cx.typeck_results().node_type(ty.hir_id);
             if let Some(did) = cx.tcx.get_diagnostic_item(type_symbol)
                 && ty.ty_adt_def() == cx.tcx.type_of(did).skip_binder().ty_adt_def()
@@ -94,7 +94,7 @@ fn is_method(
             }
             false
         },
-        hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
+        ExprKind::Closure(&hir::Closure { body, .. }) => {
             let body = cx.tcx.hir().body(body);
             let closure_expr = peel_blocks(body.value);
             let params = body.params.iter().map(|param| param.pat).collect::<Vec<_>>();
@@ -107,8 +107,8 @@ fn is_method(
 fn parent_is_map(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
     if let Some(expr) = get_parent_expr(cx, expr)
         && is_trait_method(cx, expr, sym::Iterator)
-        && let hir::ExprKind::MethodCall(path, _, _, _) = expr.kind
-        && path.ident.name == rustc_span::sym::map
+        && let ExprKind::MethodCall(path, _, _, _) = expr.kind
+        && path.ident.name == sym::map
     {
         return true;
     }
@@ -148,7 +148,7 @@ fn expression_type(
     {
         return None;
     }
-    if let hir::ExprKind::MethodCall(_, receiver, _, _) = expr.kind
+    if let ExprKind::MethodCall(_, receiver, _, _) = expr.kind
         && let receiver_ty = cx.typeck_results().expr_ty(receiver)
         && let Some(iter_item_ty) = get_iterator_item_ty(cx, receiver_ty)
     {
diff --git a/clippy_lints/src/methods/iter_kv_map.rs b/clippy_lints/src/methods/iter_kv_map.rs
index 1431a5db2d9..b9fec0c4f80 100644
--- a/clippy_lints/src/methods/iter_kv_map.rs
+++ b/clippy_lints/src/methods/iter_kv_map.rs
@@ -54,7 +54,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 ITER_KV_MAP,
                 expr.span,
-                &format!("iterating on a map's {replacement_kind}s"),
+                format!("iterating on a map's {replacement_kind}s"),
                 "try",
                 format!("{recv_snippet}.{into_prefix}{replacement_kind}s()"),
                 applicability,
@@ -64,7 +64,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 ITER_KV_MAP,
                 expr.span,
-                &format!("iterating on a map's {replacement_kind}s"),
+                format!("iterating on a map's {replacement_kind}s"),
                 "try",
                 format!(
                     "{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{}{bound_ident}| {})",
diff --git a/clippy_lints/src/methods/iter_nth.rs b/clippy_lints/src/methods/iter_nth.rs
index 5b0b70b4b96..e31fa2f777d 100644
--- a/clippy_lints/src/methods/iter_nth.rs
+++ b/clippy_lints/src/methods/iter_nth.rs
@@ -28,7 +28,7 @@ pub(super) fn check<'tcx>(
         cx,
         ITER_NTH,
         expr.span,
-        &format!("called `.{iter_method}().nth()` on a {caller_type}"),
+        format!("called `.{iter_method}().nth()` on a {caller_type}"),
         |diag| {
             let get_method = if iter_method == "iter_mut" { "get_mut" } else { "get" };
             diag.span_suggestion_verbose(
diff --git a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
index 19b7e97339d..6c9bdcff826 100644
--- a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
+++ b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
@@ -69,7 +69,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: &str, re
             cx,
             ITER_ON_SINGLE_ITEMS,
             expr.span,
-            &format!("`{method_name}` call on a collection with only one item"),
+            format!("`{method_name}` call on a collection with only one item"),
             "try",
             sugg,
             Applicability::MaybeIncorrect,
@@ -79,7 +79,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: &str, re
             cx,
             ITER_ON_EMPTY_COLLECTIONS,
             expr.span,
-            &format!("`{method_name}` call on an empty collection"),
+            format!("`{method_name}` call on an empty collection"),
             "try",
             format!("{top_crate}::iter::empty()"),
             Applicability::MaybeIncorrect,
diff --git a/clippy_lints/src/methods/iter_overeager_cloned.rs b/clippy_lints/src/methods/iter_overeager_cloned.rs
index b2fe129cd95..4729481320e 100644
--- a/clippy_lints/src/methods/iter_overeager_cloned.rs
+++ b/clippy_lints/src/methods/iter_overeager_cloned.rs
@@ -60,7 +60,7 @@ pub(super) fn check<'tcx>(
         }
 
         if let Op::NeedlessMove(expr) = op {
-            let rustc_hir::ExprKind::Closure(closure) = expr.kind else {
+            let ExprKind::Closure(closure) = expr.kind else {
                 return;
             };
             let body @ Body { params: [p], .. } = cx.tcx.hir().body(closure.body) else {
diff --git a/clippy_lints/src/methods/iter_with_drain.rs b/clippy_lints/src/methods/iter_with_drain.rs
index 2ab721ace84..1378a07cbc4 100644
--- a/clippy_lints/src/methods/iter_with_drain.rs
+++ b/clippy_lints/src/methods/iter_with_drain.rs
@@ -20,7 +20,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span
             cx,
             ITER_WITH_DRAIN,
             span.with_hi(expr.span.hi()),
-            &format!("`drain(..)` used on a `{ty_name}`"),
+            format!("`drain(..)` used on a `{ty_name}`"),
             "try",
             "into_iter()".to_string(),
             Applicability::MaybeIncorrect,
diff --git a/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/clippy_lints/src/methods/manual_saturating_arithmetic.rs
index bf437db7e72..9e3b313156e 100644
--- a/clippy_lints/src/methods/manual_saturating_arithmetic.rs
+++ b/clippy_lints/src/methods/manual_saturating_arithmetic.rs
@@ -50,7 +50,7 @@ pub fn check(
         super::MANUAL_SATURATING_ARITHMETIC,
         expr.span,
         "manual saturating arithmetic",
-        &format!("consider using `saturating_{arith}`"),
+        format!("consider using `saturating_{arith}`"),
         format!(
             "{}.saturating_{arith}({})",
             snippet_with_applicability(cx, arith_lhs.span, "..", &mut applicability),
diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs
index c3c7a3a0033..0901268e9bd 100644
--- a/clippy_lints/src/methods/map_clone.rs
+++ b/clippy_lints/src/methods/map_clone.rs
@@ -1,7 +1,7 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::ty::{is_copy, is_type_diagnostic_item};
+use clippy_utils::ty::{is_copy, is_type_diagnostic_item, should_call_clone_as_function};
 use clippy_utils::{is_diag_trait_item, match_def_path, paths, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -50,7 +50,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_
                 let closure_body = cx.tcx.hir().body(body);
                 let closure_expr = peel_blocks(closure_body.value);
                 match closure_body.params[0].pat.kind {
-                    hir::PatKind::Ref(inner, hir::Mutability::Not) => {
+                    hir::PatKind::Ref(inner, Mutability::Not) => {
                         if let hir::PatKind::Binding(hir::BindingAnnotation::NONE, .., name, None) = inner.kind {
                             if ident_eq(name, closure_expr) {
                                 lint_explicit_closure(cx, e.span, recv.span, true, msrv);
@@ -124,6 +124,7 @@ fn handle_path(
             && let ty::Ref(_, ty, Mutability::Not) = ty.kind()
             && let ty::FnDef(_, lst) = cx.typeck_results().expr_ty(arg).kind()
             && lst.iter().all(|l| l.as_type() == Some(*ty))
+            && !should_call_clone_as_function(cx, *ty)
         {
             lint_path(cx, e.span, recv.span, is_copy(cx, ty.peel_refs()));
         }
@@ -160,7 +161,7 @@ fn lint_path(cx: &LateContext<'_>, replace: Span, root: Span, is_copy: bool) {
         MAP_CLONE,
         replace,
         "you are explicitly cloning with `.map()`",
-        &format!("consider calling the dedicated `{replacement}` method"),
+        format!("consider calling the dedicated `{replacement}` method"),
         format!(
             "{}.{replacement}()",
             snippet_with_applicability(cx, root, "..", &mut applicability),
@@ -183,7 +184,7 @@ fn lint_explicit_closure(cx: &LateContext<'_>, replace: Span, root: Span, is_cop
         MAP_CLONE,
         replace,
         message,
-        &format!("consider calling the dedicated `{sugg_method}` method"),
+        format!("consider calling the dedicated `{sugg_method}` method"),
         format!(
             "{}.{sugg_method}()",
             snippet_with_applicability(cx, root, "..", &mut applicability),
diff --git a/clippy_lints/src/methods/map_flatten.rs b/clippy_lints/src/methods/map_flatten.rs
index 26ef0d10fed..def8be2ef73 100644
--- a/clippy_lints/src/methods/map_flatten.rs
+++ b/clippy_lints/src/methods/map_flatten.rs
@@ -21,8 +21,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, map_
             cx,
             MAP_FLATTEN,
             expr.span.with_lo(map_span.lo()),
-            &format!("called `map(..).flatten()` on `{caller_ty_name}`"),
-            &format!("try replacing `map` with `{method_to_use}` and remove the `.flatten()`"),
+            format!("called `map(..).flatten()` on `{caller_ty_name}`"),
+            format!("try replacing `map` with `{method_to_use}` and remove the `.flatten()`"),
             format!("{method_to_use}({closure_snippet})"),
             applicability,
         );
diff --git a/clippy_lints/src/methods/map_identity.rs b/clippy_lints/src/methods/map_identity.rs
index 6da9a87f5ee..5dd7b1b02ad 100644
--- a/clippy_lints/src/methods/map_identity.rs
+++ b/clippy_lints/src/methods/map_identity.rs
@@ -29,7 +29,7 @@ pub(super) fn check(
             MAP_IDENTITY,
             sugg_span,
             "unnecessary map of the identity function",
-            &format!("remove the call to `{name}`"),
+            format!("remove the call to `{name}`"),
             String::new(),
             Applicability::MachineApplicable,
         );
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index b6c474212cd..2fb317c8c68 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -231,8 +231,12 @@ declare_clippy_lint! {
     /// used instead.
     ///
     /// ### Why is this bad?
-    /// When applicable, `filter_map()` is more clear since it shows that
-    /// `Option` is used to produce 0 or 1 items.
+    /// `filter_map()` is known to always produce 0 or 1 output items per input item,
+    /// rather than however many the inner iterator type produces.
+    /// Therefore, it maintains the upper bound in `Iterator::size_hint()`,
+    /// and communicates to the reader that the input items are not being expanded into
+    /// multiple output items without their having to notice that the mapping function
+    /// returns an `Option`.
     ///
     /// ### Example
     /// ```no_run
@@ -2998,13 +3002,22 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Looks for calls to `<Box<dyn Any> as Any>::type_id`.
+    /// Looks for calls to `.type_id()` on a `Box<dyn _>`.
     ///
     /// ### Why is this bad?
-    /// This most certainly does not do what the user expects and is very easy to miss.
-    /// Calling `type_id` on a `Box<dyn Any>` calls `type_id` on the `Box<..>` itself,
-    /// so this will return the `TypeId` of the `Box<dyn Any>` type (not the type id
-    /// of the value referenced by the box!).
+    /// This almost certainly does not do what the user expects and can lead to subtle bugs.
+    /// Calling `.type_id()` on a `Box<dyn Trait>` returns a fixed `TypeId` of the `Box` itself,
+    /// rather than returning the `TypeId` of the underlying type behind the trait object.
+    ///
+    /// For `Box<dyn Any>` specifically (and trait objects that have `Any` as its supertrait),
+    /// this lint will provide a suggestion, which is to dereference the receiver explicitly
+    /// to go from `Box<dyn Any>` to `dyn Any`.
+    /// This makes sure that `.type_id()` resolves to a dynamic call on the trait object
+    /// and not on the box.
+    ///
+    /// If the fixed `TypeId` of the `Box` is the intended behavior, it's better to be explicit about it
+    /// and write `TypeId::of::<Box<dyn Trait>>()`:
+    /// this makes it clear that a fixed `TypeId` is returned and not the `TypeId` of the implementor.
     ///
     /// ### Example
     /// ```rust,ignore
@@ -3024,7 +3037,7 @@ declare_clippy_lint! {
     #[clippy::version = "1.73.0"]
     pub TYPE_ID_ON_BOX,
     suspicious,
-    "calling `.type_id()` on `Box<dyn Any>`"
+    "calling `.type_id()` on a boxed trait object"
 }
 
 declare_clippy_lint! {
@@ -4236,8 +4249,8 @@ impl_lint_pass!(Methods => [
 
 /// Extracts a method call name, args, and `Span` of the method name.
 pub fn method_call<'tcx>(
-    recv: &'tcx hir::Expr<'tcx>,
-) -> Option<(&'tcx str, &'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>], Span, Span)> {
+    recv: &'tcx Expr<'tcx>,
+) -> Option<(&'tcx str, &'tcx Expr<'tcx>, &'tcx [Expr<'tcx>], Span, Span)> {
     if let ExprKind::MethodCall(path, receiver, args, call_span) = recv.kind {
         if !args.iter().any(|e| e.span.from_expansion()) && !receiver.span.from_expansion() {
             let name = path.ident.name.as_str();
@@ -4248,7 +4261,7 @@ pub fn method_call<'tcx>(
 }
 
 impl<'tcx> LateLintPass<'tcx> for Methods {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if expr.span.from_expansion() {
             return;
         }
@@ -4256,12 +4269,12 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
         self.check_methods(cx, expr);
 
         match expr.kind {
-            hir::ExprKind::Call(func, args) => {
+            ExprKind::Call(func, args) => {
                 from_iter_instead_of_collect::check(cx, expr, args, func);
                 unnecessary_fallible_conversions::check_function(cx, expr, func);
                 manual_c_str_literals::check(cx, expr, func, args, &self.msrv);
             },
-            hir::ExprKind::MethodCall(method_call, receiver, args, _) => {
+            ExprKind::MethodCall(method_call, receiver, args, _) => {
                 let method_span = method_call.ident.span;
                 or_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), receiver, args);
                 expect_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), receiver, args);
@@ -4273,7 +4286,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                 single_char_pattern::check(cx, expr, method_call.ident.name, receiver, args);
                 unnecessary_to_owned::check(cx, expr, method_call.ident.name, receiver, args, &self.msrv);
             },
-            hir::ExprKind::Binary(op, lhs, rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => {
+            ExprKind::Binary(op, lhs, rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => {
                 let mut info = BinaryExprInfo {
                     expr,
                     chain: lhs,
@@ -4320,12 +4333,12 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                             cx,
                             SHOULD_IMPLEMENT_TRAIT,
                             impl_item.span,
-                            &format!(
+                            format!(
                                 "method `{}` can be confused for the standard trait method `{}::{}`",
                                 method_config.method_name, method_config.trait_name, method_config.method_name
                             ),
                             None,
-                            &format!(
+                            format!(
                                 "consider implementing the trait `{}` or choosing a less ambiguous method name",
                                 method_config.trait_name
                             ),
@@ -4995,9 +5008,9 @@ fn check_is_some_is_none(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>,
 /// Used for `lint_binary_expr_with_method_call`.
 #[derive(Copy, Clone)]
 struct BinaryExprInfo<'a> {
-    expr: &'a hir::Expr<'a>,
-    chain: &'a hir::Expr<'a>,
-    other: &'a hir::Expr<'a>,
+    expr: &'a Expr<'a>,
+    chain: &'a Expr<'a>,
+    other: &'a Expr<'a>,
     eq: bool,
 }
 
diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs
index 9e2fd92255e..662e7746496 100644
--- a/clippy_lints/src/methods/needless_collect.rs
+++ b/clippy_lints/src/methods/needless_collect.rs
@@ -107,7 +107,7 @@ pub(super) fn check<'tcx>(
                 span.push_span_label(iter_call.span, "the iterator could be used here instead");
                 span_lint_hir_and_then(
                     cx,
-                    super::NEEDLESS_COLLECT,
+                    NEEDLESS_COLLECT,
                     collect_expr.hir_id,
                     span,
                     NEEDLESS_COLLECT_MSG,
diff --git a/clippy_lints/src/methods/open_options.rs b/clippy_lints/src/methods/open_options.rs
index 77484ab91a9..d425b505a76 100644
--- a/clippy_lints/src/methods/open_options.rs
+++ b/clippy_lints/src/methods/open_options.rs
@@ -151,7 +151,7 @@ fn check_open_options(cx: &LateContext<'_>, settings: &[(OpenOption, Argument, S
                 cx,
                 NONSENSICAL_OPEN_OPTIONS,
                 prev_span,
-                &format!("the method `{}` is called more than once", &option),
+                format!("the method `{}` is called more than once", &option),
             );
         }
     }
diff --git a/clippy_lints/src/methods/option_as_ref_cloned.rs b/clippy_lints/src/methods/option_as_ref_cloned.rs
index d7fec360fa2..ba167f9d9c2 100644
--- a/clippy_lints/src/methods/option_as_ref_cloned.rs
+++ b/clippy_lints/src/methods/option_as_ref_cloned.rs
@@ -15,7 +15,7 @@ pub(super) fn check(cx: &LateContext<'_>, cloned_recv: &Expr<'_>, cloned_ident_s
             cx,
             OPTION_AS_REF_CLONED,
             as_ref_ident_span.to(cloned_ident_span),
-            &format!("cloning an `Option<_>` using `.{method}().cloned()`"),
+            format!("cloning an `Option<_>` using `.{method}().cloned()`"),
             "this can be written more concisely by cloning the `Option<_>` directly",
             "clone".into(),
             Applicability::MachineApplicable,
diff --git a/clippy_lints/src/methods/option_as_ref_deref.rs b/clippy_lints/src/methods/option_as_ref_deref.rs
index 88e2af15658..cb57689b0c4 100644
--- a/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -104,8 +104,8 @@ pub(super) fn check(
             cx,
             OPTION_AS_REF_DEREF,
             expr.span,
-            &msg,
-            &suggestion,
+            msg,
+            suggestion,
             hint,
             Applicability::MachineApplicable,
         );
diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs
index ab36f854fcb..efec9dd716d 100644
--- a/clippy_lints/src/methods/option_map_unwrap_or.rs
+++ b/clippy_lints/src/methods/option_map_unwrap_or.rs
@@ -97,7 +97,7 @@ pub(super) fn check<'tcx>(
         } else {
             "map_or(<a>, <f>)"
         };
-        let msg = &format!("called `map(<f>).unwrap_or({arg})` on an `Option` value");
+        let msg = format!("called `map(<f>).unwrap_or({arg})` on an `Option` value");
 
         span_lint_and_then(cx, MAP_UNWRAP_OR, expr.span, msg, |diag| {
             let map_arg_span = map_arg.span;
diff --git a/clippy_lints/src/methods/or_fun_call.rs b/clippy_lints/src/methods/or_fun_call.rs
index 0602eeaa704..583e04fb4b1 100644
--- a/clippy_lints/src/methods/or_fun_call.rs
+++ b/clippy_lints/src/methods/or_fun_call.rs
@@ -97,7 +97,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 UNWRAP_OR_DEFAULT,
                 method_span.with_hi(span.hi()),
-                &format!("use of `{name}` to construct default value"),
+                format!("use of `{name}` to construct default value"),
                 "try",
                 format!("{sugg}()"),
                 Applicability::MachineApplicable,
@@ -167,7 +167,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 OR_FUN_CALL,
                 span_replace_word,
-                &format!("use of `{name}` followed by a function call"),
+                format!("use of `{name}` followed by a function call"),
                 "try",
                 format!("{name}_{suffix}({sugg})"),
                 app,
diff --git a/clippy_lints/src/methods/range_zip_with_len.rs b/clippy_lints/src/methods/range_zip_with_len.rs
index 1148628b084..28ca76832eb 100644
--- a/clippy_lints/src/methods/range_zip_with_len.rs
+++ b/clippy_lints/src/methods/range_zip_with_len.rs
@@ -24,7 +24,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'
             cx,
             RANGE_ZIP_WITH_LEN,
             expr.span,
-            &format!(
+            format!(
                 "it is more idiomatic to use `{}.iter().enumerate()`",
                 snippet(cx, recv.span, "_")
             ),
diff --git a/clippy_lints/src/methods/search_is_some.rs b/clippy_lints/src/methods/search_is_some.rs
index ef1baa6c988..ac5cc2f01e5 100644
--- a/clippy_lints/src/methods/search_is_some.rs
+++ b/clippy_lints/src/methods/search_is_some.rs
@@ -39,7 +39,7 @@ pub(super) fn check<'tcx>(
                 && let closure_body = cx.tcx.hir().body(body)
                 && let Some(closure_arg) = closure_body.params.first()
             {
-                if let hir::PatKind::Ref(..) = closure_arg.pat.kind {
+                if let PatKind::Ref(..) = closure_arg.pat.kind {
                     Some(search_snippet.replacen('&', "", 1))
                 } else if let PatKind::Binding(..) = strip_pat_refs(closure_arg.pat).kind {
                     // `find()` provides a reference to the item, but `any` does not,
@@ -62,7 +62,7 @@ pub(super) fn check<'tcx>(
                     cx,
                     SEARCH_IS_SOME,
                     method_span.with_hi(expr.span.hi()),
-                    &msg,
+                    msg,
                     "consider using",
                     format!(
                         "any({})",
@@ -76,7 +76,7 @@ pub(super) fn check<'tcx>(
                     cx,
                     SEARCH_IS_SOME,
                     expr.span,
-                    &msg,
+                    msg,
                     "consider using",
                     format!(
                         "!{iter}.any({})",
@@ -94,7 +94,7 @@ pub(super) fn check<'tcx>(
                     ""
                 }
             );
-            span_lint_and_help(cx, SEARCH_IS_SOME, expr.span, &msg, None, &hint);
+            span_lint_and_help(cx, SEARCH_IS_SOME, expr.span, msg, None, hint);
         }
     }
     // lint if `find()` is called by `String` or `&str`
@@ -117,7 +117,7 @@ pub(super) fn check<'tcx>(
                         cx,
                         SEARCH_IS_SOME,
                         method_span.with_hi(expr.span.hi()),
-                        &msg,
+                        msg,
                         "consider using",
                         format!("contains({find_arg})"),
                         applicability,
@@ -131,7 +131,7 @@ pub(super) fn check<'tcx>(
                         cx,
                         SEARCH_IS_SOME,
                         expr.span,
-                        &msg,
+                        msg,
                         "consider using",
                         format!("!{string}.contains({find_arg})"),
                         applicability,
diff --git a/clippy_lints/src/methods/stable_sort_primitive.rs b/clippy_lints/src/methods/stable_sort_primitive.rs
index 0f4c97022db..aef14435d8a 100644
--- a/clippy_lints/src/methods/stable_sort_primitive.rs
+++ b/clippy_lints/src/methods/stable_sort_primitive.rs
@@ -17,7 +17,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx
             cx,
             STABLE_SORT_PRIMITIVE,
             e.span,
-            &format!("used `sort` on primitive type `{slice_type}`"),
+            format!("used `sort` on primitive type `{slice_type}`"),
             |diag| {
                 let mut app = Applicability::MachineApplicable;
                 let recv_snip = snippet_with_context(cx, recv.span, e.span.ctxt(), "..", &mut app).0;
diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs
index 946cdb49d27..55ae9746298 100644
--- a/clippy_lints/src/methods/str_splitn.rs
+++ b/clippy_lints/src/methods/str_splitn.rs
@@ -53,7 +53,7 @@ fn lint_needless(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, self_
         cx,
         NEEDLESS_SPLITN,
         expr.span,
-        &format!("unnecessary use of `{r}splitn`"),
+        format!("unnecessary use of `{r}splitn`"),
         "try",
         format!(
             "{}.{r}split({})",
@@ -154,7 +154,7 @@ fn check_manual_split_once_indirect(
         let self_snip = snippet_with_context(cx, self_arg.span, ctxt, "..", &mut app).0;
         let pat_snip = snippet_with_context(cx, pat_arg.span, ctxt, "..", &mut app).0;
 
-        span_lint_and_then(cx, MANUAL_SPLIT_ONCE, local.span, &msg, |diag| {
+        span_lint_and_then(cx, MANUAL_SPLIT_ONCE, local.span, msg, |diag| {
             diag.span_label(first.span, "first usage here");
             diag.span_label(second.span, "second usage here");
 
diff --git a/clippy_lints/src/methods/suspicious_splitn.rs b/clippy_lints/src/methods/suspicious_splitn.rs
index c45212581ee..ff5c1d1a401 100644
--- a/clippy_lints/src/methods/suspicious_splitn.rs
+++ b/clippy_lints/src/methods/suspicious_splitn.rs
@@ -37,6 +37,6 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, se
             )
         };
 
-        span_lint_and_note(cx, SUSPICIOUS_SPLITN, expr.span, &msg, None, note_msg);
+        span_lint_and_note(cx, SUSPICIOUS_SPLITN, expr.span, msg, None, note_msg);
     }
 }
diff --git a/clippy_lints/src/methods/suspicious_to_owned.rs b/clippy_lints/src/methods/suspicious_to_owned.rs
index 60864902a48..ce7aefed01f 100644
--- a/clippy_lints/src/methods/suspicious_to_owned.rs
+++ b/clippy_lints/src/methods/suspicious_to_owned.rs
@@ -23,7 +23,7 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) -
             cx,
             SUSPICIOUS_TO_OWNED,
             expr.span,
-            &with_forced_trimmed_paths!(format!(
+            with_forced_trimmed_paths!(format!(
                 "this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned"
             )),
             |diag| {
diff --git a/clippy_lints/src/methods/type_id_on_box.rs b/clippy_lints/src/methods/type_id_on_box.rs
index 4917936a932..6f9b38fcf83 100644
--- a/clippy_lints/src/methods/type_id_on_box.rs
+++ b/clippy_lints/src/methods/type_id_on_box.rs
@@ -5,13 +5,33 @@ use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment};
+use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_middle::ty::{self, ExistentialPredicate, Ty};
 use rustc_span::{sym, Span};
 
-fn is_dyn_any(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
+/// Checks if the given type is `dyn Any`, or a trait object that has `Any` as a supertrait.
+/// Only in those cases will its vtable have a `type_id` method that returns the implementor's
+/// `TypeId`, and only in those cases can we give a proper suggestion to dereference the box.
+///
+/// If this returns false, then `.type_id()` likely (this may have FNs) will not be what the user
+/// expects in any case and dereferencing it won't help either. It will likely require some
+/// other changes, but it is still worth emitting a lint.
+/// See <https://github.com/rust-lang/rust-clippy/pull/11350#discussion_r1544863005> for more details.
+fn is_subtrait_of_any(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
     if let ty::Dynamic(preds, ..) = ty.kind() {
         preds.iter().any(|p| match p.skip_binder() {
-            ExistentialPredicate::Trait(tr) => cx.tcx.is_diagnostic_item(sym::Any, tr.def_id),
+            ExistentialPredicate::Trait(tr) => {
+                cx.tcx.is_diagnostic_item(sym::Any, tr.def_id)
+                    || cx
+                        .tcx
+                        .super_predicates_of(tr.def_id)
+                        .predicates
+                        .iter()
+                        .any(|(clause, _)| {
+                            matches!(clause.kind().skip_binder(), ty::ClauseKind::Trait(super_tr)
+                            if cx.tcx.is_diagnostic_item(sym::Any, super_tr.def_id()))
+                        })
+            },
             _ => false,
         })
     } else {
@@ -26,36 +46,42 @@ pub(super) fn check(cx: &LateContext<'_>, receiver: &Expr<'_>, call_span: Span)
         && let ty::Ref(_, ty, _) = recv_ty.kind()
         && let ty::Adt(adt, args) = ty.kind()
         && adt.is_box()
-        && is_dyn_any(cx, args.type_at(0))
+        && let inner_box_ty = args.type_at(0)
+        && let ty::Dynamic(..) = inner_box_ty.kind()
     {
+        let ty_name = with_forced_trimmed_paths!(ty.to_string());
+
         span_lint_and_then(
             cx,
             TYPE_ID_ON_BOX,
             call_span,
-            "calling `.type_id()` on a `Box<dyn Any>`",
+            format!("calling `.type_id()` on `{ty_name}`"),
             |diag| {
                 let derefs = recv_adjusts
                     .iter()
                     .filter(|adj| matches!(adj.kind, Adjust::Deref(None)))
                     .count();
 
-                let mut sugg = "*".repeat(derefs + 1);
-                sugg += &snippet(cx, receiver.span, "<expr>");
-
                 diag.note(
-                    "this returns the type id of the literal type `Box<dyn Any>` instead of the \
+                    "this returns the type id of the literal type `Box<_>` instead of the \
                     type id of the boxed value, which is most likely not what you want",
                 )
-                .note(
-                    "if this is intentional, use `TypeId::of::<Box<dyn Any>>()` instead, \
-                    which makes it more clear",
-                )
-                .span_suggestion(
-                    receiver.span,
-                    "consider dereferencing first",
-                    format!("({sugg})"),
-                    Applicability::MaybeIncorrect,
-                );
+                .note(format!(
+                    "if this is intentional, use `TypeId::of::<{ty_name}>()` instead, \
+                    which makes it more clear"
+                ));
+
+                if is_subtrait_of_any(cx, inner_box_ty) {
+                    let mut sugg = "*".repeat(derefs + 1);
+                    sugg += &snippet(cx, receiver.span, "<expr>");
+
+                    diag.span_suggestion(
+                        receiver.span,
+                        "consider dereferencing first",
+                        format!("({sugg})"),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
             },
         );
     }
diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs
index fabf3fa0c0c..daf99d98614 100644
--- a/clippy_lints/src/methods/unnecessary_filter_map.rs
+++ b/clippy_lints/src/methods/unnecessary_filter_map.rs
@@ -60,7 +60,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a
                 UNNECESSARY_FIND_MAP
             },
             expr.span,
-            &format!("this `.{name}` can be written more simply using `.{sugg}`"),
+            format!("this `.{name}` can be written more simply using `.{sugg}`"),
         );
     }
 }
diff --git a/clippy_lints/src/methods/unnecessary_get_then_check.rs b/clippy_lints/src/methods/unnecessary_get_then_check.rs
index cc8053ef507..f6184222d8e 100644
--- a/clippy_lints/src/methods/unnecessary_get_then_check.rs
+++ b/clippy_lints/src/methods/unnecessary_get_then_check.rs
@@ -58,7 +58,7 @@ pub(super) fn check(
                 cx,
                 UNNECESSARY_GET_THEN_CHECK,
                 both_calls_span,
-                &format!("unnecessary use of `{snippet}`"),
+                format!("unnecessary use of `{snippet}`"),
                 "replace it with",
                 suggestion,
                 Applicability::MaybeIncorrect,
@@ -70,7 +70,7 @@ pub(super) fn check(
                 cx,
                 UNNECESSARY_GET_THEN_CHECK,
                 both_calls_span,
-                &format!("unnecessary use of `{snippet}`"),
+                format!("unnecessary use of `{snippet}`"),
                 |diag| {
                     diag.span_suggestion(
                         full_span,
diff --git a/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/clippy_lints/src/methods/unnecessary_iter_cloned.rs
index 36497d59a5a..520dcb2d52d 100644
--- a/clippy_lints/src/methods/unnecessary_iter_cloned.rs
+++ b/clippy_lints/src/methods/unnecessary_iter_cloned.rs
@@ -61,7 +61,7 @@ pub fn check_for_loop_iter(
             cx,
             UNNECESSARY_TO_OWNED,
             expr.span,
-            &format!("unnecessary use of `{method_name}`"),
+            format!("unnecessary use of `{method_name}`"),
             |diag| {
                 // If `check_into_iter_call_arg` called `check_for_loop_iter` because a call to
                 // a `to_owned`-like function was removed, then the next suggestion may be
diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
index 1b2bfbf4090..494d71fc053 100644
--- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
+++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
@@ -63,7 +63,7 @@ pub(super) fn check(
     let help_message = format!("used `{method}()` on `{constructor}` value");
     let suggestion_message = format!("remove the `{constructor}` and `{method}()`");
 
-    span_lint_and_then(cx, UNNECESSARY_LITERAL_UNWRAP, expr.span, &help_message, |diag| {
+    span_lint_and_then(cx, UNNECESSARY_LITERAL_UNWRAP, expr.span, help_message, |diag| {
         let suggestions = match (constructor, method, ty) {
             ("None", "unwrap", _) => Some(vec![(expr.span, "panic!()".to_string())]),
             ("None", "expect", _) => Some(vec![
diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs
index e58d4776427..23fc323446e 100644
--- a/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -18,8 +18,7 @@ use rustc_lint::LateContext;
 use rustc_middle::mir::Mutability;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
 use rustc_middle::ty::{
-    self, ClauseKind, GenericArg, GenericArgKind, GenericArgsRef, ParamTy, ProjectionPredicate,
-    TraitPredicate, Ty,
+    self, ClauseKind, GenericArg, GenericArgKind, GenericArgsRef, ParamTy, ProjectionPredicate, TraitPredicate, Ty,
 };
 use rustc_span::{sym, Symbol};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
@@ -138,7 +137,7 @@ fn check_addr_of_expr(
                 cx,
                 UNNECESSARY_TO_OWNED,
                 parent.span,
-                &format!("unnecessary use of `{method_name}`"),
+                format!("unnecessary use of `{method_name}`"),
                 "use",
                 format!(
                     "{:&>width$}{receiver_snippet}",
@@ -163,7 +162,7 @@ fn check_addr_of_expr(
                     cx,
                     UNNECESSARY_TO_OWNED,
                     parent.span,
-                    &format!("unnecessary use of `{method_name}`"),
+                    format!("unnecessary use of `{method_name}`"),
                     "use",
                     receiver_snippet,
                     Applicability::MachineApplicable,
@@ -173,7 +172,7 @@ fn check_addr_of_expr(
                     cx,
                     UNNECESSARY_TO_OWNED,
                     expr.span.with_lo(receiver.span.hi()),
-                    &format!("unnecessary use of `{method_name}`"),
+                    format!("unnecessary use of `{method_name}`"),
                     "remove this",
                     String::new(),
                     Applicability::MachineApplicable,
@@ -188,7 +187,7 @@ fn check_addr_of_expr(
                 cx,
                 UNNECESSARY_TO_OWNED,
                 parent.span,
-                &format!("unnecessary use of `{method_name}`"),
+                format!("unnecessary use of `{method_name}`"),
                 "use",
                 format!("{receiver_snippet}.as_ref()"),
                 Applicability::MachineApplicable,
@@ -232,7 +231,7 @@ fn check_into_iter_call_arg(
             cx,
             UNNECESSARY_TO_OWNED,
             parent.span,
-            &format!("unnecessary use of `{method_name}`"),
+            format!("unnecessary use of `{method_name}`"),
             "use",
             format!("{receiver_snippet}.iter().{cloned_or_copied}()"),
             Applicability::MaybeIncorrect,
@@ -271,7 +270,7 @@ fn check_split_call_arg(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symb
             cx,
             UNNECESSARY_TO_OWNED,
             parent.span,
-            &format!("unnecessary use of `{method_name}`"),
+            format!("unnecessary use of `{method_name}`"),
             "use",
             format!("{receiver_snippet}{as_ref}.split({arg_snippet})"),
             Applicability::MaybeIncorrect,
@@ -350,7 +349,7 @@ fn check_other_call_arg<'tcx>(
             cx,
             UNNECESSARY_TO_OWNED,
             maybe_arg.span,
-            &format!("unnecessary use of `{method_name}`"),
+            format!("unnecessary use of `{method_name}`"),
             "use",
             format!("{:&>n_refs$}{receiver_snippet}", ""),
             Applicability::MachineApplicable,
@@ -642,7 +641,7 @@ fn check_if_applicable_to_argument<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'tcx
             cx,
             UNNECESSARY_TO_OWNED,
             arg.span,
-            &format!("unnecessary use of `{method_name}`"),
+            format!("unnecessary use of `{method_name}`"),
             "replace it with",
             if original_arg_ty.is_array() {
                 format!("{snippet}.as_slice()")
diff --git a/clippy_lints/src/methods/unwrap_expect_used.rs b/clippy_lints/src/methods/unwrap_expect_used.rs
index 7bd16b473ce..516b8984ad7 100644
--- a/clippy_lints/src/methods/unwrap_expect_used.rs
+++ b/clippy_lints/src/methods/unwrap_expect_used.rs
@@ -69,7 +69,7 @@ pub(super) fn check(
         cx,
         variant.lint(),
         expr.span,
-        &format!("used `{}()` on {kind} value", variant.method_name(is_err)),
+        format!("used `{}()` on {kind} value", variant.method_name(is_err)),
         |diag| {
             diag.note(format!("if this value is {none_prefix}`{none_value}`, it will panic"));
 
diff --git a/clippy_lints/src/methods/useless_asref.rs b/clippy_lints/src/methods/useless_asref.rs
index b8baad18cc8..ae2b6e6347e 100644
--- a/clippy_lints/src/methods/useless_asref.rs
+++ b/clippy_lints/src/methods/useless_asref.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::ty::walk_ptrs_ty_depth;
+use clippy_utils::ty::{should_call_clone_as_function, walk_ptrs_ty_depth};
 use clippy_utils::{
     get_parent_expr, is_diag_trait_item, match_def_path, path_to_local_id, paths, peel_blocks, strip_pat_refs,
 };
@@ -68,7 +68,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str,
                 cx,
                 USELESS_ASREF,
                 expr.span,
-                &format!("this call to `{call_name}` does nothing"),
+                format!("this call to `{call_name}` does nothing"),
                 "try",
                 snippet_with_applicability(cx, recvr.span, "..", &mut applicability).to_string(),
                 applicability,
@@ -93,6 +93,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str,
             // And that it only has one argument.
             && let [arg] = args
             && is_calling_clone(cx, arg)
+            // And that we are not recommending recv.clone() over Arc::clone() or similar
+            && !should_call_clone_as_function(cx, rcv_ty)
         {
             lint_as_ref_clone(cx, expr.span.with_hi(parent.span.hi()), recvr, call_name);
         }
@@ -157,7 +159,7 @@ fn lint_as_ref_clone(cx: &LateContext<'_>, span: Span, recvr: &hir::Expr<'_>, ca
         cx,
         USELESS_ASREF,
         span,
-        &format!("this call to `{call_name}.map(...)` does nothing"),
+        format!("this call to `{call_name}.map(...)` does nothing"),
         "try",
         format!(
             "{}.clone()",
diff --git a/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs
index 3a0305b4d55..ef00c812d51 100644
--- a/clippy_lints/src/methods/utils.rs
+++ b/clippy_lints/src/methods/utils.rs
@@ -3,7 +3,6 @@ use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{get_parent_expr, path_to_local_id, usage};
 use rustc_ast::ast;
 use rustc_errors::Applicability;
-use rustc_hir as hir;
 use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, Mutability, Pat};
 use rustc_lint::LateContext;
@@ -13,9 +12,9 @@ use rustc_span::symbol::sym;
 
 pub(super) fn derefs_to_slice<'tcx>(
     cx: &LateContext<'tcx>,
-    expr: &'tcx hir::Expr<'tcx>,
+    expr: &'tcx Expr<'tcx>,
     ty: Ty<'tcx>,
-) -> Option<&'tcx hir::Expr<'tcx>> {
+) -> Option<&'tcx Expr<'tcx>> {
     fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool {
         match ty.kind() {
             ty::Slice(_) => true,
@@ -27,7 +26,7 @@ pub(super) fn derefs_to_slice<'tcx>(
         }
     }
 
-    if let hir::ExprKind::MethodCall(path, self_arg, ..) = &expr.kind {
+    if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind {
         if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(self_arg)) {
             Some(self_arg)
         } else {
@@ -51,10 +50,10 @@ pub(super) fn derefs_to_slice<'tcx>(
 
 pub(super) fn get_hint_if_single_char_arg(
     cx: &LateContext<'_>,
-    arg: &hir::Expr<'_>,
+    arg: &Expr<'_>,
     applicability: &mut Applicability,
 ) -> Option<String> {
-    if let hir::ExprKind::Lit(lit) = &arg.kind
+    if let ExprKind::Lit(lit) = &arg.kind
         && let ast::LitKind::Str(r, style) = lit.node
         && let string = r.as_str()
         && string.chars().count() == 1
diff --git a/clippy_lints/src/methods/verbose_file_reads.rs b/clippy_lints/src/methods/verbose_file_reads.rs
index 2fe5ae9a9ad..181b413a182 100644
--- a/clippy_lints/src/methods/verbose_file_reads.rs
+++ b/clippy_lints/src/methods/verbose_file_reads.rs
@@ -17,7 +17,7 @@ pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx Expr<'_>,
     recv: &'tcx Expr<'_>,
-    (msg, help): (&str, &str),
+    (msg, help): (&'static str, &'static str),
 ) {
     if is_trait_method(cx, expr, sym::IoRead)
         && matches!(recv.kind, ExprKind::Path(QPath::Resolved(None, _)))
diff --git a/clippy_lints/src/methods/wrong_self_convention.rs b/clippy_lints/src/methods/wrong_self_convention.rs
index 0a810a13f3f..28068c63473 100644
--- a/clippy_lints/src/methods/wrong_self_convention.rs
+++ b/clippy_lints/src/methods/wrong_self_convention.rs
@@ -137,7 +137,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 WRONG_SELF_CONVENTION,
                 first_arg_span,
-                &format!(
+                format!(
                     "{suggestion} usually take {}",
                     &self_kinds
                         .iter()
diff --git a/clippy_lints/src/min_ident_chars.rs b/clippy_lints/src/min_ident_chars.rs
index 0016fb33517..c6b7f5b0ce2 100644
--- a/clippy_lints/src/min_ident_chars.rs
+++ b/clippy_lints/src/min_ident_chars.rs
@@ -181,7 +181,7 @@ fn emit_min_ident_chars(conf: &MinIdentChars, cx: &impl LintContext, ident: &str
             conf.min_ident_chars_threshold,
         ))
     };
-    span_lint(cx, MIN_IDENT_CHARS, span, &help);
+    span_lint(cx, MIN_IDENT_CHARS, span, help);
 }
 
 /// Attempt to convert the node to an [`ItemKind::Use`] node.
diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs
index 11fecb7d72e..f5ce8dd29b1 100644
--- a/clippy_lints/src/misc.rs
+++ b/clippy_lints/src/misc.rs
@@ -246,7 +246,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
                 cx,
                 USED_UNDERSCORE_BINDING,
                 expr.span,
-                &format!(
+                format!(
                     "used binding `{name}` which is prefixed with an underscore. A leading \
                      underscore signals that a binding will not be used"
                 ),
diff --git a/clippy_lints/src/misc_early/builtin_type_shadow.rs b/clippy_lints/src/misc_early/builtin_type_shadow.rs
index 9f6b0bdc7a4..662f7cd8500 100644
--- a/clippy_lints/src/misc_early/builtin_type_shadow.rs
+++ b/clippy_lints/src/misc_early/builtin_type_shadow.rs
@@ -12,7 +12,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, param: &GenericParam) {
                 cx,
                 BUILTIN_TYPE_SHADOW,
                 param.ident.span,
-                &format!("this generic shadows the built-in type `{}`", prim_ty.name()),
+                format!("this generic shadows the built-in type `{}`", prim_ty.name()),
             );
         }
     }
diff --git a/clippy_lints/src/misc_early/literal_suffix.rs b/clippy_lints/src/misc_early/literal_suffix.rs
index eda4376f200..e0a5e401a50 100644
--- a/clippy_lints/src/misc_early/literal_suffix.rs
+++ b/clippy_lints/src/misc_early/literal_suffix.rs
@@ -16,7 +16,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, lit_snip: &str, suffi
                 cx,
                 SEPARATED_LITERAL_SUFFIX,
                 lit_span,
-                &format!("{sugg_type} type suffix should not be separated by an underscore"),
+                format!("{sugg_type} type suffix should not be separated by an underscore"),
                 "remove the underscore",
                 format!("{}{suffix}", &lit_snip[..maybe_last_sep_idx]),
                 Applicability::MachineApplicable,
@@ -26,7 +26,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, lit_snip: &str, suffi
                 cx,
                 UNSEPARATED_LITERAL_SUFFIX,
                 lit_span,
-                &format!("{sugg_type} type suffix should be separated by an underscore"),
+                format!("{sugg_type} type suffix should be separated by an underscore"),
                 "add an underscore",
                 format!("{}_{suffix}", &lit_snip[..=maybe_last_sep_idx]),
                 Applicability::MachineApplicable,
diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs
index abe5b00e888..2f5499d7656 100644
--- a/clippy_lints/src/misc_early/mod.rs
+++ b/clippy_lints/src/misc_early/mod.rs
@@ -394,7 +394,7 @@ impl EarlyLintPass for MiscEarlyLints {
                             cx,
                             DUPLICATE_UNDERSCORE_ARGUMENT,
                             *correspondence,
-                            &format!(
+                            format!(
                                 "`{arg_name}` already exists, having another argument having almost the same \
                                  name makes code comprehension and documentation more difficult"
                             ),
diff --git a/clippy_lints/src/misc_early/redundant_pattern.rs b/clippy_lints/src/misc_early/redundant_pattern.rs
index d7bb0616acb..d5b5b2bf2dd 100644
--- a/clippy_lints/src/misc_early/redundant_pattern.rs
+++ b/clippy_lints/src/misc_early/redundant_pattern.rs
@@ -12,7 +12,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
                 cx,
                 REDUNDANT_PATTERN,
                 pat.span,
-                &format!(
+                format!(
                     "the `{} @ _` pattern can be written as just `{}`",
                     ident.name, ident.name,
                 ),
diff --git a/clippy_lints/src/misc_early/unneeded_field_pattern.rs b/clippy_lints/src/misc_early/unneeded_field_pattern.rs
index 676e5d40bb7..cb305cf5582 100644
--- a/clippy_lints/src/misc_early/unneeded_field_pattern.rs
+++ b/clippy_lints/src/misc_early/unneeded_field_pattern.rs
@@ -27,7 +27,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
                 pat.span,
                 "all the struct fields are matched to a wildcard pattern, consider using `..`",
                 None,
-                &format!("try with `{type_name} {{ .. }}` instead"),
+                format!("try with `{type_name} {{ .. }}` instead"),
             );
             return;
         }
@@ -63,7 +63,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
                             "you matched a field with a wildcard pattern, consider using `..` \
                              instead",
                             None,
-                            &format!("try with `{type_name} {{ {}, .. }}`", normal[..].join(", ")),
+                            format!("try with `{type_name} {{ {}, .. }}`", normal[..].join(", ")),
                         );
                     }
                 }
diff --git a/clippy_lints/src/mismatching_type_param_order.rs b/clippy_lints/src/mismatching_type_param_order.rs
index 0739b49fe19..0842a872824 100644
--- a/clippy_lints/src/mismatching_type_param_order.rs
+++ b/clippy_lints/src/mismatching_type_param_order.rs
@@ -101,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch {
                         "try `{}`, or a name that does not conflict with `{type_name}`'s generic params",
                         type_param_names[i]
                     );
-                    span_lint_and_help(cx, MISMATCHING_TYPE_PARAM_ORDER, *impl_param_span, &msg, None, &help);
+                    span_lint_and_help(cx, MISMATCHING_TYPE_PARAM_ORDER, *impl_param_span, msg, None, help);
                 }
             }
         }
diff --git a/clippy_lints/src/missing_asserts_for_indexing.rs b/clippy_lints/src/missing_asserts_for_indexing.rs
index 39d4ea74b31..c29e46b941c 100644
--- a/clippy_lints/src/missing_asserts_for_indexing.rs
+++ b/clippy_lints/src/missing_asserts_for_indexing.rs
@@ -65,7 +65,7 @@ declare_clippy_lint! {
 }
 declare_lint_pass!(MissingAssertsForIndexing => [MISSING_ASSERTS_FOR_INDEXING]);
 
-fn report_lint<F>(cx: &LateContext<'_>, full_span: Span, msg: &str, indexes: &[Span], f: F)
+fn report_lint<F>(cx: &LateContext<'_>, full_span: Span, msg: &'static str, indexes: &[Span], f: F)
 where
     F: FnOnce(&mut Diag<'_, ()>),
 {
diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs
index 2773427e72d..2fb784dae1c 100644
--- a/clippy_lints/src/missing_doc.rs
+++ b/clippy_lints/src/missing_doc.rs
@@ -127,7 +127,7 @@ impl MissingDoc {
                 cx,
                 MISSING_DOCS_IN_PRIVATE_ITEMS,
                 sp,
-                &format!("missing documentation for {article} {desc}"),
+                format!("missing documentation for {article} {desc}"),
             );
         }
     }
diff --git a/clippy_lints/src/missing_fields_in_debug.rs b/clippy_lints/src/missing_fields_in_debug.rs
index 3bf9f75e226..a64faa124f0 100644
--- a/clippy_lints/src/missing_fields_in_debug.rs
+++ b/clippy_lints/src/missing_fields_in_debug.rs
@@ -198,7 +198,7 @@ fn check_struct<'tcx>(
 }
 
 impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug {
-    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx rustc_hir::Item<'tcx>) {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
         // is this an `impl Debug for X` block?
         if let ItemKind::Impl(Impl { of_trait: Some(trait_ref), self_ty, items, .. }) = item.kind
             && let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res
diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs
index 7393b39c8f6..c6a76478806 100644
--- a/clippy_lints/src/missing_inline.rs
+++ b/clippy_lints/src/missing_inline.rs
@@ -64,7 +64,7 @@ fn check_missing_inline_attrs(cx: &LateContext<'_>, attrs: &[ast::Attribute], sp
             cx,
             MISSING_INLINE_IN_PUBLIC_ITEMS,
             sp,
-            &format!("missing `#[inline]` for {desc}"),
+            format!("missing `#[inline]` for {desc}"),
         );
     }
 }
diff --git a/clippy_lints/src/missing_trait_methods.rs b/clippy_lints/src/missing_trait_methods.rs
index 6bbf18d52d1..6f844bc646a 100644
--- a/clippy_lints/src/missing_trait_methods.rs
+++ b/clippy_lints/src/missing_trait_methods.rs
@@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods {
                         cx,
                         MISSING_TRAIT_METHODS,
                         source_map.guess_head_span(item.span),
-                        &format!("missing trait method provided by default: `{}`", assoc.name),
+                        format!("missing trait method provided by default: `{}`", assoc.name),
                         Some(definition_span),
                         "implement the method",
                     );
diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs
index 656fb907fcd..181351910db 100644
--- a/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -325,7 +325,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
                     self.cx,
                     MIXED_READ_WRITE_IN_EXPRESSION,
                     expr.span,
-                    &format!("unsequenced read of `{}`", self.cx.tcx.hir().name(self.var)),
+                    format!("unsequenced read of `{}`", self.cx.tcx.hir().name(self.var)),
                     Some(self.write_expr.span),
                     "whether read occurs before this write depends on evaluation order",
                 );
diff --git a/clippy_lints/src/module_style.rs b/clippy_lints/src/module_style.rs
index 0226b31dd19..6c031c08175 100644
--- a/clippy_lints/src/module_style.rs
+++ b/clippy_lints/src/module_style.rs
@@ -129,9 +129,9 @@ impl EarlyLintPass for ModStyle {
                         cx,
                         SELF_NAMED_MODULE_FILES,
                         Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
-                        &format!("`mod.rs` files are required, found `{}`", path.display()),
+                        format!("`mod.rs` files are required, found `{}`", path.display()),
                         None,
-                        &format!("move `{}` to `{}`", path.display(), correct.display(),),
+                        format!("move `{}` to `{}`", path.display(), correct.display(),),
                     );
                 }
             }
@@ -169,9 +169,9 @@ fn check_self_named_mod_exists(cx: &EarlyContext<'_>, path: &Path, file: &Source
             cx,
             MOD_MODULE_FILES,
             Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
-            &format!("`mod.rs` files are not allowed, found `{}`", path.display()),
+            format!("`mod.rs` files are not allowed, found `{}`", path.display()),
             None,
-            &format!("move `{}` to `{}`", path.display(), mod_file.display()),
+            format!("move `{}` to `{}`", path.display(), mod_file.display()),
         );
     }
 }
diff --git a/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/clippy_lints/src/multiple_unsafe_ops_per_block.rs
index 648d780ac09..0e138066780 100644
--- a/clippy_lints/src/multiple_unsafe_ops_per_block.rs
+++ b/clippy_lints/src/multiple_unsafe_ops_per_block.rs
@@ -77,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleUnsafeOpsPerBlock {
                 cx,
                 MULTIPLE_UNSAFE_OPS_PER_BLOCK,
                 block.span,
-                &format!(
+                format!(
                     "this `unsafe` block contains {} unsafe operations, expected only one",
                     unsafe_ops.len()
                 ),
diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs
index 14a1e6be738..6867f76a723 100644
--- a/clippy_lints/src/mut_reference.rs
+++ b/clippy_lints/src/mut_reference.rs
@@ -60,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed {
                 let method_type = cx.tcx.type_of(def_id).instantiate(cx.tcx, args);
                 check_arguments(
                     cx,
-                    std::iter::once(receiver).chain(arguments.iter()).collect(),
+                    iter::once(receiver).chain(arguments.iter()).collect(),
                     method_type,
                     path.ident.as_str(),
                     "method",
@@ -83,14 +83,13 @@ fn check_arguments<'tcx>(
             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) => {
+                    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"),
+                                format!("the {fn_kind} `{name}` doesn't need a mutable reference"),
                             );
                         }
                     },
diff --git a/clippy_lints/src/mutable_debug_assertion.rs b/clippy_lints/src/mutable_debug_assertion.rs
index 96cd81ecdf3..e92ba93942e 100644
--- a/clippy_lints/src/mutable_debug_assertion.rs
+++ b/clippy_lints/src/mutable_debug_assertion.rs
@@ -60,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for DebugAssertWithMutCall {
                     cx,
                     DEBUG_ASSERT_WITH_MUT_CALL,
                     span,
-                    &format!("do not call a function with mutable arguments inside of `{macro_name}!`"),
+                    format!("do not call a function with mutable arguments inside of `{macro_name}!`"),
                 );
             }
         }
diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs
index 61243c83731..7ecc8617694 100644
--- a/clippy_lints/src/mutex_atomic.rs
+++ b/clippy_lints/src/mutex_atomic.rs
@@ -92,9 +92,9 @@ impl<'tcx> LateLintPass<'tcx> for Mutex {
                          behavior and not the internal type, consider using `Mutex<()>`"
                     );
                     match *mutex_param.kind() {
-                        ty::Uint(t) if t != ty::UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg),
-                        ty::Int(t) if t != ty::IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg),
-                        _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg),
+                        ty::Uint(t) if t != UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, msg),
+                        ty::Int(t) if t != IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, msg),
+                        _ => span_lint(cx, MUTEX_ATOMIC, expr.span, msg),
                     };
                 }
             }
diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs
index 166a7f71d69..f9ee4a3dc93 100644
--- a/clippy_lints/src/needless_bool.rs
+++ b/clippy_lints/src/needless_bool.rs
@@ -6,11 +6,12 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
-    higher, is_else_clause, is_expn_of, peel_blocks, peel_blocks_with_stmt, span_extract_comment, SpanlessEq,
+    higher, is_else_clause, is_expn_of, is_parent_stmt, peel_blocks, peel_blocks_with_stmt, span_extract_comment,
+    SpanlessEq,
 };
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
-use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, Node, UnOp};
+use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 use rustc_span::source_map::Spanned;
@@ -135,13 +136,6 @@ fn condition_needs_parentheses(e: &Expr<'_>) -> bool {
     false
 }
 
-fn is_parent_stmt(cx: &LateContext<'_>, id: HirId) -> bool {
-    matches!(
-        cx.tcx.parent_hir_node(id),
-        Node::Stmt(..) | Node::Block(Block { stmts: &[], .. })
-    )
-}
-
 impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         use self::Expression::{Bool, RetBool};
@@ -323,11 +317,11 @@ fn one_side_is_unary_not<'tcx>(left_side: &'tcx Expr<'_>, right_side: &'tcx Expr
 fn check_comparison<'a, 'tcx>(
     cx: &LateContext<'tcx>,
     e: &'tcx Expr<'_>,
-    left_true: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>,
-    left_false: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>,
-    right_true: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>,
-    right_false: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &str)>,
-    no_literal: Option<(impl FnOnce(Sugg<'a>, Sugg<'a>) -> Sugg<'a>, &str)>,
+    left_true: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &'static str)>,
+    left_false: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &'static str)>,
+    right_true: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &'static str)>,
+    right_false: Option<(impl FnOnce(Sugg<'a>) -> Sugg<'a>, &'static str)>,
+    no_literal: Option<(impl FnOnce(Sugg<'a>, Sugg<'a>) -> Sugg<'a>, &'static str)>,
 ) {
     if let ExprKind::Binary(op, left_side, right_side) = e.kind {
         let (l_ty, r_ty) = (
@@ -397,7 +391,7 @@ fn check_comparison<'a, 'tcx>(
                         binop_span,
                         m,
                         "try simplifying it as shown",
-                        h(left_side, right_side).to_string(),
+                        h(left_side, right_side).into_string(),
                         applicability,
                     );
                 }),
@@ -412,7 +406,7 @@ fn suggest_bool_comparison<'a, 'tcx>(
     span: Span,
     expr: &Expr<'_>,
     mut app: Applicability,
-    message: &str,
+    message: &'static str,
     conv_hint: impl FnOnce(Sugg<'a>) -> Sugg<'a>,
 ) {
     let hint = Sugg::hir_with_context(cx, expr, span.ctxt(), "..", &mut app);
@@ -422,7 +416,7 @@ fn suggest_bool_comparison<'a, 'tcx>(
         span,
         message,
         "try simplifying it as shown",
-        conv_hint(hint).to_string(),
+        conv_hint(hint).into_string(),
         app,
     );
 }
diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs
index 4710a69443b..d91329eadcb 100644
--- a/clippy_lints/src/needless_borrowed_ref.rs
+++ b/clippy_lints/src/needless_borrowed_ref.rs
@@ -119,7 +119,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
 
 fn check_subpatterns<'tcx>(
     cx: &LateContext<'tcx>,
-    message: &str,
+    message: &'static str,
     ref_pat: &Pat<'_>,
     pat: &Pat<'_>,
     subpatterns: impl IntoIterator<Item = &'tcx Pat<'tcx>>,
diff --git a/clippy_lints/src/needless_borrows_for_generic_args.rs b/clippy_lints/src/needless_borrows_for_generic_args.rs
index a32bca3d038..c555fc8675c 100644
--- a/clippy_lints/src/needless_borrows_for_generic_args.rs
+++ b/clippy_lints/src/needless_borrows_for_generic_args.rs
@@ -381,7 +381,7 @@ fn replace_types<'tcx>(
     fn_sig: FnSig<'tcx>,
     arg_index: usize,
     projection_predicates: &[ProjectionPredicate<'tcx>],
-    args: &mut [ty::GenericArg<'tcx>],
+    args: &mut [GenericArg<'tcx>],
 ) -> bool {
     let mut replaced = BitSet::new_empty(args.len());
 
@@ -399,7 +399,7 @@ fn replace_types<'tcx>(
             return false;
         }
 
-        args[param_ty.index as usize] = ty::GenericArg::from(new_ty);
+        args[param_ty.index as usize] = GenericArg::from(new_ty);
 
         // The `replaced.insert(...)` check provides some protection against infinite loops.
         if replaced.insert(param_ty.index) {
@@ -414,7 +414,7 @@ fn replace_types<'tcx>(
                     ));
 
                     if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection)
-                        && args[term_param_ty.index as usize] != ty::GenericArg::from(projected_ty)
+                        && args[term_param_ty.index as usize] != GenericArg::from(projected_ty)
                     {
                         deque.push_back((*term_param_ty, projected_ty));
                     }
diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs
index ff72b5e69ef..8b4a12bb766 100644
--- a/clippy_lints/src/needless_continue.rs
+++ b/clippy_lints/src/needless_continue.rs
@@ -313,7 +313,7 @@ fn emit_warning(cx: &EarlyContext<'_>, data: &LintData<'_>, header: &str, typ: L
         expr.span,
         message,
         None,
-        &format!("{header}\n{snip}"),
+        format!("{header}\n{snip}"),
     );
 }
 
diff --git a/clippy_lints/src/needless_question_mark.rs b/clippy_lints/src/needless_question_mark.rs
index d7adf22ff32..37463cfec9a 100644
--- a/clippy_lints/src/needless_question_mark.rs
+++ b/clippy_lints/src/needless_question_mark.rs
@@ -131,7 +131,7 @@ fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
             NEEDLESS_QUESTION_MARK,
             expr.span,
             "question mark operator is useless here",
-            &format!("try removing question mark and `{sugg_remove}`"),
+            format!("try removing question mark and `{sugg_remove}`"),
             format!("{}", snippet(cx, inner_expr.span, r#""...""#)),
             Applicability::MachineApplicable,
         );
diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs
index 627b4968d9f..78dd1e05162 100644
--- a/clippy_lints/src/new_without_default.rs
+++ b/clippy_lints/src/new_without_default.rs
@@ -134,9 +134,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
                                 NEW_WITHOUT_DEFAULT,
                                 id.into(),
                                 impl_item.span,
-                                &format!(
-                                    "you should consider adding a `Default` implementation for `{self_type_snip}`"
-                                ),
+                                format!("you should consider adding a `Default` implementation for `{self_type_snip}`"),
                                 |diag| {
                                     diag.suggest_prepend_item(
                                         cx,
diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs
index 43810ec0ec7..f915145e794 100644
--- a/clippy_lints/src/no_effect.rs
+++ b/clippy_lints/src/no_effect.rs
@@ -107,7 +107,7 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect {
         }
     }
 
-    fn check_expr(&mut self, _: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
+    fn check_expr(&mut self, _: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         if let Some(def_id) = path_to_local(expr) {
             // FIXME(rust/#120456) - is `swap_remove` correct?
             self.underscore_bindings.swap_remove(&def_id);
diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs
index 6cb84bb78b6..73fc34c2450 100644
--- a/clippy_lints/src/non_copy_const.rs
+++ b/clippy_lints/src/non_copy_const.rs
@@ -285,7 +285,7 @@ impl NonCopyConst {
         let def_id = body_id.hir_id.owner.to_def_id();
         let args = ty::GenericArgs::identity_for_item(cx.tcx, def_id);
         let instance = ty::Instance::new(def_id, args);
-        let cid = rustc_middle::mir::interpret::GlobalId {
+        let cid = GlobalId {
             instance,
             promoted: None,
         };
@@ -534,7 +534,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
     }
 }
 
-fn ignored_macro(cx: &LateContext<'_>, it: &rustc_hir::Item<'_>) -> bool {
+fn ignored_macro(cx: &LateContext<'_>, it: &Item<'_>) -> bool {
     macro_backtrace(it.span).any(|macro_call| {
         matches!(
             cx.tcx.get_diagnostic_name(macro_call.def_id),
diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs
index b8c3c7fa65a..7b26235291a 100644
--- a/clippy_lints/src/non_expressive_names.rs
+++ b/clippy_lints/src/non_expressive_names.rs
@@ -111,7 +111,7 @@ impl<'a, 'tcx> SimilarNamesLocalVisitor<'a, 'tcx> {
                 self.cx,
                 MANY_SINGLE_CHAR_NAMES,
                 span,
-                &format!("{num_single_char_names} bindings with single-character names in scope"),
+                format!("{num_single_char_names} bindings with single-character names in scope"),
             );
         }
     }
diff --git a/clippy_lints/src/non_send_fields_in_send_ty.rs b/clippy_lints/src/non_send_fields_in_send_ty.rs
index 408216229a4..74e6c57b52d 100644
--- a/clippy_lints/src/non_send_fields_in_send_ty.rs
+++ b/clippy_lints/src/non_send_fields_in_send_ty.rs
@@ -119,7 +119,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy {
                     cx,
                     NON_SEND_FIELDS_IN_SEND_TY,
                     item.span,
-                    &format!(
+                    format!(
                         "some fields in `{}` are not safe to be sent to another thread",
                         snippet(cx, hir_impl.self_ty.span, "Unknown")
                     ),
diff --git a/clippy_lints/src/nonstandard_macro_braces.rs b/clippy_lints/src/nonstandard_macro_braces.rs
index 1c6069e9c65..88f2eabaccb 100644
--- a/clippy_lints/src/nonstandard_macro_braces.rs
+++ b/clippy_lints/src/nonstandard_macro_braces.rs
@@ -121,7 +121,7 @@ fn emit_help(cx: &EarlyContext<'_>, snip: &str, (open, close): (char, char), spa
             cx,
             NONSTANDARD_MACRO_BRACES,
             span,
-            &format!("use of irregular braces for `{macro_name}!` macro"),
+            format!("use of irregular braces for `{macro_name}!` macro"),
             "consider writing",
             format!("{macro_name}!{open}{macro_args}{close}"),
             Applicability::MachineApplicable,
diff --git a/clippy_lints/src/octal_escapes.rs b/clippy_lints/src/octal_escapes.rs
index 8822dfeeddd..2fc039ae886 100644
--- a/clippy_lints/src/octal_escapes.rs
+++ b/clippy_lints/src/octal_escapes.rs
@@ -94,7 +94,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) {
         cx,
         OCTAL_ESCAPES,
         span,
-        &format!(
+        format!(
             "octal-looking escape in {} literal",
             if is_string { "string" } else { "byte string" }
         ),
diff --git a/clippy_lints/src/operators/absurd_extreme_comparisons.rs b/clippy_lints/src/operators/absurd_extreme_comparisons.rs
index f4863600ccc..9769da6d3e9 100644
--- a/clippy_lints/src/operators/absurd_extreme_comparisons.rs
+++ b/clippy_lints/src/operators/absurd_extreme_comparisons.rs
@@ -42,7 +42,7 @@ pub(super) fn check<'tcx>(
             }
         );
 
-        span_lint_and_help(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, None, &help);
+        span_lint_and_help(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, None, help);
     }
 }
 
diff --git a/clippy_lints/src/operators/bit_mask.rs b/clippy_lints/src/operators/bit_mask.rs
index 2e026c369ee..545e680ce0d 100644
--- a/clippy_lints/src/operators/bit_mask.rs
+++ b/clippy_lints/src/operators/bit_mask.rs
@@ -64,7 +64,7 @@ fn check_bit_mask(
                             cx,
                             BAD_BIT_MASK,
                             span,
-                            &format!("incompatible bit mask: `_ & {mask_value}` can never be equal to `{cmp_value}`"),
+                            format!("incompatible bit mask: `_ & {mask_value}` can never be equal to `{cmp_value}`"),
                         );
                     }
                 } else if mask_value == 0 {
@@ -77,7 +77,7 @@ fn check_bit_mask(
                         cx,
                         BAD_BIT_MASK,
                         span,
-                        &format!("incompatible bit mask: `_ | {mask_value}` can never be equal to `{cmp_value}`"),
+                        format!("incompatible bit mask: `_ | {mask_value}` can never be equal to `{cmp_value}`"),
                     );
                 }
             },
@@ -90,7 +90,7 @@ fn check_bit_mask(
                         cx,
                         BAD_BIT_MASK,
                         span,
-                        &format!("incompatible bit mask: `_ & {mask_value}` will always be lower than `{cmp_value}`"),
+                        format!("incompatible bit mask: `_ & {mask_value}` will always be lower than `{cmp_value}`"),
                     );
                 } else if mask_value == 0 {
                     span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero");
@@ -102,7 +102,7 @@ fn check_bit_mask(
                         cx,
                         BAD_BIT_MASK,
                         span,
-                        &format!("incompatible bit mask: `_ | {mask_value}` will never be lower than `{cmp_value}`"),
+                        format!("incompatible bit mask: `_ | {mask_value}` will never be lower than `{cmp_value}`"),
                     );
                 } else {
                     check_ineffective_lt(cx, span, mask_value, cmp_value, "|");
@@ -118,7 +118,7 @@ fn check_bit_mask(
                         cx,
                         BAD_BIT_MASK,
                         span,
-                        &format!("incompatible bit mask: `_ & {mask_value}` will never be higher than `{cmp_value}`"),
+                        format!("incompatible bit mask: `_ & {mask_value}` will never be higher than `{cmp_value}`"),
                     );
                 } else if mask_value == 0 {
                     span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero");
@@ -130,7 +130,7 @@ fn check_bit_mask(
                         cx,
                         BAD_BIT_MASK,
                         span,
-                        &format!("incompatible bit mask: `_ | {mask_value}` will always be higher than `{cmp_value}`"),
+                        format!("incompatible bit mask: `_ | {mask_value}` will always be higher than `{cmp_value}`"),
                     );
                 } else {
                     check_ineffective_gt(cx, span, mask_value, cmp_value, "|");
@@ -149,7 +149,7 @@ fn check_ineffective_lt(cx: &LateContext<'_>, span: Span, m: u128, c: u128, op:
             cx,
             INEFFECTIVE_BIT_MASK,
             span,
-            &format!("ineffective bit mask: `x {op} {m}` compared to `{c}`, is the same as x compared directly"),
+            format!("ineffective bit mask: `x {op} {m}` compared to `{c}`, is the same as x compared directly"),
         );
     }
 }
@@ -160,7 +160,7 @@ fn check_ineffective_gt(cx: &LateContext<'_>, span: Span, m: u128, c: u128, op:
             cx,
             INEFFECTIVE_BIT_MASK,
             span,
-            &format!("ineffective bit mask: `x {op} {m}` compared to `{c}`, is the same as x compared directly"),
+            format!("ineffective bit mask: `x {op} {m}` compared to `{c}`, is the same as x compared directly"),
         );
     }
 }
diff --git a/clippy_lints/src/operators/const_comparisons.rs b/clippy_lints/src/operators/const_comparisons.rs
index e278cf9835a..7bf9b8ef866 100644
--- a/clippy_lints/src/operators/const_comparisons.rs
+++ b/clippy_lints/src/operators/const_comparisons.rs
@@ -89,7 +89,7 @@ pub(super) fn check<'tcx>(
                     span,
                     "left-hand side of `&&` operator has no effect",
                     Some(left_cond.span.until(right_cond.span)),
-                    &format!("`if `{rhs_str}` evaluates to true, {lhs_str}` will always evaluate to true as well"),
+                    format!("`if `{rhs_str}` evaluates to true, {lhs_str}` will always evaluate to true as well"),
                 );
             } else {
                 span_lint_and_note(
@@ -98,7 +98,7 @@ pub(super) fn check<'tcx>(
                     span,
                     "right-hand side of `&&` operator has no effect",
                     Some(and_op.span.to(right_cond.span)),
-                    &format!("`if `{lhs_str}` evaluates to true, {rhs_str}` will always evaluate to true as well"),
+                    format!("`if `{lhs_str}` evaluates to true, {rhs_str}` will always evaluate to true as well"),
                 );
             }
             // We could autofix this error but choose not to,
@@ -124,7 +124,7 @@ pub(super) fn check<'tcx>(
                 span,
                 "boolean expression will never evaluate to 'true'",
                 None,
-                &note,
+                note,
             );
         };
     }
diff --git a/clippy_lints/src/operators/duration_subsec.rs b/clippy_lints/src/operators/duration_subsec.rs
index f120be13836..ca3112ce5c4 100644
--- a/clippy_lints/src/operators/duration_subsec.rs
+++ b/clippy_lints/src/operators/duration_subsec.rs
@@ -31,7 +31,7 @@ pub(crate) fn check<'tcx>(
             cx,
             DURATION_SUBSEC,
             expr.span,
-            &format!("calling `{suggested_fn}()` is more concise than this calculation"),
+            format!("calling `{suggested_fn}()` is more concise than this calculation"),
             "try",
             format!(
                 "{}.{suggested_fn}()",
diff --git a/clippy_lints/src/operators/eq_op.rs b/clippy_lints/src/operators/eq_op.rs
index 01dd418c38b..1421893274f 100644
--- a/clippy_lints/src/operators/eq_op.rs
+++ b/clippy_lints/src/operators/eq_op.rs
@@ -24,7 +24,7 @@ pub(crate) fn check_assert<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
             cx,
             EQ_OP,
             lhs.span.to(rhs.span),
-            &format!("identical args used in this `{macro_name}!` macro call"),
+            format!("identical args used in this `{macro_name}!` macro call"),
         );
     }
 }
@@ -41,7 +41,7 @@ pub(crate) fn check<'tcx>(
             cx,
             EQ_OP,
             e.span,
-            &format!("equal expressions as operands to `{}`", op.as_str()),
+            format!("equal expressions as operands to `{}`", op.as_str()),
             |diag| {
                 if let BinOpKind::Ne = op
                     && cx.typeck_results().expr_ty(left).is_floating_point()
diff --git a/clippy_lints/src/operators/modulo_arithmetic.rs b/clippy_lints/src/operators/modulo_arithmetic.rs
index 2a933a11e12..c56518ac72a 100644
--- a/clippy_lints/src/operators/modulo_arithmetic.rs
+++ b/clippy_lints/src/operators/modulo_arithmetic.rs
@@ -113,7 +113,7 @@ fn check_const_operands<'tcx>(
             cx,
             MODULO_ARITHMETIC,
             expr.span,
-            &format!(
+            format!(
                 "you are using modulo operator on constants with different signs: `{} % {}`",
                 lhs_operand.string_representation.as_ref().unwrap(),
                 rhs_operand.string_representation.as_ref().unwrap()
diff --git a/clippy_lints/src/operators/ptr_eq.rs b/clippy_lints/src/operators/ptr_eq.rs
index a69989e400b..607930561e0 100644
--- a/clippy_lints/src/operators/ptr_eq.rs
+++ b/clippy_lints/src/operators/ptr_eq.rs
@@ -30,7 +30,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 PTR_EQ,
                 expr.span,
-                &format!("use `{top_crate}::ptr::eq` when comparing raw pointers"),
+                format!("use `{top_crate}::ptr::eq` when comparing raw pointers"),
                 "try",
                 format!("{top_crate}::ptr::eq({left_snip}, {right_snip})"),
                 Applicability::MachineApplicable,
diff --git a/clippy_lints/src/operators/self_assignment.rs b/clippy_lints/src/operators/self_assignment.rs
index 7c9d5320a3a..a932378fbb5 100644
--- a/clippy_lints/src/operators/self_assignment.rs
+++ b/clippy_lints/src/operators/self_assignment.rs
@@ -14,7 +14,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, lhs: &'tcx
             cx,
             SELF_ASSIGNMENT,
             e.span,
-            &format!("self-assignment of `{rhs}` to `{lhs}`"),
+            format!("self-assignment of `{rhs}` to `{lhs}`"),
         );
     }
 }
diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs
index 556c493d36c..3cbd03a58c5 100644
--- a/clippy_lints/src/option_if_let_else.rs
+++ b/clippy_lints/src/option_if_let_else.rs
@@ -304,7 +304,7 @@ impl<'tcx> LateLintPass<'tcx> for OptionIfLetElse {
                 cx,
                 OPTION_IF_LET_ELSE,
                 expr.span,
-                format!("use Option::{} instead of an if let/else", det.method_sugg).as_str(),
+                format!("use Option::{} instead of an if let/else", det.method_sugg),
                 "try",
                 format!(
                     "{}.{}({}, {})",
diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs
index ec03ab0e41a..bb4a1de9f77 100644
--- a/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/clippy_lints/src/pass_by_ref_or_value.rs
@@ -206,7 +206,7 @@ impl<'tcx> PassByRefOrValue {
                             cx,
                             TRIVIALLY_COPY_PASS_BY_REF,
                             input.span,
-                            &format!(
+                            format!(
                                 "this argument ({size} byte) is passed by reference, but would be more efficient if passed by value (limit: {} byte)",
                                 self.ref_min_size
                             ),
@@ -236,7 +236,7 @@ impl<'tcx> PassByRefOrValue {
                             cx,
                             LARGE_TYPES_PASSED_BY_VALUE,
                             input.span,
-                            &format!(
+                            format!(
                                 "this argument ({size} byte) is passed by value, but might be more efficient if passed by reference (limit: {} byte)",
                                 self.value_max_size
                             ),
diff --git a/clippy_lints/src/pattern_type_mismatch.rs b/clippy_lints/src/pattern_type_mismatch.rs
index 127801de7de..44db061b8be 100644
--- a/clippy_lints/src/pattern_type_mismatch.rs
+++ b/clippy_lints/src/pattern_type_mismatch.rs
@@ -1,5 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_help;
-use rustc_hir::{intravisit, Body, Expr, ExprKind, FnDecl, LetExpr, LocalSource, Mutability, Pat, PatKind, Stmt, StmtKind};
+use rustc_hir::{
+    intravisit, Body, Expr, ExprKind, FnDecl, LetExpr, LocalSource, Mutability, Pat, PatKind, Stmt, StmtKind,
+};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
@@ -138,7 +140,7 @@ fn apply_lint(cx: &LateContext<'_>, pat: &Pat<'_>, deref_possible: DerefPossible
             span,
             "type of pattern does not match the expression type",
             None,
-            &format!(
+            format!(
                 "{}explicitly match against a `{}` pattern and adjust the enclosed variable bindings",
                 match (deref_possible, level) {
                     (DerefPossible::Possible, Level::Top) => "use `*` to dereference the match expression or ",
diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs
index 896c99a7104..83b32000a9f 100644
--- a/clippy_lints/src/ptr.rs
+++ b/clippy_lints/src/ptr.rs
@@ -177,7 +177,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
             )
             .filter(|arg| arg.mutability() == Mutability::Not)
             {
-                span_lint_hir_and_then(cx, PTR_ARG, arg.emission_id, arg.span, &arg.build_msg(), |diag| {
+                span_lint_hir_and_then(cx, PTR_ARG, arg.emission_id, arg.span, arg.build_msg(), |diag| {
                     diag.span_suggestion(
                         arg.span,
                         "change this to",
@@ -237,7 +237,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
         let results = check_ptr_arg_usage(cx, body, &lint_args);
 
         for (result, args) in results.iter().zip(lint_args.iter()).filter(|(r, _)| !r.skip) {
-            span_lint_hir_and_then(cx, PTR_ARG, args.emission_id, args.span, &args.build_msg(), |diag| {
+            span_lint_hir_and_then(cx, PTR_ARG, args.emission_id, args.span, args.build_msg(), |diag| {
                 diag.multipart_suggestion(
                     "change this to",
                     iter::once((args.span, format!("{}{}", args.ref_prefix, args.deref_ty.display(cx))))
@@ -628,7 +628,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
                         }
                     },
                     ExprKind::MethodCall(name, self_arg, expr_args, _) => {
-                        let i = std::iter::once(self_arg)
+                        let i = iter::once(self_arg)
                             .chain(expr_args.iter())
                             .position(|arg| arg.hir_id == child_id)
                             .unwrap_or(0);
diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs
index ff8ec2ad57c..7c82895d609 100644
--- a/clippy_lints/src/ptr_offset_with_cast.rs
+++ b/clippy_lints/src/ptr_offset_with_cast.rs
@@ -64,13 +64,13 @@ impl<'tcx> LateLintPass<'tcx> for PtrOffsetWithCast {
                 cx,
                 PTR_OFFSET_WITH_CAST,
                 expr.span,
-                &msg,
+                msg,
                 "try",
                 sugg,
                 Applicability::MachineApplicable,
             );
         } else {
-            span_lint(cx, PTR_OFFSET_WITH_CAST, expr.span, &msg);
+            span_lint(cx, PTR_OFFSET_WITH_CAST, expr.span, msg);
         }
     }
 }
diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs
index b57220e6cf0..927c6f1d519 100644
--- a/clippy_lints/src/question_mark.rs
+++ b/clippy_lints/src/question_mark.rs
@@ -4,7 +4,7 @@ use clippy_config::msrvs::Msrv;
 use clippy_config::types::MatchLintBehaviour;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use clippy_utils::{
     eq_expr_value, higher, in_constant, is_else_clause, is_lint_allowed, is_path_lang_item, is_res_lang_ctor,
     pat_and_expr_can_be_question_mark, path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt,
@@ -14,7 +14,8 @@ use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk};
 use rustc_hir::{
-    BindingAnnotation, Block, ByRef, Expr, ExprKind, LetStmt, Mutability, Node, PatKind, PathSegment, QPath, Stmt, StmtKind,
+    BindingAnnotation, Block, Body, ByRef, Expr, ExprKind, LetStmt, Mutability, Node, PatKind, PathSegment, QPath,
+    Stmt, StmtKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::Ty;
@@ -109,12 +110,31 @@ fn find_let_else_ret_expression<'hir>(block: &'hir Block<'hir>) -> Option<&'hir
 }
 
 fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
+    /// Make sure the init expr implements try trait so a valid suggestion could be given.
+    ///
+    /// Because the init expr could have the type of `&Option<T>` which does not implements `Try`.
+    ///
+    /// NB: This conveniently prevents the cause of
+    /// issue [#12412](https://github.com/rust-lang/rust-clippy/issues/12412),
+    /// since accessing an `Option` field from a borrowed struct requires borrow, such as
+    /// `&some_struct.opt`, which is type of `&Option`. And we can't suggest `&some_struct.opt?`
+    /// or `(&some_struct.opt)?` since the first one has different semantics and the later does
+    /// not implements `Try`.
+    fn init_expr_can_use_question_mark(cx: &LateContext<'_>, init_expr: &Expr<'_>) -> bool {
+        let init_ty = cx.typeck_results().expr_ty_adjusted(init_expr);
+        cx.tcx
+            .lang_items()
+            .try_trait()
+            .map_or(false, |did| implements_trait(cx, init_ty, did, &[]))
+    }
+
     if let StmtKind::Let(LetStmt {
         pat,
         init: Some(init_expr),
         els: Some(els),
         ..
     }) = stmt.kind
+        && init_expr_can_use_question_mark(cx, init_expr)
         && let Some(ret) = find_let_else_ret_expression(els)
         && let Some(inner_pat) = pat_and_expr_can_be_question_mark(cx, pat, ret)
         && !span_contains_comment(cx.tcx.sess.source_map(), els.span)
@@ -310,9 +330,9 @@ impl QuestionMark {
     }
 }
 
-fn is_try_block(cx: &LateContext<'_>, bl: &rustc_hir::Block<'_>) -> bool {
+fn is_try_block(cx: &LateContext<'_>, bl: &Block<'_>) -> bool {
     if let Some(expr) = bl.expr
-        && let rustc_hir::ExprKind::Call(callee, _) = expr.kind
+        && let ExprKind::Call(callee, _) = expr.kind
     {
         is_path_lang_item(cx, callee, LangItem::TryTraitFromOutput)
     } else {
@@ -341,7 +361,7 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark {
         }
     }
 
-    fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx rustc_hir::Block<'tcx>) {
+    fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
         if is_try_block(cx, block) {
             *self
                 .try_block_depth_stack
@@ -350,15 +370,15 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark {
         }
     }
 
-    fn check_body(&mut self, _: &LateContext<'tcx>, _: &'tcx rustc_hir::Body<'tcx>) {
+    fn check_body(&mut self, _: &LateContext<'tcx>, _: &'tcx Body<'tcx>) {
         self.try_block_depth_stack.push(0);
     }
 
-    fn check_body_post(&mut self, _: &LateContext<'tcx>, _: &'tcx rustc_hir::Body<'tcx>) {
+    fn check_body_post(&mut self, _: &LateContext<'tcx>, _: &'tcx Body<'tcx>) {
         self.try_block_depth_stack.pop();
     }
 
-    fn check_block_post(&mut self, cx: &LateContext<'tcx>, block: &'tcx rustc_hir::Block<'tcx>) {
+    fn check_block_post(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
         if is_try_block(cx, block) {
             *self
                 .try_block_depth_stack
diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs
index 6b54258dd61..186e548d373 100644
--- a/clippy_lints/src/ranges.rs
+++ b/clippy_lints/src/ranges.rs
@@ -242,7 +242,7 @@ fn check_possible_range_contains(
                 cx,
                 MANUAL_RANGE_CONTAINS,
                 span,
-                &format!("manual `{range_type}::contains` implementation"),
+                format!("manual `{range_type}::contains` implementation"),
                 "use",
                 format!("({lo}{space}{range_op}{hi}).contains(&{name})"),
                 applicability,
@@ -272,7 +272,7 @@ fn check_possible_range_contains(
                 cx,
                 MANUAL_RANGE_CONTAINS,
                 span,
-                &format!("manual `!{range_type}::contains` implementation"),
+                format!("manual `!{range_type}::contains` implementation"),
                 "use",
                 format!("!({lo}{space}{range_op}{hi}).contains(&{name})"),
                 applicability,
diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs
index 435899ddaa7..2863eb190d3 100644
--- a/clippy_lints/src/redundant_closure_call.rs
+++ b/clippy_lints/src/redundant_closure_call.rs
@@ -56,7 +56,7 @@ impl ReturnVisitor {
 
 impl<'tcx> Visitor<'tcx> for ReturnVisitor {
     fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
-        if let hir::ExprKind::Ret(_) | hir::ExprKind::Match(.., hir::MatchSource::TryDesugar(_)) = ex.kind {
+        if let ExprKind::Ret(_) | ExprKind::Match(.., hir::MatchSource::TryDesugar(_)) = ex.kind {
             self.found_return = true;
         } else {
             hir_visit::walk_expr(self, ex);
@@ -68,7 +68,7 @@ impl<'tcx> Visitor<'tcx> for ReturnVisitor {
 /// Returns true for `async || whatever_expression`, but false for `|| async { whatever_expression
 /// }`.
 fn is_async_closure(body: &hir::Body<'_>) -> bool {
-    if let hir::ExprKind::Closure(innermost_closure_generated_by_desugar) = body.value.kind
+    if let ExprKind::Closure(innermost_closure_generated_by_desugar) = body.value.kind
         // checks whether it is `async || whatever_expression`
         && let ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure))
             = innermost_closure_generated_by_desugar.kind
@@ -99,7 +99,7 @@ fn find_innermost_closure<'tcx>(
 )> {
     let mut data = None;
 
-    while let hir::ExprKind::Closure(closure) = expr.kind
+    while let ExprKind::Closure(closure) = expr.kind
         && let body = cx.tcx.hir().body(closure.body)
         && {
             let mut visitor = ReturnVisitor::new();
@@ -137,7 +137,7 @@ fn get_parent_call_exprs<'tcx>(
 ) -> (&'tcx hir::Expr<'tcx>, usize) {
     let mut depth = 1;
     while let Some(parent) = get_parent_expr(cx, expr)
-        && let hir::ExprKind::Call(recv, _) = parent.kind
+        && let ExprKind::Call(recv, _) = parent.kind
         && expr.span == recv.span
     {
         expr = parent;
@@ -152,13 +152,13 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
             return;
         }
 
-        if let hir::ExprKind::Call(recv, _) = expr.kind
+        if let ExprKind::Call(recv, _) = expr.kind
             // don't lint if the receiver is a call, too.
             // we do this in order to prevent linting multiple times; consider:
             // `(|| || 1)()()`
             //           ^^  we only want to lint for this call (but we walk up the calls to consider both calls).
             // without this check, we'd end up linting twice.
-            && !matches!(recv.kind, hir::ExprKind::Call(..))
+            && !matches!(recv.kind, ExprKind::Call(..))
             // Check if `recv` comes from a macro expansion. If it does, make sure that it's an expansion that is
             // the same as the one the call is in.
             // For instance, let's assume `x!()` returns a closure:
@@ -185,7 +185,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
                             Sugg::hir_with_context(cx, body, full_expr.span.ctxt(), "..", &mut applicability);
 
                         if coroutine_kind.is_async()
-                            && let hir::ExprKind::Closure(closure) = body.kind
+                            && let ExprKind::Closure(closure) = body.kind
                         {
                             // Like `async fn`, async closures are wrapped in an additional block
                             // to move all of the closure's arguments into the future.
@@ -202,7 +202,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
                             };
 
                             // `async x` is a syntax error, so it becomes `async { x }`
-                            if !matches!(body_expr.kind, hir::ExprKind::Block(_, _)) {
+                            if !matches!(body_expr.kind, ExprKind::Block(_, _)) {
                                 hint = hint.blockify();
                             }
 
@@ -210,7 +210,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
                         }
 
                         let is_in_fn_call_arg = if let Node::Expr(expr) = cx.tcx.parent_hir_node(expr.hir_id) {
-                            matches!(expr.kind, hir::ExprKind::Call(_, _))
+                            matches!(expr.kind, ExprKind::Call(_, _))
                         } else {
                             false
                         };
@@ -238,12 +238,12 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
                 path: &'tcx hir::Path<'tcx>,
                 count: usize,
             }
-            impl<'a, 'tcx> hir_visit::Visitor<'tcx> for ClosureUsageCount<'a, 'tcx> {
+            impl<'a, 'tcx> Visitor<'tcx> for ClosureUsageCount<'a, 'tcx> {
                 type NestedFilter = nested_filter::OnlyBodies;
 
                 fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
-                    if let hir::ExprKind::Call(closure, _) = expr.kind
-                        && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind
+                    if let ExprKind::Call(closure, _) = expr.kind
+                        && let ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind
                         && self.path.segments[0].ident == path.segments[0].ident
                         && self.path.res == path.res
                     {
@@ -263,13 +263,13 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
 
         for w in block.stmts.windows(2) {
             if let hir::StmtKind::Let(local) = w[0].kind
-                && let Option::Some(t) = local.init
-                && let hir::ExprKind::Closure { .. } = t.kind
+                && let Some(t) = local.init
+                && let ExprKind::Closure { .. } = t.kind
                 && let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind
                 && let hir::StmtKind::Semi(second) = w[1].kind
-                && let hir::ExprKind::Assign(_, call, _) = second.kind
-                && let hir::ExprKind::Call(closure, _) = call.kind
-                && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind
+                && let ExprKind::Assign(_, call, _) = second.kind
+                && let ExprKind::Call(closure, _) = call.kind
+                && let ExprKind::Path(hir::QPath::Resolved(_, path)) = closure.kind
                 && ident == path.segments[0].ident
                 && count_closure_usage(cx, block, path) == 1
             {
diff --git a/clippy_lints/src/redundant_locals.rs b/clippy_lints/src/redundant_locals.rs
index 0f579f779df..7202266deeb 100644
--- a/clippy_lints/src/redundant_locals.rs
+++ b/clippy_lints/src/redundant_locals.rs
@@ -77,9 +77,9 @@ impl<'tcx> LateLintPass<'tcx> for RedundantLocals {
                 cx,
                 REDUNDANT_LOCALS,
                 local.span,
-                &format!("redundant redefinition of a binding `{ident}`"),
+                format!("redundant redefinition of a binding `{ident}`"),
                 Some(binding_pat.span),
-                &format!("`{ident}` is initially defined here"),
+                format!("`{ident}` is initially defined here"),
             );
         }
     }
diff --git a/clippy_lints/src/redundant_pub_crate.rs b/clippy_lints/src/redundant_pub_crate.rs
index 0e43e4a7ee5..1b557730eca 100644
--- a/clippy_lints/src/redundant_pub_crate.rs
+++ b/clippy_lints/src/redundant_pub_crate.rs
@@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
                 cx,
                 REDUNDANT_PUB_CRATE,
                 span,
-                &format!("pub(crate) {descr} inside private module"),
+                format!("pub(crate) {descr} inside private module"),
                 |diag| {
                     diag.span_suggestion(
                         item.vis_span,
diff --git a/clippy_lints/src/redundant_static_lifetimes.rs b/clippy_lints/src/redundant_static_lifetimes.rs
index 07b604f2326..136e7db83bd 100644
--- a/clippy_lints/src/redundant_static_lifetimes.rs
+++ b/clippy_lints/src/redundant_static_lifetimes.rs
@@ -48,7 +48,7 @@ impl_lint_pass!(RedundantStaticLifetimes => [REDUNDANT_STATIC_LIFETIMES]);
 
 impl RedundantStaticLifetimes {
     // Recursively visit types
-    fn visit_type(ty: &Ty, cx: &EarlyContext<'_>, reason: &str) {
+    fn visit_type(ty: &Ty, cx: &EarlyContext<'_>, reason: &'static str) {
         match ty.kind {
             // Be careful of nested structures (arrays and tuples)
             TyKind::Array(ref ty, _) | TyKind::Slice(ref ty) => {
diff --git a/clippy_lints/src/redundant_type_annotations.rs b/clippy_lints/src/redundant_type_annotations.rs
index 96f6f0ec36f..11b95ee3a54 100644
--- a/clippy_lints/src/redundant_type_annotations.rs
+++ b/clippy_lints/src/redundant_type_annotations.rs
@@ -59,7 +59,7 @@ fn is_same_type<'tcx>(cx: &LateContext<'tcx>, ty_resolved_path: hir::def::Res, f
 
 fn func_hir_id_to_func_ty<'tcx>(cx: &LateContext<'tcx>, hir_id: hir::hir_id::HirId) -> Option<Ty<'tcx>> {
     if let Some((defkind, func_defid)) = cx.typeck_results().type_dependent_def(hir_id)
-        && defkind == hir::def::DefKind::AssocFn
+        && defkind == DefKind::AssocFn
         && let Some(init_ty) = cx.tcx.type_of(func_defid).no_bound_vars()
     {
         Some(init_ty)
diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs
index 687bad35a36..e925ec0271c 100644
--- a/clippy_lints/src/regex.rs
+++ b/clippy_lints/src/regex.rs
@@ -134,13 +134,13 @@ fn lint_syntax_error(cx: &LateContext<'_>, error: &regex_syntax::Error, unescape
             vec![convert_span(primary)]
         };
 
-        span_lint(cx, INVALID_REGEX, spans, &format!("regex syntax error: {kind}"));
+        span_lint(cx, INVALID_REGEX, spans, format!("regex syntax error: {kind}"));
     } else {
         span_lint_and_help(
             cx,
             INVALID_REGEX,
             base,
-            &error.to_string(),
+            error.to_string(),
             None,
             "consider using a raw string literal: `r\"..\"`",
         );
@@ -223,7 +223,7 @@ fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
                     span_lint_and_help(cx, TRIVIAL_REGEX, expr.span, "trivial regex", None, repl);
                 }
             },
-            Err(e) => span_lint(cx, INVALID_REGEX, expr.span, &e.to_string()),
+            Err(e) => span_lint(cx, INVALID_REGEX, expr.span, e.to_string()),
         }
     }
 }
diff --git a/clippy_lints/src/repeat_vec_with_capacity.rs b/clippy_lints/src/repeat_vec_with_capacity.rs
index fcb79f6d694..a358881bf80 100644
--- a/clippy_lints/src/repeat_vec_with_capacity.rs
+++ b/clippy_lints/src/repeat_vec_with_capacity.rs
@@ -55,7 +55,7 @@ fn emit_lint(cx: &LateContext<'_>, span: Span, kind: &str, note: &'static str, s
         cx,
         REPEAT_VEC_WITH_CAPACITY,
         span,
-        &format!("repeating `Vec::with_capacity` using `{kind}`, which does not retain capacity"),
+        format!("repeating `Vec::with_capacity` using `{kind}`, which does not retain capacity"),
         |diag| {
             diag.note(note);
             diag.span_suggestion_verbose(span, sugg_msg, sugg, Applicability::MaybeIncorrect);
diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs
index 8bc24eda465..e8f9d438104 100644
--- a/clippy_lints/src/returns.rs
+++ b/clippy_lints/src/returns.rs
@@ -3,7 +3,7 @@ use clippy_utils::source::{snippet_opt, snippet_with_context};
 use clippy_utils::sugg::has_enclosing_paren;
 use clippy_utils::visitors::{for_each_expr_with_closures, Descend};
 use clippy_utils::{
-    fn_def_id, is_from_proc_macro, is_inside_let_else, is_res_lang_ctor, path_res, path_to_local_id,
+    fn_def_id, is_from_proc_macro, is_inside_let_else, is_res_lang_ctor, path_res, path_to_local_id, span_contains_cfg,
     span_find_starting_semi,
 };
 use core::ops::ControlFlow;
@@ -232,6 +232,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
             && !in_external_macro(cx.sess(), initexpr.span)
             && !in_external_macro(cx.sess(), retexpr.span)
             && !local.span.from_expansion()
+            && !span_contains_cfg(cx, stmt.span.between(retexpr.span))
         {
             span_lint_hir_and_then(
                 cx,
diff --git a/clippy_lints/src/self_named_constructors.rs b/clippy_lints/src/self_named_constructors.rs
index 85a2b1a6735..23b47606f8a 100644
--- a/clippy_lints/src/self_named_constructors.rs
+++ b/clippy_lints/src/self_named_constructors.rs
@@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
                 cx,
                 SELF_NAMED_CONSTRUCTORS,
                 impl_item.span,
-                &format!("constructor `{}` has the same name as the type", impl_item.ident.name),
+                format!("constructor `{}` has the same name as the type", impl_item.ident.name),
             );
         }
     }
diff --git a/clippy_lints/src/serde_api.rs b/clippy_lints/src/serde_api.rs
index b4278d879e5..f1ec91d7aff 100644
--- a/clippy_lints/src/serde_api.rs
+++ b/clippy_lints/src/serde_api.rs
@@ -9,7 +9,7 @@ declare_clippy_lint! {
     /// Checks for misuses of the serde API.
     ///
     /// ### Why is this bad?
-    /// Serde is very finnicky about how its API should be
+    /// Serde is very finicky about how its API should be
     /// used, but the type system can't be used to enforce it (yet?).
     ///
     /// ### Example
diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs
index d98b37bda35..9db08acb03b 100644
--- a/clippy_lints/src/shadow.rs
+++ b/clippy_lints/src/shadow.rs
@@ -194,7 +194,7 @@ fn lint_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, shadowed: HirId, span: Span)
         cx,
         lint,
         span,
-        &msg,
+        msg,
         Some(cx.tcx.hir().span(shadowed)),
         "previous binding is here",
     );
diff --git a/clippy_lints/src/single_range_in_vec_init.rs b/clippy_lints/src/single_range_in_vec_init.rs
index 95b4a11a783..0a9a3c6307a 100644
--- a/clippy_lints/src/single_range_in_vec_init.rs
+++ b/clippy_lints/src/single_range_in_vec_init.rs
@@ -122,7 +122,7 @@ impl LateLintPass<'_> for SingleRangeInVecInit {
                     cx,
                     SINGLE_RANGE_IN_VEC_INIT,
                     span,
-                    &format!("{suggested_type} of `Range` that is only one element"),
+                    format!("{suggested_type} of `Range` that is only one element"),
                     |diag| {
                         if should_emit_every_value {
                             diag.span_suggestion(
diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs
index ff8e8fe7021..8a9f02b6dcb 100644
--- a/clippy_lints/src/slow_vector_initialization.rs
+++ b/clippy_lints/src/slow_vector_initialization.rs
@@ -196,7 +196,7 @@ impl SlowVectorInit {
         };
     }
 
-    fn emit_lint(cx: &LateContext<'_>, slow_fill: &Expr<'_>, vec_alloc: &VecAllocation<'_>, msg: &str) {
+    fn emit_lint(cx: &LateContext<'_>, slow_fill: &Expr<'_>, vec_alloc: &VecAllocation<'_>, msg: &'static str) {
         let len_expr = Sugg::hir(
             cx,
             match vec_alloc.size_expr {
diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs
index cf839941123..926c56332cc 100644
--- a/clippy_lints/src/std_instead_of_core.rs
+++ b/clippy_lints/src/std_instead_of_core.rs
@@ -128,8 +128,8 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
                     cx,
                     lint,
                     first_segment.ident.span,
-                    &format!("used import from `{used_mod}` instead of `{replace_with}`"),
-                    &format!("consider importing the item from `{replace_with}`"),
+                    format!("used import from `{used_mod}` instead of `{replace_with}`"),
+                    format!("consider importing the item from `{replace_with}`"),
                     replace_with.to_string(),
                     Applicability::MachineApplicable,
                 );
diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs
index 13ae1ff52dd..b3c729dacdd 100644
--- a/clippy_lints/src/strings.rs
+++ b/clippy_lints/src/strings.rs
@@ -495,8 +495,8 @@ impl<'tcx> LateLintPass<'tcx> for TrimSplitWhitespace {
                 cx,
                 TRIM_SPLIT_WHITESPACE,
                 trim_span.with_hi(split_ws_span.lo()),
-                &format!("found call to `str::{trim_fn_name}` before `str::split_whitespace`"),
-                &format!("remove `{trim_fn_name}()`"),
+                format!("found call to `str::{trim_fn_name}` before `str::split_whitespace`"),
+                format!("remove `{trim_fn_name}()`"),
                 String::new(),
                 Applicability::MachineApplicable,
             );
diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs
index 8eab3f5874e..3f030b80331 100644
--- a/clippy_lints/src/suspicious_trait_impl.rs
+++ b/clippy_lints/src/suspicious_trait_impl.rs
@@ -83,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
                 cx,
                 lint,
                 binop.span,
-                &format!(
+                format!(
                     "suspicious use of `{}` in `{}` impl",
                     binop.node.as_str(),
                     cx.tcx.item_name(trait_id)
diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs
index be590aede15..93bad865809 100644
--- a/clippy_lints/src/swap.rs
+++ b/clippy_lints/src/swap.rs
@@ -1,10 +1,16 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::source::snippet_with_context;
+use clippy_utils::source::{snippet_indent, snippet_with_context};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
+
 use clippy_utils::{can_mut_borrow_both, eq_expr_value, in_constant, std_or_core};
+use itertools::Itertools;
+
+use rustc_hir::intravisit::{walk_expr, Visitor};
+
+use crate::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_hir::{BinOpKind, Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
+use rustc_hir::{BinOpKind, Block, Expr, ExprKind, LetStmt, PatKind, QPath, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
@@ -80,7 +86,17 @@ impl<'tcx> LateLintPass<'tcx> for Swap {
     }
 }
 
-fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, span: Span, is_xor_based: bool) {
+#[allow(clippy::too_many_arguments)]
+fn generate_swap_warning<'tcx>(
+    block: &'tcx Block<'tcx>,
+    cx: &LateContext<'tcx>,
+    e1: &'tcx Expr<'tcx>,
+    e2: &'tcx Expr<'tcx>,
+    rhs1: &'tcx Expr<'tcx>,
+    rhs2: &'tcx Expr<'tcx>,
+    span: Span,
+    is_xor_based: bool,
+) {
     let ctxt = span.ctxt();
     let mut applicability = Applicability::MachineApplicable;
 
@@ -99,14 +115,25 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa
                 || is_type_diagnostic_item(cx, ty, sym::VecDeque)
             {
                 let slice = Sugg::hir_with_applicability(cx, lhs1, "<slice>", &mut applicability);
+
                 span_lint_and_sugg(
                     cx,
                     MANUAL_SWAP,
                     span,
-                    &format!("this looks like you are swapping elements of `{slice}` manually"),
+                    format!("this looks like you are swapping elements of `{slice}` manually"),
                     "try",
                     format!(
-                        "{}.swap({}, {});",
+                        "{}{}.swap({}, {});",
+                        IndexBinding {
+                            block,
+                            swap1_idx: idx1,
+                            swap2_idx: idx2,
+                            suggest_span: span,
+                            cx,
+                            ctxt,
+                            applicability: &mut applicability,
+                        }
+                        .snippet_index_bindings(&[idx1, idx2, rhs1, rhs2]),
                         slice.maybe_par(),
                         snippet_with_context(cx, idx1.span, ctxt, "..", &mut applicability).0,
                         snippet_with_context(cx, idx2.span, ctxt, "..", &mut applicability).0,
@@ -126,7 +153,7 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa
         cx,
         MANUAL_SWAP,
         span,
-        &format!("this looks like you are swapping `{first}` and `{second}` manually"),
+        format!("this looks like you are swapping `{first}` and `{second}` manually"),
         |diag| {
             diag.span_suggestion(
                 span,
@@ -142,7 +169,7 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa
 }
 
 /// Implementation of the `MANUAL_SWAP` lint.
-fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) {
+fn check_manual_swap<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
     if in_constant(cx, block.hir_id) {
         return;
     }
@@ -160,10 +187,10 @@ fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) {
             // bar() = t;
             && let StmtKind::Semi(second) = s3.kind
             && let ExprKind::Assign(lhs2, rhs2, _) = second.kind
-            && let ExprKind::Path(QPath::Resolved(None, rhs2)) = rhs2.kind
-            && rhs2.segments.len() == 1
+            && let ExprKind::Path(QPath::Resolved(None, rhs2_path)) = rhs2.kind
+            && rhs2_path.segments.len() == 1
 
-            && ident.name == rhs2.segments[0].ident.name
+            && ident.name == rhs2_path.segments[0].ident.name
             && eq_expr_value(cx, tmp_init, lhs1)
             && eq_expr_value(cx, rhs1, lhs2)
 
@@ -174,7 +201,7 @@ fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) {
             && second.span.ctxt() == ctxt
         {
             let span = s1.span.to(s3.span);
-            generate_swap_warning(cx, lhs1, lhs2, span, false);
+            generate_swap_warning(block, cx, lhs1, lhs2, rhs1, rhs2, span, false);
         }
     }
 }
@@ -201,7 +228,7 @@ fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) {
                 cx,
                 ALMOST_SWAPPED,
                 span,
-                &format!("this looks like you are trying to swap `{lhs_sugg}` and `{rhs_sugg}`"),
+                format!("this looks like you are trying to swap `{lhs_sugg}` and `{rhs_sugg}`"),
                 |diag| {
                     diag.span_suggestion(
                         span,
@@ -254,7 +281,7 @@ fn parse<'a, 'hir>(stmt: &'a Stmt<'hir>) -> Option<(ExprOrIdent<'hir>, &'a Expr<
 }
 
 /// Implementation of the xor case for `MANUAL_SWAP` lint.
-fn check_xor_swap(cx: &LateContext<'_>, block: &Block<'_>) {
+fn check_xor_swap<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
     for [s1, s2, s3] in block.stmts.array_windows::<3>() {
         let ctxt = s1.span.ctxt();
         if let Some((lhs0, rhs0)) = extract_sides_of_xor_assign(s1, ctxt)
@@ -268,7 +295,7 @@ fn check_xor_swap(cx: &LateContext<'_>, block: &Block<'_>) {
             && s3.span.ctxt() == ctxt
         {
             let span = s1.span.to(s3.span);
-            generate_swap_warning(cx, lhs0, rhs0, span, true);
+            generate_swap_warning(block, cx, lhs0, rhs0, rhs1, rhs2, span, true);
         };
     }
 }
@@ -294,3 +321,130 @@ fn extract_sides_of_xor_assign<'a, 'hir>(
         None
     }
 }
+
+struct IndexBinding<'a, 'tcx> {
+    block: &'a Block<'a>,
+    swap1_idx: &'a Expr<'a>,
+    swap2_idx: &'a Expr<'a>,
+    suggest_span: Span,
+    cx: &'a LateContext<'tcx>,
+    ctxt: SyntaxContext,
+    applicability: &'a mut Applicability,
+}
+
+impl<'a, 'tcx> IndexBinding<'a, 'tcx> {
+    fn snippet_index_bindings(&mut self, exprs: &[&'tcx Expr<'tcx>]) -> String {
+        let mut bindings = FxHashSet::default();
+        for expr in exprs {
+            bindings.insert(self.snippet_index_binding(expr));
+        }
+        bindings.into_iter().join("")
+    }
+
+    fn snippet_index_binding(&mut self, expr: &'tcx Expr<'tcx>) -> String {
+        match expr.kind {
+            ExprKind::Binary(_, lhs, rhs) => {
+                if matches!(lhs.kind, ExprKind::Lit(_)) && matches!(rhs.kind, ExprKind::Lit(_)) {
+                    return String::new();
+                }
+                let lhs_snippet = self.snippet_index_binding(lhs);
+                let rhs_snippet = self.snippet_index_binding(rhs);
+                format!("{lhs_snippet}{rhs_snippet}")
+            },
+            ExprKind::Path(QPath::Resolved(_, path)) => {
+                let init = self.cx.expr_or_init(expr);
+
+                let Some(first_segment) = path.segments.first() else {
+                    return String::new();
+                };
+                if !self.suggest_span.contains(init.span) || !self.is_used_other_than_swapping(first_segment.ident) {
+                    return String::new();
+                }
+
+                let init_str = snippet_with_context(self.cx, init.span, self.ctxt, "", self.applicability)
+                    .0
+                    .to_string();
+                let indent_str = snippet_indent(self.cx, init.span);
+                let indent_str = indent_str.as_deref().unwrap_or("");
+
+                format!("let {} = {init_str};\n{indent_str}", first_segment.ident)
+            },
+            _ => String::new(),
+        }
+    }
+
+    fn is_used_other_than_swapping(&mut self, idx_ident: Ident) -> bool {
+        if Self::is_used_slice_indexed(self.swap1_idx, idx_ident)
+            || Self::is_used_slice_indexed(self.swap2_idx, idx_ident)
+        {
+            return true;
+        }
+        self.is_used_after_swap(idx_ident)
+    }
+
+    fn is_used_after_swap(&mut self, idx_ident: Ident) -> bool {
+        let mut v = IndexBindingVisitor {
+            found_used: false,
+            suggest_span: self.suggest_span,
+            idx: idx_ident,
+        };
+
+        for stmt in self.block.stmts {
+            match stmt.kind {
+                StmtKind::Expr(expr) | StmtKind::Semi(expr) => v.visit_expr(expr),
+                StmtKind::Let(LetStmt { ref init, .. }) => {
+                    if let Some(init) = init.as_ref() {
+                        v.visit_expr(init);
+                    }
+                },
+                StmtKind::Item(_) => {},
+            }
+        }
+
+        v.found_used
+    }
+
+    fn is_used_slice_indexed(swap_index: &Expr<'_>, idx_ident: Ident) -> bool {
+        match swap_index.kind {
+            ExprKind::Binary(_, lhs, rhs) => {
+                if matches!(lhs.kind, ExprKind::Lit(_)) && matches!(rhs.kind, ExprKind::Lit(_)) {
+                    return false;
+                }
+                Self::is_used_slice_indexed(lhs, idx_ident) || Self::is_used_slice_indexed(rhs, idx_ident)
+            },
+            ExprKind::Path(QPath::Resolved(_, path)) => {
+                path.segments.first().map_or(false, |idx| idx.ident == idx_ident)
+            },
+            _ => false,
+        }
+    }
+}
+
+struct IndexBindingVisitor {
+    idx: Ident,
+    suggest_span: Span,
+    found_used: bool,
+}
+
+impl<'tcx> Visitor<'tcx> for IndexBindingVisitor {
+    fn visit_path_segment(&mut self, path_segment: &'tcx rustc_hir::PathSegment<'tcx>) -> Self::Result {
+        if path_segment.ident == self.idx {
+            self.found_used = true;
+        }
+    }
+
+    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> Self::Result {
+        if expr.span.hi() <= self.suggest_span.hi() {
+            return;
+        }
+
+        match expr.kind {
+            ExprKind::Path(QPath::Resolved(_, path)) => {
+                for segment in path.segments {
+                    self.visit_path_segment(segment);
+                }
+            },
+            _ => walk_expr(self, expr),
+        }
+    }
+}
diff --git a/clippy_lints/src/thread_local_initializer_can_be_made_const.rs b/clippy_lints/src/thread_local_initializer_can_be_made_const.rs
index f8bdb866ca3..c1e24674e3e 100644
--- a/clippy_lints/src/thread_local_initializer_can_be_made_const.rs
+++ b/clippy_lints/src/thread_local_initializer_can_be_made_const.rs
@@ -59,7 +59,7 @@ impl_lint_pass!(ThreadLocalInitializerCanBeMadeConst => [THREAD_LOCAL_INITIALIZE
 #[inline]
 fn is_thread_local_initializer(
     cx: &LateContext<'_>,
-    fn_kind: rustc_hir::intravisit::FnKind<'_>,
+    fn_kind: intravisit::FnKind<'_>,
     span: rustc_span::Span,
 ) -> Option<bool> {
     let macro_def_id = span.source_callee()?.macro_def_id?;
@@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for ThreadLocalInitializerCanBeMadeConst {
     fn check_fn(
         &mut self,
         cx: &LateContext<'tcx>,
-        fn_kind: rustc_hir::intravisit::FnKind<'tcx>,
+        fn_kind: intravisit::FnKind<'tcx>,
         _: &'tcx rustc_hir::FnDecl<'tcx>,
         body: &'tcx rustc_hir::Body<'tcx>,
         span: rustc_span::Span,
diff --git a/clippy_lints/src/trailing_empty_array.rs b/clippy_lints/src/trailing_empty_array.rs
index cbdf31c9336..462084e96a8 100644
--- a/clippy_lints/src/trailing_empty_array.rs
+++ b/clippy_lints/src/trailing_empty_array.rs
@@ -44,7 +44,7 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray {
                 item.span,
                 "trailing zero-sized array in a struct which is not marked with a `repr` attribute",
                 None,
-                &format!(
+                format!(
                     "consider annotating `{}` with `#[repr(C)]` or another `repr` attribute",
                     cx.tcx.def_path_str(item.owner_id)
                 ),
diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs
index 768623b5d03..9468d367a92 100644
--- a/clippy_lints/src/trait_bounds.rs
+++ b/clippy_lints/src/trait_bounds.rs
@@ -293,7 +293,7 @@ impl TraitBounds {
                     p.span,
                     "this type has already been used as a bound predicate",
                     None,
-                    &hint_string,
+                    hint_string,
                 );
             }
         }
@@ -420,7 +420,11 @@ fn into_comparable_trait_ref(trait_ref: &TraitRef<'_>) -> ComparableTraitRef {
     )
 }
 
-fn rollup_traits(cx: &LateContext<'_>, bounds: &[GenericBound<'_>], msg: &str) -> Vec<(ComparableTraitRef, Span)> {
+fn rollup_traits(
+    cx: &LateContext<'_>,
+    bounds: &[GenericBound<'_>],
+    msg: &'static str,
+) -> Vec<(ComparableTraitRef, Span)> {
     let mut map = FxHashMap::default();
     let mut repeated_res = false;
 
diff --git a/clippy_lints/src/transmute/crosspointer_transmute.rs b/clippy_lints/src/transmute/crosspointer_transmute.rs
index 102aee1cb95..c8f959a9854 100644
--- a/clippy_lints/src/transmute/crosspointer_transmute.rs
+++ b/clippy_lints/src/transmute/crosspointer_transmute.rs
@@ -13,7 +13,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty
                 cx,
                 CROSSPOINTER_TRANSMUTE,
                 e.span,
-                &format!("transmute from a type (`{from_ty}`) to the type that it points to (`{to_ty}`)"),
+                format!("transmute from a type (`{from_ty}`) to the type that it points to (`{to_ty}`)"),
             );
             true
         },
@@ -22,7 +22,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty
                 cx,
                 CROSSPOINTER_TRANSMUTE,
                 e.span,
-                &format!("transmute from a type (`{from_ty}`) to a pointer to that type (`{to_ty}`)"),
+                format!("transmute from a type (`{from_ty}`) to a pointer to that type (`{to_ty}`)"),
             );
             true
         },
diff --git a/clippy_lints/src/transmute/missing_transmute_annotations.rs b/clippy_lints/src/transmute/missing_transmute_annotations.rs
new file mode 100644
index 00000000000..cc6ff1cf3b4
--- /dev/null
+++ b/clippy_lints/src/transmute/missing_transmute_annotations.rs
@@ -0,0 +1,87 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use rustc_errors::Applicability;
+use rustc_hir::{GenericArg, HirId, LetStmt, Node, Path, TyKind};
+use rustc_lint::LateContext;
+use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty::Ty;
+
+use crate::transmute::MISSING_TRANSMUTE_ANNOTATIONS;
+
+fn get_parent_local_binding_ty<'tcx>(cx: &LateContext<'tcx>, expr_hir_id: HirId) -> Option<LetStmt<'tcx>> {
+    let mut parent_iter = cx.tcx.hir().parent_iter(expr_hir_id);
+    if let Some((_, node)) = parent_iter.next() {
+        match node {
+            Node::LetStmt(local) => Some(*local),
+            Node::Block(_) => {
+                if let Some((parent_hir_id, Node::Expr(expr))) = parent_iter.next()
+                    && matches!(expr.kind, rustc_hir::ExprKind::Block(_, _))
+                {
+                    get_parent_local_binding_ty(cx, parent_hir_id)
+                } else {
+                    None
+                }
+            },
+            _ => None,
+        }
+    } else {
+        None
+    }
+}
+
+fn is_function_block(cx: &LateContext<'_>, expr_hir_id: HirId) -> bool {
+    let def_id = cx.tcx.hir().enclosing_body_owner(expr_hir_id);
+    if let Some(body_id) = cx.tcx.hir().maybe_body_owned_by(def_id) {
+        let body = cx.tcx.hir().body(body_id);
+        return body.value.peel_blocks().hir_id == expr_hir_id;
+    }
+    false
+}
+
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    path: &Path<'tcx>,
+    from_ty: Ty<'tcx>,
+    to_ty: Ty<'tcx>,
+    expr_hir_id: HirId,
+) -> bool {
+    let last = path.segments.last().unwrap();
+    if in_external_macro(cx.tcx.sess, last.ident.span) {
+        // If it comes from a non-local macro, we ignore it.
+        return false;
+    }
+    let args = last.args;
+    let missing_generic = match args {
+        Some(args) if !args.args.is_empty() => args.args.iter().any(|arg| match arg {
+            GenericArg::Infer(_) => true,
+            GenericArg::Type(ty) => matches!(ty.kind, TyKind::Infer),
+            _ => false,
+        }),
+        _ => true,
+    };
+    if !missing_generic {
+        return false;
+    }
+    // If it's being set as a local variable value...
+    if let Some(local) = get_parent_local_binding_ty(cx, expr_hir_id) {
+        // ... which does have type annotations.
+        if let Some(ty) = local.ty
+            // If this is a `let x: _ =`, we should lint.
+            && !matches!(ty.kind, TyKind::Infer)
+        {
+            return false;
+        }
+    // We check if this transmute is not the only element in the function
+    } else if is_function_block(cx, expr_hir_id) {
+        return false;
+    }
+    span_lint_and_sugg(
+        cx,
+        MISSING_TRANSMUTE_ANNOTATIONS,
+        last.ident.span.with_hi(path.span.hi()),
+        "transmute used without annotations",
+        "consider adding missing annotations",
+        format!("{}::<{from_ty}, {to_ty}>", last.ident.as_str()),
+        Applicability::MaybeIncorrect,
+    );
+    true
+}
diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs
index 3c11b481310..7fa536a1a29 100644
--- a/clippy_lints/src/transmute/mod.rs
+++ b/clippy_lints/src/transmute/mod.rs
@@ -1,5 +1,6 @@
 mod crosspointer_transmute;
 mod eager_transmute;
+mod missing_transmute_annotations;
 mod transmute_float_to_int;
 mod transmute_int_to_bool;
 mod transmute_int_to_char;
@@ -520,6 +521,37 @@ declare_clippy_lint! {
     "eager evaluation of `transmute`"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks if transmute calls have all generics specified.
+    ///
+    /// ### Why is this bad?
+    /// If not set, some unexpected output type could be retrieved instead of the expected one,
+    /// potentially leading to invalid code.
+    ///
+    /// This is particularly dangerous in case a seemingly innocent/unrelated change can cause type
+    /// inference to start inferring a different type. E.g. the transmute is the tail expression of
+    /// an `if` branch, and a different branches type changes, causing the transmute to silently
+    /// have a different type, instead of a proper error.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// # unsafe {
+    /// let x: i32 = std::mem::transmute([1u16, 2u16]);
+    /// # }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// # unsafe {
+    /// let x = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+    /// # }
+    /// ```
+    #[clippy::version = "1.77.0"]
+    pub MISSING_TRANSMUTE_ANNOTATIONS,
+    suspicious,
+    "warns if a transmute call doesn't have all generics specified"
+}
+
 pub struct Transmute {
     msrv: Msrv,
 }
@@ -542,6 +574,7 @@ impl_lint_pass!(Transmute => [
     TRANSMUTING_NULL,
     TRANSMUTE_NULL_TO_FN,
     EAGER_TRANSMUTE,
+    MISSING_TRANSMUTE_ANNOTATIONS,
 ]);
 impl Transmute {
     #[must_use]
@@ -579,6 +612,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
                 | transmuting_null::check(cx, e, arg, to_ty)
                 | transmute_null_to_fn::check(cx, e, arg, to_ty)
                 | transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, &self.msrv)
+                | missing_transmute_annotations::check(cx, path, from_ty, to_ty, e.hir_id)
                 | transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context)
                 | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context)
                 | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg)
diff --git a/clippy_lints/src/transmute/transmute_float_to_int.rs b/clippy_lints/src/transmute/transmute_float_to_int.rs
index aef520923e4..ab3bb5e1062 100644
--- a/clippy_lints/src/transmute/transmute_float_to_int.rs
+++ b/clippy_lints/src/transmute/transmute_float_to_int.rs
@@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 TRANSMUTE_FLOAT_TO_INT,
                 e.span,
-                &format!("transmute from a `{from_ty}` to a `{to_ty}`"),
+                format!("transmute from a `{from_ty}` to a `{to_ty}`"),
                 |diag| {
                     let mut sugg = sugg::Sugg::hir(cx, arg, "..");
 
diff --git a/clippy_lints/src/transmute/transmute_int_to_bool.rs b/clippy_lints/src/transmute/transmute_int_to_bool.rs
index 58227c53de2..a7192809077 100644
--- a/clippy_lints/src/transmute/transmute_int_to_bool.rs
+++ b/clippy_lints/src/transmute/transmute_int_to_bool.rs
@@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 TRANSMUTE_INT_TO_BOOL,
                 e.span,
-                &format!("transmute from a `{from_ty}` to a `bool`"),
+                format!("transmute from a `{from_ty}` to a `bool`"),
                 |diag| {
                     let arg = sugg::Sugg::hir(cx, arg, "..");
                     let zero = sugg::Sugg::NonParen(Cow::from("0"));
diff --git a/clippy_lints/src/transmute/transmute_int_to_char.rs b/clippy_lints/src/transmute/transmute_int_to_char.rs
index 2a6c2481254..81d10a7d5bd 100644
--- a/clippy_lints/src/transmute/transmute_int_to_char.rs
+++ b/clippy_lints/src/transmute/transmute_int_to_char.rs
@@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 TRANSMUTE_INT_TO_CHAR,
                 e.span,
-                &format!("transmute from a `{from_ty}` to a `char`"),
+                format!("transmute from a `{from_ty}` to a `char`"),
                 |diag| {
                     let Some(top_crate) = std_or_core(cx) else { return };
                     let arg = sugg::Sugg::hir(cx, arg, "..");
diff --git a/clippy_lints/src/transmute/transmute_int_to_float.rs b/clippy_lints/src/transmute/transmute_int_to_float.rs
index cc3422edbbf..d51888e3097 100644
--- a/clippy_lints/src/transmute/transmute_int_to_float.rs
+++ b/clippy_lints/src/transmute/transmute_int_to_float.rs
@@ -22,7 +22,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 TRANSMUTE_INT_TO_FLOAT,
                 e.span,
-                &format!("transmute from a `{from_ty}` to a `{to_ty}`"),
+                format!("transmute from a `{from_ty}` to a `{to_ty}`"),
                 |diag| {
                     let arg = sugg::Sugg::hir(cx, arg, "..");
                     let arg = if let ty::Int(int_ty) = from_ty.kind() {
diff --git a/clippy_lints/src/transmute/transmute_int_to_non_zero.rs b/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
index 97068efd43c..234021f0f47 100644
--- a/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
+++ b/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
@@ -58,7 +58,7 @@ pub(super) fn check<'tcx>(
         cx,
         TRANSMUTE_INT_TO_NON_ZERO,
         e.span,
-        &format!("transmute from a `{from_ty}` to a `{nonzero_alias}`"),
+        format!("transmute from a `{from_ty}` to a `{nonzero_alias}`"),
         |diag| {
             let arg = sugg::Sugg::hir(cx, arg, "..");
             diag.span_suggestion(
diff --git a/clippy_lints/src/transmute/transmute_num_to_bytes.rs b/clippy_lints/src/transmute/transmute_num_to_bytes.rs
index 009d5a7c8ae..88b0ac5a368 100644
--- a/clippy_lints/src/transmute/transmute_num_to_bytes.rs
+++ b/clippy_lints/src/transmute/transmute_num_to_bytes.rs
@@ -31,7 +31,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 TRANSMUTE_NUM_TO_BYTES,
                 e.span,
-                &format!("transmute from a `{from_ty}` to a `{to_ty}`"),
+                format!("transmute from a `{from_ty}` to a `{to_ty}`"),
                 |diag| {
                     let arg = sugg::Sugg::hir(cx, arg, "..");
                     diag.span_suggestion(
diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
index cf78709583c..eaf927c0005 100644
--- a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
+++ b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
@@ -25,7 +25,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 TRANSMUTE_PTR_TO_REF,
                 e.span,
-                &format!("transmute from a pointer type (`{from_ty}`) to a reference type (`{to_ty}`)"),
+                format!("transmute from a pointer type (`{from_ty}`) to a reference type (`{to_ty}`)"),
                 |diag| {
                     let arg = sugg::Sugg::hir(cx, arg, "..");
                     let (deref, cast) = if *mutbl == Mutability::Mut {
diff --git a/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/clippy_lints/src/transmute/transmute_ref_to_ref.rs
index 73321c56f3f..3842c4eb60e 100644
--- a/clippy_lints/src/transmute/transmute_ref_to_ref.rs
+++ b/clippy_lints/src/transmute/transmute_ref_to_ref.rs
@@ -35,7 +35,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 TRANSMUTE_BYTES_TO_STR,
                 e.span,
-                &format!("transmute from a `{from_ty}` to a `{to_ty}`"),
+                format!("transmute from a `{from_ty}` to a `{to_ty}`"),
                 "consider using",
                 if const_context {
                     format!("{top_crate}::str::from_utf8_unchecked{postfix}({snippet})")
diff --git a/clippy_lints/src/transmute/transmute_undefined_repr.rs b/clippy_lints/src/transmute/transmute_undefined_repr.rs
index 33c4031fa87..9c8dd37d53d 100644
--- a/clippy_lints/src/transmute/transmute_undefined_repr.rs
+++ b/clippy_lints/src/transmute/transmute_undefined_repr.rs
@@ -71,7 +71,7 @@ pub(super) fn check<'tcx>(
                     cx,
                     TRANSMUTE_UNDEFINED_REPR,
                     e.span,
-                    &format!("transmute from `{from_ty_orig}` which has an undefined layout"),
+                    format!("transmute from `{from_ty_orig}` which has an undefined layout"),
                     |diag| {
                         if from_ty_orig.peel_refs() != from_ty.peel_refs() {
                             diag.note(format!("the contained type `{from_ty}` has an undefined layout"));
@@ -85,7 +85,7 @@ pub(super) fn check<'tcx>(
                     cx,
                     TRANSMUTE_UNDEFINED_REPR,
                     e.span,
-                    &format!("transmute to `{to_ty_orig}` which has an undefined layout"),
+                    format!("transmute to `{to_ty_orig}` which has an undefined layout"),
                     |diag| {
                         if to_ty_orig.peel_refs() != to_ty.peel_refs() {
                             diag.note(format!("the contained type `{to_ty}` has an undefined layout"));
@@ -111,7 +111,7 @@ pub(super) fn check<'tcx>(
                     cx,
                     TRANSMUTE_UNDEFINED_REPR,
                     e.span,
-                    &format!(
+                    format!(
                         "transmute from `{from_ty_orig}` to `{to_ty_orig}`, both of which have an undefined layout"
                     ),
                     |diag| {
@@ -140,7 +140,7 @@ pub(super) fn check<'tcx>(
                     cx,
                     TRANSMUTE_UNDEFINED_REPR,
                     e.span,
-                    &format!("transmute from `{from_ty_orig}` which has an undefined layout"),
+                    format!("transmute from `{from_ty_orig}` which has an undefined layout"),
                     |diag| {
                         if from_ty_orig.peel_refs() != from_ty {
                             diag.note(format!("the contained type `{from_ty}` has an undefined layout"));
@@ -157,7 +157,7 @@ pub(super) fn check<'tcx>(
                     cx,
                     TRANSMUTE_UNDEFINED_REPR,
                     e.span,
-                    &format!("transmute into `{to_ty_orig}` which has an undefined layout"),
+                    format!("transmute into `{to_ty_orig}` which has an undefined layout"),
                     |diag| {
                         if to_ty_orig.peel_refs() != to_ty {
                             diag.note(format!("the contained type `{to_ty}` has an undefined layout"));
diff --git a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
index 043c9c88601..6f5ac625e35 100644
--- a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
+++ b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
@@ -53,7 +53,7 @@ pub(super) fn check<'tcx>(
         cx,
         TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
         e.span,
-        &format!("transmute from `{from_ty}` to `{to_ty}` which could be expressed as a pointer cast instead"),
+        format!("transmute from `{from_ty}` to `{to_ty}` which could be expressed as a pointer cast instead"),
         "try",
         sugg,
         app,
diff --git a/clippy_lints/src/transmute/unsound_collection_transmute.rs b/clippy_lints/src/transmute/unsound_collection_transmute.rs
index 891fefc17a6..35e93830766 100644
--- a/clippy_lints/src/transmute/unsound_collection_transmute.rs
+++ b/clippy_lints/src/transmute/unsound_collection_transmute.rs
@@ -37,7 +37,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty
                     cx,
                     UNSOUND_COLLECTION_TRANSMUTE,
                     e.span,
-                    &format!("transmute from `{from_ty}` to `{to_ty}` with mismatched layout is unsound"),
+                    format!("transmute from `{from_ty}` to `{to_ty}` with mismatched layout is unsound"),
                 );
                 true
             } else {
diff --git a/clippy_lints/src/transmute/useless_transmute.rs b/clippy_lints/src/transmute/useless_transmute.rs
index 70628f3d4f4..ec5fb2793f9 100644
--- a/clippy_lints/src/transmute/useless_transmute.rs
+++ b/clippy_lints/src/transmute/useless_transmute.rs
@@ -21,7 +21,7 @@ pub(super) fn check<'tcx>(
                 cx,
                 USELESS_TRANSMUTE,
                 e.span,
-                &format!("transmute from a type (`{from_ty}`) to itself"),
+                format!("transmute from a type (`{from_ty}`) to itself"),
             );
             true
         },
diff --git a/clippy_lints/src/transmute/wrong_transmute.rs b/clippy_lints/src/transmute/wrong_transmute.rs
index ed815884a76..14a5a308a64 100644
--- a/clippy_lints/src/transmute/wrong_transmute.rs
+++ b/clippy_lints/src/transmute/wrong_transmute.rs
@@ -13,7 +13,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty
                 cx,
                 WRONG_TRANSMUTE,
                 e.span,
-                &format!("transmute from a `{from_ty}` to a pointer"),
+                format!("transmute from a `{from_ty}` to a pointer"),
             );
             true
         },
diff --git a/clippy_lints/src/types/box_collection.rs b/clippy_lints/src/types/box_collection.rs
index fc3420af020..9ac73394548 100644
--- a/clippy_lints/src/types/box_collection.rs
+++ b/clippy_lints/src/types/box_collection.rs
@@ -21,9 +21,9 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
             cx,
             BOX_COLLECTION,
             hir_ty.span,
-            &format!("you seem to be trying to use `Box<{box_content}>`. Consider using just `{box_content}`"),
+            format!("you seem to be trying to use `Box<{box_content}>`. Consider using just `{box_content}`"),
             None,
-            &format!("`{box_content}` is already on the heap, `Box<{box_content}>` makes an extra allocation"),
+            format!("`{box_content}` is already on the heap, `Box<{box_content}>` makes an extra allocation"),
         );
         true
     } else {
diff --git a/clippy_lints/src/types/redundant_allocation.rs b/clippy_lints/src/types/redundant_allocation.rs
index 37437cbfbec..0801eace4fc 100644
--- a/clippy_lints/src/types/redundant_allocation.rs
+++ b/clippy_lints/src/types/redundant_allocation.rs
@@ -29,7 +29,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath:
             cx,
             REDUNDANT_ALLOCATION,
             hir_ty.span,
-            &format!("usage of `{outer_sym}<{generic_snippet}>`"),
+            format!("usage of `{outer_sym}<{generic_snippet}>`"),
             |diag| {
                 diag.span_suggestion(hir_ty.span, "try", format!("{generic_snippet}"), applicability);
                 diag.note(format!(
@@ -73,7 +73,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath:
             cx,
             REDUNDANT_ALLOCATION,
             hir_ty.span,
-            &format!("usage of `{outer_sym}<{inner_sym}<{generic_snippet}>>`"),
+            format!("usage of `{outer_sym}<{inner_sym}<{generic_snippet}>>`"),
             |diag| {
                 diag.span_suggestion(
                     hir_ty.span,
@@ -92,7 +92,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath:
             cx,
             REDUNDANT_ALLOCATION,
             hir_ty.span,
-            &format!("usage of `{outer_sym}<{inner_sym}<{generic_snippet}>>`"),
+            format!("usage of `{outer_sym}<{inner_sym}<{generic_snippet}>>`"),
             |diag| {
                 diag.note(format!(
                     "`{inner_sym}<{generic_snippet}>` is already on the heap, `{outer_sym}<{inner_sym}<{generic_snippet}>>` makes an extra allocation"
diff --git a/clippy_lints/src/unconditional_recursion.rs b/clippy_lints/src/unconditional_recursion.rs
index 8764e3006c6..0c4e2c91aec 100644
--- a/clippy_lints/src/unconditional_recursion.rs
+++ b/clippy_lints/src/unconditional_recursion.rs
@@ -23,7 +23,7 @@ declare_clippy_lint! {
     /// implementations.
     ///
     /// ### Why is this bad?
-    /// This is a hard to find infinite recursion that will crash any code.
+    /// This is a hard to find infinite recursion that will crash any code
     /// using it.
     ///
     /// ### Example
diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs
index 5fe4b74b3a7..cbd16180077 100644
--- a/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -200,7 +200,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
         let item_has_safety_comment = item_has_safety_comment(cx, item);
         match (&item.kind, item_has_safety_comment) {
             // lint unsafe impl without safety comment
-            (hir::ItemKind::Impl(impl_), HasSafetyComment::No) if impl_.unsafety == hir::Unsafety::Unsafe => {
+            (ItemKind::Impl(impl_), HasSafetyComment::No) if impl_.unsafety == hir::Unsafety::Unsafe => {
                 if !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, item.hir_id())
                     && !is_unsafe_from_proc_macro(cx, item.span)
                 {
@@ -222,7 +222,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
                 }
             },
             // lint safe impl with unnecessary safety comment
-            (hir::ItemKind::Impl(impl_), HasSafetyComment::Yes(pos)) if impl_.unsafety == hir::Unsafety::Normal => {
+            (ItemKind::Impl(impl_), HasSafetyComment::Yes(pos)) if impl_.unsafety == hir::Unsafety::Normal => {
                 if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) {
                     let (span, help_span) = mk_spans(pos);
 
@@ -236,9 +236,9 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
                     );
                 }
             },
-            (hir::ItemKind::Impl(_), _) => {},
+            (ItemKind::Impl(_), _) => {},
             // const and static items only need a safety comment if their body is an unsafe block, lint otherwise
-            (&hir::ItemKind::Const(.., body) | &hir::ItemKind::Static(.., body), HasSafetyComment::Yes(pos)) => {
+            (&ItemKind::Const(.., body) | &ItemKind::Static(.., body), HasSafetyComment::Yes(pos)) => {
                 if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, body.hir_id) {
                     let body = cx.tcx.hir().body(body);
                     if !matches!(
@@ -251,7 +251,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
                             cx,
                             UNNECESSARY_SAFETY_COMMENT,
                             span,
-                            &format!("{} has unnecessary safety comment", item.kind.descr()),
+                            format!("{} has unnecessary safety comment", item.kind.descr()),
                             Some(help_span),
                             "consider removing the safety comment",
                         );
@@ -268,7 +268,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
                         cx,
                         UNNECESSARY_SAFETY_COMMENT,
                         span,
-                        &format!("{} has unnecessary safety comment", item.kind.descr()),
+                        format!("{} has unnecessary safety comment", item.kind.descr()),
                         Some(help_span),
                         "consider removing the safety comment",
                     );
@@ -338,13 +338,13 @@ fn block_parents_have_safety_comment(
     accept_comment_above_statement: bool,
     accept_comment_above_attributes: bool,
     cx: &LateContext<'_>,
-    id: hir::HirId,
+    id: HirId,
 ) -> bool {
     let (span, hir_id) = match cx.tcx.parent_hir_node(id) {
         Node::Expr(expr) => match cx.tcx.parent_hir_node(expr.hir_id) {
             Node::LetStmt(hir::LetStmt { span, hir_id, .. }) => (*span, *hir_id),
             Node::Item(hir::Item {
-                kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
+                kind: ItemKind::Const(..) | ItemKind::Static(..),
                 span,
                 owner_id,
                 ..
@@ -365,7 +365,7 @@ fn block_parents_have_safety_comment(
         })
         | Node::LetStmt(hir::LetStmt { span, hir_id, .. }) => (*span, *hir_id),
         Node::Item(hir::Item {
-            kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
+            kind: ItemKind::Const(..) | ItemKind::Static(..),
             span,
             owner_id,
             ..
@@ -605,11 +605,11 @@ fn get_body_search_span(cx: &LateContext<'_>) -> Option<Span> {
             Node::Expr(e) => span = e.span,
             Node::Block(_) | Node::Arm(_) | Node::Stmt(_) | Node::LetStmt(_) => (),
             Node::Item(hir::Item {
-                kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
+                kind: ItemKind::Const(..) | ItemKind::Static(..),
                 ..
             }) => maybe_global_var = true,
             Node::Item(hir::Item {
-                kind: hir::ItemKind::Mod(_),
+                kind: ItemKind::Mod(_),
                 span: item_span,
                 ..
             }) => {
diff --git a/clippy_lints/src/unit_return_expecting_ord.rs b/clippy_lints/src/unit_return_expecting_ord.rs
index 729972de6e6..214b69dc925 100644
--- a/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/clippy_lints/src/unit_return_expecting_ord.rs
@@ -153,7 +153,7 @@ impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd {
                                 cx,
                                 UNIT_RETURN_EXPECTING_ORD,
                                 span,
-                                &format!(
+                                format!(
                                     "this closure returns \
                                    the unit type which also implements {trait_name}"
                                 ),
@@ -164,7 +164,7 @@ impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd {
                                 cx,
                                 UNIT_RETURN_EXPECTING_ORD,
                                 span,
-                                &format!(
+                                format!(
                                     "this closure returns \
                                    the unit type which also implements {trait_name}"
                                 ),
diff --git a/clippy_lints/src/unit_types/let_unit_value.rs b/clippy_lints/src/unit_types/let_unit_value.rs
index ffb909d7907..80b661a757c 100644
--- a/clippy_lints/src/unit_types/let_unit_value.rs
+++ b/clippy_lints/src/unit_types/let_unit_value.rs
@@ -1,9 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_context;
-use clippy_utils::visitors::{for_each_local_assignment, for_each_value_source};
+use clippy_utils::visitors::{for_each_local_assignment, for_each_value_source, is_local_used};
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
+use rustc_hir::intravisit::{walk_body, Visitor};
 use rustc_hir::{Expr, ExprKind, HirId, HirIdSet, LetStmt, MatchSource, Node, PatKind, QPath, TyKind};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::{in_external_macro, is_from_async_await};
@@ -75,12 +76,53 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) {
                         let snip = snippet_with_context(cx, expr.span, local.span.ctxt(), "()", &mut app).0;
                         diag.span_suggestion(local.span, "omit the `let` binding", format!("{snip};"), app);
                     }
+
+                    if let PatKind::Binding(_, binding_hir_id, ident, ..) = local.pat.kind
+                        && let Some(body_id) = cx.enclosing_body.as_ref()
+                        && let body = cx.tcx.hir().body(*body_id)
+                        && is_local_used(cx, body, binding_hir_id)
+                    {
+                        let identifier = ident.as_str();
+                        let mut visitor = UnitVariableCollector::new(binding_hir_id);
+                        walk_body(&mut visitor, body);
+                        visitor.spans.into_iter().for_each(|span| {
+                            let msg =
+                                format!("variable `{identifier}` of type `()` can be replaced with explicit `()`");
+                            diag.span_suggestion(span, msg, "()", Applicability::MachineApplicable);
+                        });
+                    }
                 },
             );
         }
     }
 }
 
+struct UnitVariableCollector {
+    id: HirId,
+    spans: Vec<rustc_span::Span>,
+}
+
+impl UnitVariableCollector {
+    fn new(id: HirId) -> Self {
+        Self { id, spans: vec![] }
+    }
+}
+
+/**
+ * Collect all instances where a variable is used based on its `HirId`.
+ */
+impl<'tcx> Visitor<'tcx> for UnitVariableCollector {
+    fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) -> Self::Result {
+        if let ExprKind::Path(QPath::Resolved(None, path)) = ex.kind
+            && let Res::Local(id) = path.res
+            && id == self.id
+        {
+            self.spans.push(path.span);
+        }
+        rustc_hir::intravisit::walk_expr(self, ex);
+    }
+}
+
 /// Checks sub-expressions which create the value returned by the given expression for whether
 /// return value inference is needed. This checks through locals to see if they also need inference
 /// at this point.
diff --git a/clippy_lints/src/unit_types/unit_arg.rs b/clippy_lints/src/unit_types/unit_arg.rs
index eba7fa7b993..afc53e6f32d 100644
--- a/clippy_lints/src/unit_types/unit_arg.rs
+++ b/clippy_lints/src/unit_types/unit_arg.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_from_proc_macro;
 use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
 use rustc_errors::Applicability;
-use rustc_hir::{self as hir, Block, Expr, ExprKind, MatchSource, Node, StmtKind};
+use rustc_hir::{Block, Expr, ExprKind, MatchSource, Node, StmtKind};
 use rustc_lint::LateContext;
 
 use super::{utils, UNIT_ARG};
@@ -19,7 +19,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
     if is_questionmark_desugar_marked_call(expr) {
         return;
     }
-    if let hir::Node::Expr(parent_expr) = cx.tcx.parent_hir_node(expr.hir_id)
+    if let Node::Expr(parent_expr) = cx.tcx.parent_hir_node(expr.hir_id)
         && is_questionmark_desugar_marked_call(parent_expr)
     {
         return;
@@ -69,7 +69,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
         cx,
         UNIT_ARG,
         expr.span,
-        &format!("passing {singular}unit value{plural} to a function"),
+        format!("passing {singular}unit value{plural} to a function"),
         |db| {
             let mut or = "";
             args_to_recover
diff --git a/clippy_lints/src/unit_types/unit_cmp.rs b/clippy_lints/src/unit_types/unit_cmp.rs
index d4342ec5169..6dcc1195a70 100644
--- a/clippy_lints/src/unit_types/unit_cmp.rs
+++ b/clippy_lints/src/unit_types/unit_cmp.rs
@@ -24,7 +24,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
                 cx,
                 UNIT_CMP,
                 macro_call.span,
-                &format!("`{macro_name}` of unit values detected. This will always {result}"),
+                format!("`{macro_name}` of unit values detected. This will always {result}"),
             );
         }
         return;
@@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
                 cx,
                 UNIT_CMP,
                 expr.span,
-                &format!(
+                format!(
                     "{}-comparison of unit values detected. This will always be {result}",
                     op.as_str()
                 ),
diff --git a/clippy_lints/src/unnecessary_box_returns.rs b/clippy_lints/src/unnecessary_box_returns.rs
index c332cf076ae..bfcefb26153 100644
--- a/clippy_lints/src/unnecessary_box_returns.rs
+++ b/clippy_lints/src/unnecessary_box_returns.rs
@@ -88,7 +88,7 @@ impl UnnecessaryBoxReturns {
                 cx,
                 UNNECESSARY_BOX_RETURNS,
                 return_ty_hir.span,
-                format!("boxed return of the sized type `{boxed_ty}`").as_str(),
+                format!("boxed return of the sized type `{boxed_ty}`"),
                 |diagnostic| {
                     diagnostic.span_suggestion(
                         return_ty_hir.span,
diff --git a/clippy_lints/src/unnecessary_map_on_constructor.rs b/clippy_lints/src/unnecessary_map_on_constructor.rs
index 2b0d2d61d20..8f1eb5019f0 100644
--- a/clippy_lints/src/unnecessary_map_on_constructor.rs
+++ b/clippy_lints/src/unnecessary_map_on_constructor.rs
@@ -65,7 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMapOnConstructor {
                 hir::QPath::LangItem(..) => return,
             };
             match constructor_symbol {
-                sym::Some | sym::Ok if path.ident.name == rustc_span::sym::map => (),
+                sym::Some | sym::Ok if path.ident.name == sym::map => (),
                 sym::Err if path.ident.name == sym::map_err => (),
                 _ => return,
             }
@@ -86,7 +86,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMapOnConstructor {
                     cx,
                     UNNECESSARY_MAP_ON_CONSTRUCTOR,
                     expr.span,
-                    &format!(
+                    format!(
                         "unnecessary {} on constructor {constructor_snippet}(_)",
                         path.ident.name
                     ),
diff --git a/clippy_lints/src/unnecessary_wraps.rs b/clippy_lints/src/unnecessary_wraps.rs
index 9c8b0ae1727..5c7fbbab988 100644
--- a/clippy_lints/src/unnecessary_wraps.rs
+++ b/clippy_lints/src/unnecessary_wraps.rs
@@ -156,7 +156,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
                 )
             };
 
-            span_lint_and_then(cx, UNNECESSARY_WRAPS, span, lint_msg.as_str(), |diag| {
+            span_lint_and_then(cx, UNNECESSARY_WRAPS, span, lint_msg, |diag| {
                 diag.span_suggestion(
                     fn_decl.output.span(),
                     return_type_sugg_msg,
diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs
index d4dd31e1178..0049de931f4 100644
--- a/clippy_lints/src/unnested_or_patterns.rs
+++ b/clippy_lints/src/unnested_or_patterns.rs
@@ -215,7 +215,7 @@ macro_rules! always_pat {
 /// in `alternatives[focus_idx + 1..]`.
 fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: usize) -> bool {
     // Extract the kind; we'll need to make some changes in it.
-    let mut focus_kind = mem::replace(&mut alternatives[focus_idx].kind, PatKind::Wild);
+    let mut focus_kind = mem::replace(&mut alternatives[focus_idx].kind, Wild);
     // We'll focus on `alternatives[focus_idx]`,
     // so we're draining from `alternatives[focus_idx + 1..]`.
     let start = focus_idx + 1;
@@ -232,7 +232,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: us
         // In the case of only two patterns, replacement adds net characters.
         | Ref(_, Mutability::Not)
         // Dealt with elsewhere.
-        | Or(_) | Paren(_) => false,
+        | Or(_) | Paren(_) | Deref(_) => false,
         // Transform `box x | ... | box y` into `box (x | y)`.
         //
         // The cases below until `Slice(...)` deal with *singleton* products.
@@ -242,8 +242,6 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: us
             |k| matches!(k, Box(_)),
             |k| always_pat!(k, Box(p) => p),
         ),
-        // FIXME(deref_patterns): Should we merge patterns here?
-        Deref(_) => false,
         // Transform `&mut x | ... | &mut y` into `&mut (x | y)`.
         Ref(target, Mutability::Mut) => extend_with_matching(
             target, start, alternatives,
diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs
index 3f2f765f751..51b3ea93b6d 100644
--- a/clippy_lints/src/unsafe_removed_from_name.rs
+++ b/clippy_lints/src/unsafe_removed_from_name.rs
@@ -65,7 +65,7 @@ fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext<'_>,
             cx,
             UNSAFE_REMOVED_FROM_NAME,
             span,
-            &format!("removed `unsafe` from the name of `{old_str}` in use as `{new_str}`"),
+            format!("removed `unsafe` from the name of `{old_str}` in use as `{new_str}`"),
         );
     }
 }
diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs
index d8c5f1b7382..448946bd66d 100644
--- a/clippy_lints/src/unused_io_amount.rs
+++ b/clippy_lints/src/unused_io_amount.rs
@@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
         if let Some(exp) = block.expr
             && matches!(
                 exp.kind,
-                hir::ExprKind::If(_, _, _) | hir::ExprKind::Match(_, _, hir::MatchSource::Normal)
+                ExprKind::If(_, _, _) | ExprKind::Match(_, _, hir::MatchSource::Normal)
             )
         {
             check_expr(cx, exp);
@@ -130,7 +130,7 @@ fn non_consuming_ok_arm<'a>(cx: &LateContext<'a>, arm: &hir::Arm<'a>) -> bool {
 
 fn check_expr<'a>(cx: &LateContext<'a>, expr: &'a hir::Expr<'a>) {
     match expr.kind {
-        hir::ExprKind::If(cond, _, _)
+        ExprKind::If(cond, _, _)
             if let ExprKind::Let(hir::LetExpr { pat, init, .. }) = cond.kind
                 && is_ok_wild_or_dotdot_pattern(cx, pat)
                 && let Some(op) = should_lint(cx, init) =>
@@ -140,7 +140,7 @@ fn check_expr<'a>(cx: &LateContext<'a>, expr: &'a hir::Expr<'a>) {
         // we will capture only the case where the match is Ok( ) or Err( )
         // prefer to match the minimum possible, and expand later if needed
         // to avoid false positives on something as used as this
-        hir::ExprKind::Match(expr, [arm1, arm2], hir::MatchSource::Normal) if let Some(op) = should_lint(cx, expr) => {
+        ExprKind::Match(expr, [arm1, arm2], hir::MatchSource::Normal) if let Some(op) = should_lint(cx, expr) => {
             if non_consuming_ok_arm(cx, arm1) && non_consuming_err_arm(cx, arm2) {
                 emit_lint(cx, expr.span, expr.hir_id, op, &[arm1.pat.span]);
             }
@@ -148,7 +148,7 @@ fn check_expr<'a>(cx: &LateContext<'a>, expr: &'a hir::Expr<'a>) {
                 emit_lint(cx, expr.span, expr.hir_id, op, &[arm2.pat.span]);
             }
         },
-        hir::ExprKind::Match(_, _, hir::MatchSource::Normal) => {},
+        ExprKind::Match(_, _, hir::MatchSource::Normal) => {},
         _ if let Some(op) = should_lint(cx, expr) => {
             emit_lint(cx, expr.span, expr.hir_id, op, &[]);
         },
@@ -201,7 +201,7 @@ fn is_unreachable_or_panic(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
 }
 
 fn unpack_call_chain<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
-    while let hir::ExprKind::MethodCall(path, receiver, ..) = expr.kind {
+    while let ExprKind::MethodCall(path, receiver, ..) = expr.kind {
         if matches!(
             path.ident.as_str(),
             "unwrap" | "expect" | "unwrap_or" | "unwrap_or_else" | "ok" | "is_ok" | "is_err" | "or_else" | "or"
@@ -215,10 +215,10 @@ fn unpack_call_chain<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
 }
 
 fn unpack_try<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
-    while let hir::ExprKind::Call(func, [ref arg_0, ..]) = expr.kind
+    while let ExprKind::Call(func, [ref arg_0, ..]) = expr.kind
         && matches!(
             func.kind,
-            hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, ..))
+            ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, ..))
         )
     {
         expr = arg_0;
@@ -227,7 +227,7 @@ fn unpack_try<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
 }
 
 fn unpack_match<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
-    while let hir::ExprKind::Match(res, _, _) = expr.kind {
+    while let ExprKind::Match(res, _, _) = expr.kind {
         expr = res;
     }
     expr
@@ -236,11 +236,11 @@ fn unpack_match<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
 /// If `expr` is an (e).await, return the inner expression "e" that's being
 /// waited on.  Otherwise return None.
 fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &hir::Expr<'a> {
-    if let hir::ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind {
-        if let hir::ExprKind::Call(func, [ref arg_0, ..]) = expr.kind {
+    if let ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind {
+        if let ExprKind::Call(func, [ref arg_0, ..]) = expr.kind {
             if matches!(
                 func.kind,
-                hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..))
+                ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..))
             ) {
                 return arg_0;
             }
@@ -251,7 +251,7 @@ fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &hir::Expr<'a> {
 
 /// Check whether the current expr is a function call for an IO operation
 fn check_io_mode(cx: &LateContext<'_>, call: &hir::Expr<'_>) -> Option<IoOp> {
-    let hir::ExprKind::MethodCall(path, ..) = call.kind else {
+    let ExprKind::MethodCall(path, ..) = call.kind else {
         return None;
     };
 
diff --git a/clippy_lints/src/unused_rounding.rs b/clippy_lints/src/unused_rounding.rs
index d5ca844b9e2..3e5afec541c 100644
--- a/clippy_lints/src/unused_rounding.rs
+++ b/clippy_lints/src/unused_rounding.rs
@@ -55,8 +55,8 @@ impl EarlyLintPass for UnusedRounding {
                 cx,
                 UNUSED_ROUNDING,
                 expr.span,
-                &format!("used the `{method_name}` method with a whole number float"),
-                &format!("remove the `{method_name}` method call"),
+                format!("used the `{method_name}` method with a whole number float"),
+                format!("remove the `{method_name}` method call"),
                 float,
                 Applicability::MachineApplicable,
             );
diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs
index f2eb774b5cb..2622abd59cb 100644
--- a/clippy_lints/src/unwrap.rs
+++ b/clippy_lints/src/unwrap.rs
@@ -338,7 +338,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
                         UNNECESSARY_UNWRAP,
                         expr.hir_id,
                         expr.span,
-                        &format!(
+                        format!(
                             "called `{}` on `{unwrappable_variable_name}` after checking its variant with `{}`",
                             method_name.ident.name,
                             unwrappable.check_name.ident.as_str(),
@@ -373,7 +373,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
                         PANICKING_UNWRAP,
                         expr.hir_id,
                         expr.span,
-                        &format!("this call to `{}()` will always panic", method_name.ident.name),
+                        format!("this call to `{}()` will always panic", method_name.ident.name),
                         |diag| {
                             diag.span_label(unwrappable.check.span, "because of this check");
                         },
diff --git a/clippy_lints/src/unwrap_in_result.rs b/clippy_lints/src/unwrap_in_result.rs
index a615ef11691..aca500590ce 100644
--- a/clippy_lints/src/unwrap_in_result.rs
+++ b/clippy_lints/src/unwrap_in_result.rs
@@ -59,7 +59,7 @@ declare_lint_pass!(UnwrapInResult=> [UNWRAP_IN_RESULT]);
 
 impl<'tcx> LateLintPass<'tcx> for UnwrapInResult {
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
-        if let hir::ImplItemKind::Fn(ref _signature, _) = impl_item.kind
+        if let ImplItemKind::Fn(ref _signature, _) = impl_item.kind
             // first check if it's a method or function
             // checking if its return type is `result` or `option`
             && (is_type_diagnostic_item(cx, return_ty(cx, impl_item.owner_id), sym::Result)
diff --git a/clippy_lints/src/upper_case_acronyms.rs b/clippy_lints/src/upper_case_acronyms.rs
index d2a1d42f279..f376d349646 100644
--- a/clippy_lints/src/upper_case_acronyms.rs
+++ b/clippy_lints/src/upper_case_acronyms.rs
@@ -94,7 +94,7 @@ fn check_ident(cx: &LateContext<'_>, ident: &Ident, hir_id: HirId, be_aggressive
             UPPER_CASE_ACRONYMS,
             hir_id,
             span,
-            &format!("name `{ident}` contains a capitalized acronym"),
+            format!("name `{ident}` contains a capitalized acronym"),
             |diag| {
                 diag.span_suggestion(
                     span,
diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs
index a6b411d6c0f..0bab917607d 100644
--- a/clippy_lints/src/use_self.rs
+++ b/clippy_lints/src/use_self.rs
@@ -207,7 +207,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
         }
     }
 
-    fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) {
+    fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &Ty<'tcx>) {
         if !hir_ty.span.from_expansion()
             && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS)
             && let Some(&StackItem::Check {
@@ -286,7 +286,7 @@ impl<'tcx> Visitor<'tcx> for SkipTyCollector {
 
         walk_inf(self, inf);
     }
-    fn visit_ty(&mut self, hir_ty: &hir::Ty<'_>) {
+    fn visit_ty(&mut self, hir_ty: &Ty<'_>) {
         self.types_to_skip.push(hir_ty.hir_id);
 
         walk_ty(self, hir_ty);
diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs
index f7a455977fa..75541766156 100644
--- a/clippy_lints/src/useless_conversion.rs
+++ b/clippy_lints/src/useless_conversion.rs
@@ -184,7 +184,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                             cx,
                             USELESS_CONVERSION,
                             e.span,
-                            &format!("useless conversion to the same type: `{b}`"),
+                            format!("useless conversion to the same type: `{b}`"),
                             "consider removing `.into()`",
                             sugg.into_owned(),
                             app,
@@ -301,7 +301,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                             cx,
                             USELESS_CONVERSION,
                             e.span,
-                            &format!("useless conversion to the same type: `{b}`"),
+                            format!("useless conversion to the same type: `{b}`"),
                             "consider removing `.into_iter()`",
                             sugg,
                             Applicability::MachineApplicable, // snippet
@@ -321,7 +321,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                         cx,
                         USELESS_CONVERSION,
                         e.span,
-                        &format!("useless conversion to the same type: `{b}`"),
+                        format!("useless conversion to the same type: `{b}`"),
                         None,
                         "consider removing `.try_into()`",
                     );
@@ -346,9 +346,9 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                             cx,
                             USELESS_CONVERSION,
                             e.span,
-                            &format!("useless conversion to the same type: `{b}`"),
+                            format!("useless conversion to the same type: `{b}`"),
                             None,
-                            &hint,
+                            hint,
                         );
                     }
 
@@ -360,8 +360,8 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                             cx,
                             USELESS_CONVERSION,
                             e.span,
-                            &format!("useless conversion to the same type: `{b}`"),
-                            &sugg_msg,
+                            format!("useless conversion to the same type: `{b}`"),
+                            sugg_msg,
                             sugg.to_string(),
                             app,
                         );
diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs
index e45beb4910b..7b43abeef67 100644
--- a/clippy_lints/src/utils/author.rs
+++ b/clippy_lints/src/utils/author.rs
@@ -754,7 +754,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
     }
 }
 
-fn has_attr(cx: &LateContext<'_>, hir_id: hir::HirId) -> bool {
+fn has_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
     let attrs = cx.tcx.hir().attrs(hir_id);
     get_attr(cx.sess(), attrs, "author").count() > 0
 }
@@ -771,7 +771,7 @@ fn path_to_string(path: &QPath<'_>) -> Result<String, ()> {
                 }
             },
             QPath::TypeRelative(ty, segment) => match &ty.kind {
-                hir::TyKind::Path(inner_path) => {
+                TyKind::Path(inner_path) => {
                     inner(s, inner_path)?;
                     *s += ", ";
                     write!(s, "{:?}", segment.ident.as_str()).unwrap();
diff --git a/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs b/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs
index 4822970e47e..5483e80f932 100644
--- a/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs
+++ b/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs
@@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for AlmostStandardFormulation {
                                         ident.span,
                                         "non-standard lint formulation",
                                         None,
-                                        &format!("consider using `{}`", formulation.correction),
+                                        format!("consider using `{}`", formulation.correction),
                                     );
                                 }
                                 return;
diff --git a/clippy_lints/src/utils/internal_lints/collapsible_calls.rs b/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
index 7c70d3f45db..f7529682675 100644
--- a/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
+++ b/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::{is_expr_path_def_path, is_lint_allowed, peel_blocks_with_stmt, SpanlessEq};
 use rustc_errors::Applicability;
-use rustc_hir as hir;
 use rustc_hir::{Closure, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
@@ -72,7 +71,7 @@ declare_clippy_lint! {
 declare_lint_pass!(CollapsibleCalls => [COLLAPSIBLE_SPAN_LINT_CALLS]);
 
 impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if is_lint_allowed(cx, COLLAPSIBLE_SPAN_LINT_CALLS, expr.hir_id) {
             return;
         }
diff --git a/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs b/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs
index df37619227c..9b6b6871818 100644
--- a/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs
+++ b/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs
@@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions {
                 path.ident.span,
                 "usage of a compiler lint function",
                 None,
-                &format!("please use the Clippy variant of this function: `{sugg}`"),
+                format!("please use the Clippy variant of this function: `{sugg}`"),
             );
         }
     }
diff --git a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
index 370ed430bcf..9be225759df 100644
--- a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
+++ b/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
@@ -181,7 +181,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
                                 cx,
                                 DEFAULT_LINT,
                                 item.span,
-                                &format!("the lint `{}` has the default lint description", item.ident.name),
+                                format!("the lint `{}` has the default lint description", item.ident.name),
                             );
                         }
 
@@ -191,7 +191,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
                             cx,
                             DEFAULT_DEPRECATION_REASON,
                             item.span,
-                            &format!("the lint `{}` has the default deprecation reason", item.ident.name),
+                            format!("the lint `{}` has the default deprecation reason", item.ident.name),
                         );
                     }
                 }
@@ -247,7 +247,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
                     cx,
                     LINT_WITHOUT_LINT_PASS,
                     lint_span,
-                    &format!("the lint `{lint_name}` is not added to any `LintPass`"),
+                    format!("the lint `{lint_name}` is not added to any `LintPass`"),
                 );
             }
         }
diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index c56c8ddc7a9..5c1ebb922f1 100644
--- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -153,7 +153,7 @@ impl MetadataCollector {
             lints: BinaryHeap::<LintMetadata>::default(),
             applicability_info: FxHashMap::<String, ApplicabilityInfo>::default(),
             config: get_configuration_metadata(),
-            clippy_project_root: std::env::current_dir()
+            clippy_project_root: env::current_dir()
                 .expect("failed to get current dir")
                 .ancestors()
                 .nth(1)
@@ -243,7 +243,7 @@ Please use that command to update the file and do not edit it by hand.
         .unwrap();
 
         // Write configuration links to CHANGELOG.md
-        let changelog = std::fs::read_to_string(CHANGELOG_PATH).unwrap();
+        let changelog = fs::read_to_string(CHANGELOG_PATH).unwrap();
         let mut changelog_file = File::create(CHANGELOG_PATH).unwrap();
         let position = changelog
             .find("<!-- begin autogenerated links to configuration documentation -->")
@@ -822,7 +822,7 @@ fn lint_collection_error_item(cx: &LateContext<'_>, item: &Item<'_>, message: &s
         cx,
         METADATA_COLLECTOR,
         item.ident.span,
-        &format!("metadata collection error for `{}`: {message}", item.ident.name),
+        format!("metadata collection error for `{}`: {message}", item.ident.name),
     );
 }
 
@@ -912,7 +912,7 @@ impl<'a, 'hir> LintResolver<'a, 'hir> {
     }
 }
 
-impl<'a, 'hir> intravisit::Visitor<'hir> for LintResolver<'a, 'hir> {
+impl<'a, 'hir> Visitor<'hir> for LintResolver<'a, 'hir> {
     type NestedFilter = nested_filter::All;
 
     fn nested_visit_map(&mut self) -> Self::Map {
@@ -963,7 +963,7 @@ impl<'a, 'hir> ApplicabilityResolver<'a, 'hir> {
     }
 }
 
-impl<'a, 'hir> intravisit::Visitor<'hir> for ApplicabilityResolver<'a, 'hir> {
+impl<'a, 'hir> Visitor<'hir> for ApplicabilityResolver<'a, 'hir> {
     type NestedFilter = nested_filter::All;
 
     fn nested_visit_map(&mut self) -> Self::Map {
@@ -994,7 +994,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for ApplicabilityResolver<'a, 'hir> {
 }
 
 /// This returns the parent local node if the expression is a reference one
-fn get_parent_local<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -> Option<&'hir hir::Local<'hir>> {
+fn get_parent_local<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -> Option<&'hir hir::LetStmt<'hir>> {
     if let ExprKind::Path(QPath::Resolved(_, path)) = expr.kind {
         if let hir::def::Res::Local(local_hir) = path.res {
             return get_parent_local_hir_id(cx, local_hir);
@@ -1004,7 +1004,7 @@ fn get_parent_local<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -
     None
 }
 
-fn get_parent_local_hir_id<'hir>(cx: &LateContext<'hir>, hir_id: hir::HirId) -> Option<&'hir hir::Local<'hir>> {
+fn get_parent_local_hir_id<'hir>(cx: &LateContext<'hir>, hir_id: hir::HirId) -> Option<&'hir hir::LetStmt<'hir>> {
     match cx.tcx.parent_hir_node(hir_id) {
         hir::Node::LetStmt(local) => Some(local),
         hir::Node::Pat(pattern) => get_parent_local_hir_id(cx, pattern.hir_id),
@@ -1042,7 +1042,7 @@ impl<'a, 'hir> IsMultiSpanScanner<'a, 'hir> {
     }
 }
 
-impl<'a, 'hir> intravisit::Visitor<'hir> for IsMultiSpanScanner<'a, 'hir> {
+impl<'a, 'hir> Visitor<'hir> for IsMultiSpanScanner<'a, 'hir> {
     type NestedFilter = nested_filter::All;
 
     fn nested_visit_map(&mut self) -> Self::Map {
diff --git a/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs b/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
index 8d208fbb7e9..63fcbd61528 100644
--- a/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
+++ b/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
@@ -51,8 +51,8 @@ impl LateLintPass<'_> for MsrvAttrImpl {
                 cx,
                 MISSING_MSRV_ATTR_IMPL,
                 span,
-                &format!("`extract_msrv_attr!` macro missing from `{lint_pass}` implementation"),
-                &format!("add `extract_msrv_attr!({context})` to the `{lint_pass}` implementation"),
+                format!("`extract_msrv_attr!` macro missing from `{lint_pass}` implementation"),
+                format!("add `extract_msrv_attr!({context})` to the `{lint_pass}` implementation"),
                 format!("{}\n    extract_msrv_attr!({context});", snippet(cx, span, "..")),
                 Applicability::MachineApplicable,
             );
diff --git a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
index 304a1379374..8cf42832761 100644
--- a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
+++ b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
@@ -4,10 +4,9 @@ use clippy_utils::{def_path_def_ids, is_lint_allowed, match_any_def_paths, peel_
 use rustc_ast::ast::LitKind;
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_errors::Applicability;
-use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
-use rustc_hir::{Expr, ExprKind, Local, Mutability, Node};
+use rustc_hir::{Expr, ExprKind, LetStmt, Mutability, Node};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::interpret::{Allocation, GlobalAlloc};
 use rustc_middle::mir::ConstValue;
@@ -49,7 +48,7 @@ pub struct UnnecessaryDefPath {
 }
 
 impl<'tcx> LateLintPass<'tcx> for UnnecessaryDefPath {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if is_lint_allowed(cx, UNNECESSARY_DEF_PATH, expr.hir_id) {
             return;
         }
@@ -79,9 +78,9 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryDefPath {
                 cx,
                 UNNECESSARY_DEF_PATH,
                 span,
-                &format!("hardcoded path to a {msg}"),
+                format!("hardcoded path to a {msg}"),
                 None,
-                &format!("convert all references to use `{sugg}`"),
+                format!("convert all references to use `{sugg}`"),
             );
         }
     }
@@ -213,11 +212,11 @@ impl UnnecessaryDefPath {
     }
 }
 
-fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Vec<String>> {
+fn path_to_matched_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Vec<String>> {
     match peel_hir_expr_refs(expr).0.kind {
         ExprKind::Path(ref qpath) => match cx.qpath_res(qpath, expr.hir_id) {
             Res::Local(hir_id) => {
-                if let Node::LetStmt(Local { init: Some(init), .. }) = cx.tcx.parent_hir_node(hir_id) {
+                if let Node::LetStmt(LetStmt { init: Some(init), .. }) = cx.tcx.parent_hir_node(hir_id) {
                     path_to_matched_type(cx, init)
                 } else {
                     None
diff --git a/clippy_lints/src/visibility.rs b/clippy_lints/src/visibility.rs
index 83369c66367..9818b98dd5b 100644
--- a/clippy_lints/src/visibility.rs
+++ b/clippy_lints/src/visibility.rs
@@ -89,7 +89,7 @@ impl EarlyLintPass for Visibility {
                     cx,
                     NEEDLESS_PUB_SELF,
                     item.vis.span,
-                    &format!("unnecessary `pub({}self)`", if *shorthand { "" } else { "in " }),
+                    format!("unnecessary `pub({}self)`", if *shorthand { "" } else { "in " }),
                     "remove it",
                     String::new(),
                     Applicability::MachineApplicable,
diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs
index be16d2e5cc3..26c6859233d 100644
--- a/clippy_lints/src/write.rs
+++ b/clippy_lints/src/write.rs
@@ -297,11 +297,11 @@ impl<'tcx> LateLintPass<'tcx> for Write {
         match diag_name {
             sym::print_macro | sym::println_macro if !allowed_in_tests => {
                 if !is_build_script {
-                    span_lint(cx, PRINT_STDOUT, macro_call.span, &format!("use of `{name}!`"));
+                    span_lint(cx, PRINT_STDOUT, macro_call.span, format!("use of `{name}!`"));
                 }
             },
             sym::eprint_macro | sym::eprintln_macro if !allowed_in_tests => {
-                span_lint(cx, PRINT_STDERR, macro_call.span, &format!("use of `{name}!`"));
+                span_lint(cx, PRINT_STDERR, macro_call.span, format!("use of `{name}!`"));
             },
             sym::write_macro | sym::writeln_macro => {},
             _ => return,
@@ -390,7 +390,7 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgs, macro_call: &Ma
             cx,
             lint,
             macro_call.span,
-            &format!("using `{name}!()` with a format string that ends in a single newline"),
+            format!("using `{name}!()` with a format string that ends in a single newline"),
             |diag| {
                 let name_span = cx.sess().source_map().span_until_char(macro_call.span, '!');
                 let Some(format_snippet) = snippet_opt(cx, format_string_span) else {
@@ -440,7 +440,7 @@ fn check_empty_string(cx: &LateContext<'_>, format_args: &FormatArgs, macro_call
             cx,
             lint,
             macro_call.span,
-            &format!("empty string literal in `{name}!`"),
+            format!("empty string literal in `{name}!`"),
             |diag| {
                 diag.span_suggestion(
                     span,
diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs
index d3623d6fda4..662242f6196 100644
--- a/clippy_lints/src/zero_div_zero.rs
+++ b/clippy_lints/src/zero_div_zero.rs
@@ -53,7 +53,7 @@ impl<'tcx> LateLintPass<'tcx> for ZeroDiv {
                 expr.span,
                 "constant division of `0.0` with `0.0` will always result in NaN",
                 None,
-                &format!("consider using `{float_type}::NAN` if you would like a constant representing NaN",),
+                format!("consider using `{float_type}::NAN` if you would like a constant representing NaN",),
             );
         }
     }
diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs
index f7532121aeb..f594a40ff59 100644
--- a/clippy_utils/src/ast_utils.rs
+++ b/clippy_utils/src/ast_utils.rs
@@ -97,8 +97,8 @@ pub fn eq_path_seg(l: &PathSegment, r: &PathSegment) -> bool {
 
 pub fn eq_generic_args(l: &GenericArgs, r: &GenericArgs) -> bool {
     match (l, r) {
-        (GenericArgs::AngleBracketed(l), GenericArgs::AngleBracketed(r)) => over(&l.args, &r.args, eq_angle_arg),
-        (GenericArgs::Parenthesized(l), GenericArgs::Parenthesized(r)) => {
+        (AngleBracketed(l), AngleBracketed(r)) => over(&l.args, &r.args, eq_angle_arg),
+        (Parenthesized(l), Parenthesized(r)) => {
             over(&l.inputs, &r.inputs, |l, r| eq_ty(l, r)) && eq_fn_ret_ty(&l.output, &r.output)
         },
         _ => false,
@@ -304,25 +304,25 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         (ExternCrate(l), ExternCrate(r)) => l == r,
         (Use(l), Use(r)) => eq_use_tree(l, r),
         (
-            Static(box ast::StaticItem {
+            Static(box StaticItem {
                 ty: lt,
                 mutability: lm,
                 expr: le,
             }),
-            Static(box ast::StaticItem {
+            Static(box StaticItem {
                 ty: rt,
                 mutability: rm,
                 expr: re,
             }),
         ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re),
         (
-            Const(box ast::ConstItem {
+            Const(box ConstItem {
                 defaultness: ld,
                 generics: lg,
                 ty: lt,
                 expr: le,
             }),
-            Const(box ast::ConstItem {
+            Const(box ConstItem {
                 defaultness: rd,
                 generics: rg,
                 ty: rt,
@@ -493,13 +493,13 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
     use AssocItemKind::*;
     match (l, r) {
         (
-            Const(box ast::ConstItem {
+            Const(box ConstItem {
                 defaultness: ld,
                 generics: lg,
                 ty: lt,
                 expr: le,
             }),
-            Const(box ast::ConstItem {
+            Const(box ConstItem {
                 defaultness: rd,
                 generics: rg,
                 ty: rt,
@@ -523,14 +523,14 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
             eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
         },
         (
-            Type(box ast::TyAlias {
+            Type(box TyAlias {
                 defaultness: ld,
                 generics: lg,
                 bounds: lb,
                 ty: lt,
                 ..
             }),
-            Type(box ast::TyAlias {
+            Type(box TyAlias {
                 defaultness: rd,
                 generics: rg,
                 bounds: rb,
diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs
index 2d0c2cf1253..d2200bcf710 100644
--- a/clippy_utils/src/attrs.rs
+++ b/clippy_utils/src/attrs.rs
@@ -1,10 +1,15 @@
 use rustc_ast::{ast, attr};
 use rustc_errors::Applicability;
+use rustc_lexer::TokenKind;
+use rustc_lint::LateContext;
 use rustc_middle::ty::{AdtDef, TyCtxt};
 use rustc_session::Session;
-use rustc_span::sym;
+use rustc_span::{sym, Span};
 use std::str::FromStr;
 
+use crate::source::snippet_opt;
+use crate::tokenize_with_text;
+
 /// Deprecation status of attributes known by Clippy.
 pub enum DeprecationStatus {
     /// Attribute is deprecated
@@ -171,3 +176,28 @@ pub fn has_non_exhaustive_attr(tcx: TyCtxt<'_>, adt: AdtDef<'_>) -> bool {
             .all_fields()
             .any(|field_def| tcx.has_attr(field_def.did, sym::non_exhaustive))
 }
+
+/// Checks if the given span contains a `#[cfg(..)]` attribute
+pub fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool {
+    let Some(snip) = snippet_opt(cx, s) else {
+        // Assume true. This would require either an invalid span, or one which crosses file boundaries.
+        return true;
+    };
+    let mut iter = tokenize_with_text(&snip);
+
+    // Search for the token sequence [`#`, `[`, `cfg`]
+    while iter.any(|(t, _)| matches!(t, TokenKind::Pound)) {
+        let mut iter = iter.by_ref().skip_while(|(t, _)| {
+            matches!(
+                t,
+                TokenKind::Whitespace | TokenKind::LineComment { .. } | TokenKind::BlockComment { .. }
+            )
+        });
+        if matches!(iter.next(), Some((TokenKind::OpenBracket, _)))
+            && matches!(iter.next(), Some((TokenKind::Ident, "cfg")))
+        {
+            return true;
+        }
+    }
+    false
+}
diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs
index d751aeaf902..42267310513 100644
--- a/clippy_utils/src/check_proc_macro.rs
+++ b/clippy_utils/src/check_proc_macro.rs
@@ -24,7 +24,7 @@ use rustc_hir::{
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
-use rustc_span::symbol::Ident;
+use rustc_span::symbol::{kw, Ident};
 use rustc_span::{Span, Symbol};
 use rustc_target::spec::abi::Abi;
 
@@ -99,9 +99,13 @@ fn qpath_search_pat(path: &QPath<'_>) -> (Pat, Pat) {
             let start = if ty.is_some() {
                 Pat::Str("<")
             } else {
-                path.segments
-                    .first()
-                    .map_or(Pat::Str(""), |seg| Pat::Sym(seg.ident.name))
+                path.segments.first().map_or(Pat::Str(""), |seg| {
+                    if seg.ident.name == kw::PathRoot {
+                        Pat::Str("::")
+                    } else {
+                        Pat::Sym(seg.ident.name)
+                    }
+                })
             };
             let end = path.segments.last().map_or(Pat::Str(""), |seg| {
                 if seg.args.is_some() {
diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs
index 6b86630339f..253ae3aca68 100644
--- a/clippy_utils/src/consts.rs
+++ b/clippy_utils/src/consts.rs
@@ -17,14 +17,14 @@ use rustc_span::def_id::DefId;
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::SyntaxContext;
 use rustc_target::abi::Size;
-use std::cmp::Ordering::{self, Equal};
+use std::cmp::Ordering;
 use std::hash::{Hash, Hasher};
 use std::iter;
 
 /// A `LitKind`-like enum to fold constant `Expr`s into.
 #[derive(Debug, Clone)]
 pub enum Constant<'tcx> {
-    Adt(rustc_middle::mir::Const<'tcx>),
+    Adt(mir::Const<'tcx>),
     /// A `String` (e.g., "abc").
     Str(String),
     /// A binary string (e.g., `b"abc"`).
@@ -230,7 +230,7 @@ impl<'tcx> Constant<'tcx> {
                     lv,
                     rv,
                 ) {
-                    Some(Equal) => Some(ls.cmp(rs)),
+                    Some(Ordering::Equal) => Some(ls.cmp(rs)),
                     x => x,
                 }
             },
@@ -579,7 +579,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     /// Lookup a possibly constant expression from an `ExprKind::Path` and apply a function on it.
     fn fetch_path_and_apply<T, F>(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>, f: F) -> Option<T>
     where
-        F: FnOnce(&mut Self, rustc_middle::mir::Const<'tcx>) -> Option<T>,
+        F: FnOnce(&mut Self, mir::Const<'tcx>) -> Option<T>,
     {
         let res = self.typeck_results.qpath_res(qpath, id);
         match res {
@@ -612,7 +612,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
                     .tcx
                     .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), qpath.span())
                     .ok()
-                    .map(|val| rustc_middle::mir::Const::from_value(val, ty))?;
+                    .map(|val| mir::Const::from_value(val, ty))?;
                 f(self, result)
             },
             _ => None,
diff --git a/clippy_utils/src/diagnostics.rs b/clippy_utils/src/diagnostics.rs
index 0352696f93e..dc0a139e3c7 100644
--- a/clippy_utils/src/diagnostics.rs
+++ b/clippy_utils/src/diagnostics.rs
@@ -8,7 +8,7 @@
 //! Thank you!
 //! ~The `INTERNAL_METADATA_COLLECTOR` lint
 
-use rustc_errors::{Applicability, Diag, MultiSpan};
+use rustc_errors::{Applicability, Diag, DiagMessage, MultiSpan, SubdiagMessage};
 use rustc_hir::HirId;
 use rustc_lint::{LateContext, Lint, LintContext};
 use rustc_span::Span;
@@ -59,9 +59,9 @@ fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) {
 /// 17 |     std::mem::forget(seven);
 ///    |     ^^^^^^^^^^^^^^^^^^^^^^^
 /// ```
-pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<MultiSpan>, msg: &str) {
+pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
     #[expect(clippy::disallowed_methods)]
-    cx.span_lint(lint, sp, msg.to_string(), |diag| {
+    cx.span_lint(lint, sp, msg.into(), |diag| {
         docs_link(diag, lint);
     });
 }
@@ -104,17 +104,16 @@ pub fn span_lint_and_help<T: LintContext>(
     cx: &T,
     lint: &'static Lint,
     span: impl Into<MultiSpan>,
-    msg: &str,
+    msg: impl Into<DiagMessage>,
     help_span: Option<Span>,
-    help: &str,
+    help: impl Into<SubdiagMessage>,
 ) {
     #[expect(clippy::disallowed_methods)]
-    cx.span_lint(lint, span, msg.to_string(), |diag| {
-        let help = help.to_string();
+    cx.span_lint(lint, span, msg.into(), |diag| {
         if let Some(help_span) = help_span {
-            diag.span_help(help_span, help);
+            diag.span_help(help_span, help.into());
         } else {
-            diag.help(help);
+            diag.help(help.into());
         }
         docs_link(diag, lint);
     });
@@ -161,17 +160,16 @@ pub fn span_lint_and_note<T: LintContext>(
     cx: &T,
     lint: &'static Lint,
     span: impl Into<MultiSpan>,
-    msg: &str,
+    msg: impl Into<DiagMessage>,
     note_span: Option<Span>,
-    note: &str,
+    note: impl Into<SubdiagMessage>,
 ) {
     #[expect(clippy::disallowed_methods)]
-    cx.span_lint(lint, span, msg.to_string(), |diag| {
-        let note = note.to_string();
+    cx.span_lint(lint, span, msg.into(), |diag| {
         if let Some(note_span) = note_span {
-            diag.span_note(note_span, note);
+            diag.span_note(note_span, note.into());
         } else {
-            diag.note(note);
+            diag.note(note.into());
         }
         docs_link(diag, lint);
     });
@@ -195,14 +193,15 @@ pub fn span_lint_and_note<T: LintContext>(
 /// If you're unsure which function you should use, you can test if the `#[allow]` attribute works
 /// where you would expect it to.
 /// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead.
-pub fn span_lint_and_then<C, S, F>(cx: &C, lint: &'static Lint, sp: S, msg: &str, f: F)
+pub fn span_lint_and_then<C, S, M, F>(cx: &C, lint: &'static Lint, sp: S, msg: M, f: F)
 where
     C: LintContext,
     S: Into<MultiSpan>,
+    M: Into<DiagMessage>,
     F: FnOnce(&mut Diag<'_, ()>),
 {
     #[expect(clippy::disallowed_methods)]
-    cx.span_lint(lint, sp, msg.to_string(), |diag| {
+    cx.span_lint(lint, sp, msg, |diag| {
         f(diag);
         docs_link(diag, lint);
     });
@@ -232,9 +231,9 @@ where
 /// Instead, use this function and also pass the `HirId` of `<expr_1>`, which will let
 /// the compiler check lint level attributes at the place of the expression and
 /// the `#[allow]` will work.
-pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) {
+pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: impl Into<DiagMessage>) {
     #[expect(clippy::disallowed_methods)]
-    cx.tcx.node_span_lint(lint, hir_id, sp, msg.to_string(), |diag| {
+    cx.tcx.node_span_lint(lint, hir_id, sp, msg.into(), |diag| {
         docs_link(diag, lint);
     });
 }
@@ -268,11 +267,11 @@ pub fn span_lint_hir_and_then(
     lint: &'static Lint,
     hir_id: HirId,
     sp: impl Into<MultiSpan>,
-    msg: &str,
+    msg: impl Into<DiagMessage>,
     f: impl FnOnce(&mut Diag<'_, ()>),
 ) {
     #[expect(clippy::disallowed_methods)]
-    cx.tcx.node_span_lint(lint, hir_id, sp, msg.to_string(), |diag| {
+    cx.tcx.node_span_lint(lint, hir_id, sp, msg.into(), |diag| {
         f(diag);
         docs_link(diag, lint);
     });
@@ -316,13 +315,13 @@ pub fn span_lint_and_sugg<T: LintContext>(
     cx: &T,
     lint: &'static Lint,
     sp: Span,
-    msg: &str,
-    help: &str,
+    msg: impl Into<DiagMessage>,
+    help: impl Into<SubdiagMessage>,
     sugg: String,
     applicability: Applicability,
 ) {
-    span_lint_and_then(cx, lint, sp, msg, |diag| {
-        diag.span_suggestion(sp, help.to_string(), sugg, applicability);
+    span_lint_and_then(cx, lint, sp, msg.into(), |diag| {
+        diag.span_suggestion(sp, help.into(), sugg, applicability);
     });
 }
 
@@ -332,7 +331,7 @@ pub fn span_lint_and_sugg<T: LintContext>(
 /// appear once per
 /// replacement. In human-readable format though, it only appears once before
 /// the whole suggestion.
-pub fn multispan_sugg<I>(diag: &mut Diag<'_, ()>, help_msg: &str, sugg: I)
+pub fn multispan_sugg<I>(diag: &mut Diag<'_, ()>, help_msg: impl Into<SubdiagMessage>, sugg: I)
 where
     I: IntoIterator<Item = (Span, String)>,
 {
@@ -346,11 +345,11 @@ where
 /// Suggestions with multiple spans will be silently ignored.
 pub fn multispan_sugg_with_applicability<I>(
     diag: &mut Diag<'_, ()>,
-    help_msg: &str,
+    help_msg: impl Into<SubdiagMessage>,
     applicability: Applicability,
     sugg: I,
 ) where
     I: IntoIterator<Item = (Span, String)>,
 {
-    diag.multipart_suggestion(help_msg.to_string(), sugg.into_iter().collect(), applicability);
+    diag.multipart_suggestion(help_msg.into(), sugg.into_iter().collect(), applicability);
 }
diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs
index 8ce19998a08..801a9852159 100644
--- a/clippy_utils/src/higher.rs
+++ b/clippy_utils/src/higher.rs
@@ -16,11 +16,11 @@ use rustc_span::{sym, symbol, Span};
 /// `for pat in arg { body }` becomes `(pat, arg, body)`. Returns `(pat, arg, body, span)`.
 pub struct ForLoop<'tcx> {
     /// `for` loop item
-    pub pat: &'tcx hir::Pat<'tcx>,
+    pub pat: &'tcx Pat<'tcx>,
     /// `IntoIterator` argument
-    pub arg: &'tcx hir::Expr<'tcx>,
+    pub arg: &'tcx Expr<'tcx>,
     /// `for` loop body
-    pub body: &'tcx hir::Expr<'tcx>,
+    pub body: &'tcx Expr<'tcx>,
     /// Compare this against `hir::Destination.target`
     pub loop_id: HirId,
     /// entire `for` loop span
@@ -30,13 +30,13 @@ pub struct ForLoop<'tcx> {
 impl<'tcx> ForLoop<'tcx> {
     /// Parses a desugared `for` loop
     pub fn hir(expr: &Expr<'tcx>) -> Option<Self> {
-        if let hir::ExprKind::DropTemps(e) = expr.kind
-            && let hir::ExprKind::Match(iterexpr, [arm], hir::MatchSource::ForLoopDesugar) = e.kind
-            && let hir::ExprKind::Call(_, [arg]) = iterexpr.kind
-            && let hir::ExprKind::Loop(block, ..) = arm.body.kind
+        if let ExprKind::DropTemps(e) = expr.kind
+            && let ExprKind::Match(iterexpr, [arm], MatchSource::ForLoopDesugar) = e.kind
+            && let ExprKind::Call(_, [arg]) = iterexpr.kind
+            && let ExprKind::Loop(block, ..) = arm.body.kind
             && let [stmt] = block.stmts
             && let hir::StmtKind::Expr(e) = stmt.kind
-            && let hir::ExprKind::Match(_, [_, some_arm], _) = e.kind
+            && let ExprKind::Match(_, [_, some_arm], _) = e.kind
             && let hir::PatKind::Struct(_, [field], _) = some_arm.pat.kind
         {
             return Some(Self {
@@ -209,28 +209,28 @@ impl<'hir> IfOrIfLet<'hir> {
 #[derive(Debug, Copy, Clone)]
 pub struct Range<'a> {
     /// The lower bound of the range, or `None` for ranges such as `..X`.
-    pub start: Option<&'a hir::Expr<'a>>,
+    pub start: Option<&'a Expr<'a>>,
     /// The upper bound of the range, or `None` for ranges such as `X..`.
-    pub end: Option<&'a hir::Expr<'a>>,
+    pub end: Option<&'a Expr<'a>>,
     /// Whether the interval is open or closed.
     pub limits: ast::RangeLimits,
 }
 
 impl<'a> Range<'a> {
     /// Higher a `hir` range to something similar to `ast::ExprKind::Range`.
-    pub fn hir(expr: &'a hir::Expr<'_>) -> Option<Range<'a>> {
+    pub fn hir(expr: &'a Expr<'_>) -> Option<Range<'a>> {
         /// Finds the field named `name` in the field. Always return `Some` for
         /// convenience.
-        fn get_field<'c>(name: &str, fields: &'c [hir::ExprField<'_>]) -> Option<&'c hir::Expr<'c>> {
+        fn get_field<'c>(name: &str, fields: &'c [hir::ExprField<'_>]) -> Option<&'c Expr<'c>> {
             let expr = &fields.iter().find(|field| field.ident.name.as_str() == name)?.expr;
             Some(expr)
         }
 
         match expr.kind {
-            hir::ExprKind::Call(path, args)
+            ExprKind::Call(path, args)
                 if matches!(
                     path.kind,
-                    hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, ..))
+                    ExprKind::Path(QPath::LangItem(hir::LangItem::RangeInclusiveNew, ..))
                 ) =>
             {
                 Some(Range {
@@ -239,28 +239,28 @@ impl<'a> Range<'a> {
                     limits: ast::RangeLimits::Closed,
                 })
             },
-            hir::ExprKind::Struct(path, fields, None) => match &path {
-                hir::QPath::LangItem(hir::LangItem::RangeFull, ..) => Some(Range {
+            ExprKind::Struct(path, fields, None) => match &path {
+                QPath::LangItem(hir::LangItem::RangeFull, ..) => Some(Range {
                     start: None,
                     end: None,
                     limits: ast::RangeLimits::HalfOpen,
                 }),
-                hir::QPath::LangItem(hir::LangItem::RangeFrom, ..) => Some(Range {
+                QPath::LangItem(hir::LangItem::RangeFrom, ..) => Some(Range {
                     start: Some(get_field("start", fields)?),
                     end: None,
                     limits: ast::RangeLimits::HalfOpen,
                 }),
-                hir::QPath::LangItem(hir::LangItem::Range, ..) => Some(Range {
+                QPath::LangItem(hir::LangItem::Range, ..) => Some(Range {
                     start: Some(get_field("start", fields)?),
                     end: Some(get_field("end", fields)?),
                     limits: ast::RangeLimits::HalfOpen,
                 }),
-                hir::QPath::LangItem(hir::LangItem::RangeToInclusive, ..) => Some(Range {
+                QPath::LangItem(hir::LangItem::RangeToInclusive, ..) => Some(Range {
                     start: None,
                     end: Some(get_field("end", fields)?),
                     limits: ast::RangeLimits::Closed,
                 }),
-                hir::QPath::LangItem(hir::LangItem::RangeTo, ..) => Some(Range {
+                QPath::LangItem(hir::LangItem::RangeTo, ..) => Some(Range {
                     start: None,
                     end: Some(get_field("end", fields)?),
                     limits: ast::RangeLimits::HalfOpen,
@@ -275,17 +275,17 @@ impl<'a> Range<'a> {
 /// Represents the pre-expansion arguments of a `vec!` invocation.
 pub enum VecArgs<'a> {
     /// `vec![elem; len]`
-    Repeat(&'a hir::Expr<'a>, &'a hir::Expr<'a>),
+    Repeat(&'a Expr<'a>, &'a Expr<'a>),
     /// `vec![a, b, c]`
-    Vec(&'a [hir::Expr<'a>]),
+    Vec(&'a [Expr<'a>]),
 }
 
 impl<'a> VecArgs<'a> {
     /// Returns the arguments of the `vec!` macro if this expression was expanded
     /// from `vec!`.
-    pub fn hir(cx: &LateContext<'_>, expr: &'a hir::Expr<'_>) -> Option<VecArgs<'a>> {
-        if let hir::ExprKind::Call(fun, args) = expr.kind
-            && let hir::ExprKind::Path(ref qpath) = fun.kind
+    pub fn hir(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option<VecArgs<'a>> {
+        if let ExprKind::Call(fun, args) = expr.kind
+            && let ExprKind::Path(ref qpath) = fun.kind
             && is_expn_of(fun.span, "vec").is_some()
             && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id()
         {
@@ -294,8 +294,8 @@ impl<'a> VecArgs<'a> {
                 Some(VecArgs::Repeat(&args[0], &args[1]))
             } else if match_def_path(cx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 {
                 // `vec![a, b, c]` case
-                if let hir::ExprKind::Call(_, [arg]) = &args[0].kind
-                    && let hir::ExprKind::Array(args) = arg.kind
+                if let ExprKind::Call(_, [arg]) = &args[0].kind
+                    && let ExprKind::Array(args) = arg.kind
                 {
                     Some(VecArgs::Vec(args))
                 } else {
diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs
index 7a4eba9790e..f8bbe997774 100644
--- a/clippy_utils/src/hir_utils.rs
+++ b/clippy_utils/src/hir_utils.rs
@@ -954,8 +954,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     self.hash_pat(pat);
                 }
             },
-            PatKind::Box(pat) => self.hash_pat(pat),
-            PatKind::Deref(pat) => self.hash_pat(pat),
+            PatKind::Box(pat) | PatKind::Deref(pat) => self.hash_pat(pat),
             PatKind::Lit(expr) => self.hash_expr(expr),
             PatKind::Or(pats) => {
                 for pat in pats {
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 95bab5801d1..37c12dd850c 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -16,12 +16,14 @@
     rustc::diagnostic_outside_of_impl,
     rustc::untranslatable_diagnostic
 )]
-// warn on the same lints as `clippy_lints`
-#![warn(trivial_casts, trivial_numeric_casts)]
-// warn on lints, that are included in `rust-lang/rust`s bootstrap
-#![warn(rust_2018_idioms, unused_lifetimes)]
-// warn on rustc internal lints
-#![warn(rustc::internal)]
+#![warn(
+    trivial_casts,
+    trivial_numeric_casts,
+    rust_2018_idioms,
+    unused_lifetimes,
+    unused_qualifications,
+    rustc::internal
+)]
 
 // FIXME: switch to something more ergonomic here, once available.
 // (Currently there is no way to opt into sysroot crates without `extern crate`.)
@@ -99,8 +101,8 @@ use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
 use rustc_hir::{
     self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, ByRef, Closure, Destination, Expr,
     ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, Item,
-    ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path, PathSegment, PrimTy,
-    QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp,
+    ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path, PathSegment,
+    PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp,
 };
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::{LateContext, Level, Lint, LintContext};
@@ -297,9 +299,10 @@ pub fn is_ty_alias(qpath: &QPath<'_>) -> bool {
 /// Checks if the method call given in `expr` belongs to the given trait.
 /// This is a deprecated function, consider using [`is_trait_method`].
 pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool {
-    let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
-    let trt_id = cx.tcx.trait_of_item(def_id);
-    trt_id.map_or(false, |trt_id| match_def_path(cx, trt_id, path))
+    cx.typeck_results()
+        .type_dependent_def_id(expr.hir_id)
+        .and_then(|defid| cx.tcx.trait_of_item(defid))
+        .map_or(false, |trt_id| match_def_path(cx, trt_id, path))
 }
 
 /// Checks if a method is defined in an impl of a diagnostic item
@@ -348,7 +351,7 @@ pub fn is_def_id_trait_method(cx: &LateContext<'_>, def_id: LocalDefId) -> bool
 /// refers to an item of the trait `Default`, which is associated with the
 /// `diag_item` of `sym::Default`.
 pub fn is_trait_item(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
-    if let hir::ExprKind::Path(ref qpath) = expr.kind {
+    if let ExprKind::Path(ref qpath) = expr.kind {
         cx.qpath_res(qpath, expr.hir_id)
             .opt_def_id()
             .map_or(false, |def_id| is_diag_trait_item(cx, def_id, diag_item))
@@ -722,8 +725,8 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, def_id: LocalDefId) ->
     let hir_id = cx.tcx.local_def_id_to_hir_id(def_id);
     let parent_impl = cx.tcx.hir().get_parent_item(hir_id);
     if parent_impl != hir::CRATE_OWNER_ID
-        && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(parent_impl.def_id)
-        && let hir::ItemKind::Impl(impl_) = &item.kind
+        && let Node::Item(item) = cx.tcx.hir_node_by_def_id(parent_impl.def_id)
+        && let ItemKind::Impl(impl_) = &item.kind
     {
         return impl_.of_trait.as_ref();
     }
@@ -829,7 +832,7 @@ fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<
 
 /// Returns true if the expr is equal to `Default::default` when evaluated.
 pub fn is_default_equivalent_call(cx: &LateContext<'_>, repl_func: &Expr<'_>) -> bool {
-    if let hir::ExprKind::Path(ref repl_func_qpath) = repl_func.kind
+    if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind
         && let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id()
         && (is_diag_trait_item(cx, repl_def_id, sym::Default)
             || is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath))
@@ -1295,7 +1298,7 @@ pub fn contains_name<'tcx>(name: Symbol, expr: &'tcx Expr<'_>, cx: &LateContext<
 /// Returns `true` if `expr` contains a return expression
 pub fn contains_return<'tcx>(expr: impl Visitable<'tcx>) -> bool {
     for_each_expr(expr, |e| {
-        if matches!(e.kind, hir::ExprKind::Ret(..)) {
+        if matches!(e.kind, ExprKind::Ret(..)) {
             ControlFlow::Break(())
         } else {
             ControlFlow::Continue(())
@@ -1311,7 +1314,7 @@ pub fn get_parent_expr<'tcx>(cx: &LateContext<'tcx>, e: &Expr<'_>) -> Option<&'t
 
 /// This retrieves the parent for the given `HirId` if it's an expression. This is useful for
 /// constraint lints
-pub fn get_parent_expr_for_hir<'tcx>(cx: &LateContext<'tcx>, hir_id: hir::HirId) -> Option<&'tcx Expr<'tcx>> {
+pub fn get_parent_expr_for_hir<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> {
     match cx.tcx.parent_hir_node(hir_id) {
         Node::Expr(parent) => Some(parent),
         _ => None,
@@ -1635,13 +1638,13 @@ pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
 }
 
 /// Convenience function to get the return type of a function.
-pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_def_id: hir::OwnerId) -> Ty<'tcx> {
+pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_def_id: OwnerId) -> Ty<'tcx> {
     let ret_ty = cx.tcx.fn_sig(fn_def_id).instantiate_identity().output();
     cx.tcx.instantiate_bound_regions_with_erased(ret_ty)
 }
 
 /// Convenience function to get the nth argument type of a function.
-pub fn nth_arg<'tcx>(cx: &LateContext<'tcx>, fn_def_id: hir::OwnerId, nth: usize) -> Ty<'tcx> {
+pub fn nth_arg<'tcx>(cx: &LateContext<'tcx>, fn_def_id: OwnerId, nth: usize) -> Ty<'tcx> {
     let arg = cx.tcx.fn_sig(fn_def_id).instantiate_identity().input(nth);
     cx.tcx.instantiate_bound_regions_with_erased(arg)
 }
@@ -1652,8 +1655,8 @@ pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_
         if let ExprKind::Path(ref qp) = fun.kind {
             let res = cx.qpath_res(qp, fun.hir_id);
             return match res {
-                def::Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true,
-                def::Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id),
+                Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true,
+                Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id),
                 _ => false,
             };
         }
@@ -1667,7 +1670,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
     fn is_enum_variant(cx: &LateContext<'_>, qpath: &QPath<'_>, id: HirId) -> bool {
         matches!(
             cx.qpath_res(qpath, id),
-            def::Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), _)
+            Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), _)
         )
     }
 
@@ -1823,26 +1826,26 @@ pub fn strip_pat_refs<'hir>(mut pat: &'hir Pat<'hir>) -> &'hir Pat<'hir> {
     pat
 }
 
-pub fn int_bits(tcx: TyCtxt<'_>, ity: rustc_ty::IntTy) -> u64 {
+pub fn int_bits(tcx: TyCtxt<'_>, ity: IntTy) -> u64 {
     Integer::from_int_ty(&tcx, ity).size().bits()
 }
 
 #[expect(clippy::cast_possible_wrap)]
 /// Turn a constant int byte representation into an i128
-pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::IntTy) -> i128 {
+pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: IntTy) -> i128 {
     let amt = 128 - int_bits(tcx, ity);
     ((u as i128) << amt) >> amt
 }
 
 #[expect(clippy::cast_sign_loss)]
 /// clip unused bytes
-pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: rustc_ty::IntTy) -> u128 {
+pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: IntTy) -> u128 {
     let amt = 128 - int_bits(tcx, ity);
     ((u as u128) << amt) >> amt
 }
 
 /// clip unused bytes
-pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::UintTy) -> u128 {
+pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: UintTy) -> u128 {
     let bits = Integer::from_uint_ty(&tcx, ity).size().bits();
     let amt = 128 - bits;
     (u << amt) >> amt
@@ -2007,7 +2010,7 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let did = match expr.kind {
         ExprKind::Call(path, _) => {
             if let ExprKind::Path(ref qpath) = path.kind
-                && let def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id)
+                && let Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id)
             {
                 Some(did)
             } else {
@@ -2218,7 +2221,7 @@ pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
 /// ```
 pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool {
     if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) {
-        matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
+        matches!(item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. }))
     } else {
         false
     }
@@ -2254,7 +2257,7 @@ pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
 pub fn fn_def_id_with_node_args<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &Expr<'_>,
-) -> Option<(DefId, rustc_ty::GenericArgsRef<'tcx>)> {
+) -> Option<(DefId, GenericArgsRef<'tcx>)> {
     let typeck = cx.typeck_results();
     match &expr.kind {
         ExprKind::MethodCall(..) => Some((
@@ -2500,7 +2503,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Sym
 /// Checks if the function containing the given `HirId` is a `#[test]` function
 ///
 /// Note: Add `//@compile-flags: --test` to UI tests with a `#[test]` function
-pub fn is_in_test_function(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
+pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool {
     with_test_item_names(tcx, tcx.parent_module(id), |names| {
         tcx.hir()
             .parent_iter(id)
@@ -2523,7 +2526,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
 ///
 /// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent
 /// use [`is_in_cfg_test`]
-pub fn is_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
+pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
     tcx.hir().attrs(id).iter().any(|attr| {
         if attr.has_name(sym::cfg)
             && let Some(items) = attr.meta_item_list()
@@ -2538,7 +2541,7 @@ pub fn is_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
 }
 
 /// Checks if any parent node of `HirId` has `#[cfg(test)]` attribute applied
-pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
+pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
     tcx.hir()
         .parent_id_iter(id)
         .any(|parent_id| is_cfg_test(tcx, parent_id))
@@ -3333,3 +3336,12 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
         repeat(String::from("super")).take(go_up_by).chain(path).join("::")
     }
 }
+
+/// Returns true if the specified `HirId` is the top-level expression of a statement or the only
+/// expression in a block.
+pub fn is_parent_stmt(cx: &LateContext<'_>, id: HirId) -> bool {
+    matches!(
+        cx.tcx.parent_hir_node(id),
+        Node::Stmt(..) | Node::Block(Block { stmts: &[], .. })
+    )
+}
diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs
index c475e7b7c43..f166087dc3c 100644
--- a/clippy_utils/src/macros.rs
+++ b/clippy_utils/src/macros.rs
@@ -429,7 +429,7 @@ pub fn find_format_args(cx: &LateContext<'_>, start: &Expr<'_>, expn_id: ExpnId)
 pub fn find_format_arg_expr<'hir, 'ast>(
     start: &'hir Expr<'hir>,
     target: &'ast FormatArgument,
-) -> Result<&'hir rustc_hir::Expr<'hir>, &'ast rustc_ast::Expr> {
+) -> Result<&'hir Expr<'hir>, &'ast rustc_ast::Expr> {
     let SpanData {
         lo,
         hi,
diff --git a/clippy_utils/src/mir/mod.rs b/clippy_utils/src/mir/mod.rs
index 9dbb4c68d13..e4966690d8c 100644
--- a/clippy_utils/src/mir/mod.rs
+++ b/clippy_utils/src/mir/mod.rs
@@ -111,7 +111,7 @@ pub fn block_in_cycle(body: &Body<'_>, block: BasicBlock) -> bool {
 }
 
 /// Convenience wrapper around `visit_local_usage`.
-pub fn used_exactly_once(mir: &Body<'_>, local: rustc_middle::mir::Local) -> Option<bool> {
+pub fn used_exactly_once(mir: &Body<'_>, local: Local) -> Option<bool> {
     visit_local_usage(
         &[local],
         mir,
diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs
index 5090d0bd98b..8d6057272c4 100644
--- a/clippy_utils/src/sugg.rs
+++ b/clippy_utils/src/sugg.rs
@@ -41,7 +41,7 @@ pub const ONE: Sugg<'static> = Sugg::NonParen(Cow::Borrowed("1"));
 pub const EMPTY: Sugg<'static> = Sugg::NonParen(Cow::Borrowed(""));
 
 impl Display for Sugg<'_> {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
         match *self {
             Sugg::NonParen(ref s) | Sugg::MaybeParen(ref s) => s.fmt(f),
             Sugg::BinOp(op, ref lhs, ref rhs) => binop_to_string(op, lhs, rhs).fmt(f),
@@ -124,48 +124,48 @@ impl<'a> Sugg<'a> {
         }
 
         match expr.kind {
-            hir::ExprKind::AddrOf(..)
-            | hir::ExprKind::If(..)
-            | hir::ExprKind::Let(..)
-            | hir::ExprKind::Closure { .. }
-            | hir::ExprKind::Unary(..)
-            | hir::ExprKind::Match(..) => Sugg::MaybeParen(get_snippet(expr.span)),
-            hir::ExprKind::Continue(..)
-            | hir::ExprKind::Yield(..)
-            | hir::ExprKind::Array(..)
-            | hir::ExprKind::Block(..)
-            | hir::ExprKind::Break(..)
-            | hir::ExprKind::Call(..)
-            | hir::ExprKind::Field(..)
-            | hir::ExprKind::Index(..)
-            | hir::ExprKind::InlineAsm(..)
-            | hir::ExprKind::OffsetOf(..)
-            | hir::ExprKind::ConstBlock(..)
-            | hir::ExprKind::Lit(..)
-            | hir::ExprKind::Loop(..)
-            | hir::ExprKind::MethodCall(..)
-            | hir::ExprKind::Path(..)
-            | hir::ExprKind::Repeat(..)
-            | hir::ExprKind::Ret(..)
-            | hir::ExprKind::Become(..)
-            | hir::ExprKind::Struct(..)
-            | hir::ExprKind::Tup(..)
-            | hir::ExprKind::Err(_) => Sugg::NonParen(get_snippet(expr.span)),
-            hir::ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet),
-            hir::ExprKind::Assign(lhs, rhs, _) => {
+            ExprKind::AddrOf(..)
+            | ExprKind::If(..)
+            | ExprKind::Let(..)
+            | ExprKind::Closure { .. }
+            | ExprKind::Unary(..)
+            | ExprKind::Match(..) => Sugg::MaybeParen(get_snippet(expr.span)),
+            ExprKind::Continue(..)
+            | ExprKind::Yield(..)
+            | ExprKind::Array(..)
+            | ExprKind::Block(..)
+            | ExprKind::Break(..)
+            | ExprKind::Call(..)
+            | ExprKind::Field(..)
+            | ExprKind::Index(..)
+            | ExprKind::InlineAsm(..)
+            | ExprKind::OffsetOf(..)
+            | ExprKind::ConstBlock(..)
+            | ExprKind::Lit(..)
+            | ExprKind::Loop(..)
+            | ExprKind::MethodCall(..)
+            | ExprKind::Path(..)
+            | ExprKind::Repeat(..)
+            | ExprKind::Ret(..)
+            | ExprKind::Become(..)
+            | ExprKind::Struct(..)
+            | ExprKind::Tup(..)
+            | ExprKind::Err(_) => Sugg::NonParen(get_snippet(expr.span)),
+            ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet),
+            ExprKind::Assign(lhs, rhs, _) => {
                 Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))
             },
-            hir::ExprKind::AssignOp(op, lhs, rhs) => {
+            ExprKind::AssignOp(op, lhs, rhs) => {
                 Sugg::BinOp(hirbinop2assignop(op), get_snippet(lhs.span), get_snippet(rhs.span))
             },
-            hir::ExprKind::Binary(op, lhs, rhs) => Sugg::BinOp(
+            ExprKind::Binary(op, lhs, rhs) => Sugg::BinOp(
                 AssocOp::from_ast_binop(op.node),
                 get_snippet(lhs.span),
                 get_snippet(rhs.span),
             ),
-            hir::ExprKind::Cast(lhs, ty) |
+            ExprKind::Cast(lhs, ty) |
             //FIXME(chenyukang), remove this after type ascription is removed from AST
-            hir::ExprKind::Type(lhs, ty) => Sugg::BinOp(AssocOp::As, get_snippet(lhs.span), get_snippet(ty.span)),
+            ExprKind::Type(lhs, ty) => Sugg::BinOp(AssocOp::As, get_snippet(lhs.span), get_snippet(ty.span)),
         }
     }
 
@@ -358,6 +358,13 @@ impl<'a> Sugg<'a> {
             },
         }
     }
+
+    pub fn into_string(self) -> String {
+        match self {
+            Sugg::NonParen(p) | Sugg::MaybeParen(p) => p.into_owned(),
+            Sugg::BinOp(b, l, r) => binop_to_string(b, &l, &r),
+        }
+    }
 }
 
 /// Generates a string from the operator and both sides.
@@ -508,7 +515,7 @@ impl<T> ParenHelper<T> {
 }
 
 impl<T: Display> Display for ParenHelper<T> {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
         if self.paren {
             write!(f, "({})", self.wrapped)
         } else {
@@ -801,7 +808,7 @@ pub struct DerefClosure {
 ///
 /// note: this only works on single line immutable closures with exactly one input parameter.
 pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Option<DerefClosure> {
-    if let hir::ExprKind::Closure(&Closure {
+    if let ExprKind::Closure(&Closure {
         fn_decl, def_id, body, ..
     }) = closure.kind
     {
diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs
index 97ce755adbb..ab1be66dc78 100644
--- a/clippy_utils/src/ty.rs
+++ b/clippy_utils/src/ty.rs
@@ -91,12 +91,16 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
                     return true;
                 }
 
-                if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *inner_ty.kind() {
+                if let ty::Alias(ty::Opaque, AliasTy { def_id, .. }) = *inner_ty.kind() {
                     if !seen.insert(def_id) {
                         return false;
                     }
 
-                    for (predicate, _span) in cx.tcx.explicit_item_super_predicates(def_id).instantiate_identity_iter_copied() {
+                    for (predicate, _span) in cx
+                        .tcx
+                        .explicit_item_super_predicates(def_id)
+                        .instantiate_identity_iter_copied()
+                    {
                         match predicate.kind().skip_binder() {
                             // For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
                             // and check substitutions to find `U`.
@@ -159,6 +163,16 @@ pub fn get_type_diagnostic_name(cx: &LateContext<'_>, ty: Ty<'_>) -> Option<Symb
     }
 }
 
+/// Returns true if `ty` is a type on which calling `Clone` through a function instead of
+/// as a method, such as `Arc::clone()` is considered idiomatic. Lints should avoid suggesting to
+/// replace instances of `ty::Clone()` by `.clone()` for objects of those types.
+pub fn should_call_clone_as_function(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
+    matches!(
+        get_type_diagnostic_name(cx, ty),
+        Some(sym::Arc | sym::ArcWeak | sym::Rc | sym::RcWeak)
+    )
+}
+
 /// Returns true if ty has `iter` or `iter_mut` methods
 pub fn has_iter_method(cx: &LateContext<'_>, probably_ref_ty: Ty<'_>) -> Option<Symbol> {
     // FIXME: instead of this hard-coded list, we should check if `<adt>::iter`
@@ -301,7 +315,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
         cause: ObligationCause::dummy(),
         param_env,
         recursion_depth: 0,
-        predicate: ty::Binder::dummy(trait_ref).to_predicate(tcx),
+        predicate: Binder::dummy(trait_ref).to_predicate(tcx),
     };
     infcx
         .evaluate_obligation(&obligation)
@@ -327,7 +341,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
             is_must_use_ty(cx, *ty)
         },
         ty::Tuple(args) => args.iter().any(|ty| is_must_use_ty(cx, ty)),
-        ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
+        ty::Alias(ty::Opaque, AliasTy { def_id, .. }) => {
             for (predicate, _) in cx.tcx.explicit_item_super_predicates(def_id).skip_binder() {
                 if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() {
                     if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) {
@@ -356,13 +370,13 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
 // not succeed
 /// Checks if `Ty` is normalizable. This function is useful
 /// to avoid crashes on `layout_of`.
-pub fn is_normalizable<'tcx>(cx: &LateContext<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
+pub fn is_normalizable<'tcx>(cx: &LateContext<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
     is_normalizable_helper(cx, param_env, ty, &mut FxHashMap::default())
 }
 
 fn is_normalizable_helper<'tcx>(
     cx: &LateContext<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    param_env: ParamEnv<'tcx>,
     ty: Ty<'tcx>,
     cache: &mut FxHashMap<Ty<'tcx>, bool>,
 ) -> bool {
@@ -372,7 +386,7 @@ fn is_normalizable_helper<'tcx>(
     // prevent recursive loops, false-negative is better than endless loop leading to stack overflow
     cache.insert(ty, false);
     let infcx = cx.tcx.infer_ctxt().build();
-    let cause = rustc_middle::traits::ObligationCause::dummy();
+    let cause = ObligationCause::dummy();
     let result = if infcx.at(&cause, param_env).query_normalize(ty).is_ok() {
         match ty.kind() {
             ty::Adt(def, args) => def.variants().iter().all(|variant| {
@@ -446,7 +460,7 @@ pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symb
 /// Checks if the type is equal to a lang item.
 ///
 /// Returns `false` if the `LangItem` is not defined.
-pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangItem) -> bool {
+pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: LangItem) -> bool {
     match ty.kind() {
         ty::Adt(adt, _) => cx.tcx.lang_items().get(lang_item) == Some(adt.did()),
         _ => false,
@@ -726,7 +740,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
             Some(ExprFnSig::Closure(decl, subs.as_closure().sig()))
         },
         ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.fn_sig(id).instantiate(cx.tcx, subs), Some(id))),
-        ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => sig_from_bounds(
+        ty::Alias(ty::Opaque, AliasTy { def_id, args, .. }) => sig_from_bounds(
             cx,
             ty,
             cx.tcx.item_super_predicates(def_id).iter_instantiated(cx.tcx, args),
@@ -807,7 +821,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option
 
     for (pred, _) in cx
         .tcx
-        .explicit_item_super_predicates(ty.def_id)
+        .explicit_item_bounds(ty.def_id)
         .iter_instantiated_copied(cx.tcx, ty.args)
     {
         match pred.kind().skip_binder() {
@@ -899,7 +913,7 @@ pub fn is_c_void(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
     if let ty::Adt(adt, _) = ty.kind()
         && let &[krate, .., name] = &*cx.get_def_path(adt.did())
         && let sym::libc | sym::core | sym::std = krate
-        && name == rustc_span::sym::c_void
+        && name == sym::c_void
     {
         true
     } else {
@@ -1134,7 +1148,7 @@ pub fn make_projection<'tcx>(
         #[cfg(debug_assertions)]
         assert_generic_args_match(tcx, assoc_item.def_id, args);
 
-        Some(ty::AliasTy::new(tcx, assoc_item.def_id, args))
+        Some(AliasTy::new(tcx, assoc_item.def_id, args))
     }
     helper(
         tcx,
@@ -1251,7 +1265,7 @@ pub fn make_normalized_projection_with_regions<'tcx>(
             );
             return None;
         }
-        let cause = rustc_middle::traits::ObligationCause::dummy();
+        let cause = ObligationCause::dummy();
         match tcx
             .infer_ctxt()
             .build()
@@ -1269,7 +1283,7 @@ pub fn make_normalized_projection_with_regions<'tcx>(
 }
 
 pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
-    let cause = rustc_middle::traits::ObligationCause::dummy();
+    let cause = ObligationCause::dummy();
     match tcx.infer_ctxt().build().at(&cause, param_env).query_normalize(ty) {
         Ok(ty) => ty.value,
         Err(_) => ty,
diff --git a/clippy_utils/src/usage.rs b/clippy_utils/src/usage.rs
index ec131c7f6a3..a145920aa85 100644
--- a/clippy_utils/src/usage.rs
+++ b/clippy_utils/src/usage.rs
@@ -83,15 +83,15 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
         self.update(cmt);
     }
 
-    fn fake_read(&mut self, _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+    fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
 }
 
 pub struct ParamBindingIdCollector {
-    pub binding_hir_ids: Vec<hir::HirId>,
+    pub binding_hir_ids: Vec<HirId>,
 }
 impl<'tcx> ParamBindingIdCollector {
-    fn collect_binding_hir_ids(body: &'tcx hir::Body<'tcx>) -> Vec<hir::HirId> {
-        let mut hir_ids: Vec<hir::HirId> = Vec::new();
+    fn collect_binding_hir_ids(body: &'tcx hir::Body<'tcx>) -> Vec<HirId> {
+        let mut hir_ids: Vec<HirId> = Vec::new();
         for param in body.params {
             let mut finder = ParamBindingIdCollector {
                 binding_hir_ids: Vec::new(),
@@ -104,7 +104,7 @@ impl<'tcx> ParamBindingIdCollector {
         hir_ids
     }
 }
-impl<'tcx> intravisit::Visitor<'tcx> for ParamBindingIdCollector {
+impl<'tcx> Visitor<'tcx> for ParamBindingIdCollector {
     fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
         if let hir::PatKind::Binding(_, hir_id, ..) = pat.kind {
             self.binding_hir_ids.push(hir_id);
@@ -115,7 +115,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for ParamBindingIdCollector {
 
 pub struct BindingUsageFinder<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
-    binding_ids: Vec<hir::HirId>,
+    binding_ids: Vec<HirId>,
     usage_found: bool,
 }
 impl<'a, 'tcx> BindingUsageFinder<'a, 'tcx> {
@@ -129,16 +129,16 @@ impl<'a, 'tcx> BindingUsageFinder<'a, 'tcx> {
         finder.usage_found
     }
 }
-impl<'a, 'tcx> intravisit::Visitor<'tcx> for BindingUsageFinder<'a, 'tcx> {
+impl<'a, 'tcx> Visitor<'tcx> for BindingUsageFinder<'a, 'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
-    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
+    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
         if !self.usage_found {
             intravisit::walk_expr(self, expr);
         }
     }
 
-    fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) {
+    fn visit_path(&mut self, path: &hir::Path<'tcx>, _: HirId) {
         if let Res::Local(id) = path.res {
             if self.binding_ids.contains(&id) {
                 self.usage_found = true;
diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs
index 0a05ac029ea..a3f3b32ed37 100644
--- a/clippy_utils/src/visitors.rs
+++ b/clippy_utils/src/visitors.rs
@@ -180,9 +180,9 @@ pub fn for_each_expr_with_closures<'tcx, B, C: Continue>(
 }
 
 /// returns `true` if expr contains match expr desugared from try
-fn contains_try(expr: &hir::Expr<'_>) -> bool {
+fn contains_try(expr: &Expr<'_>) -> bool {
     for_each_expr(expr, |e| {
-        if matches!(e.kind, hir::ExprKind::Match(_, _, hir::MatchSource::TryDesugar(_))) {
+        if matches!(e.kind, ExprKind::Match(_, _, hir::MatchSource::TryDesugar(_))) {
             ControlFlow::Break(())
         } else {
             ControlFlow::Continue(())
@@ -191,9 +191,9 @@ fn contains_try(expr: &hir::Expr<'_>) -> bool {
     .is_some()
 }
 
-pub fn find_all_ret_expressions<'hir, F>(_cx: &LateContext<'_>, expr: &'hir hir::Expr<'hir>, callback: F) -> bool
+pub fn find_all_ret_expressions<'hir, F>(_cx: &LateContext<'_>, expr: &'hir Expr<'hir>, callback: F) -> bool
 where
-    F: FnMut(&'hir hir::Expr<'hir>) -> bool,
+    F: FnMut(&'hir Expr<'hir>) -> bool,
 {
     struct RetFinder<F> {
         in_stmt: bool,
@@ -236,37 +236,37 @@ where
         }
     }
 
-    impl<'hir, F: FnMut(&'hir hir::Expr<'hir>) -> bool> intravisit::Visitor<'hir> for RetFinder<F> {
-        fn visit_stmt(&mut self, stmt: &'hir hir::Stmt<'_>) {
+    impl<'hir, F: FnMut(&'hir Expr<'hir>) -> bool> Visitor<'hir> for RetFinder<F> {
+        fn visit_stmt(&mut self, stmt: &'hir Stmt<'_>) {
             intravisit::walk_stmt(&mut *self.inside_stmt(true), stmt);
         }
 
-        fn visit_expr(&mut self, expr: &'hir hir::Expr<'_>) {
+        fn visit_expr(&mut self, expr: &'hir Expr<'_>) {
             if self.failed {
                 return;
             }
             if self.in_stmt {
                 match expr.kind {
-                    hir::ExprKind::Ret(Some(expr)) => self.inside_stmt(false).visit_expr(expr),
-                    _ => intravisit::walk_expr(self, expr),
+                    ExprKind::Ret(Some(expr)) => self.inside_stmt(false).visit_expr(expr),
+                    _ => walk_expr(self, expr),
                 }
             } else {
                 match expr.kind {
-                    hir::ExprKind::If(cond, then, else_opt) => {
+                    ExprKind::If(cond, then, else_opt) => {
                         self.inside_stmt(true).visit_expr(cond);
                         self.visit_expr(then);
                         if let Some(el) = else_opt {
                             self.visit_expr(el);
                         }
                     },
-                    hir::ExprKind::Match(cond, arms, _) => {
+                    ExprKind::Match(cond, arms, _) => {
                         self.inside_stmt(true).visit_expr(cond);
                         for arm in arms {
                             self.visit_expr(arm.body);
                         }
                     },
-                    hir::ExprKind::Block(..) => intravisit::walk_expr(self, expr),
-                    hir::ExprKind::Ret(Some(expr)) => self.visit_expr(expr),
+                    ExprKind::Block(..) => walk_expr(self, expr),
+                    ExprKind::Ret(Some(expr)) => self.visit_expr(expr),
                     _ => self.failed |= !(self.cb)(expr),
                 }
             }
@@ -316,7 +316,7 @@ pub fn is_const_evaluatable<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) ->
         is_const: bool,
     }
     impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> {
-        type NestedFilter = rustc_hir::intravisit::nested_filter::None;
+        type NestedFilter = intravisit::nested_filter::None;
 
         fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
             if !self.is_const {
diff --git a/lintcheck/src/main.rs b/lintcheck/src/main.rs
index 66442998161..4251151c454 100644
--- a/lintcheck/src/main.rs
+++ b/lintcheck/src/main.rs
@@ -5,6 +5,13 @@
 // When a new lint is introduced, we can search the results for new warnings and check for false
 // positives.
 
+#![warn(
+    trivial_casts,
+    trivial_numeric_casts,
+    rust_2018_idioms,
+    unused_lifetimes,
+    unused_qualifications
+)]
 #![allow(clippy::collapsible_else_if)]
 
 mod config;
@@ -189,13 +196,13 @@ impl CrateSource {
                 // don't download/extract if we already have done so
                 if !krate_file_path.is_file() {
                     // create a file path to download and write the crate data into
-                    let mut krate_dest = std::fs::File::create(&krate_file_path).unwrap();
+                    let mut krate_dest = fs::File::create(&krate_file_path).unwrap();
                     let mut krate_req = get(&url).unwrap().into_reader();
                     // copy the crate into the file
-                    std::io::copy(&mut krate_req, &mut krate_dest).unwrap();
+                    io::copy(&mut krate_req, &mut krate_dest).unwrap();
 
                     // unzip the tarball
-                    let ungz_tar = flate2::read::GzDecoder::new(std::fs::File::open(&krate_file_path).unwrap());
+                    let ungz_tar = flate2::read::GzDecoder::new(fs::File::open(&krate_file_path).unwrap());
                     // extract the tar archive
                     let mut archive = tar::Archive::new(ungz_tar);
                     archive.unpack(&extract_dir).expect("Failed to extract!");
@@ -257,7 +264,7 @@ impl CrateSource {
             },
             CrateSource::Path { name, path, options } => {
                 fn is_cache_dir(entry: &DirEntry) -> bool {
-                    std::fs::read(entry.path().join("CACHEDIR.TAG"))
+                    fs::read(entry.path().join("CACHEDIR.TAG"))
                         .map(|x| x.starts_with(b"Signature: 8a477f597d28d172789f06886806bc55"))
                         .unwrap_or(false)
                 }
@@ -268,7 +275,7 @@ impl CrateSource {
                 let dest_crate_root = PathBuf::from(LINTCHECK_SOURCES).join(name);
                 if dest_crate_root.exists() {
                     println!("Deleting existing directory at {dest_crate_root:?}");
-                    std::fs::remove_dir_all(&dest_crate_root).unwrap();
+                    fs::remove_dir_all(&dest_crate_root).unwrap();
                 }
 
                 println!("Copying {path:?} to {dest_crate_root:?}");
@@ -281,9 +288,9 @@ impl CrateSource {
                     let metadata = entry_path.symlink_metadata().unwrap();
 
                     if metadata.is_dir() {
-                        std::fs::create_dir(dest_path).unwrap();
+                        fs::create_dir(dest_path).unwrap();
                     } else if metadata.is_file() {
-                        std::fs::copy(entry_path, dest_path).unwrap();
+                        fs::copy(entry_path, dest_path).unwrap();
                     }
                 }
 
@@ -330,7 +337,7 @@ impl Crate {
             );
         }
 
-        let cargo_clippy_path = std::fs::canonicalize(cargo_clippy_path).unwrap();
+        let cargo_clippy_path = fs::canonicalize(cargo_clippy_path).unwrap();
 
         let shared_target_dir = clippy_project_root().join("target/lintcheck/shared_target_dir");
 
@@ -353,7 +360,7 @@ impl Crate {
             clippy_args.push("--cap-lints=warn");
         } else {
             clippy_args.push("--cap-lints=allow");
-            clippy_args.extend(lint_filter.iter().map(std::string::String::as_str));
+            clippy_args.extend(lint_filter.iter().map(String::as_str));
         }
 
         if let Some(server) = server {
@@ -454,7 +461,7 @@ fn build_clippy() {
 /// Read a `lintcheck_crates.toml` file
 fn read_crates(toml_path: &Path) -> (Vec<CrateSource>, RecursiveOptions) {
     let toml_content: String =
-        std::fs::read_to_string(toml_path).unwrap_or_else(|_| panic!("Failed to read {}", toml_path.display()));
+        fs::read_to_string(toml_path).unwrap_or_else(|_| panic!("Failed to read {}", toml_path.display()));
     let crate_list: SourceList =
         toml::from_str(&toml_content).unwrap_or_else(|e| panic!("Failed to parse {}: \n{e}", toml_path.display()));
     // parse the hashmap of the toml file into a list of crates
@@ -549,7 +556,7 @@ fn main() {
     }
 
     // assert that we launch lintcheck from the repo root (via cargo lintcheck)
-    if std::fs::metadata("lintcheck/Cargo.toml").is_err() {
+    if fs::metadata("lintcheck/Cargo.toml").is_err() {
         eprintln!("lintcheck needs to be run from clippy's repo root!\nUse `cargo lintcheck` alternatively.");
         std::process::exit(3);
     }
@@ -570,7 +577,7 @@ fn main() {
         cargo_clippy_path.display()
     );
 
-    let clippy_ver = std::process::Command::new(&cargo_clippy_path)
+    let clippy_ver = Command::new(&cargo_clippy_path)
         .arg("--version")
         .output()
         .map(|o| String::from_utf8_lossy(&o.stdout).into_owned())
@@ -699,7 +706,7 @@ fn main() {
 
 /// read the previous stats from the lintcheck-log file
 fn read_stats_from_file(file_path: &Path) -> HashMap<String, usize> {
-    let file_content: String = match std::fs::read_to_string(file_path).ok() {
+    let file_content: String = match fs::read_to_string(file_path).ok() {
         Some(content) => content,
         None => {
             return HashMap::new();
@@ -779,17 +786,17 @@ fn print_stats(old_stats: HashMap<String, usize>, new_stats: HashMap<&String, us
 ///
 /// This function panics if creating one of the dirs fails.
 fn create_dirs(krate_download_dir: &Path, extract_dir: &Path) {
-    std::fs::create_dir("target/lintcheck/").unwrap_or_else(|err| {
+    fs::create_dir("target/lintcheck/").unwrap_or_else(|err| {
         assert_eq!(
             err.kind(),
             ErrorKind::AlreadyExists,
             "cannot create lintcheck target dir"
         );
     });
-    std::fs::create_dir(krate_download_dir).unwrap_or_else(|err| {
+    fs::create_dir(krate_download_dir).unwrap_or_else(|err| {
         assert_eq!(err.kind(), ErrorKind::AlreadyExists, "cannot create crate download dir");
     });
-    std::fs::create_dir(extract_dir).unwrap_or_else(|err| {
+    fs::create_dir(extract_dir).unwrap_or_else(|err| {
         assert_eq!(
             err.kind(),
             ErrorKind::AlreadyExists,
@@ -816,7 +823,7 @@ fn lintcheck_test() {
         "--crates-toml",
         "lintcheck/test_sources.toml",
     ];
-    let status = std::process::Command::new(env::var("CARGO").unwrap_or("cargo".into()))
+    let status = Command::new(env::var("CARGO").unwrap_or("cargo".into()))
         .args(args)
         .current_dir("..") // repo root
         .status();
diff --git a/rust-toolchain b/rust-toolchain
index a63e66f3214..b2fe5c8bee7 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2024-03-21"
+channel = "nightly-2024-04-04"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/tests/compile-test.rs b/tests/compile-test.rs
index a0c8bf9334c..32a31f5e082 100644
--- a/tests/compile-test.rs
+++ b/tests/compile-test.rs
@@ -146,6 +146,8 @@ fn base_config(test_dir: &str) -> (Config, Args) {
     );
 
     config.program.args.extend(EXTERN_FLAGS.iter().map(OsString::from));
+    // Prevent rustc from creating `rustc-ice-*` files the console output is enough.
+    config.program.envs.push(("RUSTC_ICE".into(), Some("0".into())));
 
     if let Some(host_libs) = option_env!("HOST_LIBS") {
         let dep = format!("-Ldependency={}", Path::new(host_libs).join("deps").display());
diff --git a/tests/ui-toml/absolute_paths/absolute_paths.rs b/tests/ui-toml/absolute_paths/absolute_paths.rs
index 0e6a54452ee..a828701bcee 100644
--- a/tests/ui-toml/absolute_paths/absolute_paths.rs
+++ b/tests/ui-toml/absolute_paths/absolute_paths.rs
@@ -3,7 +3,7 @@
 //@revisions: allow_crates disallow_crates
 //@[allow_crates] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/allow_crates
 //@[disallow_crates] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/disallow_crates
-#![allow(clippy::no_effect, unused)]
+#![allow(clippy::no_effect, clippy::legacy_numeric_constants, unused)]
 #![warn(clippy::absolute_paths)]
 #![feature(decl_macro)]
 
diff --git a/tests/ui-toml/large_stack_frames/large_stack_frames.rs b/tests/ui-toml/large_stack_frames/large_stack_frames.rs
index 39798ffea49..a612e56570f 100644
--- a/tests/ui-toml/large_stack_frames/large_stack_frames.rs
+++ b/tests/ui-toml/large_stack_frames/large_stack_frames.rs
@@ -10,7 +10,7 @@ fn f() {
     let _x = create_array::<1000>();
 }
 fn f2() {
-    //~^ ERROR: this function allocates a large amount of stack space
+    //~^ ERROR: this function may allocate 1001 bytes on the stack
     let _x = create_array::<1001>();
 }
 
diff --git a/tests/ui-toml/large_stack_frames/large_stack_frames.stderr b/tests/ui-toml/large_stack_frames/large_stack_frames.stderr
index c23fac14564..19983e2f3e8 100644
--- a/tests/ui-toml/large_stack_frames/large_stack_frames.stderr
+++ b/tests/ui-toml/large_stack_frames/large_stack_frames.stderr
@@ -1,13 +1,14 @@
-error: this function allocates a large amount of stack space
-  --> tests/ui-toml/large_stack_frames/large_stack_frames.rs:12:1
+error: this function may allocate 1001 bytes on the stack
+  --> tests/ui-toml/large_stack_frames/large_stack_frames.rs:12:4
    |
-LL | / fn f2() {
-LL | |
-LL | |     let _x = create_array::<1001>();
-LL | | }
-   | |_^
+LL | fn f2() {
+   |    ^^
+LL |
+LL |     let _x = create_array::<1001>();
+   |         -- `_x` is the largest part, at 1001 bytes for type `[u8; 1001]`
    |
-   = note: allocating large amounts of stack space can overflow the stack
+   = note: 1001 bytes is larger than Clippy's configured `stack-size-threshold` of 1000
+   = note: allocating large amounts of stack space can overflow the stack and cause the program to abort
    = note: `-D clippy::large-stack-frames` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::large_stack_frames)]`
 
diff --git a/tests/ui/assigning_clones.fixed b/tests/ui/assigning_clones.fixed
index 160f3b94663..8387c7d6156 100644
--- a/tests/ui/assigning_clones.fixed
+++ b/tests/ui/assigning_clones.fixed
@@ -153,6 +153,19 @@ fn clone_inside_macro() {
     clone_inside!(a, b);
 }
 
+// Make sure that we don't suggest the lint when we call clone inside a Clone impl
+// https://github.com/rust-lang/rust-clippy/issues/12600
+pub struct AvoidRecursiveCloneFrom;
+
+impl Clone for AvoidRecursiveCloneFrom {
+    fn clone(&self) -> Self {
+        Self
+    }
+    fn clone_from(&mut self, source: &Self) {
+        *self = source.clone();
+    }
+}
+
 // ToOwned
 fn owned_method_mut_ref(mut_string: &mut String, ref_str: &str) {
     ref_str.clone_into(mut_string);
diff --git a/tests/ui/assigning_clones.rs b/tests/ui/assigning_clones.rs
index 14ba1d4db9a..6f4da9f652c 100644
--- a/tests/ui/assigning_clones.rs
+++ b/tests/ui/assigning_clones.rs
@@ -153,6 +153,19 @@ fn clone_inside_macro() {
     clone_inside!(a, b);
 }
 
+// Make sure that we don't suggest the lint when we call clone inside a Clone impl
+// https://github.com/rust-lang/rust-clippy/issues/12600
+pub struct AvoidRecursiveCloneFrom;
+
+impl Clone for AvoidRecursiveCloneFrom {
+    fn clone(&self) -> Self {
+        Self
+    }
+    fn clone_from(&mut self, source: &Self) {
+        *self = source.clone();
+    }
+}
+
 // ToOwned
 fn owned_method_mut_ref(mut_string: &mut String, ref_str: &str) {
     *mut_string = ref_str.to_owned();
diff --git a/tests/ui/assigning_clones.stderr b/tests/ui/assigning_clones.stderr
index ba59f067431..793927bd1cb 100644
--- a/tests/ui/assigning_clones.stderr
+++ b/tests/ui/assigning_clones.stderr
@@ -86,37 +86,37 @@ LL |     a = c.to_owned();
    |     ^^^^^^^^^^^^^^^^ help: use `clone_into()`: `c.clone_into(&mut a)`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:158:5
+  --> tests/ui/assigning_clones.rs:171:5
    |
 LL |     *mut_string = ref_str.to_owned();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(mut_string)`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:162:5
+  --> tests/ui/assigning_clones.rs:175:5
    |
 LL |     mut_string = ref_str.to_owned();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut mut_string)`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:183:5
+  --> tests/ui/assigning_clones.rs:196:5
    |
 LL |     **mut_box_string = ref_str.to_owned();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:187:5
+  --> tests/ui/assigning_clones.rs:200:5
    |
 LL |     **mut_box_string = ref_str.to_owned();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:191:5
+  --> tests/ui/assigning_clones.rs:204:5
    |
 LL |     *mut_thing = ToOwned::to_owned(ref_str);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, mut_thing)`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:195:5
+  --> tests/ui/assigning_clones.rs:208:5
    |
 LL |     mut_thing = ToOwned::to_owned(ref_str);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, &mut mut_thing)`
diff --git a/tests/ui/author/issue_3849.rs b/tests/ui/author/issue_3849.rs
index bae4570e539..5f65746d71f 100644
--- a/tests/ui/author/issue_3849.rs
+++ b/tests/ui/author/issue_3849.rs
@@ -1,7 +1,7 @@
 #![allow(dead_code)]
 #![allow(clippy::zero_ptr)]
 #![allow(clippy::transmute_ptr_to_ref)]
-#![allow(clippy::transmuting_null)]
+#![allow(clippy::transmuting_null, clippy::missing_transmute_annotations)]
 
 pub const ZPTR: *const usize = 0 as *const _;
 
diff --git a/tests/ui/auxiliary/macro_rules.rs b/tests/ui/auxiliary/macro_rules.rs
index 6b164967a28..9efbb390849 100644
--- a/tests/ui/auxiliary/macro_rules.rs
+++ b/tests/ui/auxiliary/macro_rules.rs
@@ -50,3 +50,10 @@ macro_rules! macro_with_panic {
         panic!()
     };
 }
+
+#[macro_export]
+macro_rules! bad_transmute {
+    ($e:expr) => {
+        std::mem::transmute($e)
+    };
+}
diff --git a/tests/ui/blocks_in_conditions.fixed b/tests/ui/blocks_in_conditions.fixed
index caf29e23d54..a2da5f9c5fb 100644
--- a/tests/ui/blocks_in_conditions.fixed
+++ b/tests/ui/blocks_in_conditions.fixed
@@ -1,7 +1,12 @@
 //@aux-build:proc_macro_attr.rs
 
 #![warn(clippy::blocks_in_conditions)]
-#![allow(unused, clippy::let_and_return, clippy::needless_if)]
+#![allow(
+    unused,
+    clippy::let_and_return,
+    clippy::needless_if,
+    clippy::missing_transmute_annotations
+)]
 #![warn(clippy::nonminimal_bool)]
 
 macro_rules! blocky {
diff --git a/tests/ui/blocks_in_conditions.rs b/tests/ui/blocks_in_conditions.rs
index e72daaa910d..608ca4cf267 100644
--- a/tests/ui/blocks_in_conditions.rs
+++ b/tests/ui/blocks_in_conditions.rs
@@ -1,7 +1,12 @@
 //@aux-build:proc_macro_attr.rs
 
 #![warn(clippy::blocks_in_conditions)]
-#![allow(unused, clippy::let_and_return, clippy::needless_if)]
+#![allow(
+    unused,
+    clippy::let_and_return,
+    clippy::needless_if,
+    clippy::missing_transmute_annotations
+)]
 #![warn(clippy::nonminimal_bool)]
 
 macro_rules! blocky {
diff --git a/tests/ui/blocks_in_conditions.stderr b/tests/ui/blocks_in_conditions.stderr
index 3641e71aae8..a55e1efb575 100644
--- a/tests/ui/blocks_in_conditions.stderr
+++ b/tests/ui/blocks_in_conditions.stderr
@@ -1,5 +1,5 @@
 error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
-  --> tests/ui/blocks_in_conditions.rs:25:5
+  --> tests/ui/blocks_in_conditions.rs:30:5
    |
 LL | /     if {
 LL | |
@@ -20,13 +20,13 @@ LL ~     }; if res {
    |
 
 error: omit braces around single expression condition
-  --> tests/ui/blocks_in_conditions.rs:37:8
+  --> tests/ui/blocks_in_conditions.rs:42:8
    |
 LL |     if { true } { 6 } else { 10 }
    |        ^^^^^^^^ help: try: `true`
 
 error: this boolean expression can be simplified
-  --> tests/ui/blocks_in_conditions.rs:43:8
+  --> tests/ui/blocks_in_conditions.rs:48:8
    |
 LL |     if true && x == 3 { 6 } else { 10 }
    |        ^^^^^^^^^^^^^^ help: try: `x == 3`
@@ -35,7 +35,7 @@ LL |     if true && x == 3 { 6 } else { 10 }
    = help: to override `-D warnings` add `#[allow(clippy::nonminimal_bool)]`
 
 error: in a `match` scrutinee, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
-  --> tests/ui/blocks_in_conditions.rs:70:5
+  --> tests/ui/blocks_in_conditions.rs:75:5
    |
 LL | /     match {
 LL | |
diff --git a/tests/ui/box_default.fixed b/tests/ui/box_default.fixed
index fea7405c685..6c2896b3aa0 100644
--- a/tests/ui/box_default.fixed
+++ b/tests/ui/box_default.fixed
@@ -1,5 +1,5 @@
 #![warn(clippy::box_default)]
-#![allow(clippy::default_constructed_unit_structs)]
+#![allow(clippy::boxed_local, clippy::default_constructed_unit_structs)]
 
 #[derive(Default)]
 struct ImplementsDefault;
@@ -12,26 +12,50 @@ impl OwnDefault {
     }
 }
 
-macro_rules! outer {
-    ($e: expr) => {
-        $e
+macro_rules! default {
+    () => {
+        Default::default()
+    };
+}
+
+macro_rules! string_new {
+    () => {
+        String::new()
+    };
+}
+
+macro_rules! box_new {
+    ($e:expr) => {
+        Box::new($e)
     };
 }
 
 fn main() {
-    let _string: Box<String> = Box::default();
-    let _byte = Box::<u8>::default();
-    let _vec = Box::<Vec::<u8>>::default();
-    let _impl = Box::<ImplementsDefault>::default();
-    let _impl2 = Box::<ImplementsDefault>::default();
-    let _impl3: Box<ImplementsDefault> = Box::default();
-    let _own = Box::new(OwnDefault::default()); // should not lint
-    let _in_macro = outer!(Box::<String>::default());
-    let _string_default = outer!(Box::<String>::default());
-    let _vec2: Box<Vec<ImplementsDefault>> = Box::default();
-    let _vec3: Box<Vec<bool>> = Box::default();
-    let _vec4: Box<_> = Box::<Vec<bool>>::default();
-    let _more = ret_ty_fn();
+    let string1: Box<String> = Box::default();
+    let string2: Box<String> = Box::default();
+    let impl1: Box<ImplementsDefault> = Box::default();
+    let vec: Box<Vec<u8>> = Box::default();
+    let byte: Box<u8> = Box::default();
+    let vec2: Box<Vec<ImplementsDefault>> = Box::default();
+    let vec3: Box<Vec<bool>> = Box::default();
+
+    let plain_default = Box::default();
+    let _: Box<String> = plain_default;
+
+    let _: Box<String> = Box::new(default!());
+    let _: Box<String> = Box::new(string_new!());
+    let _: Box<String> = box_new!(Default::default());
+    let _: Box<String> = box_new!(String::new());
+    let _: Box<String> = box_new!(default!());
+    let _: Box<String> = box_new!(string_new!());
+
+    let own: Box<OwnDefault> = Box::new(OwnDefault::default()); // should not lint
+
+    // Do not suggest where a turbofish would be required
+    let impl2 = Box::new(ImplementsDefault::default());
+    let impl3 = Box::new(<ImplementsDefault as Default>::default());
+    let vec4: Box<_> = Box::new(Vec::from([false; 0]));
+    let more = ret_ty_fn();
     call_ty_fn(Box::default());
     issue_10381();
 
@@ -44,10 +68,9 @@ fn main() {
 }
 
 fn ret_ty_fn() -> Box<bool> {
-    Box::<bool>::default()
+    Box::new(bool::default()) // Could lint, currently doesn't
 }
 
-#[allow(clippy::boxed_local)]
 fn call_ty_fn(_b: Box<u8>) {
     issue_9621_dyn_trait();
 }
@@ -61,7 +84,7 @@ impl Read for ImplementsDefault {
 }
 
 fn issue_9621_dyn_trait() {
-    let _: Box<dyn Read> = Box::<ImplementsDefault>::default();
+    let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
     issue_10089();
 }
 
@@ -70,7 +93,7 @@ fn issue_10089() {
         #[derive(Default)]
         struct WeirdPathed;
 
-        let _ = Box::<WeirdPathed>::default();
+        let _ = Box::new(WeirdPathed::default());
     };
 }
 
@@ -82,7 +105,7 @@ fn issue_10381() {
 
     fn maybe_get_bar(i: u32) -> Option<Box<dyn Bar>> {
         if i % 2 == 0 {
-            Some(Box::<Foo>::default())
+            Some(Box::new(Foo::default()))
         } else {
             None
         }
@@ -91,20 +114,6 @@ fn issue_10381() {
     assert!(maybe_get_bar(2).is_some());
 }
 
-#[allow(unused)]
-fn issue_11868() {
-    fn foo(_: &mut Vec<usize>) {}
-
-    macro_rules! bar {
-        ($baz:expr) => {
-            Box::leak(Box::new($baz))
-        };
-    }
-
-    foo(bar!(vec![]));
-    foo(bar!(vec![1]));
-}
-
 // Issue #11927: The quickfix for the `Box::new` suggests replacing with `Box::<Inner>::default()`,
 // removing the `outer::` segment.
 fn issue_11927() {
@@ -116,7 +125,7 @@ fn issue_11927() {
     }
 
     fn foo() {
-        let _b = Box::<outer::Inner>::default();
-        let _b = Box::<std::collections::HashSet::<i32>>::default();
+        let _b = Box::new(outer::Inner::default());
+        let _b = Box::new(std::collections::HashSet::<i32>::new());
     }
 }
diff --git a/tests/ui/box_default.rs b/tests/ui/box_default.rs
index eecba7464ec..e19a62a9022 100644
--- a/tests/ui/box_default.rs
+++ b/tests/ui/box_default.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::box_default)]
-#![allow(clippy::default_constructed_unit_structs)]
+#![allow(clippy::boxed_local, clippy::default_constructed_unit_structs)]
 
 #[derive(Default)]
 struct ImplementsDefault;
@@ -12,26 +12,50 @@ impl OwnDefault {
     }
 }
 
-macro_rules! outer {
-    ($e: expr) => {
-        $e
+macro_rules! default {
+    () => {
+        Default::default()
+    };
+}
+
+macro_rules! string_new {
+    () => {
+        String::new()
+    };
+}
+
+macro_rules! box_new {
+    ($e:expr) => {
+        Box::new($e)
     };
 }
 
 fn main() {
-    let _string: Box<String> = Box::new(Default::default());
-    let _byte = Box::new(u8::default());
-    let _vec = Box::new(Vec::<u8>::new());
-    let _impl = Box::new(ImplementsDefault::default());
-    let _impl2 = Box::new(<ImplementsDefault as Default>::default());
-    let _impl3: Box<ImplementsDefault> = Box::new(Default::default());
-    let _own = Box::new(OwnDefault::default()); // should not lint
-    let _in_macro = outer!(Box::new(String::new()));
-    let _string_default = outer!(Box::new(String::from("")));
-    let _vec2: Box<Vec<ImplementsDefault>> = Box::new(vec![]);
-    let _vec3: Box<Vec<bool>> = Box::new(Vec::from([]));
-    let _vec4: Box<_> = Box::new(Vec::from([false; 0]));
-    let _more = ret_ty_fn();
+    let string1: Box<String> = Box::new(Default::default());
+    let string2: Box<String> = Box::new(String::new());
+    let impl1: Box<ImplementsDefault> = Box::new(Default::default());
+    let vec: Box<Vec<u8>> = Box::new(Vec::new());
+    let byte: Box<u8> = Box::new(u8::default());
+    let vec2: Box<Vec<ImplementsDefault>> = Box::new(vec![]);
+    let vec3: Box<Vec<bool>> = Box::new(Vec::from([]));
+
+    let plain_default = Box::new(Default::default());
+    let _: Box<String> = plain_default;
+
+    let _: Box<String> = Box::new(default!());
+    let _: Box<String> = Box::new(string_new!());
+    let _: Box<String> = box_new!(Default::default());
+    let _: Box<String> = box_new!(String::new());
+    let _: Box<String> = box_new!(default!());
+    let _: Box<String> = box_new!(string_new!());
+
+    let own: Box<OwnDefault> = Box::new(OwnDefault::default()); // should not lint
+
+    // Do not suggest where a turbofish would be required
+    let impl2 = Box::new(ImplementsDefault::default());
+    let impl3 = Box::new(<ImplementsDefault as Default>::default());
+    let vec4: Box<_> = Box::new(Vec::from([false; 0]));
+    let more = ret_ty_fn();
     call_ty_fn(Box::new(u8::default()));
     issue_10381();
 
@@ -44,10 +68,9 @@ fn main() {
 }
 
 fn ret_ty_fn() -> Box<bool> {
-    Box::new(bool::default())
+    Box::new(bool::default()) // Could lint, currently doesn't
 }
 
-#[allow(clippy::boxed_local)]
 fn call_ty_fn(_b: Box<u8>) {
     issue_9621_dyn_trait();
 }
@@ -91,20 +114,6 @@ fn issue_10381() {
     assert!(maybe_get_bar(2).is_some());
 }
 
-#[allow(unused)]
-fn issue_11868() {
-    fn foo(_: &mut Vec<usize>) {}
-
-    macro_rules! bar {
-        ($baz:expr) => {
-            Box::leak(Box::new($baz))
-        };
-    }
-
-    foo(bar!(vec![]));
-    foo(bar!(vec![1]));
-}
-
 // Issue #11927: The quickfix for the `Box::new` suggests replacing with `Box::<Inner>::default()`,
 // removing the `outer::` segment.
 fn issue_11927() {
diff --git a/tests/ui/box_default.stderr b/tests/ui/box_default.stderr
index 8bb5917a627..f172a875dce 100644
--- a/tests/ui/box_default.stderr
+++ b/tests/ui/box_default.stderr
@@ -1,113 +1,59 @@
 error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:22:32
+  --> tests/ui/box_default.rs:34:32
    |
-LL |     let _string: Box<String> = Box::new(Default::default());
+LL |     let string1: Box<String> = Box::new(Default::default());
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
    |
    = note: `-D clippy::box-default` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::box_default)]`
 
 error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:23:17
+  --> tests/ui/box_default.rs:35:32
    |
-LL |     let _byte = Box::new(u8::default());
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<u8>::default()`
+LL |     let string2: Box<String> = Box::new(String::new());
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 
 error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:24:16
+  --> tests/ui/box_default.rs:36:41
    |
-LL |     let _vec = Box::new(Vec::<u8>::new());
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Vec::<u8>>::default()`
+LL |     let impl1: Box<ImplementsDefault> = Box::new(Default::default());
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 
 error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:25:17
+  --> tests/ui/box_default.rs:37:29
    |
-LL |     let _impl = Box::new(ImplementsDefault::default());
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
+LL |     let vec: Box<Vec<u8>> = Box::new(Vec::new());
+   |                             ^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 
 error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:26:18
+  --> tests/ui/box_default.rs:38:25
    |
-LL |     let _impl2 = Box::new(<ImplementsDefault as Default>::default());
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
+LL |     let byte: Box<u8> = Box::new(u8::default());
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 
 error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:27:42
+  --> tests/ui/box_default.rs:39:45
    |
-LL |     let _impl3: Box<ImplementsDefault> = Box::new(Default::default());
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
+LL |     let vec2: Box<Vec<ImplementsDefault>> = Box::new(vec![]);
+   |                                             ^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 
 error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:29:28
+  --> tests/ui/box_default.rs:40:32
    |
-LL |     let _in_macro = outer!(Box::new(String::new()));
-   |                            ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<String>::default()`
+LL |     let vec3: Box<Vec<bool>> = Box::new(Vec::from([]));
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 
 error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:30:34
+  --> tests/ui/box_default.rs:42:25
    |
-LL |     let _string_default = outer!(Box::new(String::from("")));
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<String>::default()`
+LL |     let plain_default = Box::new(Default::default());
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 
 error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:31:46
-   |
-LL |     let _vec2: Box<Vec<ImplementsDefault>> = Box::new(vec![]);
-   |                                              ^^^^^^^^^^^^^^^^ help: try: `Box::default()`
-
-error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:32:33
-   |
-LL |     let _vec3: Box<Vec<bool>> = Box::new(Vec::from([]));
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
-
-error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:33:25
-   |
-LL |     let _vec4: Box<_> = Box::new(Vec::from([false; 0]));
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Vec<bool>>::default()`
-
-error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:35:16
+  --> tests/ui/box_default.rs:59:16
    |
 LL |     call_ty_fn(Box::new(u8::default()));
    |                ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 
-error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:47:5
-   |
-LL |     Box::new(bool::default())
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<bool>::default()`
-
-error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:64:28
-   |
-LL |     let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
-   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
-
-error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:73:17
-   |
-LL |         let _ = Box::new(WeirdPathed::default());
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<WeirdPathed>::default()`
-
-error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:85:18
-   |
-LL |             Some(Box::new(Foo::default()))
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Foo>::default()`
-
-error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:119:18
-   |
-LL |         let _b = Box::new(outer::Inner::default());
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<outer::Inner>::default()`
-
-error: `Box::new(_)` of default value
-  --> tests/ui/box_default.rs:120:18
-   |
-LL |         let _b = Box::new(std::collections::HashSet::<i32>::new());
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::collections::HashSet::<i32>>::default()`
-
-error: aborting due to 18 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs
index a7331ddc7d0..ce76ad3d3ad 100644
--- a/tests/ui/cast.rs
+++ b/tests/ui/cast.rs
@@ -9,7 +9,12 @@
     clippy::cast_sign_loss,
     clippy::cast_possible_wrap
 )]
-#![allow(clippy::cast_abs_to_unsigned, clippy::no_effect, clippy::unnecessary_operation)]
+#![allow(
+    clippy::cast_abs_to_unsigned,
+    clippy::no_effect,
+    clippy::unnecessary_operation,
+    clippy::unnecessary_literal_unwrap
+)]
 
 fn main() {
     // Test clippy::cast_precision_loss
@@ -457,3 +462,8 @@ fn issue11642() {
         //~^ ERROR: casting `i32` to `u32` may lose the sign of the value
     }
 }
+
+fn issue12506() -> usize {
+    let bar: Result<Option<i64>, u32> = Ok(Some(10));
+    bar.unwrap().unwrap() as usize
+}
diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr
index dd5d339b81b..3736e8aee0a 100644
--- a/tests/ui/cast.stderr
+++ b/tests/ui/cast.stderr
@@ -1,5 +1,5 @@
 error: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide)
-  --> tests/ui/cast.rs:17:5
+  --> tests/ui/cast.rs:22:5
    |
 LL |     x0 as f32;
    |     ^^^^^^^^^
@@ -8,37 +8,37 @@ LL |     x0 as f32;
    = help: to override `-D warnings` add `#[allow(clippy::cast_precision_loss)]`
 
 error: casting `i64` to `f32` causes a loss of precision (`i64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide)
-  --> tests/ui/cast.rs:21:5
+  --> tests/ui/cast.rs:26:5
    |
 LL |     x1 as f32;
    |     ^^^^^^^^^
 
 error: casting `i64` to `f64` causes a loss of precision (`i64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
-  --> tests/ui/cast.rs:23:5
+  --> tests/ui/cast.rs:28:5
    |
 LL |     x1 as f64;
    |     ^^^^^^^^^
 
 error: casting `u32` to `f32` causes a loss of precision (`u32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide)
-  --> tests/ui/cast.rs:26:5
+  --> tests/ui/cast.rs:31:5
    |
 LL |     x2 as f32;
    |     ^^^^^^^^^
 
 error: casting `u64` to `f32` causes a loss of precision (`u64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide)
-  --> tests/ui/cast.rs:29:5
+  --> tests/ui/cast.rs:34:5
    |
 LL |     x3 as f32;
    |     ^^^^^^^^^
 
 error: casting `u64` to `f64` causes a loss of precision (`u64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
-  --> tests/ui/cast.rs:31:5
+  --> tests/ui/cast.rs:36:5
    |
 LL |     x3 as f64;
    |     ^^^^^^^^^
 
 error: casting `f32` to `i32` may truncate the value
-  --> tests/ui/cast.rs:34:5
+  --> tests/ui/cast.rs:39:5
    |
 LL |     1f32 as i32;
    |     ^^^^^^^^^^^
@@ -48,7 +48,7 @@ LL |     1f32 as i32;
    = help: to override `-D warnings` add `#[allow(clippy::cast_possible_truncation)]`
 
 error: casting `f32` to `u32` may truncate the value
-  --> tests/ui/cast.rs:36:5
+  --> tests/ui/cast.rs:41:5
    |
 LL |     1f32 as u32;
    |     ^^^^^^^^^^^
@@ -56,7 +56,7 @@ LL |     1f32 as u32;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 
 error: casting `f32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:36:5
+  --> tests/ui/cast.rs:41:5
    |
 LL |     1f32 as u32;
    |     ^^^^^^^^^^^
@@ -65,7 +65,7 @@ LL |     1f32 as u32;
    = help: to override `-D warnings` add `#[allow(clippy::cast_sign_loss)]`
 
 error: casting `f64` to `f32` may truncate the value
-  --> tests/ui/cast.rs:40:5
+  --> tests/ui/cast.rs:45:5
    |
 LL |     1f64 as f32;
    |     ^^^^^^^^^^^
@@ -73,7 +73,7 @@ LL |     1f64 as f32;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 
 error: casting `i32` to `i8` may truncate the value
-  --> tests/ui/cast.rs:42:5
+  --> tests/ui/cast.rs:47:5
    |
 LL |     1i32 as i8;
    |     ^^^^^^^^^^
@@ -85,7 +85,7 @@ LL |     i8::try_from(1i32);
    |     ~~~~~~~~~~~~~~~~~~
 
 error: casting `i32` to `u8` may truncate the value
-  --> tests/ui/cast.rs:44:5
+  --> tests/ui/cast.rs:49:5
    |
 LL |     1i32 as u8;
    |     ^^^^^^^^^^
@@ -97,7 +97,7 @@ LL |     u8::try_from(1i32);
    |     ~~~~~~~~~~~~~~~~~~
 
 error: casting `f64` to `isize` may truncate the value
-  --> tests/ui/cast.rs:46:5
+  --> tests/ui/cast.rs:51:5
    |
 LL |     1f64 as isize;
    |     ^^^^^^^^^^^^^
@@ -105,7 +105,7 @@ LL |     1f64 as isize;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 
 error: casting `f64` to `usize` may truncate the value
-  --> tests/ui/cast.rs:48:5
+  --> tests/ui/cast.rs:53:5
    |
 LL |     1f64 as usize;
    |     ^^^^^^^^^^^^^
@@ -113,13 +113,13 @@ LL |     1f64 as usize;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 
 error: casting `f64` to `usize` may lose the sign of the value
-  --> tests/ui/cast.rs:48:5
+  --> tests/ui/cast.rs:53:5
    |
 LL |     1f64 as usize;
    |     ^^^^^^^^^^^^^
 
 error: casting `u32` to `u16` may truncate the value
-  --> tests/ui/cast.rs:51:5
+  --> tests/ui/cast.rs:56:5
    |
 LL |     1f32 as u32 as u16;
    |     ^^^^^^^^^^^^^^^^^^
@@ -131,7 +131,7 @@ LL |     u16::try_from(1f32 as u32);
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `f32` to `u32` may truncate the value
-  --> tests/ui/cast.rs:51:5
+  --> tests/ui/cast.rs:56:5
    |
 LL |     1f32 as u32 as u16;
    |     ^^^^^^^^^^^
@@ -139,13 +139,13 @@ LL |     1f32 as u32 as u16;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 
 error: casting `f32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:51:5
+  --> tests/ui/cast.rs:56:5
    |
 LL |     1f32 as u32 as u16;
    |     ^^^^^^^^^^^
 
 error: casting `i32` to `i8` may truncate the value
-  --> tests/ui/cast.rs:56:22
+  --> tests/ui/cast.rs:61:22
    |
 LL |         let _x: i8 = 1i32 as _;
    |                      ^^^^^^^^^
@@ -157,7 +157,7 @@ LL |         let _x: i8 = 1i32.try_into();
    |                      ~~~~~~~~~~~~~~~
 
 error: casting `f32` to `i32` may truncate the value
-  --> tests/ui/cast.rs:58:9
+  --> tests/ui/cast.rs:63:9
    |
 LL |         1f32 as i32;
    |         ^^^^^^^^^^^
@@ -165,7 +165,7 @@ LL |         1f32 as i32;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 
 error: casting `f64` to `i32` may truncate the value
-  --> tests/ui/cast.rs:60:9
+  --> tests/ui/cast.rs:65:9
    |
 LL |         1f64 as i32;
    |         ^^^^^^^^^^^
@@ -173,7 +173,7 @@ LL |         1f64 as i32;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 
 error: casting `f32` to `u8` may truncate the value
-  --> tests/ui/cast.rs:62:9
+  --> tests/ui/cast.rs:67:9
    |
 LL |         1f32 as u8;
    |         ^^^^^^^^^^
@@ -181,13 +181,13 @@ LL |         1f32 as u8;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 
 error: casting `f32` to `u8` may lose the sign of the value
-  --> tests/ui/cast.rs:62:9
+  --> tests/ui/cast.rs:67:9
    |
 LL |         1f32 as u8;
    |         ^^^^^^^^^^
 
 error: casting `u8` to `i8` may wrap around the value
-  --> tests/ui/cast.rs:67:5
+  --> tests/ui/cast.rs:72:5
    |
 LL |     1u8 as i8;
    |     ^^^^^^^^^
@@ -196,31 +196,31 @@ LL |     1u8 as i8;
    = help: to override `-D warnings` add `#[allow(clippy::cast_possible_wrap)]`
 
 error: casting `u16` to `i16` may wrap around the value
-  --> tests/ui/cast.rs:70:5
+  --> tests/ui/cast.rs:75:5
    |
 LL |     1u16 as i16;
    |     ^^^^^^^^^^^
 
 error: casting `u32` to `i32` may wrap around the value
-  --> tests/ui/cast.rs:72:5
+  --> tests/ui/cast.rs:77:5
    |
 LL |     1u32 as i32;
    |     ^^^^^^^^^^^
 
 error: casting `u64` to `i64` may wrap around the value
-  --> tests/ui/cast.rs:74:5
+  --> tests/ui/cast.rs:79:5
    |
 LL |     1u64 as i64;
    |     ^^^^^^^^^^^
 
 error: casting `usize` to `isize` may wrap around the value
-  --> tests/ui/cast.rs:76:5
+  --> tests/ui/cast.rs:81:5
    |
 LL |     1usize as isize;
    |     ^^^^^^^^^^^^^^^
 
 error: casting `usize` to `i8` may truncate the value
-  --> tests/ui/cast.rs:79:5
+  --> tests/ui/cast.rs:84:5
    |
 LL |     1usize as i8;
    |     ^^^^^^^^^^^^
@@ -232,7 +232,7 @@ LL |     i8::try_from(1usize);
    |     ~~~~~~~~~~~~~~~~~~~~
 
 error: casting `usize` to `i16` may truncate the value
-  --> tests/ui/cast.rs:82:5
+  --> tests/ui/cast.rs:87:5
    |
 LL |     1usize as i16;
    |     ^^^^^^^^^^^^^
@@ -244,7 +244,7 @@ LL |     i16::try_from(1usize);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `usize` to `i16` may wrap around the value on targets with 16-bit wide pointers
-  --> tests/ui/cast.rs:82:5
+  --> tests/ui/cast.rs:87:5
    |
 LL |     1usize as i16;
    |     ^^^^^^^^^^^^^
@@ -253,7 +253,7 @@ LL |     1usize as i16;
    = note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types
 
 error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers
-  --> tests/ui/cast.rs:87:5
+  --> tests/ui/cast.rs:92:5
    |
 LL |     1usize as i32;
    |     ^^^^^^^^^^^^^
@@ -265,19 +265,19 @@ LL |     i32::try_from(1usize);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers
-  --> tests/ui/cast.rs:87:5
+  --> tests/ui/cast.rs:92:5
    |
 LL |     1usize as i32;
    |     ^^^^^^^^^^^^^
 
 error: casting `usize` to `i64` may wrap around the value on targets with 64-bit wide pointers
-  --> tests/ui/cast.rs:91:5
+  --> tests/ui/cast.rs:96:5
    |
 LL |     1usize as i64;
    |     ^^^^^^^^^^^^^
 
 error: casting `u16` to `isize` may wrap around the value on targets with 16-bit wide pointers
-  --> tests/ui/cast.rs:96:5
+  --> tests/ui/cast.rs:101:5
    |
 LL |     1u16 as isize;
    |     ^^^^^^^^^^^^^
@@ -286,13 +286,13 @@ LL |     1u16 as isize;
    = note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types
 
 error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers
-  --> tests/ui/cast.rs:100:5
+  --> tests/ui/cast.rs:105:5
    |
 LL |     1u32 as isize;
    |     ^^^^^^^^^^^^^
 
 error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers
-  --> tests/ui/cast.rs:103:5
+  --> tests/ui/cast.rs:108:5
    |
 LL |     1u64 as isize;
    |     ^^^^^^^^^^^^^
@@ -304,55 +304,55 @@ LL |     isize::try_from(1u64);
    |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers
-  --> tests/ui/cast.rs:103:5
+  --> tests/ui/cast.rs:108:5
    |
 LL |     1u64 as isize;
    |     ^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:108:5
+  --> tests/ui/cast.rs:113:5
    |
 LL |     -1i32 as u32;
    |     ^^^^^^^^^^^^
 
 error: casting `isize` to `usize` may lose the sign of the value
-  --> tests/ui/cast.rs:111:5
+  --> tests/ui/cast.rs:116:5
    |
 LL |     -1isize as usize;
    |     ^^^^^^^^^^^^^^^^
 
 error: casting `i8` to `u8` may lose the sign of the value
-  --> tests/ui/cast.rs:122:5
+  --> tests/ui/cast.rs:127:5
    |
 LL |     (i8::MIN).abs() as u8;
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i64` to `u64` may lose the sign of the value
-  --> tests/ui/cast.rs:126:5
+  --> tests/ui/cast.rs:131:5
    |
 LL |     (-1i64).abs() as u64;
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: casting `isize` to `usize` may lose the sign of the value
-  --> tests/ui/cast.rs:127:5
+  --> tests/ui/cast.rs:132:5
    |
 LL |     (-1isize).abs() as usize;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i64` to `u64` may lose the sign of the value
-  --> tests/ui/cast.rs:134:5
+  --> tests/ui/cast.rs:139:5
    |
 LL |     (unsafe { (-1i64).checked_abs().unwrap_unchecked() }) as u64;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i64` to `u64` may lose the sign of the value
-  --> tests/ui/cast.rs:149:5
+  --> tests/ui/cast.rs:154:5
    |
 LL |     (unsafe { (-1i64).checked_isqrt().unwrap_unchecked() }) as u64;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i64` to `i8` may truncate the value
-  --> tests/ui/cast.rs:200:5
+  --> tests/ui/cast.rs:205:5
    |
 LL |     (-99999999999i64).min(1) as i8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -364,7 +364,7 @@ LL |     i8::try_from((-99999999999i64).min(1));
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `u64` to `u8` may truncate the value
-  --> tests/ui/cast.rs:214:5
+  --> tests/ui/cast.rs:219:5
    |
 LL |     999999u64.clamp(0, 256) as u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -376,7 +376,7 @@ LL |     u8::try_from(999999u64.clamp(0, 256));
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E2` to `u8` may truncate the value
-  --> tests/ui/cast.rs:237:21
+  --> tests/ui/cast.rs:242:21
    |
 LL |             let _ = self as u8;
    |                     ^^^^^^^^^^
@@ -388,7 +388,7 @@ LL |             let _ = u8::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E2::B` to `u8` will truncate the value
-  --> tests/ui/cast.rs:239:21
+  --> tests/ui/cast.rs:244:21
    |
 LL |             let _ = Self::B as u8;
    |                     ^^^^^^^^^^^^^
@@ -397,7 +397,7 @@ LL |             let _ = Self::B as u8;
    = help: to override `-D warnings` add `#[allow(clippy::cast_enum_truncation)]`
 
 error: casting `main::E5` to `i8` may truncate the value
-  --> tests/ui/cast.rs:281:21
+  --> tests/ui/cast.rs:286:21
    |
 LL |             let _ = self as i8;
    |                     ^^^^^^^^^^
@@ -409,13 +409,13 @@ LL |             let _ = i8::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E5::A` to `i8` will truncate the value
-  --> tests/ui/cast.rs:283:21
+  --> tests/ui/cast.rs:288:21
    |
 LL |             let _ = Self::A as i8;
    |                     ^^^^^^^^^^^^^
 
 error: casting `main::E6` to `i16` may truncate the value
-  --> tests/ui/cast.rs:300:21
+  --> tests/ui/cast.rs:305:21
    |
 LL |             let _ = self as i16;
    |                     ^^^^^^^^^^^
@@ -427,7 +427,7 @@ LL |             let _ = i16::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers
-  --> tests/ui/cast.rs:319:21
+  --> tests/ui/cast.rs:324:21
    |
 LL |             let _ = self as usize;
    |                     ^^^^^^^^^^^^^
@@ -439,7 +439,7 @@ LL |             let _ = usize::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E10` to `u16` may truncate the value
-  --> tests/ui/cast.rs:366:21
+  --> tests/ui/cast.rs:371:21
    |
 LL |             let _ = self as u16;
    |                     ^^^^^^^^^^^
@@ -451,7 +451,7 @@ LL |             let _ = u16::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~~
 
 error: casting `u32` to `u8` may truncate the value
-  --> tests/ui/cast.rs:377:13
+  --> tests/ui/cast.rs:382:13
    |
 LL |     let c = (q >> 16) as u8;
    |             ^^^^^^^^^^^^^^^
@@ -463,7 +463,7 @@ LL |     let c = u8::try_from(q >> 16);
    |             ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `u32` to `u8` may truncate the value
-  --> tests/ui/cast.rs:381:13
+  --> tests/ui/cast.rs:386:13
    |
 LL |     let c = (q / 1000) as u8;
    |             ^^^^^^^^^^^^^^^^
@@ -475,85 +475,85 @@ LL |     let c = u8::try_from(q / 1000);
    |             ~~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:393:9
+  --> tests/ui/cast.rs:398:9
    |
 LL |         (x * x) as u32;
    |         ^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:398:32
+  --> tests/ui/cast.rs:403:32
    |
 LL |     let _a = |x: i32| -> u32 { (x * x * x * x) as u32 };
    |                                ^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:400:5
+  --> tests/ui/cast.rs:405:5
    |
 LL |     (2_i32).checked_pow(3).unwrap() as u32;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:401:5
+  --> tests/ui/cast.rs:406:5
    |
 LL |     (-2_i32).pow(3) as u32;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:406:5
+  --> tests/ui/cast.rs:411:5
    |
 LL |     (-5_i32 % 2) as u32;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:408:5
+  --> tests/ui/cast.rs:413:5
    |
 LL |     (-5_i32 % -2) as u32;
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:411:5
+  --> tests/ui/cast.rs:416:5
    |
 LL |     (-2_i32 >> 1) as u32;
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:415:5
+  --> tests/ui/cast.rs:420:5
    |
 LL |     (x * x) as u32;
    |     ^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:416:5
+  --> tests/ui/cast.rs:421:5
    |
 LL |     (x * x * x) as u32;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: casting `i16` to `u16` may lose the sign of the value
-  --> tests/ui/cast.rs:420:5
+  --> tests/ui/cast.rs:425:5
    |
 LL |     (y * y * y * y * -2) as u16;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i16` to `u16` may lose the sign of the value
-  --> tests/ui/cast.rs:422:5
+  --> tests/ui/cast.rs:427:5
    |
 LL |     (y * y * y / y * 2) as u16;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i16` to `u16` may lose the sign of the value
-  --> tests/ui/cast.rs:423:5
+  --> tests/ui/cast.rs:428:5
    |
 LL |     (y * y / y * 2) as u16;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i16` to `u16` may lose the sign of the value
-  --> tests/ui/cast.rs:425:5
+  --> tests/ui/cast.rs:430:5
    |
 LL |     (y / y * y * -2) as u16;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `/`
-  --> tests/ui/cast.rs:425:6
+  --> tests/ui/cast.rs:430:6
    |
 LL |     (y / y * y * -2) as u16;
    |      ^^^^^
@@ -561,94 +561,112 @@ LL |     (y / y * y * -2) as u16;
    = note: `#[deny(clippy::eq_op)]` on by default
 
 error: casting `i16` to `u16` may lose the sign of the value
-  --> tests/ui/cast.rs:428:5
+  --> tests/ui/cast.rs:433:5
    |
 LL |     (y + y + y + -2) as u16;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i16` to `u16` may lose the sign of the value
-  --> tests/ui/cast.rs:430:5
+  --> tests/ui/cast.rs:435:5
    |
 LL |     (y + y + y + 2) as u16;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i16` to `u16` may lose the sign of the value
-  --> tests/ui/cast.rs:434:5
+  --> tests/ui/cast.rs:439:5
    |
 LL |     (z + -2) as u16;
    |     ^^^^^^^^^^^^^^^
 
 error: casting `i16` to `u16` may lose the sign of the value
-  --> tests/ui/cast.rs:436:5
+  --> tests/ui/cast.rs:441:5
    |
 LL |     (z + z + 2) as u16;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:439:9
+  --> tests/ui/cast.rs:444:9
    |
 LL |         (a * a * b * b * c * c) as u32;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:440:9
+  --> tests/ui/cast.rs:445:9
    |
 LL |         (a * b * c) as u32;
    |         ^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:442:9
+  --> tests/ui/cast.rs:447:9
    |
 LL |         (a * -b * c) as u32;
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:444:9
+  --> tests/ui/cast.rs:449:9
    |
 LL |         (a * b * c * c) as u32;
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:445:9
+  --> tests/ui/cast.rs:450:9
    |
 LL |         (a * -2) as u32;
    |         ^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:447:9
+  --> tests/ui/cast.rs:452:9
    |
 LL |         (a * b * c * -2) as u32;
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:449:9
+  --> tests/ui/cast.rs:454:9
    |
 LL |         (a / b) as u32;
    |         ^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:450:9
+  --> tests/ui/cast.rs:455:9
    |
 LL |         (a / b * c) as u32;
    |         ^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:452:9
+  --> tests/ui/cast.rs:457:9
    |
 LL |         (a / b + b * c) as u32;
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:454:9
+  --> tests/ui/cast.rs:459:9
    |
 LL |         a.saturating_pow(3) as u32;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:456:9
+  --> tests/ui/cast.rs:461:9
    |
 LL |         (a.abs() * b.pow(2) / c.abs()) as u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 85 previous errors
+error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers
+  --> tests/ui/cast.rs:468:5
+   |
+LL |     bar.unwrap().unwrap() as usize
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+   |
+LL |     usize::try_from(bar.unwrap().unwrap())
+   |
+
+error: casting `i64` to `usize` may lose the sign of the value
+  --> tests/ui/cast.rs:468:5
+   |
+LL |     bar.unwrap().unwrap() as usize
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 87 previous errors
 
diff --git a/tests/ui/checked_conversions.fixed b/tests/ui/checked_conversions.fixed
index 0e05a27429b..1e8da331614 100644
--- a/tests/ui/checked_conversions.fixed
+++ b/tests/ui/checked_conversions.fixed
@@ -1,5 +1,6 @@
 #![allow(
     clippy::cast_lossless,
+    clippy::legacy_numeric_constants,
     unused,
     // Int::max_value will be deprecated in the future
     deprecated,
diff --git a/tests/ui/checked_conversions.rs b/tests/ui/checked_conversions.rs
index ac782699265..67a9adc049e 100644
--- a/tests/ui/checked_conversions.rs
+++ b/tests/ui/checked_conversions.rs
@@ -1,5 +1,6 @@
 #![allow(
     clippy::cast_lossless,
+    clippy::legacy_numeric_constants,
     unused,
     // Int::max_value will be deprecated in the future
     deprecated,
diff --git a/tests/ui/checked_conversions.stderr b/tests/ui/checked_conversions.stderr
index 223e379cce9..453cd7fcf01 100644
--- a/tests/ui/checked_conversions.stderr
+++ b/tests/ui/checked_conversions.stderr
@@ -1,5 +1,5 @@
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:14:13
+  --> tests/ui/checked_conversions.rs:15:13
    |
 LL |     let _ = value <= (u32::max_value() as i64) && value >= 0;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()`
@@ -8,97 +8,97 @@ LL |     let _ = value <= (u32::max_value() as i64) && value >= 0;
    = help: to override `-D warnings` add `#[allow(clippy::checked_conversions)]`
 
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:15:13
+  --> tests/ui/checked_conversions.rs:16:13
    |
 LL |     let _ = value <= (u32::MAX as i64) && value >= 0;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()`
 
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:19:13
+  --> tests/ui/checked_conversions.rs:20:13
    |
 LL |     let _ = value <= i64::from(u16::max_value()) && value >= 0;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()`
 
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:20:13
+  --> tests/ui/checked_conversions.rs:21:13
    |
 LL |     let _ = value <= i64::from(u16::MAX) && value >= 0;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()`
 
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:24:13
+  --> tests/ui/checked_conversions.rs:25:13
    |
 LL |     let _ = value <= (u8::max_value() as isize) && value >= 0;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()`
 
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:25:13
+  --> tests/ui/checked_conversions.rs:26:13
    |
 LL |     let _ = value <= (u8::MAX as isize) && value >= 0;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()`
 
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:31:13
+  --> tests/ui/checked_conversions.rs:32:13
    |
 LL |     let _ = value <= (i32::max_value() as i64) && value >= (i32::min_value() as i64);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()`
 
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:32:13
+  --> tests/ui/checked_conversions.rs:33:13
    |
 LL |     let _ = value <= (i32::MAX as i64) && value >= (i32::MIN as i64);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()`
 
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:36:13
+  --> tests/ui/checked_conversions.rs:37:13
    |
 LL |     let _ = value <= i64::from(i16::max_value()) && value >= i64::from(i16::min_value());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i16::try_from(value).is_ok()`
 
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:37:13
+  --> tests/ui/checked_conversions.rs:38:13
    |
 LL |     let _ = value <= i64::from(i16::MAX) && value >= i64::from(i16::MIN);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i16::try_from(value).is_ok()`
 
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:43:13
+  --> tests/ui/checked_conversions.rs:44:13
    |
 LL |     let _ = value <= i32::max_value() as u32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()`
 
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:44:13
+  --> tests/ui/checked_conversions.rs:45:13
    |
 LL |     let _ = value <= i32::MAX as u32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()`
 
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:48:13
+  --> tests/ui/checked_conversions.rs:49:13
    |
 LL |     let _ = value <= isize::max_value() as usize && value as i32 == 5;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `isize::try_from(value).is_ok()`
 
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:49:13
+  --> tests/ui/checked_conversions.rs:50:13
    |
 LL |     let _ = value <= isize::MAX as usize && value as i32 == 5;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `isize::try_from(value).is_ok()`
 
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:53:13
+  --> tests/ui/checked_conversions.rs:54:13
    |
 LL |     let _ = value <= u16::max_value() as u32 && value as i32 == 5;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()`
 
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:54:13
+  --> tests/ui/checked_conversions.rs:55:13
    |
 LL |     let _ = value <= u16::MAX as u32 && value as i32 == 5;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()`
 
 error: checked cast can be simplified
-  --> tests/ui/checked_conversions.rs:87:13
+  --> tests/ui/checked_conversions.rs:88:13
    |
 LL |     let _ = value <= (u32::MAX as i64) && value >= 0;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()`
diff --git a/tests/ui/crashes/ice-12616.fixed b/tests/ui/crashes/ice-12616.fixed
new file mode 100644
index 00000000000..a5a5b3d1e78
--- /dev/null
+++ b/tests/ui/crashes/ice-12616.fixed
@@ -0,0 +1,7 @@
+#![warn(clippy::ptr_as_ptr)]
+#![allow(clippy::unnecessary_operation, clippy::unnecessary_cast)]
+
+fn main() {
+    let s = std::ptr::null::<()>;
+    s().cast::<()>();
+}
diff --git a/tests/ui/crashes/ice-12616.rs b/tests/ui/crashes/ice-12616.rs
new file mode 100644
index 00000000000..6ee9a5ec08f
--- /dev/null
+++ b/tests/ui/crashes/ice-12616.rs
@@ -0,0 +1,7 @@
+#![warn(clippy::ptr_as_ptr)]
+#![allow(clippy::unnecessary_operation, clippy::unnecessary_cast)]
+
+fn main() {
+    let s = std::ptr::null::<()>;
+    s() as *const ();
+}
diff --git a/tests/ui/crashes/ice-12616.stderr b/tests/ui/crashes/ice-12616.stderr
new file mode 100644
index 00000000000..ef573f55cf3
--- /dev/null
+++ b/tests/ui/crashes/ice-12616.stderr
@@ -0,0 +1,19 @@
+error: `as` casting between raw pointers without changing its mutability
+  --> tests/ui/crashes/ice-12616.rs:6:5
+   |
+LL |     s() as *const ();
+   |     ^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `s().cast::<()>()`
+   |
+   = note: `-D clippy::ptr-as-ptr` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::ptr_as_ptr)]`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> tests/ui/crashes/ice-12616.rs:6:5
+   |
+LL |     s() as *const ();
+   |     ^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `s().cast::<()>()`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/crashes/ice-1782.rs b/tests/ui/crashes/ice-1782.rs
index 19ab03418ee..73de5721cbc 100644
--- a/tests/ui/crashes/ice-1782.rs
+++ b/tests/ui/crashes/ice-1782.rs
@@ -1,5 +1,5 @@
 #![allow(dead_code, unused_variables)]
-#![allow(clippy::unnecessary_cast)]
+#![allow(clippy::unnecessary_cast, clippy::missing_transmute_annotations)]
 
 /// Should not trigger an ICE in `SpanlessEq` / `consts::constant`
 ///
diff --git a/tests/ui/duplicated_attributes.rs b/tests/ui/duplicated_attributes.rs
index 0f036c684c1..d051c881f15 100644
--- a/tests/ui/duplicated_attributes.rs
+++ b/tests/ui/duplicated_attributes.rs
@@ -2,16 +2,17 @@
 #![cfg(any(unix, windows))]
 #![allow(dead_code)]
 #![allow(dead_code)] //~ ERROR: duplicated attribute
-#![cfg(any(unix, windows))]
-//~^ ERROR: duplicated attribute
-//~| ERROR: duplicated attribute
+#![cfg(any(unix, windows))] // Should not warn!
 
 #[cfg(any(unix, windows, target_os = "linux"))]
 #[allow(dead_code)]
 #[allow(dead_code)] //~ ERROR: duplicated attribute
-#[cfg(any(unix, windows, target_os = "linux"))]
-//~^ ERROR: duplicated attribute
-//~| ERROR: duplicated attribute
+#[cfg(any(unix, windows, target_os = "linux"))] // Should not warn!
 fn foo() {}
 
+#[cfg(unix)]
+#[cfg(windows)]
+#[cfg(unix)] //~ ERROR: duplicated attribute
+fn bar() {}
+
 fn main() {}
diff --git a/tests/ui/duplicated_attributes.stderr b/tests/ui/duplicated_attributes.stderr
index 1c6578dbb43..9e26ba990ac 100644
--- a/tests/ui/duplicated_attributes.stderr
+++ b/tests/ui/duplicated_attributes.stderr
@@ -18,106 +18,38 @@ LL | #![allow(dead_code)]
    = help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]`
 
 error: duplicated attribute
-  --> tests/ui/duplicated_attributes.rs:5:12
-   |
-LL | #![cfg(any(unix, windows))]
-   |            ^^^^
-   |
-note: first defined here
-  --> tests/ui/duplicated_attributes.rs:2:12
-   |
-LL | #![cfg(any(unix, windows))]
-   |            ^^^^
-help: remove this attribute
-  --> tests/ui/duplicated_attributes.rs:5:12
-   |
-LL | #![cfg(any(unix, windows))]
-   |            ^^^^
-
-error: duplicated attribute
-  --> tests/ui/duplicated_attributes.rs:5:18
-   |
-LL | #![cfg(any(unix, windows))]
-   |                  ^^^^^^^
-   |
-note: first defined here
-  --> tests/ui/duplicated_attributes.rs:2:18
-   |
-LL | #![cfg(any(unix, windows))]
-   |                  ^^^^^^^
-help: remove this attribute
-  --> tests/ui/duplicated_attributes.rs:5:18
-   |
-LL | #![cfg(any(unix, windows))]
-   |                  ^^^^^^^
-
-error: duplicated attribute
-  --> tests/ui/duplicated_attributes.rs:11:9
+  --> tests/ui/duplicated_attributes.rs:9:9
    |
 LL | #[allow(dead_code)]
    |         ^^^^^^^^^
    |
 note: first defined here
-  --> tests/ui/duplicated_attributes.rs:10:9
+  --> tests/ui/duplicated_attributes.rs:8:9
    |
 LL | #[allow(dead_code)]
    |         ^^^^^^^^^
 help: remove this attribute
-  --> tests/ui/duplicated_attributes.rs:11:9
+  --> tests/ui/duplicated_attributes.rs:9:9
    |
 LL | #[allow(dead_code)]
    |         ^^^^^^^^^
 
 error: duplicated attribute
-  --> tests/ui/duplicated_attributes.rs:12:11
+  --> tests/ui/duplicated_attributes.rs:15:7
    |
-LL | #[cfg(any(unix, windows, target_os = "linux"))]
-   |           ^^^^
+LL | #[cfg(unix)]
+   |       ^^^^
    |
 note: first defined here
-  --> tests/ui/duplicated_attributes.rs:9:11
+  --> tests/ui/duplicated_attributes.rs:13:7
    |
-LL | #[cfg(any(unix, windows, target_os = "linux"))]
-   |           ^^^^
+LL | #[cfg(unix)]
+   |       ^^^^
 help: remove this attribute
-  --> tests/ui/duplicated_attributes.rs:12:11
+  --> tests/ui/duplicated_attributes.rs:15:7
    |
-LL | #[cfg(any(unix, windows, target_os = "linux"))]
-   |           ^^^^
+LL | #[cfg(unix)]
+   |       ^^^^
 
-error: duplicated attribute
-  --> tests/ui/duplicated_attributes.rs:12:17
-   |
-LL | #[cfg(any(unix, windows, target_os = "linux"))]
-   |                 ^^^^^^^
-   |
-note: first defined here
-  --> tests/ui/duplicated_attributes.rs:9:17
-   |
-LL | #[cfg(any(unix, windows, target_os = "linux"))]
-   |                 ^^^^^^^
-help: remove this attribute
-  --> tests/ui/duplicated_attributes.rs:12:17
-   |
-LL | #[cfg(any(unix, windows, target_os = "linux"))]
-   |                 ^^^^^^^
-
-error: duplicated attribute
-  --> tests/ui/duplicated_attributes.rs:12:26
-   |
-LL | #[cfg(any(unix, windows, target_os = "linux"))]
-   |                          ^^^^^^^^^^^^^^^^^^^
-   |
-note: first defined here
-  --> tests/ui/duplicated_attributes.rs:9:26
-   |
-LL | #[cfg(any(unix, windows, target_os = "linux"))]
-   |                          ^^^^^^^^^^^^^^^^^^^
-help: remove this attribute
-  --> tests/ui/duplicated_attributes.rs:12:26
-   |
-LL | #[cfg(any(unix, windows, target_os = "linux"))]
-   |                          ^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 7 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/eager_transmute.fixed b/tests/ui/eager_transmute.fixed
index bece09bba1a..c29e7dd9ab3 100644
--- a/tests/ui/eager_transmute.fixed
+++ b/tests/ui/eager_transmute.fixed
@@ -1,6 +1,6 @@
 #![feature(rustc_attrs)]
 #![warn(clippy::eager_transmute)]
-#![allow(clippy::transmute_int_to_non_zero)]
+#![allow(clippy::transmute_int_to_non_zero, clippy::missing_transmute_annotations)]
 
 use std::num::NonZeroU8;
 
diff --git a/tests/ui/eager_transmute.rs b/tests/ui/eager_transmute.rs
index a82bd578f76..491a9485c93 100644
--- a/tests/ui/eager_transmute.rs
+++ b/tests/ui/eager_transmute.rs
@@ -1,6 +1,6 @@
 #![feature(rustc_attrs)]
 #![warn(clippy::eager_transmute)]
-#![allow(clippy::transmute_int_to_non_zero)]
+#![allow(clippy::transmute_int_to_non_zero, clippy::missing_transmute_annotations)]
 
 use std::num::NonZeroU8;
 
diff --git a/tests/ui/filter_map_identity.fixed b/tests/ui/filter_map_identity.fixed
index ad438afaca7..f3f6848e5f9 100644
--- a/tests/ui/filter_map_identity.fixed
+++ b/tests/ui/filter_map_identity.fixed
@@ -1,17 +1,83 @@
-#![allow(unused_imports, clippy::needless_return)]
+#![allow(unused_imports, clippy::needless_return, clippy::useless_vec)]
 #![warn(clippy::filter_map_identity)]
+#![feature(stmt_expr_attributes)]
+
+use std::option::Option;
+struct NonCopy;
+use std::convert::identity;
+
+fn non_copy_vec() -> Vec<Option<NonCopy>> {
+    todo!()
+}
+
+fn copy_vec<T: Copy>() -> Vec<Option<T>> {
+    todo!()
+}
+
+fn copy_vec_non_inferred() -> Vec<Option<i32>> {
+    todo!()
+}
+
+fn opaque<T: Default>() -> impl IntoIterator<Item = Option<T>> {
+    vec![Some(T::default())]
+}
 
 fn main() {
-    let iterator = vec![Some(1), None, Some(2)].into_iter();
-    let _ = iterator.flatten();
+    {
+        // into_iter
+        copy_vec_non_inferred().into_iter().flatten();
+        //~^ ERROR: use of
+        copy_vec_non_inferred().into_iter().flatten();
+        //~^ ERROR: use of
+        copy_vec_non_inferred().into_iter().flatten();
+        //~^ ERROR: use of
+        copy_vec_non_inferred().into_iter().flatten();
+        //~^ ERROR: use of
+        copy_vec_non_inferred().into_iter().flatten();
+        //~^ ERROR: use of
 
-    let iterator = vec![Some(1), None, Some(2)].into_iter();
-    let _ = iterator.flatten();
+        non_copy_vec().into_iter().flatten();
+        //~^ ERROR: use of
+        non_copy_vec().into_iter().flatten();
+        //~^ ERROR: use of
 
-    use std::convert::identity;
-    let iterator = vec![Some(1), None, Some(2)].into_iter();
-    let _ = iterator.flatten();
+        non_copy_vec().into_iter().flatten();
+        //~^ ERROR: use of
+        non_copy_vec().into_iter().flatten();
+        //~^ ERROR: use of
+        non_copy_vec().into_iter().flatten();
+        //~^ ERROR: use of
+        non_copy_vec().into_iter().flatten();
+        //~^ ERROR: use of
 
-    let iterator = vec![Some(1), None, Some(2)].into_iter();
-    let _ = iterator.flatten();
+        copy_vec::<i32>().into_iter().flatten();
+        //~^ ERROR: use of
+        copy_vec::<i32>().into_iter().flatten();
+        //~^ ERROR: use of
+        copy_vec::<i32>().into_iter().flatten();
+        //~^ ERROR: use of
+        copy_vec::<i32>().into_iter().flatten();
+        //~^ ERROR: use of
+
+        // we are forced to pass the type in the call.
+        copy_vec::<i32>().into_iter().flatten();
+        //~^ ERROR: use of
+        copy_vec::<i32>().into_iter().flatten();
+        //~^ ERROR: use of
+        copy_vec::<i32>().into_iter().flatten();
+        //~^ ERROR: use of
+        copy_vec::<i32>().into_iter().flatten();
+        //~^ ERROR: use of
+        #[rustfmt::skip]
+            copy_vec::<i32>().into_iter().flatten();
+        //~^ ERROR: use of
+        #[rustfmt::skip]
+            copy_vec::<i32>().into_iter().flatten();
+        //~^ ERROR: use of
+
+        // note, the compiler requires that we pass the type to `opaque`. This is mostly for reference,
+        // it behaves the same as copy_vec.
+        opaque::<i32>().into_iter().flatten();
+        //~^ ERROR: use of
+    }
 }
diff --git a/tests/ui/filter_map_identity.rs b/tests/ui/filter_map_identity.rs
index d7423276872..b9aa9c05be8 100644
--- a/tests/ui/filter_map_identity.rs
+++ b/tests/ui/filter_map_identity.rs
@@ -1,17 +1,83 @@
-#![allow(unused_imports, clippy::needless_return)]
+#![allow(unused_imports, clippy::needless_return, clippy::useless_vec)]
 #![warn(clippy::filter_map_identity)]
+#![feature(stmt_expr_attributes)]
+
+use std::option::Option;
+struct NonCopy;
+use std::convert::identity;
+
+fn non_copy_vec() -> Vec<Option<NonCopy>> {
+    todo!()
+}
+
+fn copy_vec<T: Copy>() -> Vec<Option<T>> {
+    todo!()
+}
+
+fn copy_vec_non_inferred() -> Vec<Option<i32>> {
+    todo!()
+}
+
+fn opaque<T: Default>() -> impl IntoIterator<Item = Option<T>> {
+    vec![Some(T::default())]
+}
 
 fn main() {
-    let iterator = vec![Some(1), None, Some(2)].into_iter();
-    let _ = iterator.filter_map(|x| x);
+    {
+        // into_iter
+        copy_vec_non_inferred().into_iter().filter_map(|x| x);
+        //~^ ERROR: use of
+        copy_vec_non_inferred().into_iter().filter_map(std::convert::identity);
+        //~^ ERROR: use of
+        copy_vec_non_inferred().into_iter().filter_map(identity);
+        //~^ ERROR: use of
+        copy_vec_non_inferred().into_iter().filter_map(|x| return x);
+        //~^ ERROR: use of
+        copy_vec_non_inferred().into_iter().filter_map(|x| return x);
+        //~^ ERROR: use of
 
-    let iterator = vec![Some(1), None, Some(2)].into_iter();
-    let _ = iterator.filter_map(std::convert::identity);
+        non_copy_vec().into_iter().filter_map(|x| x);
+        //~^ ERROR: use of
+        non_copy_vec().into_iter().filter_map(|x| x);
+        //~^ ERROR: use of
 
-    use std::convert::identity;
-    let iterator = vec![Some(1), None, Some(2)].into_iter();
-    let _ = iterator.filter_map(identity);
+        non_copy_vec().into_iter().filter_map(std::convert::identity);
+        //~^ ERROR: use of
+        non_copy_vec().into_iter().filter_map(identity);
+        //~^ ERROR: use of
+        non_copy_vec().into_iter().filter_map(|x| return x);
+        //~^ ERROR: use of
+        non_copy_vec().into_iter().filter_map(|x| return x);
+        //~^ ERROR: use of
 
-    let iterator = vec![Some(1), None, Some(2)].into_iter();
-    let _ = iterator.filter_map(|x| return x);
+        copy_vec::<i32>().into_iter().filter_map(|x: Option<_>| x);
+        //~^ ERROR: use of
+        copy_vec::<i32>().into_iter().filter_map(|x: Option<_>| x);
+        //~^ ERROR: use of
+        copy_vec::<i32>().into_iter().filter_map(|x: Option<_>| return x);
+        //~^ ERROR: use of
+        copy_vec::<i32>().into_iter().filter_map(|x: Option<_>| return x);
+        //~^ ERROR: use of
+
+        // we are forced to pass the type in the call.
+        copy_vec::<i32>().into_iter().filter_map(|x: Option<i32>| x);
+        //~^ ERROR: use of
+        copy_vec::<i32>().into_iter().filter_map(|x: Option<i32>| x);
+        //~^ ERROR: use of
+        copy_vec::<i32>().into_iter().filter_map(|x: Option<i32>| return x);
+        //~^ ERROR: use of
+        copy_vec::<i32>().into_iter().filter_map(|x: Option<i32>| return x);
+        //~^ ERROR: use of
+        #[rustfmt::skip]
+            copy_vec::<i32>().into_iter().filter_map(|x: Option<i32>| -> Option<i32> {{ x }});
+        //~^ ERROR: use of
+        #[rustfmt::skip]
+            copy_vec::<i32>().into_iter().filter_map(|x: Option<i32>| -> Option<i32> {{ return x }});
+        //~^ ERROR: use of
+
+        // note, the compiler requires that we pass the type to `opaque`. This is mostly for reference,
+        // it behaves the same as copy_vec.
+        opaque::<i32>().into_iter().filter_map(|x| x);
+        //~^ ERROR: use of
+    }
 }
diff --git a/tests/ui/filter_map_identity.stderr b/tests/ui/filter_map_identity.stderr
index 5aa46ad6d23..55068db4e9d 100644
--- a/tests/ui/filter_map_identity.stderr
+++ b/tests/ui/filter_map_identity.stderr
@@ -1,29 +1,137 @@
 error: use of `filter_map` with an identity function
-  --> tests/ui/filter_map_identity.rs:6:22
+  --> tests/ui/filter_map_identity.rs:28:45
    |
-LL |     let _ = iterator.filter_map(|x| x);
-   |                      ^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+LL |         copy_vec_non_inferred().into_iter().filter_map(|x| x);
+   |                                             ^^^^^^^^^^^^^^^^^ help: try: `flatten()`
    |
    = note: `-D clippy::filter-map-identity` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::filter_map_identity)]`
 
 error: use of `filter_map` with an identity function
-  --> tests/ui/filter_map_identity.rs:9:22
+  --> tests/ui/filter_map_identity.rs:30:45
    |
-LL |     let _ = iterator.filter_map(std::convert::identity);
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+LL |         copy_vec_non_inferred().into_iter().filter_map(std::convert::identity);
+   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
 
 error: use of `filter_map` with an identity function
-  --> tests/ui/filter_map_identity.rs:13:22
+  --> tests/ui/filter_map_identity.rs:32:45
    |
-LL |     let _ = iterator.filter_map(identity);
-   |                      ^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+LL |         copy_vec_non_inferred().into_iter().filter_map(identity);
+   |                                             ^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
 
 error: use of `filter_map` with an identity function
-  --> tests/ui/filter_map_identity.rs:16:22
+  --> tests/ui/filter_map_identity.rs:34:45
    |
-LL |     let _ = iterator.filter_map(|x| return x);
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+LL |         copy_vec_non_inferred().into_iter().filter_map(|x| return x);
+   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
 
-error: aborting due to 4 previous errors
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:36:45
+   |
+LL |         copy_vec_non_inferred().into_iter().filter_map(|x| return x);
+   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:39:36
+   |
+LL |         non_copy_vec().into_iter().filter_map(|x| x);
+   |                                    ^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:41:36
+   |
+LL |         non_copy_vec().into_iter().filter_map(|x| x);
+   |                                    ^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:44:36
+   |
+LL |         non_copy_vec().into_iter().filter_map(std::convert::identity);
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:46:36
+   |
+LL |         non_copy_vec().into_iter().filter_map(identity);
+   |                                    ^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:48:36
+   |
+LL |         non_copy_vec().into_iter().filter_map(|x| return x);
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:50:36
+   |
+LL |         non_copy_vec().into_iter().filter_map(|x| return x);
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:53:39
+   |
+LL |         copy_vec::<i32>().into_iter().filter_map(|x: Option<_>| x);
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:55:39
+   |
+LL |         copy_vec::<i32>().into_iter().filter_map(|x: Option<_>| x);
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:57:39
+   |
+LL |         copy_vec::<i32>().into_iter().filter_map(|x: Option<_>| return x);
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:59:39
+   |
+LL |         copy_vec::<i32>().into_iter().filter_map(|x: Option<_>| return x);
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:63:39
+   |
+LL |         copy_vec::<i32>().into_iter().filter_map(|x: Option<i32>| x);
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:65:39
+   |
+LL |         copy_vec::<i32>().into_iter().filter_map(|x: Option<i32>| x);
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:67:39
+   |
+LL |         copy_vec::<i32>().into_iter().filter_map(|x: Option<i32>| return x);
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:69:39
+   |
+LL |         copy_vec::<i32>().into_iter().filter_map(|x: Option<i32>| return x);
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:72:43
+   |
+LL |             copy_vec::<i32>().into_iter().filter_map(|x: Option<i32>| -> Option<i32> {{ x }});
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:75:43
+   |
+LL |             copy_vec::<i32>().into_iter().filter_map(|x: Option<i32>| -> Option<i32> {{ return x }});
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: use of `filter_map` with an identity function
+  --> tests/ui/filter_map_identity.rs:80:37
+   |
+LL |         opaque::<i32>().into_iter().filter_map(|x| x);
+   |                                     ^^^^^^^^^^^^^^^^^ help: try: `flatten()`
+
+error: aborting due to 22 previous errors
 
diff --git a/tests/ui/large_stack_frames.rs b/tests/ui/large_stack_frames.rs
index f32368f9397..e6c030b8a9e 100644
--- a/tests/ui/large_stack_frames.rs
+++ b/tests/ui/large_stack_frames.rs
@@ -1,3 +1,5 @@
+//@ normalize-stderr-test: "\b10000(08|16|32)\b" -> "100$$PTR"
+//@ normalize-stderr-test: "\b2500(060|120)\b" -> "250$$PTR"
 #![allow(unused, incomplete_features)]
 #![warn(clippy::large_stack_frames)]
 #![feature(unsized_locals)]
@@ -23,8 +25,7 @@ impl<const N: usize> Default for ArrayDefault<N> {
 }
 
 fn many_small_arrays() {
-    //~^ ERROR: this function allocates a large amount of stack space
-    //~| NOTE: allocating large amounts of stack space can overflow the stack
+    //~^ ERROR: this function may allocate
     let x = [0u8; 500_000];
     let x2 = [0u8; 500_000];
     let x3 = [0u8; 500_000];
@@ -34,17 +35,21 @@ fn many_small_arrays() {
 }
 
 fn large_return_value() -> ArrayDefault<1_000_000> {
-    //~^ ERROR: this function allocates a large amount of stack space
-    //~| NOTE: allocating large amounts of stack space can overflow the stack
+    //~^ ERROR: this function may allocate 1000000 bytes on the stack
     Default::default()
 }
 
 fn large_fn_arg(x: ArrayDefault<1_000_000>) {
-    //~^ ERROR: this function allocates a large amount of stack space
-    //~| NOTE: allocating large amounts of stack space can overflow the stack
+    //~^ ERROR: this function may allocate
     black_box(&x);
 }
 
+fn has_large_closure() {
+    let f = || black_box(&[0u8; 1_000_000]);
+    //~^ ERROR: this function may allocate
+    f();
+}
+
 fn main() {
     generic::<ArrayDefault<1_000_000>>();
 }
diff --git a/tests/ui/large_stack_frames.stderr b/tests/ui/large_stack_frames.stderr
index b99500fd9c3..f2e0a127f5f 100644
--- a/tests/ui/large_stack_frames.stderr
+++ b/tests/ui/large_stack_frames.stderr
@@ -1,42 +1,42 @@
-error: this function allocates a large amount of stack space
-  --> tests/ui/large_stack_frames.rs:25:1
+error: this function may allocate 250$PTR bytes on the stack
+  --> tests/ui/large_stack_frames.rs:27:4
    |
-LL | / fn many_small_arrays() {
-LL | |
-LL | |
-LL | |     let x = [0u8; 500_000];
-...  |
-LL | |     black_box((&x, &x2, &x3, &x4, &x5));
-LL | | }
-   | |_^
+LL | fn many_small_arrays() {
+   |    ^^^^^^^^^^^^^^^^^
+...
+LL |     let x5 = [0u8; 500_000];
+   |         -- `x5` is the largest part, at 500000 bytes for type `[u8; 500000]`
    |
-   = note: allocating large amounts of stack space can overflow the stack
+   = note: 250$PTR bytes is larger than Clippy's configured `stack-size-threshold` of 512000
+   = note: allocating large amounts of stack space can overflow the stack and cause the program to abort
    = note: `-D clippy::large-stack-frames` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::large_stack_frames)]`
 
-error: this function allocates a large amount of stack space
-  --> tests/ui/large_stack_frames.rs:36:1
+error: this function may allocate 1000000 bytes on the stack
+  --> tests/ui/large_stack_frames.rs:37:4
    |
-LL | / fn large_return_value() -> ArrayDefault<1_000_000> {
-LL | |
-LL | |
-LL | |     Default::default()
-LL | | }
-   | |_^
+LL | fn large_return_value() -> ArrayDefault<1_000_000> {
+   |    ^^^^^^^^^^^^^^^^^^      ----------------------- this is the largest part, at 1000000 bytes for type `ArrayDefault<1000000>`
    |
-   = note: allocating large amounts of stack space can overflow the stack
+   = note: 1000000 bytes is larger than Clippy's configured `stack-size-threshold` of 512000
 
-error: this function allocates a large amount of stack space
-  --> tests/ui/large_stack_frames.rs:42:1
+error: this function may allocate 100$PTR bytes on the stack
+  --> tests/ui/large_stack_frames.rs:42:4
    |
-LL | / fn large_fn_arg(x: ArrayDefault<1_000_000>) {
-LL | |
-LL | |
-LL | |     black_box(&x);
-LL | | }
-   | |_^
+LL | fn large_fn_arg(x: ArrayDefault<1_000_000>) {
+   |    ^^^^^^^^^^^^ - `x` is the largest part, at 1000000 bytes for type `ArrayDefault<1000000>`
    |
-   = note: allocating large amounts of stack space can overflow the stack
+   = note: 100$PTR bytes is larger than Clippy's configured `stack-size-threshold` of 512000
 
-error: aborting due to 3 previous errors
+error: this function may allocate 100$PTR bytes on the stack
+  --> tests/ui/large_stack_frames.rs:48:13
+   |
+LL |     let f = || black_box(&[0u8; 1_000_000]);
+   |             ^^^^^^^^^^^^^^----------------^
+   |                           |
+   |                           this is the largest part, at 1000000 bytes for type `[u8; 1000000]`
+   |
+   = note: 100$PTR bytes is larger than Clippy's configured `stack-size-threshold` of 512000
+
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/legacy_numeric_constants.fixed b/tests/ui/legacy_numeric_constants.fixed
new file mode 100644
index 00000000000..a6ef8f8c119
--- /dev/null
+++ b/tests/ui/legacy_numeric_constants.fixed
@@ -0,0 +1,117 @@
+//@aux-build:proc_macros.rs
+#![allow(clippy::no_effect, deprecated, unused)]
+#![allow(clippy::legacy_numeric_constants)] // For imports.
+
+#[macro_use]
+extern crate proc_macros;
+
+pub mod a {
+    pub use std::u128;
+}
+
+macro_rules! b {
+    () => {
+        mod b {
+            #[warn(clippy::legacy_numeric_constants)]
+            fn b() {
+                let x = u64::MAX;
+                //~^ ERROR: usage of a legacy numeric constant
+                //~| HELP: use the associated constant instead
+            }
+        }
+    };
+}
+
+use std::u32::MAX;
+use std::u8::MIN;
+use std::{f64, u32};
+
+#[warn(clippy::legacy_numeric_constants)]
+fn main() {
+    f32::EPSILON;
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+    u8::MIN;
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+    usize::MIN;
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+    u32::MAX;
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+    u32::MAX;
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+    u32::MAX;
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+    i32::MAX;
+    //~^ ERROR: usage of a legacy numeric method
+    //~| HELP: use the associated constant instead
+    u8::MAX;
+    //~^ ERROR: usage of a legacy numeric method
+    //~| HELP: use the associated constant instead
+    u8::MIN;
+    //~^ ERROR: usage of a legacy numeric method
+    //~| HELP: use the associated constant instead
+    u8::MIN;
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+    ::std::primitive::u8::MIN;
+    //~^ ERROR: usage of a legacy numeric method
+    //~| HELP: use the associated constant instead
+    std::primitive::i32::MAX;
+    //~^ ERROR: usage of a legacy numeric method
+    //~| HELP: use the associated constant instead
+    u128::MAX;
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+    u32::MAX;
+    u128::MAX;
+    f32::EPSILON;
+    ::std::primitive::u8::MIN;
+    std::f32::consts::E;
+    f64::consts::E;
+    u8::MIN;
+    std::f32::consts::E;
+    f64::consts::E;
+    b!();
+
+    [(0, "", i128::MAX)];
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+}
+
+#[warn(clippy::legacy_numeric_constants)]
+fn ext() {
+    external! {
+        ::std::primitive::u8::MIN;
+        ::std::u8::MIN;
+        ::std::primitive::u8::min_value();
+        use std::u64;
+        use std::u8::MIN;
+    }
+}
+
+#[allow(clippy::legacy_numeric_constants)]
+fn allow() {
+    ::std::primitive::u8::MIN;
+    ::std::u8::MIN;
+    ::std::primitive::u8::min_value();
+    use std::u64;
+    use std::u8::MIN;
+}
+
+#[warn(clippy::legacy_numeric_constants)]
+#[clippy::msrv = "1.42.0"]
+fn msrv_too_low() {
+    std::u32::MAX;
+}
+
+#[warn(clippy::legacy_numeric_constants)]
+#[clippy::msrv = "1.43.0"]
+fn msrv_juust_right() {
+    u32::MAX;
+    //~^ ERROR: usage of a legacy numeric constant
+}
diff --git a/tests/ui/legacy_numeric_constants.rs b/tests/ui/legacy_numeric_constants.rs
new file mode 100644
index 00000000000..cd633545372
--- /dev/null
+++ b/tests/ui/legacy_numeric_constants.rs
@@ -0,0 +1,117 @@
+//@aux-build:proc_macros.rs
+#![allow(clippy::no_effect, deprecated, unused)]
+#![allow(clippy::legacy_numeric_constants)] // For imports.
+
+#[macro_use]
+extern crate proc_macros;
+
+pub mod a {
+    pub use std::u128;
+}
+
+macro_rules! b {
+    () => {
+        mod b {
+            #[warn(clippy::legacy_numeric_constants)]
+            fn b() {
+                let x = std::u64::MAX;
+                //~^ ERROR: usage of a legacy numeric constant
+                //~| HELP: use the associated constant instead
+            }
+        }
+    };
+}
+
+use std::u32::MAX;
+use std::u8::MIN;
+use std::{f64, u32};
+
+#[warn(clippy::legacy_numeric_constants)]
+fn main() {
+    std::f32::EPSILON;
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+    std::u8::MIN;
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+    std::usize::MIN;
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+    std::u32::MAX;
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+    core::u32::MAX;
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+    MAX;
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+    i32::max_value();
+    //~^ ERROR: usage of a legacy numeric method
+    //~| HELP: use the associated constant instead
+    u8::max_value();
+    //~^ ERROR: usage of a legacy numeric method
+    //~| HELP: use the associated constant instead
+    u8::min_value();
+    //~^ ERROR: usage of a legacy numeric method
+    //~| HELP: use the associated constant instead
+    ::std::u8::MIN;
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+    ::std::primitive::u8::min_value();
+    //~^ ERROR: usage of a legacy numeric method
+    //~| HELP: use the associated constant instead
+    std::primitive::i32::max_value();
+    //~^ ERROR: usage of a legacy numeric method
+    //~| HELP: use the associated constant instead
+    self::a::u128::MAX;
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+    u32::MAX;
+    u128::MAX;
+    f32::EPSILON;
+    ::std::primitive::u8::MIN;
+    std::f32::consts::E;
+    f64::consts::E;
+    u8::MIN;
+    std::f32::consts::E;
+    f64::consts::E;
+    b!();
+
+    [(0, "", std::i128::MAX)];
+    //~^ ERROR: usage of a legacy numeric constant
+    //~| HELP: use the associated constant instead
+}
+
+#[warn(clippy::legacy_numeric_constants)]
+fn ext() {
+    external! {
+        ::std::primitive::u8::MIN;
+        ::std::u8::MIN;
+        ::std::primitive::u8::min_value();
+        use std::u64;
+        use std::u8::MIN;
+    }
+}
+
+#[allow(clippy::legacy_numeric_constants)]
+fn allow() {
+    ::std::primitive::u8::MIN;
+    ::std::u8::MIN;
+    ::std::primitive::u8::min_value();
+    use std::u64;
+    use std::u8::MIN;
+}
+
+#[warn(clippy::legacy_numeric_constants)]
+#[clippy::msrv = "1.42.0"]
+fn msrv_too_low() {
+    std::u32::MAX;
+}
+
+#[warn(clippy::legacy_numeric_constants)]
+#[clippy::msrv = "1.43.0"]
+fn msrv_juust_right() {
+    std::u32::MAX;
+    //~^ ERROR: usage of a legacy numeric constant
+}
diff --git a/tests/ui/legacy_numeric_constants.stderr b/tests/ui/legacy_numeric_constants.stderr
new file mode 100644
index 00000000000..267b9ac8e4d
--- /dev/null
+++ b/tests/ui/legacy_numeric_constants.stderr
@@ -0,0 +1,184 @@
+error: usage of a legacy numeric constant
+  --> tests/ui/legacy_numeric_constants.rs:31:5
+   |
+LL |     std::f32::EPSILON;
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::legacy-numeric-constants` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::legacy_numeric_constants)]`
+help: use the associated constant instead
+   |
+LL |     f32::EPSILON;
+   |     ~~~~~~~~~~~~
+
+error: usage of a legacy numeric constant
+  --> tests/ui/legacy_numeric_constants.rs:34:5
+   |
+LL |     std::u8::MIN;
+   |     ^^^^^^^^^^^^
+   |
+help: use the associated constant instead
+   |
+LL |     u8::MIN;
+   |     ~~~~~~~
+
+error: usage of a legacy numeric constant
+  --> tests/ui/legacy_numeric_constants.rs:37:5
+   |
+LL |     std::usize::MIN;
+   |     ^^^^^^^^^^^^^^^
+   |
+help: use the associated constant instead
+   |
+LL |     usize::MIN;
+   |     ~~~~~~~~~~
+
+error: usage of a legacy numeric constant
+  --> tests/ui/legacy_numeric_constants.rs:40:5
+   |
+LL |     std::u32::MAX;
+   |     ^^^^^^^^^^^^^
+   |
+help: use the associated constant instead
+   |
+LL |     u32::MAX;
+   |     ~~~~~~~~
+
+error: usage of a legacy numeric constant
+  --> tests/ui/legacy_numeric_constants.rs:43:5
+   |
+LL |     core::u32::MAX;
+   |     ^^^^^^^^^^^^^^
+   |
+help: use the associated constant instead
+   |
+LL |     u32::MAX;
+   |     ~~~~~~~~
+
+error: usage of a legacy numeric constant
+  --> tests/ui/legacy_numeric_constants.rs:46:5
+   |
+LL |     MAX;
+   |     ^^^
+   |
+help: use the associated constant instead
+   |
+LL |     u32::MAX;
+   |     ~~~~~~~~
+
+error: usage of a legacy numeric method
+  --> tests/ui/legacy_numeric_constants.rs:49:10
+   |
+LL |     i32::max_value();
+   |          ^^^^^^^^^^^
+   |
+help: use the associated constant instead
+   |
+LL |     i32::MAX;
+   |          ~~~
+
+error: usage of a legacy numeric method
+  --> tests/ui/legacy_numeric_constants.rs:52:9
+   |
+LL |     u8::max_value();
+   |         ^^^^^^^^^^^
+   |
+help: use the associated constant instead
+   |
+LL |     u8::MAX;
+   |         ~~~
+
+error: usage of a legacy numeric method
+  --> tests/ui/legacy_numeric_constants.rs:55:9
+   |
+LL |     u8::min_value();
+   |         ^^^^^^^^^^^
+   |
+help: use the associated constant instead
+   |
+LL |     u8::MIN;
+   |         ~~~
+
+error: usage of a legacy numeric constant
+  --> tests/ui/legacy_numeric_constants.rs:58:5
+   |
+LL |     ::std::u8::MIN;
+   |     ^^^^^^^^^^^^^^
+   |
+help: use the associated constant instead
+   |
+LL |     u8::MIN;
+   |     ~~~~~~~
+
+error: usage of a legacy numeric method
+  --> tests/ui/legacy_numeric_constants.rs:61:27
+   |
+LL |     ::std::primitive::u8::min_value();
+   |                           ^^^^^^^^^^^
+   |
+help: use the associated constant instead
+   |
+LL |     ::std::primitive::u8::MIN;
+   |                           ~~~
+
+error: usage of a legacy numeric method
+  --> tests/ui/legacy_numeric_constants.rs:64:26
+   |
+LL |     std::primitive::i32::max_value();
+   |                          ^^^^^^^^^^^
+   |
+help: use the associated constant instead
+   |
+LL |     std::primitive::i32::MAX;
+   |                          ~~~
+
+error: usage of a legacy numeric constant
+  --> tests/ui/legacy_numeric_constants.rs:67:5
+   |
+LL |     self::a::u128::MAX;
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+help: use the associated constant instead
+   |
+LL |     u128::MAX;
+   |     ~~~~~~~~~
+
+error: usage of a legacy numeric constant
+  --> tests/ui/legacy_numeric_constants.rs:17:25
+   |
+LL |                 let x = std::u64::MAX;
+   |                         ^^^^^^^^^^^^^
+...
+LL |     b!();
+   |     ---- in this macro invocation
+   |
+   = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the associated constant instead
+   |
+LL |                 let x = u64::MAX;
+   |                         ~~~~~~~~
+
+error: usage of a legacy numeric constant
+  --> tests/ui/legacy_numeric_constants.rs:81:14
+   |
+LL |     [(0, "", std::i128::MAX)];
+   |              ^^^^^^^^^^^^^^
+   |
+help: use the associated constant instead
+   |
+LL |     [(0, "", i128::MAX)];
+   |              ~~~~~~~~~
+
+error: usage of a legacy numeric constant
+  --> tests/ui/legacy_numeric_constants.rs:115:5
+   |
+LL |     std::u32::MAX;
+   |     ^^^^^^^^^^^^^
+   |
+help: use the associated constant instead
+   |
+LL |     u32::MAX;
+   |     ~~~~~~~~
+
+error: aborting due to 16 previous errors
+
diff --git a/tests/ui/legacy_numeric_constants_unfixable.rs b/tests/ui/legacy_numeric_constants_unfixable.rs
new file mode 100644
index 00000000000..86738ede210
--- /dev/null
+++ b/tests/ui/legacy_numeric_constants_unfixable.rs
@@ -0,0 +1,78 @@
+//@no-rustfix
+//@aux-build:proc_macros.rs
+#![allow(clippy::no_effect, deprecated, unused)]
+#![warn(clippy::legacy_numeric_constants)]
+
+#[macro_use]
+extern crate proc_macros;
+
+use std::u128 as _;
+//~^ ERROR: importing legacy numeric constants
+//~| HELP: remove this import
+pub mod a {
+    pub use std::{mem, u128};
+    //~^ ERROR: importing legacy numeric constants
+    //~| HELP: remove this import
+}
+
+macro_rules! b {
+    () => {
+        mod b {
+            use std::u32;
+            //~^ ERROR: importing legacy numeric constants
+            //~| HELP: remove this import
+        }
+    };
+}
+
+fn main() {
+    use std::u32::MAX;
+    //~^ ERROR: importing a legacy numeric constant
+    //~| HELP: remove this import and use the associated constant `u32::MAX`
+    use std::u8::MIN;
+    //~^ ERROR: importing a legacy numeric constant
+    //~| HELP: remove this import and use the associated constant `u8::MIN`
+    f64::MAX;
+    use std::u32;
+    //~^ ERROR: importing legacy numeric constants
+    //~| HELP: remove this import
+    u32::MAX;
+    use std::f32::MIN_POSITIVE;
+    //~^ ERROR: importing a legacy numeric constant
+    //~| HELP: remove this import and use the associated constant `f32::MIN_POSITIVE`
+    use std::f64;
+    use std::i16::*;
+    //~^ ERROR: importing legacy numeric constants
+    //~| HELP: remove this import and use associated constants `i16::<CONST>`
+    u128::MAX;
+    f32::EPSILON;
+    f64::EPSILON;
+    ::std::primitive::u8::MIN;
+    std::f32::consts::E;
+    f64::consts::E;
+    u8::MIN;
+    std::f32::consts::E;
+    f64::consts::E;
+    b!();
+}
+
+fn ext() {
+    external! {
+        ::std::primitive::u8::MIN;
+        ::std::u8::MIN;
+        ::std::primitive::u8::min_value();
+        use std::u64;
+        use std::u8::MIN;
+    }
+}
+
+#[clippy::msrv = "1.42.0"]
+fn msrv_too_low() {
+    use std::u32::MAX;
+}
+
+#[clippy::msrv = "1.43.0"]
+fn msrv_juust_right() {
+    use std::u32::MAX;
+    //~^ ERROR: importing a legacy numeric constant
+}
diff --git a/tests/ui/legacy_numeric_constants_unfixable.stderr b/tests/ui/legacy_numeric_constants_unfixable.stderr
new file mode 100644
index 00000000000..2edcf718836
--- /dev/null
+++ b/tests/ui/legacy_numeric_constants_unfixable.stderr
@@ -0,0 +1,83 @@
+error: importing legacy numeric constants
+  --> tests/ui/legacy_numeric_constants_unfixable.rs:9:5
+   |
+LL | use std::u128 as _;
+   |     ^^^^^^^^^
+   |
+   = help: remove this import
+   = note: `-D clippy::legacy-numeric-constants` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::legacy_numeric_constants)]`
+
+error: importing legacy numeric constants
+  --> tests/ui/legacy_numeric_constants_unfixable.rs:13:24
+   |
+LL |     pub use std::{mem, u128};
+   |                        ^^^^
+   |
+   = help: remove this import
+   = note: then `u128::<CONST>` will resolve to the respective associated constant
+
+error: importing a legacy numeric constant
+  --> tests/ui/legacy_numeric_constants_unfixable.rs:29:9
+   |
+LL |     use std::u32::MAX;
+   |         ^^^^^^^^^^^^^
+   |
+   = help: remove this import and use the associated constant `u32::MAX` from the primitive type instead
+
+error: importing a legacy numeric constant
+  --> tests/ui/legacy_numeric_constants_unfixable.rs:32:9
+   |
+LL |     use std::u8::MIN;
+   |         ^^^^^^^^^^^^
+   |
+   = help: remove this import and use the associated constant `u8::MIN` from the primitive type instead
+
+error: importing legacy numeric constants
+  --> tests/ui/legacy_numeric_constants_unfixable.rs:36:9
+   |
+LL |     use std::u32;
+   |         ^^^^^^^^
+   |
+   = help: remove this import
+   = note: then `u32::<CONST>` will resolve to the respective associated constant
+
+error: importing a legacy numeric constant
+  --> tests/ui/legacy_numeric_constants_unfixable.rs:40:9
+   |
+LL |     use std::f32::MIN_POSITIVE;
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: remove this import and use the associated constant `f32::MIN_POSITIVE` from the primitive type instead
+
+error: importing legacy numeric constants
+  --> tests/ui/legacy_numeric_constants_unfixable.rs:44:9
+   |
+LL |     use std::i16::*;
+   |         ^^^^^^^^
+   |
+   = help: remove this import and use associated constants `i16::<CONST>` from the primitive type instead
+
+error: importing legacy numeric constants
+  --> tests/ui/legacy_numeric_constants_unfixable.rs:21:17
+   |
+LL |             use std::u32;
+   |                 ^^^^^^^^
+...
+LL |     b!();
+   |     ---- in this macro invocation
+   |
+   = help: remove this import
+   = note: then `u32::<CONST>` will resolve to the respective associated constant
+   = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: importing a legacy numeric constant
+  --> tests/ui/legacy_numeric_constants_unfixable.rs:76:9
+   |
+LL |     use std::u32::MAX;
+   |         ^^^^^^^^^^^^^
+   |
+   = help: remove this import and use the associated constant `u32::MAX` from the primitive type instead
+
+error: aborting due to 9 previous errors
+
diff --git a/tests/ui/len_zero.fixed b/tests/ui/len_zero.fixed
index c16d7a26616..27319d9c20e 100644
--- a/tests/ui/len_zero.fixed
+++ b/tests/ui/len_zero.fixed
@@ -189,3 +189,40 @@ fn main() {
 fn test_slice(b: &[u8]) {
     if !b.is_empty() {}
 }
+
+// issue #11992
+fn binop_with_macros() {
+    macro_rules! len {
+        ($seq:ident) => {
+            $seq.len()
+        };
+    }
+
+    macro_rules! compare_to {
+        ($val:literal) => {
+            $val
+        };
+        ($val:expr) => {{ $val }};
+    }
+
+    macro_rules! zero {
+        () => {
+            0
+        };
+    }
+
+    let has_is_empty = HasIsEmpty;
+    // Don't lint, suggesting changes might break macro compatibility.
+    (len!(has_is_empty) > 0).then(|| println!("This can happen."));
+    // Don't lint, suggesting changes might break macro compatibility.
+    if len!(has_is_empty) == 0 {}
+    // Don't lint
+    if has_is_empty.len() == compare_to!(if true { 0 } else { 1 }) {}
+    // This is fine
+    if has_is_empty.len() == compare_to!(1) {}
+
+    if has_is_empty.is_empty() {}
+    if has_is_empty.is_empty() {}
+
+    (!has_is_empty.is_empty()).then(|| println!("This can happen."));
+}
diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs
index 5c49a5abf81..03c05bc6ed7 100644
--- a/tests/ui/len_zero.rs
+++ b/tests/ui/len_zero.rs
@@ -189,3 +189,40 @@ fn main() {
 fn test_slice(b: &[u8]) {
     if b.len() != 0 {}
 }
+
+// issue #11992
+fn binop_with_macros() {
+    macro_rules! len {
+        ($seq:ident) => {
+            $seq.len()
+        };
+    }
+
+    macro_rules! compare_to {
+        ($val:literal) => {
+            $val
+        };
+        ($val:expr) => {{ $val }};
+    }
+
+    macro_rules! zero {
+        () => {
+            0
+        };
+    }
+
+    let has_is_empty = HasIsEmpty;
+    // Don't lint, suggesting changes might break macro compatibility.
+    (len!(has_is_empty) > 0).then(|| println!("This can happen."));
+    // Don't lint, suggesting changes might break macro compatibility.
+    if len!(has_is_empty) == 0 {}
+    // Don't lint
+    if has_is_empty.len() == compare_to!(if true { 0 } else { 1 }) {}
+    // This is fine
+    if has_is_empty.len() == compare_to!(1) {}
+
+    if has_is_empty.len() == compare_to!(0) {}
+    if has_is_empty.len() == zero!() {}
+
+    (compare_to!(0) < has_is_empty.len()).then(|| println!("This can happen."));
+}
diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr
index dd07a85d62c..5c849a2aca6 100644
--- a/tests/ui/len_zero.stderr
+++ b/tests/ui/len_zero.stderr
@@ -142,5 +142,23 @@ error: length comparison to zero
 LL |     if b.len() != 0 {}
    |        ^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!b.is_empty()`
 
-error: aborting due to 23 previous errors
+error: length comparison to zero
+  --> tests/ui/len_zero.rs:224:8
+   |
+LL |     if has_is_empty.len() == compare_to!(0) {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
+
+error: length comparison to zero
+  --> tests/ui/len_zero.rs:225:8
+   |
+LL |     if has_is_empty.len() == zero!() {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
+
+error: length comparison to zero
+  --> tests/ui/len_zero.rs:227:6
+   |
+LL |     (compare_to!(0) < has_is_empty.len()).then(|| println!("This can happen."));
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
+
+error: aborting due to 26 previous errors
 
diff --git a/tests/ui/let_and_return.fixed b/tests/ui/let_and_return.fixed
index b5584fcde8c..4187019e589 100644
--- a/tests/ui/let_and_return.fixed
+++ b/tests/ui/let_and_return.fixed
@@ -203,4 +203,11 @@ fn_in_macro!({
     return 1;
 });
 
+fn issue9150() -> usize {
+    let x = 1;
+    #[cfg(any())]
+    panic!("can't see me");
+    x
+}
+
 fn main() {}
diff --git a/tests/ui/let_and_return.rs b/tests/ui/let_and_return.rs
index f13c7c4e203..54444957b7d 100644
--- a/tests/ui/let_and_return.rs
+++ b/tests/ui/let_and_return.rs
@@ -203,4 +203,11 @@ fn_in_macro!({
     return 1;
 });
 
+fn issue9150() -> usize {
+    let x = 1;
+    #[cfg(any())]
+    panic!("can't see me");
+    x
+}
+
 fn main() {}
diff --git a/tests/ui/let_unit.fixed b/tests/ui/let_unit.fixed
index 4d41b5e5e50..20940daffa7 100644
--- a/tests/ui/let_unit.fixed
+++ b/tests/ui/let_unit.fixed
@@ -177,3 +177,21 @@ async fn issue10433() {
 }
 
 pub async fn issue11502(a: ()) {}
+
+pub fn issue12594() {
+    fn returns_unit() {}
+
+    fn returns_result<T>(res: T) -> Result<T, ()> {
+        Ok(res)
+    }
+
+    fn actual_test() {
+        // create first a unit value'd value
+        returns_unit();
+        returns_result(()).unwrap();
+        returns_result(()).unwrap();
+        // make sure we replace only the first variable
+        let res = 1;
+        returns_result(res).unwrap();
+    }
+}
diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs
index daa660be25e..dca66f2e3ed 100644
--- a/tests/ui/let_unit.rs
+++ b/tests/ui/let_unit.rs
@@ -177,3 +177,21 @@ async fn issue10433() {
 }
 
 pub async fn issue11502(a: ()) {}
+
+pub fn issue12594() {
+    fn returns_unit() {}
+
+    fn returns_result<T>(res: T) -> Result<T, ()> {
+        Ok(res)
+    }
+
+    fn actual_test() {
+        // create first a unit value'd value
+        let res = returns_unit();
+        returns_result(res).unwrap();
+        returns_result(res).unwrap();
+        // make sure we replace only the first variable
+        let res = 1;
+        returns_result(res).unwrap();
+    }
+}
diff --git a/tests/ui/let_unit.stderr b/tests/ui/let_unit.stderr
index 0f1f3d78223..aafb77bcd0d 100644
--- a/tests/ui/let_unit.stderr
+++ b/tests/ui/let_unit.stderr
@@ -51,5 +51,24 @@ LL +         Some(_) => (),
 LL +     };
    |
 
-error: aborting due to 3 previous errors
+error: this let-binding has unit value
+  --> tests/ui/let_unit.rs:190:9
+   |
+LL |         let res = returns_unit();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: omit the `let` binding
+   |
+LL |         returns_unit();
+   |
+help: variable `res` of type `()` can be replaced with explicit `()`
+   |
+LL |         returns_result(()).unwrap();
+   |                        ~~
+help: variable `res` of type `()` can be replaced with explicit `()`
+   |
+LL |         returns_result(()).unwrap();
+   |                        ~~
+
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/manual_assert.edition2018.fixed b/tests/ui/manual_assert.edition2018.fixed
index 75beedfa450..75835780801 100644
--- a/tests/ui/manual_assert.edition2018.fixed
+++ b/tests/ui/manual_assert.edition2018.fixed
@@ -66,3 +66,11 @@ fn issue7730(a: u8) {
 // comment after `panic!`
 assert!(!(a > 2), "panic with comment");
 }
+
+fn issue12505() {
+    struct Foo<T, const N: usize>(T);
+
+    impl<T, const N: usize> Foo<T, N> {
+        const BAR: () = assert!(!(N == 0), );
+    }
+}
diff --git a/tests/ui/manual_assert.edition2018.stderr b/tests/ui/manual_assert.edition2018.stderr
index 57015933d40..1eebe1bfe17 100644
--- a/tests/ui/manual_assert.edition2018.stderr
+++ b/tests/ui/manual_assert.edition2018.stderr
@@ -82,5 +82,14 @@ help: try instead
 LL |     assert!(!(a > 2), "panic with comment");
    |
 
-error: aborting due to 9 previous errors
+error: only a `panic!` in `if`-then statement
+  --> tests/ui/manual_assert.rs:91:25
+   |
+LL |           const BAR: () = if N == 0 {
+   |  _________________________^
+LL | |             panic!()
+LL | |         };
+   | |_________^ help: try instead: `assert!(!(N == 0), )`
+
+error: aborting due to 10 previous errors
 
diff --git a/tests/ui/manual_assert.edition2021.fixed b/tests/ui/manual_assert.edition2021.fixed
index 75beedfa450..75835780801 100644
--- a/tests/ui/manual_assert.edition2021.fixed
+++ b/tests/ui/manual_assert.edition2021.fixed
@@ -66,3 +66,11 @@ fn issue7730(a: u8) {
 // comment after `panic!`
 assert!(!(a > 2), "panic with comment");
 }
+
+fn issue12505() {
+    struct Foo<T, const N: usize>(T);
+
+    impl<T, const N: usize> Foo<T, N> {
+        const BAR: () = assert!(!(N == 0), );
+    }
+}
diff --git a/tests/ui/manual_assert.edition2021.stderr b/tests/ui/manual_assert.edition2021.stderr
index 57015933d40..1eebe1bfe17 100644
--- a/tests/ui/manual_assert.edition2021.stderr
+++ b/tests/ui/manual_assert.edition2021.stderr
@@ -82,5 +82,14 @@ help: try instead
 LL |     assert!(!(a > 2), "panic with comment");
    |
 
-error: aborting due to 9 previous errors
+error: only a `panic!` in `if`-then statement
+  --> tests/ui/manual_assert.rs:91:25
+   |
+LL |           const BAR: () = if N == 0 {
+   |  _________________________^
+LL | |             panic!()
+LL | |         };
+   | |_________^ help: try instead: `assert!(!(N == 0), )`
+
+error: aborting due to 10 previous errors
 
diff --git a/tests/ui/manual_assert.rs b/tests/ui/manual_assert.rs
index 5979496ca83..363bafdf05d 100644
--- a/tests/ui/manual_assert.rs
+++ b/tests/ui/manual_assert.rs
@@ -83,3 +83,13 @@ fn issue7730(a: u8) {
         panic!("panic with comment") // comment after `panic!`
     }
 }
+
+fn issue12505() {
+    struct Foo<T, const N: usize>(T);
+
+    impl<T, const N: usize> Foo<T, N> {
+        const BAR: () = if N == 0 {
+            panic!()
+        };
+    }
+}
diff --git a/tests/ui/manual_clamp.fixed b/tests/ui/manual_clamp.fixed
index c5355cce8e2..8d57cbbf51b 100644
--- a/tests/ui/manual_clamp.fixed
+++ b/tests/ui/manual_clamp.fixed
@@ -17,48 +17,171 @@ const CONST_F64_MIN: f64 = 4.0;
 
 fn main() {
     let (input, min, max) = (0, -2, 3);
-    // Lint
-    let x0 = input.clamp(min, max);
+    // Min and max are not const, so this shouldn't trigger the lint.
+    let x0 = if max < input {
+        max
+    } else if min > input {
+        min
+    } else {
+        input
+    };
 
-    let x1 = input.clamp(min, max);
+    let x1 = if input > max {
+        max
+    } else if input < min {
+        min
+    } else {
+        input
+    };
 
-    let x2 = input.clamp(min, max);
+    let x2 = if input < min {
+        min
+    } else if input > max {
+        max
+    } else {
+        input
+    };
 
-    let x3 = input.clamp(min, max);
+    let x3 = if min > input {
+        min
+    } else if max < input {
+        max
+    } else {
+        input
+    };
 
-    let x4 = input.clamp(min, max);
-    //~^ ERROR: clamp-like pattern without using clamp function
-    //~| NOTE: clamp will panic if max < min
+    let x4 = input.max(min).min(max);
 
-    let x5 = input.clamp(min, max);
-    //~^ ERROR: clamp-like pattern without using clamp function
-    //~| NOTE: clamp will panic if max < min
+    let x5 = input.min(max).max(min);
 
-    let x6 = input.clamp(min, max);
+    let x6 = match input {
+        x if x > max => max,
+        x if x < min => min,
+        x => x,
+    };
 
-    let x7 = input.clamp(min, max);
+    let x7 = match input {
+        x if x < min => min,
+        x if x > max => max,
+        x => x,
+    };
 
-    let x8 = input.clamp(min, max);
+    let x8 = match input {
+        x if max < x => max,
+        x if min > x => min,
+        x => x,
+    };
 
     let mut x9 = input;
-    x9 = x9.clamp(min, max);
+    if x9 < min {
+        x9 = min;
+    }
+    if x9 > max {
+        x9 = max;
+    }
 
-    let x10 = input.clamp(min, max);
+    let x10 = match input {
+        x if min > x => min,
+        x if max < x => max,
+        x => x,
+    };
 
     let mut x11 = input;
     let _ = 1;
-    x11 = x11.clamp(min, max);
+    if x11 > max {
+        x11 = max;
+    }
+    if x11 < min {
+        x11 = min;
+    }
 
     let mut x12 = input;
-    x12 = x12.clamp(min, max);
+    if min > x12 {
+        x12 = min;
+    }
+    if max < x12 {
+        x12 = max;
+    }
 
     let mut x13 = input;
-    x13 = x13.clamp(min, max);
+    if max < x13 {
+        x13 = max;
+    }
+    if min > x13 {
+        x13 = min;
+    }
+
+    {
+        let (input, min, max) = (0.0f64, -2.0, 3.0);
+        let x14 = if input > max {
+            max
+        } else if input < min {
+            min
+        } else {
+            input
+        };
+    }
+    let mut x15 = input;
+    if x15 < min {
+        x15 = min;
+    } else if x15 > max {
+        x15 = max;
+    }
+
+    // It's important this be the last set of statements
+    let mut x16 = input;
+    if max < x16 {
+        x16 = max;
+    }
+    if min > x16 {
+        x16 = min;
+    }
+}
+
+fn const_main() {
+    let input = 0;
+    // Min and max are const, so this should trigger the lint.
+    let x0 = input.clamp(CONST_MIN, CONST_MAX);
+
+    let x1 = input.clamp(CONST_MIN, CONST_MAX);
+
+    let x2 = input.clamp(CONST_MIN, CONST_MAX);
+
+    let x3 = input.clamp(CONST_MIN, CONST_MAX);
+
+    let x4 = input.clamp(CONST_MIN, CONST_MAX);
+    //~^ ERROR: clamp-like pattern without using clamp function
+    //~| NOTE: clamp will panic if max < min
+
+    let x5 = input.clamp(CONST_MIN, CONST_MAX);
+    //~^ ERROR: clamp-like pattern without using clamp function
+    //~| NOTE: clamp will panic if max < min
+
+    let x6 = input.clamp(CONST_MIN, CONST_MAX);
+
+    let x7 = input.clamp(CONST_MIN, CONST_MAX);
+
+    let x8 = input.clamp(CONST_MIN, CONST_MAX);
+
+    let mut x9 = input;
+    x9 = x9.clamp(CONST_MIN, CONST_MAX);
+
+    let x10 = input.clamp(CONST_MIN, CONST_MAX);
+
+    let mut x11 = input;
+    let _ = 1;
+    x11 = x11.clamp(CONST_MIN, CONST_MAX);
+
+    let mut x12 = input;
+    x12 = x12.clamp(CONST_MIN, CONST_MAX);
+
+    let mut x13 = input;
+    x13 = x13.clamp(CONST_MIN, CONST_MAX);
 
     let x14 = input.clamp(CONST_MIN, CONST_MAX);
     {
-        let (input, min, max) = (0.0f64, -2.0, 3.0);
-        let x15 = input.clamp(min, max);
+        let input = 0.0f64;
+        let x15 = input.clamp(CONST_F64_MIN, CONST_F64_MAX);
     }
     {
         let input: i32 = cmp_min_max(1);
@@ -114,108 +237,128 @@ fn main() {
         //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan()
     }
     let mut x32 = input;
-    x32 = x32.clamp(min, max);
+    x32 = x32.clamp(CONST_MIN, CONST_MAX);
+
+    // Flip the script, swap the places of min and max. Make sure this doesn't
+    // trigger when clamp would be guaranteed to panic.
+    let mut x33 = input;
+    if x33 < CONST_MAX {
+        x33 = CONST_MAX;
+    } else if x33 > CONST_MIN {
+        x33 = CONST_MIN;
+    }
+
+    // Do it again for NaN
+    #[allow(invalid_nan_comparisons)]
+    {
+        let mut x34 = input as f64;
+        if x34 < f64::NAN {
+            x34 = f64::NAN;
+        } else if x34 > CONST_F64_MAX {
+            x34 = CONST_F64_MAX;
+        }
+    }
 
     // It's important this be the last set of statements
-    let mut x33 = input;
-    x33 = x33.clamp(min, max);
+    let mut x35 = input;
+    x35 = x35.clamp(CONST_MIN, CONST_MAX);
 }
 
 // This code intentionally nonsense.
 fn no_lint() {
-    let (input, min, max) = (0, -2, 3);
-    let x0 = if max < input {
-        max
-    } else if min > input {
-        max
+    let input = 0;
+    let x0 = if CONST_MAX < input {
+        CONST_MAX
+    } else if CONST_MIN > input {
+        CONST_MAX
     } else {
-        min
+        CONST_MIN
     };
 
-    let x1 = if input > max {
-        max
-    } else if input > min {
-        min
+    let x1 = if input > CONST_MAX {
+        CONST_MAX
+    } else if input > CONST_MIN {
+        CONST_MIN
     } else {
-        max
+        CONST_MAX
     };
 
-    let x2 = if max < min {
-        min
-    } else if input > max {
+    let x2 = if CONST_MAX < CONST_MIN {
+        CONST_MIN
+    } else if input > CONST_MAX {
         input
     } else {
         input
     };
 
-    let x3 = if min > input {
+    let x3 = if CONST_MIN > input {
         input
-    } else if max < input {
-        max
+    } else if CONST_MAX < input {
+        CONST_MAX
     } else {
-        max
+        CONST_MAX
     };
 
     let x6 = match input {
-        x if x < max => x,
-        x if x < min => x,
+        x if x < CONST_MAX => x,
+        x if x < CONST_MIN => x,
         x => x,
     };
 
     let x7 = match input {
-        x if x < min => max,
-        x if x > max => min,
+        x if x < CONST_MIN => CONST_MAX,
+        x if x > CONST_MAX => CONST_MIN,
         x => x,
     };
 
     let x8 = match input {
-        x if max > x => max,
-        x if min > x => min,
+        x if CONST_MAX > x => CONST_MAX,
+        x if CONST_MIN > x => CONST_MIN,
         x => x,
     };
 
     let mut x9 = input;
-    if x9 > min {
-        x9 = min;
+    if x9 > CONST_MIN {
+        x9 = CONST_MIN;
     }
-    if x9 > max {
-        x9 = max;
+    if x9 > CONST_MAX {
+        x9 = CONST_MAX;
     }
 
     let x10 = match input {
-        x if min > x => min,
-        x if max < x => max,
-        x => min,
+        x if CONST_MIN > x => CONST_MIN,
+        x if CONST_MAX < x => CONST_MAX,
+        x => CONST_MIN,
     };
 
     let mut x11 = input;
-    if x11 > max {
-        x11 = min;
+    if x11 > CONST_MAX {
+        x11 = CONST_MIN;
     }
-    if x11 < min {
-        x11 = max;
+    if x11 < CONST_MIN {
+        x11 = CONST_MAX;
     }
 
     let mut x12 = input;
-    if min > x12 {
-        x12 = max * 3;
+    if CONST_MIN > x12 {
+        x12 = CONST_MAX * 3;
     }
-    if max < x12 {
-        x12 = min;
+    if CONST_MAX < x12 {
+        x12 = CONST_MIN;
     }
 
     let mut x13 = input;
-    if max < x13 {
-        let x13 = max;
+    if CONST_MAX < x13 {
+        let x13 = CONST_MAX;
     }
-    if min > x13 {
-        x13 = min;
+    if CONST_MIN > x13 {
+        x13 = CONST_MIN;
     }
     let mut x14 = input;
-    if x14 < min {
+    if x14 < CONST_MIN {
         x14 = 3;
-    } else if x14 > max {
-        x14 = max;
+    } else if x14 > CONST_MAX {
+        x14 = CONST_MAX;
     }
     {
         let input: i32 = cmp_min_max(1);
@@ -272,8 +415,8 @@ fn msrv_1_49() {
 
 #[clippy::msrv = "1.50"]
 fn msrv_1_50() {
-    let (input, min, max) = (0, -1, 2);
-    let _ = input.clamp(min, max);
+    let input = 0;
+    let _ = input.clamp(CONST_MIN, CONST_MAX);
 }
 
 const fn _const() {
diff --git a/tests/ui/manual_clamp.rs b/tests/ui/manual_clamp.rs
index cacb40ae027..4d2a0c47bbd 100644
--- a/tests/ui/manual_clamp.rs
+++ b/tests/ui/manual_clamp.rs
@@ -17,10 +17,8 @@ const CONST_F64_MIN: f64 = 4.0;
 
 fn main() {
     let (input, min, max) = (0, -2, 3);
-    // Lint
+    // Min and max are not const, so this shouldn't trigger the lint.
     let x0 = if max < input {
-        //~^ ERROR: clamp-like pattern without using clamp function
-        //~| NOTE: clamp will panic if max < min
         max
     } else if min > input {
         min
@@ -29,8 +27,6 @@ fn main() {
     };
 
     let x1 = if input > max {
-        //~^ ERROR: clamp-like pattern without using clamp function
-        //~| NOTE: clamp will panic if max < min
         max
     } else if input < min {
         min
@@ -39,8 +35,6 @@ fn main() {
     };
 
     let x2 = if input < min {
-        //~^ ERROR: clamp-like pattern without using clamp function
-        //~| NOTE: clamp will panic if max < min
         min
     } else if input > max {
         max
@@ -49,8 +43,6 @@ fn main() {
     };
 
     let x3 = if min > input {
-        //~^ ERROR: clamp-like pattern without using clamp function
-        //~| NOTE: clamp will panic if max < min
         min
     } else if max < input {
         max
@@ -59,32 +51,22 @@ fn main() {
     };
 
     let x4 = input.max(min).min(max);
-    //~^ ERROR: clamp-like pattern without using clamp function
-    //~| NOTE: clamp will panic if max < min
 
     let x5 = input.min(max).max(min);
-    //~^ ERROR: clamp-like pattern without using clamp function
-    //~| NOTE: clamp will panic if max < min
 
     let x6 = match input {
-        //~^ ERROR: clamp-like pattern without using clamp function
-        //~| NOTE: clamp will panic if max < min
         x if x > max => max,
         x if x < min => min,
         x => x,
     };
 
     let x7 = match input {
-        //~^ ERROR: clamp-like pattern without using clamp function
-        //~| NOTE: clamp will panic if max < min
         x if x < min => min,
         x if x > max => max,
         x => x,
     };
 
     let x8 = match input {
-        //~^ ERROR: clamp-like pattern without using clamp function
-        //~| NOTE: clamp will panic if max < min
         x if max < x => max,
         x if min > x => min,
         x => x,
@@ -92,8 +74,6 @@ fn main() {
 
     let mut x9 = input;
     if x9 < min {
-        //~^ ERROR: clamp-like pattern without using clamp function
-        //~| NOTE: clamp will panic if max < min
         x9 = min;
     }
     if x9 > max {
@@ -101,8 +81,6 @@ fn main() {
     }
 
     let x10 = match input {
-        //~^ ERROR: clamp-like pattern without using clamp function
-        //~| NOTE: clamp will panic if max < min
         x if min > x => min,
         x if max < x => max,
         x => x,
@@ -111,8 +89,6 @@ fn main() {
     let mut x11 = input;
     let _ = 1;
     if x11 > max {
-        //~^ ERROR: clamp-like pattern without using clamp function
-        //~| NOTE: clamp will panic if max < min
         x11 = max;
     }
     if x11 < min {
@@ -121,8 +97,6 @@ fn main() {
 
     let mut x12 = input;
     if min > x12 {
-        //~^ ERROR: clamp-like pattern without using clamp function
-        //~| NOTE: clamp will panic if max < min
         x12 = min;
     }
     if max < x12 {
@@ -131,14 +105,163 @@ fn main() {
 
     let mut x13 = input;
     if max < x13 {
-        //~^ ERROR: clamp-like pattern without using clamp function
-        //~| NOTE: clamp will panic if max < min
         x13 = max;
     }
     if min > x13 {
         x13 = min;
     }
 
+    {
+        let (input, min, max) = (0.0f64, -2.0, 3.0);
+        let x14 = if input > max {
+            max
+        } else if input < min {
+            min
+        } else {
+            input
+        };
+    }
+    let mut x15 = input;
+    if x15 < min {
+        x15 = min;
+    } else if x15 > max {
+        x15 = max;
+    }
+
+    // It's important this be the last set of statements
+    let mut x16 = input;
+    if max < x16 {
+        x16 = max;
+    }
+    if min > x16 {
+        x16 = min;
+    }
+}
+
+fn const_main() {
+    let input = 0;
+    // Min and max are const, so this should trigger the lint.
+    let x0 = if CONST_MAX < input {
+        //~^ ERROR: clamp-like pattern without using clamp function
+        //~| NOTE: clamp will panic if max < min
+        CONST_MAX
+    } else if CONST_MIN > input {
+        CONST_MIN
+    } else {
+        input
+    };
+
+    let x1 = if input > CONST_MAX {
+        //~^ ERROR: clamp-like pattern without using clamp function
+        //~| NOTE: clamp will panic if max < min
+        CONST_MAX
+    } else if input < CONST_MIN {
+        CONST_MIN
+    } else {
+        input
+    };
+
+    let x2 = if input < CONST_MIN {
+        //~^ ERROR: clamp-like pattern without using clamp function
+        //~| NOTE: clamp will panic if max < min
+        CONST_MIN
+    } else if input > CONST_MAX {
+        CONST_MAX
+    } else {
+        input
+    };
+
+    let x3 = if CONST_MIN > input {
+        //~^ ERROR: clamp-like pattern without using clamp function
+        //~| NOTE: clamp will panic if max < min
+        CONST_MIN
+    } else if CONST_MAX < input {
+        CONST_MAX
+    } else {
+        input
+    };
+
+    let x4 = input.max(CONST_MIN).min(CONST_MAX);
+    //~^ ERROR: clamp-like pattern without using clamp function
+    //~| NOTE: clamp will panic if max < min
+
+    let x5 = input.min(CONST_MAX).max(CONST_MIN);
+    //~^ ERROR: clamp-like pattern without using clamp function
+    //~| NOTE: clamp will panic if max < min
+
+    let x6 = match input {
+        //~^ ERROR: clamp-like pattern without using clamp function
+        //~| NOTE: clamp will panic if max < min
+        x if x > CONST_MAX => CONST_MAX,
+        x if x < CONST_MIN => CONST_MIN,
+        x => x,
+    };
+
+    let x7 = match input {
+        //~^ ERROR: clamp-like pattern without using clamp function
+        //~| NOTE: clamp will panic if max < min
+        x if x < CONST_MIN => CONST_MIN,
+        x if x > CONST_MAX => CONST_MAX,
+        x => x,
+    };
+
+    let x8 = match input {
+        //~^ ERROR: clamp-like pattern without using clamp function
+        //~| NOTE: clamp will panic if max < min
+        x if CONST_MAX < x => CONST_MAX,
+        x if CONST_MIN > x => CONST_MIN,
+        x => x,
+    };
+
+    let mut x9 = input;
+    if x9 < CONST_MIN {
+        //~^ ERROR: clamp-like pattern without using clamp function
+        //~| NOTE: clamp will panic if max < min
+        x9 = CONST_MIN;
+    }
+    if x9 > CONST_MAX {
+        x9 = CONST_MAX;
+    }
+
+    let x10 = match input {
+        //~^ ERROR: clamp-like pattern without using clamp function
+        //~| NOTE: clamp will panic if max < min
+        x if CONST_MIN > x => CONST_MIN,
+        x if CONST_MAX < x => CONST_MAX,
+        x => x,
+    };
+
+    let mut x11 = input;
+    let _ = 1;
+    if x11 > CONST_MAX {
+        //~^ ERROR: clamp-like pattern without using clamp function
+        //~| NOTE: clamp will panic if max < min
+        x11 = CONST_MAX;
+    }
+    if x11 < CONST_MIN {
+        x11 = CONST_MIN;
+    }
+
+    let mut x12 = input;
+    if CONST_MIN > x12 {
+        //~^ ERROR: clamp-like pattern without using clamp function
+        //~| NOTE: clamp will panic if max < min
+        x12 = CONST_MIN;
+    }
+    if CONST_MAX < x12 {
+        x12 = CONST_MAX;
+    }
+
+    let mut x13 = input;
+    if CONST_MAX < x13 {
+        //~^ ERROR: clamp-like pattern without using clamp function
+        //~| NOTE: clamp will panic if max < min
+        x13 = CONST_MAX;
+    }
+    if CONST_MIN > x13 {
+        x13 = CONST_MIN;
+    }
+
     let x14 = if input > CONST_MAX {
         //~^ ERROR: clamp-like pattern without using clamp function
         //~| NOTE: clamp will panic if max < min
@@ -149,13 +272,13 @@ fn main() {
         input
     };
     {
-        let (input, min, max) = (0.0f64, -2.0, 3.0);
-        let x15 = if input > max {
+        let input = 0.0f64;
+        let x15 = if input > CONST_F64_MAX {
             //~^ ERROR: clamp-like pattern without using clamp function
-            //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan()
-            max
-        } else if input < min {
-            min
+            //~| NOTE: clamp will panic if max < min
+            CONST_F64_MAX
+        } else if input < CONST_F64_MIN {
+            CONST_F64_MIN
         } else {
             input
         };
@@ -214,121 +337,141 @@ fn main() {
         //~| NOTE: clamp will panic if max < min, min.is_nan(), or max.is_nan()
     }
     let mut x32 = input;
-    if x32 < min {
+    if x32 < CONST_MIN {
         //~^ ERROR: clamp-like pattern without using clamp function
         //~| NOTE: clamp will panic if max < min
-        x32 = min;
-    } else if x32 > max {
-        x32 = max;
+        x32 = CONST_MIN;
+    } else if x32 > CONST_MAX {
+        x32 = CONST_MAX;
+    }
+
+    // Flip the script, swap the places of min and max. Make sure this doesn't
+    // trigger when clamp would be guaranteed to panic.
+    let mut x33 = input;
+    if x33 < CONST_MAX {
+        x33 = CONST_MAX;
+    } else if x33 > CONST_MIN {
+        x33 = CONST_MIN;
+    }
+
+    // Do it again for NaN
+    #[allow(invalid_nan_comparisons)]
+    {
+        let mut x34 = input as f64;
+        if x34 < f64::NAN {
+            x34 = f64::NAN;
+        } else if x34 > CONST_F64_MAX {
+            x34 = CONST_F64_MAX;
+        }
     }
 
     // It's important this be the last set of statements
-    let mut x33 = input;
-    if max < x33 {
+    let mut x35 = input;
+    if CONST_MAX < x35 {
         //~^ ERROR: clamp-like pattern without using clamp function
         //~| NOTE: clamp will panic if max < min
-        x33 = max;
+        x35 = CONST_MAX;
     }
-    if min > x33 {
-        x33 = min;
+    if CONST_MIN > x35 {
+        x35 = CONST_MIN;
     }
 }
 
 // This code intentionally nonsense.
 fn no_lint() {
-    let (input, min, max) = (0, -2, 3);
-    let x0 = if max < input {
-        max
-    } else if min > input {
-        max
+    let input = 0;
+    let x0 = if CONST_MAX < input {
+        CONST_MAX
+    } else if CONST_MIN > input {
+        CONST_MAX
     } else {
-        min
+        CONST_MIN
     };
 
-    let x1 = if input > max {
-        max
-    } else if input > min {
-        min
+    let x1 = if input > CONST_MAX {
+        CONST_MAX
+    } else if input > CONST_MIN {
+        CONST_MIN
     } else {
-        max
+        CONST_MAX
     };
 
-    let x2 = if max < min {
-        min
-    } else if input > max {
+    let x2 = if CONST_MAX < CONST_MIN {
+        CONST_MIN
+    } else if input > CONST_MAX {
         input
     } else {
         input
     };
 
-    let x3 = if min > input {
+    let x3 = if CONST_MIN > input {
         input
-    } else if max < input {
-        max
+    } else if CONST_MAX < input {
+        CONST_MAX
     } else {
-        max
+        CONST_MAX
     };
 
     let x6 = match input {
-        x if x < max => x,
-        x if x < min => x,
+        x if x < CONST_MAX => x,
+        x if x < CONST_MIN => x,
         x => x,
     };
 
     let x7 = match input {
-        x if x < min => max,
-        x if x > max => min,
+        x if x < CONST_MIN => CONST_MAX,
+        x if x > CONST_MAX => CONST_MIN,
         x => x,
     };
 
     let x8 = match input {
-        x if max > x => max,
-        x if min > x => min,
+        x if CONST_MAX > x => CONST_MAX,
+        x if CONST_MIN > x => CONST_MIN,
         x => x,
     };
 
     let mut x9 = input;
-    if x9 > min {
-        x9 = min;
+    if x9 > CONST_MIN {
+        x9 = CONST_MIN;
     }
-    if x9 > max {
-        x9 = max;
+    if x9 > CONST_MAX {
+        x9 = CONST_MAX;
     }
 
     let x10 = match input {
-        x if min > x => min,
-        x if max < x => max,
-        x => min,
+        x if CONST_MIN > x => CONST_MIN,
+        x if CONST_MAX < x => CONST_MAX,
+        x => CONST_MIN,
     };
 
     let mut x11 = input;
-    if x11 > max {
-        x11 = min;
+    if x11 > CONST_MAX {
+        x11 = CONST_MIN;
     }
-    if x11 < min {
-        x11 = max;
+    if x11 < CONST_MIN {
+        x11 = CONST_MAX;
     }
 
     let mut x12 = input;
-    if min > x12 {
-        x12 = max * 3;
+    if CONST_MIN > x12 {
+        x12 = CONST_MAX * 3;
     }
-    if max < x12 {
-        x12 = min;
+    if CONST_MAX < x12 {
+        x12 = CONST_MIN;
     }
 
     let mut x13 = input;
-    if max < x13 {
-        let x13 = max;
+    if CONST_MAX < x13 {
+        let x13 = CONST_MAX;
     }
-    if min > x13 {
-        x13 = min;
+    if CONST_MIN > x13 {
+        x13 = CONST_MIN;
     }
     let mut x14 = input;
-    if x14 < min {
+    if x14 < CONST_MIN {
         x14 = 3;
-    } else if x14 > max {
-        x14 = max;
+    } else if x14 > CONST_MAX {
+        x14 = CONST_MAX;
     }
     {
         let input: i32 = cmp_min_max(1);
@@ -385,13 +528,13 @@ fn msrv_1_49() {
 
 #[clippy::msrv = "1.50"]
 fn msrv_1_50() {
-    let (input, min, max) = (0, -1, 2);
-    let _ = if input < min {
+    let input = 0;
+    let _ = if input > CONST_MAX {
         //~^ ERROR: clamp-like pattern without using clamp function
         //~| NOTE: clamp will panic if max < min
-        min
-    } else if input > max {
-        max
+        CONST_MAX
+    } else if input < CONST_MIN {
+        CONST_MIN
     } else {
         input
     };
diff --git a/tests/ui/manual_clamp.stderr b/tests/ui/manual_clamp.stderr
index 52c816f2b34..459d46796d8 100644
--- a/tests/ui/manual_clamp.stderr
+++ b/tests/ui/manual_clamp.stderr
@@ -1,213 +1,213 @@
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:94:5
+  --> tests/ui/manual_clamp.rs:217:5
    |
-LL | /     if x9 < min {
+LL | /     if x9 < CONST_MIN {
 LL | |
 LL | |
-LL | |         x9 = min;
+LL | |         x9 = CONST_MIN;
 ...  |
-LL | |         x9 = max;
+LL | |         x9 = CONST_MAX;
 LL | |     }
-   | |_____^ help: replace with clamp: `x9 = x9.clamp(min, max);`
+   | |_____^ help: replace with clamp: `x9 = x9.clamp(CONST_MIN, CONST_MAX);`
    |
    = note: clamp will panic if max < min
    = note: `-D clippy::manual-clamp` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::manual_clamp)]`
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:113:5
+  --> tests/ui/manual_clamp.rs:236:5
    |
-LL | /     if x11 > max {
+LL | /     if x11 > CONST_MAX {
 LL | |
 LL | |
-LL | |         x11 = max;
+LL | |         x11 = CONST_MAX;
 ...  |
-LL | |         x11 = min;
+LL | |         x11 = CONST_MIN;
 LL | |     }
-   | |_____^ help: replace with clamp: `x11 = x11.clamp(min, max);`
+   | |_____^ help: replace with clamp: `x11 = x11.clamp(CONST_MIN, CONST_MAX);`
    |
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:123:5
+  --> tests/ui/manual_clamp.rs:246:5
    |
-LL | /     if min > x12 {
+LL | /     if CONST_MIN > x12 {
 LL | |
 LL | |
-LL | |         x12 = min;
+LL | |         x12 = CONST_MIN;
 ...  |
-LL | |         x12 = max;
+LL | |         x12 = CONST_MAX;
 LL | |     }
-   | |_____^ help: replace with clamp: `x12 = x12.clamp(min, max);`
+   | |_____^ help: replace with clamp: `x12 = x12.clamp(CONST_MIN, CONST_MAX);`
    |
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:133:5
+  --> tests/ui/manual_clamp.rs:256:5
    |
-LL | /     if max < x13 {
+LL | /     if CONST_MAX < x13 {
 LL | |
 LL | |
-LL | |         x13 = max;
+LL | |         x13 = CONST_MAX;
 ...  |
-LL | |         x13 = min;
+LL | |         x13 = CONST_MIN;
 LL | |     }
-   | |_____^ help: replace with clamp: `x13 = x13.clamp(min, max);`
+   | |_____^ help: replace with clamp: `x13 = x13.clamp(CONST_MIN, CONST_MAX);`
    |
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:227:5
+  --> tests/ui/manual_clamp.rs:370:5
    |
-LL | /     if max < x33 {
+LL | /     if CONST_MAX < x35 {
 LL | |
 LL | |
-LL | |         x33 = max;
+LL | |         x35 = CONST_MAX;
 ...  |
-LL | |         x33 = min;
+LL | |         x35 = CONST_MIN;
 LL | |     }
-   | |_____^ help: replace with clamp: `x33 = x33.clamp(min, max);`
+   | |_____^ help: replace with clamp: `x35 = x35.clamp(CONST_MIN, CONST_MAX);`
    |
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:21:14
+  --> tests/ui/manual_clamp.rs:144:14
    |
-LL |       let x0 = if max < input {
+LL |       let x0 = if CONST_MAX < input {
    |  ______________^
 LL | |
 LL | |
-LL | |         max
+LL | |         CONST_MAX
 ...  |
 LL | |         input
 LL | |     };
-   | |_____^ help: replace with clamp: `input.clamp(min, max)`
+   | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
    |
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:31:14
+  --> tests/ui/manual_clamp.rs:154:14
    |
-LL |       let x1 = if input > max {
+LL |       let x1 = if input > CONST_MAX {
    |  ______________^
 LL | |
 LL | |
-LL | |         max
+LL | |         CONST_MAX
 ...  |
 LL | |         input
 LL | |     };
-   | |_____^ help: replace with clamp: `input.clamp(min, max)`
+   | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
    |
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:41:14
+  --> tests/ui/manual_clamp.rs:164:14
    |
-LL |       let x2 = if input < min {
+LL |       let x2 = if input < CONST_MIN {
    |  ______________^
 LL | |
 LL | |
-LL | |         min
+LL | |         CONST_MIN
 ...  |
 LL | |         input
 LL | |     };
-   | |_____^ help: replace with clamp: `input.clamp(min, max)`
+   | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
    |
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:51:14
+  --> tests/ui/manual_clamp.rs:174:14
    |
-LL |       let x3 = if min > input {
+LL |       let x3 = if CONST_MIN > input {
    |  ______________^
 LL | |
 LL | |
-LL | |         min
+LL | |         CONST_MIN
 ...  |
 LL | |         input
 LL | |     };
-   | |_____^ help: replace with clamp: `input.clamp(min, max)`
+   | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
    |
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:61:14
+  --> tests/ui/manual_clamp.rs:184:14
    |
-LL |     let x4 = input.max(min).min(max);
-   |              ^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(min, max)`
+LL |     let x4 = input.max(CONST_MIN).min(CONST_MAX);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
    |
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:65:14
+  --> tests/ui/manual_clamp.rs:188:14
    |
-LL |     let x5 = input.min(max).max(min);
-   |              ^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(min, max)`
+LL |     let x5 = input.min(CONST_MAX).max(CONST_MIN);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
    |
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:69:14
+  --> tests/ui/manual_clamp.rs:192:14
    |
 LL |       let x6 = match input {
    |  ______________^
 LL | |
 LL | |
-LL | |         x if x > max => max,
-LL | |         x if x < min => min,
+LL | |         x if x > CONST_MAX => CONST_MAX,
+LL | |         x if x < CONST_MIN => CONST_MIN,
 LL | |         x => x,
 LL | |     };
-   | |_____^ help: replace with clamp: `input.clamp(min, max)`
+   | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
    |
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:77:14
+  --> tests/ui/manual_clamp.rs:200:14
    |
 LL |       let x7 = match input {
    |  ______________^
 LL | |
 LL | |
-LL | |         x if x < min => min,
-LL | |         x if x > max => max,
+LL | |         x if x < CONST_MIN => CONST_MIN,
+LL | |         x if x > CONST_MAX => CONST_MAX,
 LL | |         x => x,
 LL | |     };
-   | |_____^ help: replace with clamp: `input.clamp(min, max)`
+   | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
    |
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:85:14
+  --> tests/ui/manual_clamp.rs:208:14
    |
 LL |       let x8 = match input {
    |  ______________^
 LL | |
 LL | |
-LL | |         x if max < x => max,
-LL | |         x if min > x => min,
+LL | |         x if CONST_MAX < x => CONST_MAX,
+LL | |         x if CONST_MIN > x => CONST_MIN,
 LL | |         x => x,
 LL | |     };
-   | |_____^ help: replace with clamp: `input.clamp(min, max)`
+   | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
    |
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:103:15
+  --> tests/ui/manual_clamp.rs:226:15
    |
 LL |       let x10 = match input {
    |  _______________^
 LL | |
 LL | |
-LL | |         x if min > x => min,
-LL | |         x if max < x => max,
+LL | |         x if CONST_MIN > x => CONST_MIN,
+LL | |         x if CONST_MAX < x => CONST_MAX,
 LL | |         x => x,
 LL | |     };
-   | |_____^ help: replace with clamp: `input.clamp(min, max)`
+   | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
    |
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:142:15
+  --> tests/ui/manual_clamp.rs:265:15
    |
 LL |       let x14 = if input > CONST_MAX {
    |  _______________^
@@ -222,23 +222,23 @@ LL | |     };
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:153:19
+  --> tests/ui/manual_clamp.rs:276:19
    |
-LL |           let x15 = if input > max {
+LL |           let x15 = if input > CONST_F64_MAX {
    |  ___________________^
 LL | |
 LL | |
-LL | |             max
+LL | |             CONST_F64_MAX
 ...  |
 LL | |             input
 LL | |         };
-   | |_________^ help: replace with clamp: `input.clamp(min, max)`
+   | |_________^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
    |
    = note: clamp will panic if max < min, min.is_nan(), or max.is_nan()
    = note: clamp returns NaN if the input is NaN
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:166:19
+  --> tests/ui/manual_clamp.rs:289:19
    |
 LL |         let x16 = cmp_max(cmp_min(input, CONST_MAX), CONST_MIN);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
@@ -246,7 +246,7 @@ LL |         let x16 = cmp_max(cmp_min(input, CONST_MAX), CONST_MIN);
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:169:19
+  --> tests/ui/manual_clamp.rs:292:19
    |
 LL |         let x17 = cmp_min(cmp_max(input, CONST_MIN), CONST_MAX);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
@@ -254,7 +254,7 @@ LL |         let x17 = cmp_min(cmp_max(input, CONST_MIN), CONST_MAX);
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:172:19
+  --> tests/ui/manual_clamp.rs:295:19
    |
 LL |         let x18 = cmp_max(CONST_MIN, cmp_min(input, CONST_MAX));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
@@ -262,7 +262,7 @@ LL |         let x18 = cmp_max(CONST_MIN, cmp_min(input, CONST_MAX));
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:175:19
+  --> tests/ui/manual_clamp.rs:298:19
    |
 LL |         let x19 = cmp_min(CONST_MAX, cmp_max(input, CONST_MIN));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
@@ -270,7 +270,7 @@ LL |         let x19 = cmp_min(CONST_MAX, cmp_max(input, CONST_MIN));
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:178:19
+  --> tests/ui/manual_clamp.rs:301:19
    |
 LL |         let x20 = cmp_max(cmp_min(CONST_MAX, input), CONST_MIN);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
@@ -278,7 +278,7 @@ LL |         let x20 = cmp_max(cmp_min(CONST_MAX, input), CONST_MIN);
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:181:19
+  --> tests/ui/manual_clamp.rs:304:19
    |
 LL |         let x21 = cmp_min(cmp_max(CONST_MIN, input), CONST_MAX);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
@@ -286,7 +286,7 @@ LL |         let x21 = cmp_min(cmp_max(CONST_MIN, input), CONST_MAX);
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:184:19
+  --> tests/ui/manual_clamp.rs:307:19
    |
 LL |         let x22 = cmp_max(CONST_MIN, cmp_min(CONST_MAX, input));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
@@ -294,7 +294,7 @@ LL |         let x22 = cmp_max(CONST_MIN, cmp_min(CONST_MAX, input));
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:187:19
+  --> tests/ui/manual_clamp.rs:310:19
    |
 LL |         let x23 = cmp_min(CONST_MAX, cmp_max(CONST_MIN, input));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
@@ -302,7 +302,7 @@ LL |         let x23 = cmp_min(CONST_MAX, cmp_max(CONST_MIN, input));
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:191:19
+  --> tests/ui/manual_clamp.rs:314:19
    |
 LL |         let x24 = f64::max(f64::min(input, CONST_F64_MAX), CONST_F64_MIN);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
@@ -311,7 +311,7 @@ LL |         let x24 = f64::max(f64::min(input, CONST_F64_MAX), CONST_F64_MIN);
    = note: clamp returns NaN if the input is NaN
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:194:19
+  --> tests/ui/manual_clamp.rs:317:19
    |
 LL |         let x25 = f64::min(f64::max(input, CONST_F64_MIN), CONST_F64_MAX);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
@@ -320,7 +320,7 @@ LL |         let x25 = f64::min(f64::max(input, CONST_F64_MIN), CONST_F64_MAX);
    = note: clamp returns NaN if the input is NaN
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:197:19
+  --> tests/ui/manual_clamp.rs:320:19
    |
 LL |         let x26 = f64::max(CONST_F64_MIN, f64::min(input, CONST_F64_MAX));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
@@ -329,7 +329,7 @@ LL |         let x26 = f64::max(CONST_F64_MIN, f64::min(input, CONST_F64_MAX));
    = note: clamp returns NaN if the input is NaN
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:200:19
+  --> tests/ui/manual_clamp.rs:323:19
    |
 LL |         let x27 = f64::min(CONST_F64_MAX, f64::max(input, CONST_F64_MIN));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
@@ -338,7 +338,7 @@ LL |         let x27 = f64::min(CONST_F64_MAX, f64::max(input, CONST_F64_MIN));
    = note: clamp returns NaN if the input is NaN
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:203:19
+  --> tests/ui/manual_clamp.rs:326:19
    |
 LL |         let x28 = f64::max(f64::min(CONST_F64_MAX, input), CONST_F64_MIN);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
@@ -347,7 +347,7 @@ LL |         let x28 = f64::max(f64::min(CONST_F64_MAX, input), CONST_F64_MIN);
    = note: clamp returns NaN if the input is NaN
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:206:19
+  --> tests/ui/manual_clamp.rs:329:19
    |
 LL |         let x29 = f64::min(f64::max(CONST_F64_MIN, input), CONST_F64_MAX);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
@@ -356,7 +356,7 @@ LL |         let x29 = f64::min(f64::max(CONST_F64_MIN, input), CONST_F64_MAX);
    = note: clamp returns NaN if the input is NaN
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:209:19
+  --> tests/ui/manual_clamp.rs:332:19
    |
 LL |         let x30 = f64::max(CONST_F64_MIN, f64::min(CONST_F64_MAX, input));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
@@ -365,7 +365,7 @@ LL |         let x30 = f64::max(CONST_F64_MIN, f64::min(CONST_F64_MAX, input));
    = note: clamp returns NaN if the input is NaN
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:212:19
+  --> tests/ui/manual_clamp.rs:335:19
    |
 LL |         let x31 = f64::min(CONST_F64_MAX, f64::max(CONST_F64_MIN, input));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
@@ -374,31 +374,31 @@ LL |         let x31 = f64::min(CONST_F64_MAX, f64::max(CONST_F64_MIN, input));
    = note: clamp returns NaN if the input is NaN
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:217:5
+  --> tests/ui/manual_clamp.rs:340:5
    |
-LL | /     if x32 < min {
+LL | /     if x32 < CONST_MIN {
 LL | |
 LL | |
-LL | |         x32 = min;
-LL | |     } else if x32 > max {
-LL | |         x32 = max;
+LL | |         x32 = CONST_MIN;
+LL | |     } else if x32 > CONST_MAX {
+LL | |         x32 = CONST_MAX;
 LL | |     }
-   | |_____^ help: replace with clamp: `x32 = x32.clamp(min, max);`
+   | |_____^ help: replace with clamp: `x32 = x32.clamp(CONST_MIN, CONST_MAX);`
    |
    = note: clamp will panic if max < min
 
 error: clamp-like pattern without using clamp function
-  --> tests/ui/manual_clamp.rs:389:13
+  --> tests/ui/manual_clamp.rs:532:13
    |
-LL |       let _ = if input < min {
+LL |       let _ = if input > CONST_MAX {
    |  _____________^
 LL | |
 LL | |
-LL | |         min
+LL | |         CONST_MAX
 ...  |
 LL | |         input
 LL | |     };
-   | |_____^ help: replace with clamp: `input.clamp(min, max)`
+   | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
    |
    = note: clamp will panic if max < min
 
diff --git a/tests/ui/manual_saturating_arithmetic.fixed b/tests/ui/manual_saturating_arithmetic.fixed
index 8218f10881a..41a32df32ee 100644
--- a/tests/ui/manual_saturating_arithmetic.fixed
+++ b/tests/ui/manual_saturating_arithmetic.fixed
@@ -1,4 +1,4 @@
-#![allow(unused_imports)]
+#![allow(clippy::legacy_numeric_constants, unused_imports)]
 
 use std::{i128, i32, u128, u32};
 
diff --git a/tests/ui/manual_saturating_arithmetic.rs b/tests/ui/manual_saturating_arithmetic.rs
index 60022b54b02..3a6b32d8069 100644
--- a/tests/ui/manual_saturating_arithmetic.rs
+++ b/tests/ui/manual_saturating_arithmetic.rs
@@ -1,4 +1,4 @@
-#![allow(unused_imports)]
+#![allow(clippy::legacy_numeric_constants, unused_imports)]
 
 use std::{i128, i32, u128, u32};
 
diff --git a/tests/ui/manual_swap_auto_fix.fixed b/tests/ui/manual_swap_auto_fix.fixed
new file mode 100644
index 00000000000..28466ff3f9b
--- /dev/null
+++ b/tests/ui/manual_swap_auto_fix.fixed
@@ -0,0 +1,57 @@
+#![warn(clippy::manual_swap)]
+#![no_main]
+
+fn swap1() {
+    let mut v = [3, 2, 1, 0];
+    let index = v[0];
+    v.swap(0, index);
+}
+
+fn swap2() {
+    let mut v = [3, 2, 1, 0];
+    let tmp = v[0];
+    v.swap(0, 1);
+    // check not found in this scope.
+    let _ = tmp;
+}
+
+fn swap3() {
+    let mut v = [3, 2];
+    let i1 = 0;
+    let i2 = 1;
+    v.swap(i1, i2);
+}
+
+fn swap4() {
+    let mut v = [3, 2, 1];
+    let i1 = 0;
+    let i2 = 1;
+    v.swap(i1, i2 + 1);
+}
+
+fn swap5() {
+    let mut v = [0, 1, 2, 3];
+    let i1 = 0;
+    let i2 = 1;
+    v.swap(i1, i2 + 1);
+}
+
+fn swap6() {
+    let mut v = [0, 1, 2, 3];
+    let index = v[0];
+    v.swap(0, index + 1);
+}
+
+fn swap7() {
+    let mut v = [0, 1, 2, 3];
+    let i1 = 0;
+    let i2 = 6;
+    v.swap(i1 * 3, i2 / 2);
+}
+
+fn swap8() {
+    let mut v = [1, 2, 3, 4];
+    let i1 = 1;
+    let i2 = 1;
+    v.swap(i1 + i2, i2);
+}
diff --git a/tests/ui/manual_swap_auto_fix.rs b/tests/ui/manual_swap_auto_fix.rs
new file mode 100644
index 00000000000..702a9e67d3d
--- /dev/null
+++ b/tests/ui/manual_swap_auto_fix.rs
@@ -0,0 +1,72 @@
+#![warn(clippy::manual_swap)]
+#![no_main]
+
+fn swap1() {
+    let mut v = [3, 2, 1, 0];
+    let index = v[0];
+    //~^ ERROR: this looks like you are swapping elements of `v` manually
+    v[0] = v[index];
+    v[index] = index;
+}
+
+fn swap2() {
+    let mut v = [3, 2, 1, 0];
+    let tmp = v[0];
+    v[0] = v[1];
+    v[1] = tmp;
+    // check not found in this scope.
+    let _ = tmp;
+}
+
+fn swap3() {
+    let mut v = [3, 2];
+    let i1 = 0;
+    let i2 = 1;
+    let temp = v[i1];
+    v[i1] = v[i2];
+    v[i2] = temp;
+}
+
+fn swap4() {
+    let mut v = [3, 2, 1];
+    let i1 = 0;
+    let i2 = 1;
+    let temp = v[i1];
+    v[i1] = v[i2 + 1];
+    v[i2 + 1] = temp;
+}
+
+fn swap5() {
+    let mut v = [0, 1, 2, 3];
+    let i1 = 0;
+    let i2 = 1;
+    let temp = v[i1];
+    v[i1] = v[i2 + 1];
+    v[i2 + 1] = temp;
+}
+
+fn swap6() {
+    let mut v = [0, 1, 2, 3];
+    let index = v[0];
+    //~^ ERROR: this looks like you are swapping elements of `v` manually
+    v[0] = v[index + 1];
+    v[index + 1] = index;
+}
+
+fn swap7() {
+    let mut v = [0, 1, 2, 3];
+    let i1 = 0;
+    let i2 = 6;
+    let tmp = v[i1 * 3];
+    v[i1 * 3] = v[i2 / 2];
+    v[i2 / 2] = tmp;
+}
+
+fn swap8() {
+    let mut v = [1, 2, 3, 4];
+    let i1 = 1;
+    let i2 = 1;
+    let tmp = v[i1 + i2];
+    v[i1 + i2] = v[i2];
+    v[i2] = tmp;
+}
diff --git a/tests/ui/manual_swap_auto_fix.stderr b/tests/ui/manual_swap_auto_fix.stderr
new file mode 100644
index 00000000000..eecfcd3977b
--- /dev/null
+++ b/tests/ui/manual_swap_auto_fix.stderr
@@ -0,0 +1,88 @@
+error: this looks like you are swapping elements of `v` manually
+  --> tests/ui/manual_swap_auto_fix.rs:6:5
+   |
+LL | /     let index = v[0];
+LL | |
+LL | |     v[0] = v[index];
+LL | |     v[index] = index;
+   | |_____________________^
+   |
+   = note: `-D clippy::manual-swap` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::manual_swap)]`
+help: try
+   |
+LL ~     let index = v[0];
+LL +     v.swap(0, index);
+   |
+
+error: this looks like you are swapping elements of `v` manually
+  --> tests/ui/manual_swap_auto_fix.rs:14:5
+   |
+LL | /     let tmp = v[0];
+LL | |     v[0] = v[1];
+LL | |     v[1] = tmp;
+   | |_______________^
+   |
+help: try
+   |
+LL ~     let tmp = v[0];
+LL +     v.swap(0, 1);
+   |
+
+error: this looks like you are swapping elements of `v` manually
+  --> tests/ui/manual_swap_auto_fix.rs:25:5
+   |
+LL | /     let temp = v[i1];
+LL | |     v[i1] = v[i2];
+LL | |     v[i2] = temp;
+   | |_________________^ help: try: `v.swap(i1, i2);`
+
+error: this looks like you are swapping elements of `v` manually
+  --> tests/ui/manual_swap_auto_fix.rs:34:5
+   |
+LL | /     let temp = v[i1];
+LL | |     v[i1] = v[i2 + 1];
+LL | |     v[i2 + 1] = temp;
+   | |_____________________^ help: try: `v.swap(i1, i2 + 1);`
+
+error: this looks like you are swapping elements of `v` manually
+  --> tests/ui/manual_swap_auto_fix.rs:43:5
+   |
+LL | /     let temp = v[i1];
+LL | |     v[i1] = v[i2 + 1];
+LL | |     v[i2 + 1] = temp;
+   | |_____________________^ help: try: `v.swap(i1, i2 + 1);`
+
+error: this looks like you are swapping elements of `v` manually
+  --> tests/ui/manual_swap_auto_fix.rs:50:5
+   |
+LL | /     let index = v[0];
+LL | |
+LL | |     v[0] = v[index + 1];
+LL | |     v[index + 1] = index;
+   | |_________________________^
+   |
+help: try
+   |
+LL ~     let index = v[0];
+LL +     v.swap(0, index + 1);
+   |
+
+error: this looks like you are swapping elements of `v` manually
+  --> tests/ui/manual_swap_auto_fix.rs:60:5
+   |
+LL | /     let tmp = v[i1 * 3];
+LL | |     v[i1 * 3] = v[i2 / 2];
+LL | |     v[i2 / 2] = tmp;
+   | |____________________^ help: try: `v.swap(i1 * 3, i2 / 2);`
+
+error: this looks like you are swapping elements of `v` manually
+  --> tests/ui/manual_swap_auto_fix.rs:69:5
+   |
+LL | /     let tmp = v[i1 + i2];
+LL | |     v[i1 + i2] = v[i2];
+LL | |     v[i2] = tmp;
+   | |________________^ help: try: `v.swap(i1 + i2, i2);`
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/manual_unwrap_or_default.fixed b/tests/ui/manual_unwrap_or_default.fixed
index c8456805ee6..a0b707628a8 100644
--- a/tests/ui/manual_unwrap_or_default.fixed
+++ b/tests/ui/manual_unwrap_or_default.fixed
@@ -17,3 +17,48 @@ fn main() {
     let x: Option<Vec<String>> = None;
     x.unwrap_or_default();
 }
+
+// Issue #12531
+unsafe fn no_deref_ptr(a: Option<i32>, b: *const Option<i32>) -> i32 {
+    match a {
+        // `*b` being correct depends on `a == Some(_)`
+        Some(_) => (*b).unwrap_or_default(),
+        _ => 0,
+    }
+}
+
+const fn issue_12568(opt: Option<bool>) -> bool {
+    match opt {
+        Some(s) => s,
+        None => false,
+    }
+}
+
+fn issue_12569() {
+    let match_none_se = match 1u32.checked_div(0) {
+        Some(v) => v,
+        None => {
+            println!("important");
+            0
+        },
+    };
+    let match_some_se = match 1u32.checked_div(0) {
+        Some(v) => {
+            println!("important");
+            v
+        },
+        None => 0,
+    };
+    let iflet_else_se = if let Some(v) = 1u32.checked_div(0) {
+        v
+    } else {
+        println!("important");
+        0
+    };
+    let iflet_then_se = if let Some(v) = 1u32.checked_div(0) {
+        println!("important");
+        v
+    } else {
+        0
+    };
+}
diff --git a/tests/ui/manual_unwrap_or_default.rs b/tests/ui/manual_unwrap_or_default.rs
index 820717be53a..1d4cca12f6c 100644
--- a/tests/ui/manual_unwrap_or_default.rs
+++ b/tests/ui/manual_unwrap_or_default.rs
@@ -38,3 +38,51 @@ fn main() {
         Vec::default()
     };
 }
+
+// Issue #12531
+unsafe fn no_deref_ptr(a: Option<i32>, b: *const Option<i32>) -> i32 {
+    match a {
+        // `*b` being correct depends on `a == Some(_)`
+        Some(_) => match *b {
+            Some(v) => v,
+            _ => 0,
+        },
+        _ => 0,
+    }
+}
+
+const fn issue_12568(opt: Option<bool>) -> bool {
+    match opt {
+        Some(s) => s,
+        None => false,
+    }
+}
+
+fn issue_12569() {
+    let match_none_se = match 1u32.checked_div(0) {
+        Some(v) => v,
+        None => {
+            println!("important");
+            0
+        },
+    };
+    let match_some_se = match 1u32.checked_div(0) {
+        Some(v) => {
+            println!("important");
+            v
+        },
+        None => 0,
+    };
+    let iflet_else_se = if let Some(v) = 1u32.checked_div(0) {
+        v
+    } else {
+        println!("important");
+        0
+    };
+    let iflet_then_se = if let Some(v) = 1u32.checked_div(0) {
+        println!("important");
+        v
+    } else {
+        0
+    };
+}
diff --git a/tests/ui/manual_unwrap_or_default.stderr b/tests/ui/manual_unwrap_or_default.stderr
index f4eb6583588..d89212e6045 100644
--- a/tests/ui/manual_unwrap_or_default.stderr
+++ b/tests/ui/manual_unwrap_or_default.stderr
@@ -52,5 +52,15 @@ LL | |         Vec::default()
 LL | |     };
    | |_____^ help: replace it with: `x.unwrap_or_default()`
 
-error: aborting due to 5 previous errors
+error: match can be simplified with `.unwrap_or_default()`
+  --> tests/ui/manual_unwrap_or_default.rs:46:20
+   |
+LL |           Some(_) => match *b {
+   |  ____________________^
+LL | |             Some(v) => v,
+LL | |             _ => 0,
+LL | |         },
+   | |_________^ help: replace it with: `(*b).unwrap_or_default()`
+
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui/map_clone.fixed b/tests/ui/map_clone.fixed
index e58b6b2f19e..f9f8dc1a512 100644
--- a/tests/ui/map_clone.fixed
+++ b/tests/ui/map_clone.fixed
@@ -131,4 +131,28 @@ fn main() {
         let x: Vec<&u8> = vec![];
         let y = x.into_iter().map(|x| u8::clone(loop {}));
     }
+
+    // Issue #12528
+    {
+        // Don't lint these
+        use std::rc::{Rc, Weak as RcWeak};
+        use std::sync::{Arc, Weak as ArcWeak};
+        struct Foo;
+
+        let x = Arc::new(Foo);
+        let y = Some(&x);
+        let _z = y.map(Arc::clone);
+
+        let x = Rc::new(Foo);
+        let y = Some(&x);
+        let _z = y.map(Rc::clone);
+
+        let x = Arc::downgrade(&Arc::new(Foo));
+        let y = Some(&x);
+        let _z = y.map(ArcWeak::clone);
+
+        let x = Rc::downgrade(&Rc::new(Foo));
+        let y = Some(&x);
+        let _z = y.map(RcWeak::clone);
+    }
 }
diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs
index e642e4046f8..a5c19ce0631 100644
--- a/tests/ui/map_clone.rs
+++ b/tests/ui/map_clone.rs
@@ -131,4 +131,28 @@ fn main() {
         let x: Vec<&u8> = vec![];
         let y = x.into_iter().map(|x| u8::clone(loop {}));
     }
+
+    // Issue #12528
+    {
+        // Don't lint these
+        use std::rc::{Rc, Weak as RcWeak};
+        use std::sync::{Arc, Weak as ArcWeak};
+        struct Foo;
+
+        let x = Arc::new(Foo);
+        let y = Some(&x);
+        let _z = y.map(Arc::clone);
+
+        let x = Rc::new(Foo);
+        let y = Some(&x);
+        let _z = y.map(Rc::clone);
+
+        let x = Arc::downgrade(&Arc::new(Foo));
+        let y = Some(&x);
+        let _z = y.map(ArcWeak::clone);
+
+        let x = Rc::downgrade(&Rc::new(Foo));
+        let y = Some(&x);
+        let _z = y.map(RcWeak::clone);
+    }
 }
diff --git a/tests/ui/missing_const_for_fn/could_be_const.rs b/tests/ui/missing_const_for_fn/could_be_const.rs
index 6985c2d0c19..12a8320c8f3 100644
--- a/tests/ui/missing_const_for_fn/could_be_const.rs
+++ b/tests/ui/missing_const_for_fn/could_be_const.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::missing_const_for_fn)]
-#![allow(incomplete_features, clippy::let_and_return)]
+#![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)]
 #![feature(const_mut_refs)]
 #![feature(const_trait_impl)]
 
diff --git a/tests/ui/missing_transmute_annotations.fixed b/tests/ui/missing_transmute_annotations.fixed
new file mode 100644
index 00000000000..a3c94ab139e
--- /dev/null
+++ b/tests/ui/missing_transmute_annotations.fixed
@@ -0,0 +1,78 @@
+//@aux-build:macro_rules.rs
+
+#![warn(clippy::missing_transmute_annotations)]
+#![allow(clippy::let_with_type_underscore)]
+
+#[macro_use]
+extern crate macro_rules;
+
+macro_rules! local_bad_transmute {
+    ($e:expr) => {
+        std::mem::transmute::<[u16; 2], i32>($e)
+        //~^ ERROR: transmute used without annotations
+    };
+}
+
+fn bar(x: i32) -> i32 {
+    x
+}
+
+unsafe fn foo1() -> i32 {
+    // Should not warn!
+    std::mem::transmute([1u16, 2u16])
+}
+
+// Should not warn!
+const _: i32 = unsafe { std::mem::transmute([1u16, 2u16]) };
+
+#[repr(i32)]
+enum Foo {
+    A = 0,
+}
+
+unsafe fn foo2() -> i32 {
+    let mut i: i32 = 0;
+    i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+    //~^ ERROR: transmute used without annotations
+    i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+    //~^ ERROR: transmute used without annotations
+    i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+    //~^ ERROR: transmute used without annotations
+    i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+    //~^ ERROR: transmute used without annotations
+
+    let x: i32 = bar(std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]));
+    //~^ ERROR: transmute used without annotations
+    bar(std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]));
+    //~^ ERROR: transmute used without annotations
+
+    i = local_bad_transmute!([1u16, 2u16]);
+
+    // Should not warn.
+    i = bad_transmute!([1u16, 2u16]);
+
+    i = std::mem::transmute::<[i16; 2], i32>([0i16, 0i16]);
+    //~^ ERROR: transmute used without annotations
+
+    i = std::mem::transmute::<Foo, i32>(Foo::A);
+    //~^ ERROR: transmute used without annotations
+
+    i
+}
+
+fn main() {
+    let x: _ = unsafe { std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]) };
+    //~^ ERROR: transmute used without annotations
+    unsafe {
+        let x: _ = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+        //~^ ERROR: transmute used without annotations
+
+        // Should not warn.
+        std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+        let x = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+        let x: i32 = std::mem::transmute::<[u16; 2], _>([1u16, 2u16]);
+        let x: i32 = std::mem::transmute::<_, i32>([1u16, 2u16]);
+        let x: i32 = std::mem::transmute([1u16, 2u16]);
+    }
+    let x: i32 = unsafe { std::mem::transmute([1u16, 2u16]) };
+}
diff --git a/tests/ui/missing_transmute_annotations.rs b/tests/ui/missing_transmute_annotations.rs
new file mode 100644
index 00000000000..c12e1b0f8d2
--- /dev/null
+++ b/tests/ui/missing_transmute_annotations.rs
@@ -0,0 +1,78 @@
+//@aux-build:macro_rules.rs
+
+#![warn(clippy::missing_transmute_annotations)]
+#![allow(clippy::let_with_type_underscore)]
+
+#[macro_use]
+extern crate macro_rules;
+
+macro_rules! local_bad_transmute {
+    ($e:expr) => {
+        std::mem::transmute($e)
+        //~^ ERROR: transmute used without annotations
+    };
+}
+
+fn bar(x: i32) -> i32 {
+    x
+}
+
+unsafe fn foo1() -> i32 {
+    // Should not warn!
+    std::mem::transmute([1u16, 2u16])
+}
+
+// Should not warn!
+const _: i32 = unsafe { std::mem::transmute([1u16, 2u16]) };
+
+#[repr(i32)]
+enum Foo {
+    A = 0,
+}
+
+unsafe fn foo2() -> i32 {
+    let mut i: i32 = 0;
+    i = std::mem::transmute([1u16, 2u16]);
+    //~^ ERROR: transmute used without annotations
+    i = std::mem::transmute::<_, _>([1u16, 2u16]);
+    //~^ ERROR: transmute used without annotations
+    i = std::mem::transmute::<_, i32>([1u16, 2u16]);
+    //~^ ERROR: transmute used without annotations
+    i = std::mem::transmute::<[u16; 2], _>([1u16, 2u16]);
+    //~^ ERROR: transmute used without annotations
+
+    let x: i32 = bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]));
+    //~^ ERROR: transmute used without annotations
+    bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]));
+    //~^ ERROR: transmute used without annotations
+
+    i = local_bad_transmute!([1u16, 2u16]);
+
+    // Should not warn.
+    i = bad_transmute!([1u16, 2u16]);
+
+    i = std::mem::transmute([0i16, 0i16]);
+    //~^ ERROR: transmute used without annotations
+
+    i = std::mem::transmute(Foo::A);
+    //~^ ERROR: transmute used without annotations
+
+    i
+}
+
+fn main() {
+    let x: _ = unsafe { std::mem::transmute::<_, i32>([1u16, 2u16]) };
+    //~^ ERROR: transmute used without annotations
+    unsafe {
+        let x: _ = std::mem::transmute::<_, i32>([1u16, 2u16]);
+        //~^ ERROR: transmute used without annotations
+
+        // Should not warn.
+        std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+        let x = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+        let x: i32 = std::mem::transmute::<[u16; 2], _>([1u16, 2u16]);
+        let x: i32 = std::mem::transmute::<_, i32>([1u16, 2u16]);
+        let x: i32 = std::mem::transmute([1u16, 2u16]);
+    }
+    let x: i32 = unsafe { std::mem::transmute([1u16, 2u16]) };
+}
diff --git a/tests/ui/missing_transmute_annotations.stderr b/tests/ui/missing_transmute_annotations.stderr
new file mode 100644
index 00000000000..5903ed488ef
--- /dev/null
+++ b/tests/ui/missing_transmute_annotations.stderr
@@ -0,0 +1,76 @@
+error: transmute used without annotations
+  --> tests/ui/missing_transmute_annotations.rs:35:19
+   |
+LL |     i = std::mem::transmute([1u16, 2u16]);
+   |                   ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+   |
+   = note: `-D clippy::missing-transmute-annotations` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::missing_transmute_annotations)]`
+
+error: transmute used without annotations
+  --> tests/ui/missing_transmute_annotations.rs:37:19
+   |
+LL |     i = std::mem::transmute::<_, _>([1u16, 2u16]);
+   |                   ^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+
+error: transmute used without annotations
+  --> tests/ui/missing_transmute_annotations.rs:39:19
+   |
+LL |     i = std::mem::transmute::<_, i32>([1u16, 2u16]);
+   |                   ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+
+error: transmute used without annotations
+  --> tests/ui/missing_transmute_annotations.rs:41:19
+   |
+LL |     i = std::mem::transmute::<[u16; 2], _>([1u16, 2u16]);
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+
+error: transmute used without annotations
+  --> tests/ui/missing_transmute_annotations.rs:44:32
+   |
+LL |     let x: i32 = bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]));
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+
+error: transmute used without annotations
+  --> tests/ui/missing_transmute_annotations.rs:46:19
+   |
+LL |     bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]));
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+
+error: transmute used without annotations
+  --> tests/ui/missing_transmute_annotations.rs:11:19
+   |
+LL |         std::mem::transmute($e)
+   |                   ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+...
+LL |     i = local_bad_transmute!([1u16, 2u16]);
+   |         ---------------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `local_bad_transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: transmute used without annotations
+  --> tests/ui/missing_transmute_annotations.rs:54:19
+   |
+LL |     i = std::mem::transmute([0i16, 0i16]);
+   |                   ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[i16; 2], i32>`
+
+error: transmute used without annotations
+  --> tests/ui/missing_transmute_annotations.rs:57:19
+   |
+LL |     i = std::mem::transmute(Foo::A);
+   |                   ^^^^^^^^^ help: consider adding missing annotations: `transmute::<Foo, i32>`
+
+error: transmute used without annotations
+  --> tests/ui/missing_transmute_annotations.rs:64:35
+   |
+LL |     let x: _ = unsafe { std::mem::transmute::<_, i32>([1u16, 2u16]) };
+   |                                   ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+
+error: transmute used without annotations
+  --> tests/ui/missing_transmute_annotations.rs:67:30
+   |
+LL |         let x: _ = std::mem::transmute::<_, i32>([1u16, 2u16]);
+   |                              ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+
+error: aborting due to 11 previous errors
+
diff --git a/tests/ui/mixed_attributes_style.rs b/tests/ui/mixed_attributes_style.rs
index 4f89aa8a5e5..1a646c26522 100644
--- a/tests/ui/mixed_attributes_style.rs
+++ b/tests/ui/mixed_attributes_style.rs
@@ -1,6 +1,12 @@
+//@aux-build:proc_macro_attr.rs
+//@compile-flags: --test --cfg dummy_cfg
+#![feature(custom_inner_attributes)]
 #![warn(clippy::mixed_attributes_style)]
 #![allow(clippy::duplicated_attributes)]
 
+#[macro_use]
+extern crate proc_macro_attr;
+
 #[allow(unused)] //~ ERROR: item has both inner and outer attributes
 fn foo1() {
     #![allow(unused)]
@@ -38,3 +44,57 @@ mod bar {
 fn main() {
     // test code goes here
 }
+
+// issue #12435
+#[cfg(test)]
+mod tests {
+    //! Module doc, don't lint
+}
+#[allow(unused)]
+mod baz {
+    //! Module doc, don't lint
+    const FOO: u8 = 0;
+}
+/// Module doc, don't lint
+mod quz {
+    #![allow(unused)]
+}
+
+mod issue_12530 {
+    // don't lint different attributes entirely
+    #[cfg(test)]
+    mod tests {
+        #![allow(clippy::unreadable_literal)]
+
+        #[allow(dead_code)] //~ ERROR: item has both inner and outer attributes
+        mod inner_mod {
+            #![allow(dead_code)]
+        }
+    }
+    #[cfg(dummy_cfg)]
+    mod another_mod {
+        #![allow(clippy::question_mark)]
+    }
+    /// Nested mod
+    mod nested_mod {
+        #[allow(dead_code)] //~ ERROR: item has both inner and outer attributes
+        mod inner_mod {
+            #![allow(dead_code)]
+        }
+    }
+    /// Nested mod //~ ERROR: item has both inner and outer attributes
+    #[allow(unused)]
+    mod nest_mod_2 {
+        #![allow(unused)]
+
+        #[allow(dead_code)] //~ ERROR: item has both inner and outer attributes
+        mod inner_mod {
+            #![allow(dead_code)]
+        }
+    }
+    // Different path symbols - Known FN
+    #[dummy]
+    fn use_dummy() {
+        #![proc_macro_attr::dummy]
+    }
+}
diff --git a/tests/ui/mixed_attributes_style.stderr b/tests/ui/mixed_attributes_style.stderr
index ed798073cb7..a1d3fc430f6 100644
--- a/tests/ui/mixed_attributes_style.stderr
+++ b/tests/ui/mixed_attributes_style.stderr
@@ -1,5 +1,5 @@
 error: item has both inner and outer attributes
-  --> tests/ui/mixed_attributes_style.rs:4:1
+  --> tests/ui/mixed_attributes_style.rs:10:1
    |
 LL | / #[allow(unused)]
 LL | | fn foo1() {
@@ -10,7 +10,7 @@ LL | |     #![allow(unused)]
    = help: to override `-D warnings` add `#[allow(clippy::mixed_attributes_style)]`
 
 error: item has both inner and outer attributes
-  --> tests/ui/mixed_attributes_style.rs:18:1
+  --> tests/ui/mixed_attributes_style.rs:24:1
    |
 LL | / /// linux
 LL | |
@@ -19,12 +19,45 @@ LL | |     //! windows
    | |_______________^
 
 error: item has both inner and outer attributes
-  --> tests/ui/mixed_attributes_style.rs:33:1
+  --> tests/ui/mixed_attributes_style.rs:39:1
    |
 LL | / #[allow(unused)]
 LL | | mod bar {
 LL | |     #![allow(unused)]
    | |_____________________^
 
-error: aborting due to 3 previous errors
+error: item has both inner and outer attributes
+  --> tests/ui/mixed_attributes_style.rs:69:9
+   |
+LL | /         #[allow(dead_code)]
+LL | |         mod inner_mod {
+LL | |             #![allow(dead_code)]
+   | |________________________________^
+
+error: item has both inner and outer attributes
+  --> tests/ui/mixed_attributes_style.rs:80:9
+   |
+LL | /         #[allow(dead_code)]
+LL | |         mod inner_mod {
+LL | |             #![allow(dead_code)]
+   | |________________________________^
+
+error: item has both inner and outer attributes
+  --> tests/ui/mixed_attributes_style.rs:85:5
+   |
+LL | /     /// Nested mod
+LL | |     #[allow(unused)]
+LL | |     mod nest_mod_2 {
+LL | |         #![allow(unused)]
+   | |_________________________^
+
+error: item has both inner and outer attributes
+  --> tests/ui/mixed_attributes_style.rs:90:9
+   |
+LL | /         #[allow(dead_code)]
+LL | |         mod inner_mod {
+LL | |             #![allow(dead_code)]
+   | |________________________________^
+
+error: aborting due to 7 previous errors
 
diff --git a/tests/ui/mixed_attributes_style/auxiliary/submodule.rs b/tests/ui/mixed_attributes_style/auxiliary/submodule.rs
new file mode 100644
index 00000000000..df44b07a694
--- /dev/null
+++ b/tests/ui/mixed_attributes_style/auxiliary/submodule.rs
@@ -0,0 +1,9 @@
+//! Module level doc
+
+#![allow(dead_code)]
+
+#[allow(unused)]
+//~^ ERROR: item has both inner and outer attributes
+mod foo {
+    #![allow(dead_code)]
+}
diff --git a/tests/ui/mixed_attributes_style/global_allow.rs b/tests/ui/mixed_attributes_style/global_allow.rs
new file mode 100644
index 00000000000..153262e6557
--- /dev/null
+++ b/tests/ui/mixed_attributes_style/global_allow.rs
@@ -0,0 +1,7 @@
+// issue 12436
+#![allow(clippy::mixed_attributes_style)]
+
+#[path = "auxiliary/submodule.rs"]
+mod submodule;
+
+fn main() {}
diff --git a/tests/ui/mixed_attributes_style/mod_declaration.rs b/tests/ui/mixed_attributes_style/mod_declaration.rs
new file mode 100644
index 00000000000..b0f1f0bda9e
--- /dev/null
+++ b/tests/ui/mixed_attributes_style/mod_declaration.rs
@@ -0,0 +1,3 @@
+#[path = "auxiliary/submodule.rs"] // don't lint.
+/// This doc comment should not lint, it could be used to add context to the original module doc
+mod submodule;
diff --git a/tests/ui/mixed_attributes_style/mod_declaration.stderr b/tests/ui/mixed_attributes_style/mod_declaration.stderr
new file mode 100644
index 00000000000..968c537c7e4
--- /dev/null
+++ b/tests/ui/mixed_attributes_style/mod_declaration.stderr
@@ -0,0 +1,14 @@
+error: item has both inner and outer attributes
+  --> tests/ui/mixed_attributes_style/auxiliary/submodule.rs:5:1
+   |
+LL | / #[allow(unused)]
+LL | |
+LL | | mod foo {
+LL | |     #![allow(dead_code)]
+   | |________________________^
+   |
+   = note: `-D clippy::mixed-attributes-style` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::mixed_attributes_style)]`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/ptr_cast_constness.fixed b/tests/ui/ptr_cast_constness.fixed
index c410a660dc4..33c0725faad 100644
--- a/tests/ui/ptr_cast_constness.fixed
+++ b/tests/ui/ptr_cast_constness.fixed
@@ -1,7 +1,12 @@
 //@aux-build:proc_macros.rs
 
 #![warn(clippy::ptr_cast_constness)]
-#![allow(clippy::transmute_ptr_to_ref, clippy::unnecessary_cast, unused)]
+#![allow(
+    clippy::transmute_ptr_to_ref,
+    clippy::unnecessary_cast,
+    unused,
+    clippy::missing_transmute_annotations
+)]
 
 extern crate proc_macros;
 use proc_macros::{external, inline_macros};
diff --git a/tests/ui/ptr_cast_constness.rs b/tests/ui/ptr_cast_constness.rs
index 6025b857b8f..24d959856db 100644
--- a/tests/ui/ptr_cast_constness.rs
+++ b/tests/ui/ptr_cast_constness.rs
@@ -1,7 +1,12 @@
 //@aux-build:proc_macros.rs
 
 #![warn(clippy::ptr_cast_constness)]
-#![allow(clippy::transmute_ptr_to_ref, clippy::unnecessary_cast, unused)]
+#![allow(
+    clippy::transmute_ptr_to_ref,
+    clippy::unnecessary_cast,
+    unused,
+    clippy::missing_transmute_annotations
+)]
 
 extern crate proc_macros;
 use proc_macros::{external, inline_macros};
diff --git a/tests/ui/ptr_cast_constness.stderr b/tests/ui/ptr_cast_constness.stderr
index 8e2bec527ff..322c3585e62 100644
--- a/tests/ui/ptr_cast_constness.stderr
+++ b/tests/ui/ptr_cast_constness.stderr
@@ -1,5 +1,5 @@
 error: `as` casting between raw pointers while changing only its constness
-  --> tests/ui/ptr_cast_constness.rs:10:41
+  --> tests/ui/ptr_cast_constness.rs:15:41
    |
 LL |     let _: &mut T = std::mem::transmute(p as *mut T);
    |                                         ^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `p.cast_mut()`
@@ -8,37 +8,37 @@ LL |     let _: &mut T = std::mem::transmute(p as *mut T);
    = help: to override `-D warnings` add `#[allow(clippy::ptr_cast_constness)]`
 
 error: `as` casting between raw pointers while changing only its constness
-  --> tests/ui/ptr_cast_constness.rs:11:19
+  --> tests/ui/ptr_cast_constness.rs:16:19
    |
 LL |     let _ = &mut *(p as *mut T);
    |                   ^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `p.cast_mut()`
 
 error: `as` casting between raw pointers while changing only its constness
-  --> tests/ui/ptr_cast_constness.rs:26:17
+  --> tests/ui/ptr_cast_constness.rs:31:17
    |
 LL |         let _ = *ptr_ptr as *mut u32;
    |                 ^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `(*ptr_ptr).cast_mut()`
 
 error: `as` casting between raw pointers while changing only its constness
-  --> tests/ui/ptr_cast_constness.rs:29:13
+  --> tests/ui/ptr_cast_constness.rs:34:13
    |
 LL |     let _ = ptr as *mut u32;
    |             ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()`
 
 error: `as` casting between raw pointers while changing only its constness
-  --> tests/ui/ptr_cast_constness.rs:30:13
+  --> tests/ui/ptr_cast_constness.rs:35:13
    |
 LL |     let _ = mut_ptr as *const u32;
    |             ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()`
 
 error: `as` casting between raw pointers while changing only its constness
-  --> tests/ui/ptr_cast_constness.rs:59:13
+  --> tests/ui/ptr_cast_constness.rs:64:13
    |
 LL |     let _ = ptr as *mut u32;
    |             ^^^^^^^^^^^^^^^ help: try `pointer::cast_mut`, a safer alternative: `ptr.cast_mut()`
 
 error: `as` casting between raw pointers while changing only its constness
-  --> tests/ui/ptr_cast_constness.rs:60:13
+  --> tests/ui/ptr_cast_constness.rs:65:13
    |
 LL |     let _ = mut_ptr as *const u32;
    |             ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()`
diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed
index 567472a8af2..679388372e6 100644
--- a/tests/ui/question_mark.fixed
+++ b/tests/ui/question_mark.fixed
@@ -283,3 +283,37 @@ fn issue12337() -> Option<i32> {
     };
     Some(42)
 }
+
+fn issue11983(option: &Option<String>) -> Option<()> {
+    // Don't lint, `&Option` dose not impl `Try`.
+    let Some(v) = option else { return None };
+
+    let opt = Some(String::new());
+    // Don't lint, `branch` method in `Try` takes ownership of `opt`,
+    // and `(&opt)?` also doesn't work since it's `&Option`.
+    let Some(v) = &opt else { return None };
+    let mov = opt;
+
+    Some(())
+}
+
+struct Foo {
+    owned: Option<String>,
+}
+struct Bar {
+    foo: Foo,
+}
+#[allow(clippy::disallowed_names)]
+fn issue12412(foo: &Foo, bar: &Bar) -> Option<()> {
+    // Don't lint, `owned` is behind a shared reference.
+    let Some(v) = &foo.owned else {
+        return None;
+    };
+    // Don't lint, `owned` is behind a shared reference.
+    let Some(v) = &bar.foo.owned else {
+        return None;
+    };
+    // lint
+    let v = bar.foo.owned.clone()?;
+    Some(())
+}
diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs
index abf8c270de8..601ab78bf5a 100644
--- a/tests/ui/question_mark.rs
+++ b/tests/ui/question_mark.rs
@@ -323,3 +323,39 @@ fn issue12337() -> Option<i32> {
     };
     Some(42)
 }
+
+fn issue11983(option: &Option<String>) -> Option<()> {
+    // Don't lint, `&Option` dose not impl `Try`.
+    let Some(v) = option else { return None };
+
+    let opt = Some(String::new());
+    // Don't lint, `branch` method in `Try` takes ownership of `opt`,
+    // and `(&opt)?` also doesn't work since it's `&Option`.
+    let Some(v) = &opt else { return None };
+    let mov = opt;
+
+    Some(())
+}
+
+struct Foo {
+    owned: Option<String>,
+}
+struct Bar {
+    foo: Foo,
+}
+#[allow(clippy::disallowed_names)]
+fn issue12412(foo: &Foo, bar: &Bar) -> Option<()> {
+    // Don't lint, `owned` is behind a shared reference.
+    let Some(v) = &foo.owned else {
+        return None;
+    };
+    // Don't lint, `owned` is behind a shared reference.
+    let Some(v) = &bar.foo.owned else {
+        return None;
+    };
+    // lint
+    let Some(v) = bar.foo.owned.clone() else {
+        return None;
+    };
+    Some(())
+}
diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr
index 4fcccdf5512..5f26a7ea2c3 100644
--- a/tests/ui/question_mark.stderr
+++ b/tests/ui/question_mark.stderr
@@ -141,5 +141,13 @@ LL | |                 // https://github.com/rust-lang/rust-clippy/pull/11001#is
 LL | |             }
    | |_____________^ help: replace it with: `a?;`
 
-error: aborting due to 16 previous errors
+error: this `let...else` may be rewritten with the `?` operator
+  --> tests/ui/question_mark.rs:357:5
+   |
+LL | /     let Some(v) = bar.foo.owned.clone() else {
+LL | |         return None;
+LL | |     };
+   | |______^ help: replace it with: `let v = bar.foo.owned.clone()?;`
+
+error: aborting due to 17 previous errors
 
diff --git a/tests/ui/suspicious_arithmetic_impl.rs b/tests/ui/suspicious_arithmetic_impl.rs
index 1bd4cd5fb50..07280351e76 100644
--- a/tests/ui/suspicious_arithmetic_impl.rs
+++ b/tests/ui/suspicious_arithmetic_impl.rs
@@ -1,3 +1,4 @@
+#![allow(clippy::legacy_numeric_constants)]
 #![warn(clippy::suspicious_arithmetic_impl)]
 use std::ops::{
     Add, AddAssign, BitAnd, BitOr, BitOrAssign, BitXor, Div, DivAssign, Mul, MulAssign, Rem, Shl, Shr, Sub,
diff --git a/tests/ui/suspicious_arithmetic_impl.stderr b/tests/ui/suspicious_arithmetic_impl.stderr
index 193cd64149b..1bfca49a635 100644
--- a/tests/ui/suspicious_arithmetic_impl.stderr
+++ b/tests/ui/suspicious_arithmetic_impl.stderr
@@ -1,5 +1,5 @@
 error: suspicious use of `-` in `Add` impl
-  --> tests/ui/suspicious_arithmetic_impl.rs:13:20
+  --> tests/ui/suspicious_arithmetic_impl.rs:14:20
    |
 LL |         Foo(self.0 - other.0)
    |                    ^
@@ -8,7 +8,7 @@ LL |         Foo(self.0 - other.0)
    = help: to override `-D warnings` add `#[allow(clippy::suspicious_arithmetic_impl)]`
 
 error: suspicious use of `-` in `AddAssign` impl
-  --> tests/ui/suspicious_arithmetic_impl.rs:21:23
+  --> tests/ui/suspicious_arithmetic_impl.rs:22:23
    |
 LL |         *self = *self - other;
    |                       ^
@@ -17,43 +17,43 @@ LL |         *self = *self - other;
    = help: to override `-D warnings` add `#[allow(clippy::suspicious_op_assign_impl)]`
 
 error: suspicious use of `/` in `MulAssign` impl
-  --> tests/ui/suspicious_arithmetic_impl.rs:36:16
+  --> tests/ui/suspicious_arithmetic_impl.rs:37:16
    |
 LL |         self.0 /= other.0;
    |                ^^
 
 error: suspicious use of `/` in `Rem` impl
-  --> tests/ui/suspicious_arithmetic_impl.rs:75:20
+  --> tests/ui/suspicious_arithmetic_impl.rs:76:20
    |
 LL |         Foo(self.0 / other.0)
    |                    ^
 
 error: suspicious use of `|` in `BitAnd` impl
-  --> tests/ui/suspicious_arithmetic_impl.rs:84:20
+  --> tests/ui/suspicious_arithmetic_impl.rs:85:20
    |
 LL |         Foo(self.0 | other.0)
    |                    ^
 
 error: suspicious use of `^` in `BitOr` impl
-  --> tests/ui/suspicious_arithmetic_impl.rs:93:20
+  --> tests/ui/suspicious_arithmetic_impl.rs:94:20
    |
 LL |         Foo(self.0 ^ other.0)
    |                    ^
 
 error: suspicious use of `&` in `BitXor` impl
-  --> tests/ui/suspicious_arithmetic_impl.rs:102:20
+  --> tests/ui/suspicious_arithmetic_impl.rs:103:20
    |
 LL |         Foo(self.0 & other.0)
    |                    ^
 
 error: suspicious use of `>>` in `Shl` impl
-  --> tests/ui/suspicious_arithmetic_impl.rs:111:20
+  --> tests/ui/suspicious_arithmetic_impl.rs:112:20
    |
 LL |         Foo(self.0 >> other.0)
    |                    ^^
 
 error: suspicious use of `<<` in `Shr` impl
-  --> tests/ui/suspicious_arithmetic_impl.rs:120:20
+  --> tests/ui/suspicious_arithmetic_impl.rs:121:20
    |
 LL |         Foo(self.0 << other.0)
    |                    ^^
diff --git a/tests/ui/suspicious_else_formatting.rs b/tests/ui/suspicious_else_formatting.rs
index c0856427eae..3d5c892eb60 100644
--- a/tests/ui/suspicious_else_formatting.rs
+++ b/tests/ui/suspicious_else_formatting.rs
@@ -120,6 +120,34 @@ fn main() {
     /* whelp */
     {
     }
+
+    // #12497 Don't trigger lint as rustfmt wants it
+    if true {
+        println!("true");
+    }
+    /*else if false {
+}*/
+    else {
+        println!("false");
+    }
+
+    if true {
+        println!("true");
+    } // else if false {}
+    else {
+        println!("false");
+    }
+
+    if true {
+        println!("true");
+    } /* if true {
+        println!("true");
+}
+    */
+    else {
+        println!("false");
+    }
+
 }
 
 // #7650 - Don't lint. Proc-macro using bad spans for `if` expressions.
diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs
index 1796ccaf28e..be6e071767d 100644
--- a/tests/ui/transmute.rs
+++ b/tests/ui/transmute.rs
@@ -1,4 +1,9 @@
-#![allow(dead_code, clippy::borrow_as_ptr, clippy::needless_lifetimes)]
+#![allow(
+    dead_code,
+    clippy::borrow_as_ptr,
+    clippy::needless_lifetimes,
+    clippy::missing_transmute_annotations
+)]
 //@no-rustfix
 extern crate core;
 
diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr
index 3ed6cb2b3f9..375e8f19dd6 100644
--- a/tests/ui/transmute.stderr
+++ b/tests/ui/transmute.stderr
@@ -1,5 +1,5 @@
 error: transmute from a reference to a pointer
-  --> tests/ui/transmute.rs:24:23
+  --> tests/ui/transmute.rs:29:23
    |
 LL |     let _: *const T = core::intrinsics::transmute(t);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T`
@@ -8,61 +8,61 @@ LL |     let _: *const T = core::intrinsics::transmute(t);
    = help: to override `-D warnings` add `#[allow(clippy::useless_transmute)]`
 
 error: transmute from a reference to a pointer
-  --> tests/ui/transmute.rs:28:21
+  --> tests/ui/transmute.rs:33:21
    |
 LL |     let _: *mut T = core::intrinsics::transmute(t);
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T`
 
 error: transmute from a reference to a pointer
-  --> tests/ui/transmute.rs:31:23
+  --> tests/ui/transmute.rs:36:23
    |
 LL |     let _: *const U = core::intrinsics::transmute(t);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U`
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:38:27
+  --> tests/ui/transmute.rs:43:27
    |
 LL |         let _: Vec<i32> = core::intrinsics::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:41:27
+  --> tests/ui/transmute.rs:46:27
    |
 LL |         let _: Vec<i32> = core::mem::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:44:27
+  --> tests/ui/transmute.rs:49:27
    |
 LL |         let _: Vec<i32> = std::intrinsics::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:47:27
+  --> tests/ui/transmute.rs:52:27
    |
 LL |         let _: Vec<i32> = std::mem::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:50:27
+  --> tests/ui/transmute.rs:55:27
    |
 LL |         let _: Vec<i32> = my_transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from an integer to a pointer
-  --> tests/ui/transmute.rs:53:31
+  --> tests/ui/transmute.rs:58:31
    |
 LL |         let _: *const usize = std::mem::transmute(5_isize);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize`
 
 error: transmute from an integer to a pointer
-  --> tests/ui/transmute.rs:58:31
+  --> tests/ui/transmute.rs:63:31
    |
 LL |         let _: *const usize = std::mem::transmute(1 + 1usize);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize`
 
 error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`)
-  --> tests/ui/transmute.rs:90:24
+  --> tests/ui/transmute.rs:95:24
    |
 LL |         let _: Usize = core::intrinsics::transmute(int_const_ptr);
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,25 +71,25 @@ LL |         let _: Usize = core::intrinsics::transmute(int_const_ptr);
    = help: to override `-D warnings` add `#[allow(clippy::crosspointer_transmute)]`
 
 error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`)
-  --> tests/ui/transmute.rs:94:24
+  --> tests/ui/transmute.rs:99:24
    |
 LL |         let _: Usize = core::intrinsics::transmute(int_mut_ptr);
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`)
-  --> tests/ui/transmute.rs:97:31
+  --> tests/ui/transmute.rs:102:31
    |
 LL |         let _: *const Usize = core::intrinsics::transmute(my_int());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`)
-  --> tests/ui/transmute.rs:100:29
+  --> tests/ui/transmute.rs:105:29
    |
 LL |         let _: *mut Usize = core::intrinsics::transmute(my_int());
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a `u8` to a `bool`
-  --> tests/ui/transmute.rs:107:28
+  --> tests/ui/transmute.rs:112:28
    |
 LL |     let _: bool = unsafe { std::mem::transmute(0_u8) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0`
@@ -98,7 +98,7 @@ LL |     let _: bool = unsafe { std::mem::transmute(0_u8) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_bool)]`
 
 error: transmute from a `u32` to a `f32`
-  --> tests/ui/transmute.rs:115:31
+  --> tests/ui/transmute.rs:120:31
    |
 LL |         let _: f32 = unsafe { std::mem::transmute(0_u32) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)`
@@ -107,25 +107,25 @@ LL |         let _: f32 = unsafe { std::mem::transmute(0_u32) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_float)]`
 
 error: transmute from a `i32` to a `f32`
-  --> tests/ui/transmute.rs:118:31
+  --> tests/ui/transmute.rs:123:31
    |
 LL |         let _: f32 = unsafe { std::mem::transmute(0_i32) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)`
 
 error: transmute from a `u64` to a `f64`
-  --> tests/ui/transmute.rs:120:31
+  --> tests/ui/transmute.rs:125:31
    |
 LL |         let _: f64 = unsafe { std::mem::transmute(0_u64) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_u64)`
 
 error: transmute from a `i64` to a `f64`
-  --> tests/ui/transmute.rs:122:31
+  --> tests/ui/transmute.rs:127:31
    |
 LL |         let _: f64 = unsafe { std::mem::transmute(0_i64) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)`
 
 error: transmute from a `u8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:143:30
+  --> tests/ui/transmute.rs:148:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0u8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()`
@@ -134,85 +134,85 @@ LL |             let _: [u8; 1] = std::mem::transmute(0u8);
    = help: to override `-D warnings` add `#[allow(clippy::transmute_num_to_bytes)]`
 
 error: transmute from a `u32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:146:30
+  --> tests/ui/transmute.rs:151:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0u32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()`
 
 error: transmute from a `u128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:148:31
+  --> tests/ui/transmute.rs:153:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0u128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()`
 
 error: transmute from a `i8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:150:30
+  --> tests/ui/transmute.rs:155:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0i8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()`
 
 error: transmute from a `i32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:152:30
+  --> tests/ui/transmute.rs:157:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0i32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()`
 
 error: transmute from a `i128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:154:31
+  --> tests/ui/transmute.rs:159:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0i128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()`
 
 error: transmute from a `f32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:156:30
+  --> tests/ui/transmute.rs:161:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0.0f32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()`
 
 error: transmute from a `f64` to a `[u8; 8]`
-  --> tests/ui/transmute.rs:158:30
+  --> tests/ui/transmute.rs:163:30
    |
 LL |             let _: [u8; 8] = std::mem::transmute(0.0f64);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()`
 
 error: transmute from a `u8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:164:30
+  --> tests/ui/transmute.rs:169:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0u8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()`
 
 error: transmute from a `u32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:166:30
+  --> tests/ui/transmute.rs:171:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0u32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()`
 
 error: transmute from a `u128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:168:31
+  --> tests/ui/transmute.rs:173:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0u128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()`
 
 error: transmute from a `i8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:170:30
+  --> tests/ui/transmute.rs:175:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0i8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()`
 
 error: transmute from a `i32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:172:30
+  --> tests/ui/transmute.rs:177:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0i32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()`
 
 error: transmute from a `i128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:174:31
+  --> tests/ui/transmute.rs:179:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0i128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()`
 
 error: transmute from a `&[u8]` to a `&str`
-  --> tests/ui/transmute.rs:185:28
+  --> tests/ui/transmute.rs:190:28
    |
 LL |     let _: &str = unsafe { std::mem::transmute(B) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()`
@@ -221,13 +221,13 @@ LL |     let _: &str = unsafe { std::mem::transmute(B) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_bytes_to_str)]`
 
 error: transmute from a `&mut [u8]` to a `&mut str`
-  --> tests/ui/transmute.rs:188:32
+  --> tests/ui/transmute.rs:193:32
    |
 LL |     let _: &mut str = unsafe { std::mem::transmute(mb) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()`
 
 error: transmute from a `&[u8]` to a `&str`
-  --> tests/ui/transmute.rs:190:30
+  --> tests/ui/transmute.rs:195:30
    |
 LL |     const _: &str = unsafe { std::mem::transmute(B) };
    |                              ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)`
diff --git a/tests/ui/transmute_collection.rs b/tests/ui/transmute_collection.rs
index 8bf45457335..e30b34a5d7d 100644
--- a/tests/ui/transmute_collection.rs
+++ b/tests/ui/transmute_collection.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::unsound_collection_transmute)]
+#![allow(clippy::missing_transmute_annotations)]
 
 use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
 use std::mem::{transmute, MaybeUninit};
diff --git a/tests/ui/transmute_collection.stderr b/tests/ui/transmute_collection.stderr
index f71fba6315c..06db9321064 100644
--- a/tests/ui/transmute_collection.stderr
+++ b/tests/ui/transmute_collection.stderr
@@ -1,5 +1,5 @@
 error: transmute from `std::vec::Vec<u8>` to `std::vec::Vec<u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:9:17
+  --> tests/ui/transmute_collection.rs:10:17
    |
 LL |         let _ = transmute::<_, Vec<u32>>(vec![0u8]);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,103 +8,103 @@ LL |         let _ = transmute::<_, Vec<u32>>(vec![0u8]);
    = help: to override `-D warnings` add `#[allow(clippy::unsound_collection_transmute)]`
 
 error: transmute from `std::vec::Vec<u32>` to `std::vec::Vec<[u8; 4]>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:13:17
+  --> tests/ui/transmute_collection.rs:14:17
    |
 LL |         let _ = transmute::<_, Vec<[u8; 4]>>(vec![1234u32]);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `std::collections::VecDeque<u8>` to `std::collections::VecDeque<u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:17:17
+  --> tests/ui/transmute_collection.rs:18:17
    |
 LL |         let _ = transmute::<_, VecDeque<u32>>(VecDeque::<u8>::new());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `std::collections::VecDeque<[u8; 4]>` to `std::collections::VecDeque<u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:20:17
+  --> tests/ui/transmute_collection.rs:21:17
    |
 LL |         let _ = transmute::<_, VecDeque<u32>>(VecDeque::<[u8; 4]>::new());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `std::collections::BinaryHeap<u8>` to `std::collections::BinaryHeap<u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:24:17
+  --> tests/ui/transmute_collection.rs:25:17
    |
 LL |         let _ = transmute::<_, BinaryHeap<u32>>(BinaryHeap::<u8>::new());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `std::collections::BinaryHeap<[u8; 4]>` to `std::collections::BinaryHeap<u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:27:17
+  --> tests/ui/transmute_collection.rs:28:17
    |
 LL |         let _ = transmute::<_, BinaryHeap<u32>>(BinaryHeap::<[u8; 4]>::new());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `std::collections::BTreeSet<u8>` to `std::collections::BTreeSet<u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:31:17
+  --> tests/ui/transmute_collection.rs:32:17
    |
 LL |         let _ = transmute::<_, BTreeSet<u32>>(BTreeSet::<u8>::new());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `std::collections::BTreeSet<[u8; 4]>` to `std::collections::BTreeSet<u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:34:17
+  --> tests/ui/transmute_collection.rs:35:17
    |
 LL |         let _ = transmute::<_, BTreeSet<u32>>(BTreeSet::<[u8; 4]>::new());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `std::collections::HashSet<u8>` to `std::collections::HashSet<u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:38:17
+  --> tests/ui/transmute_collection.rs:39:17
    |
 LL |         let _ = transmute::<_, HashSet<u32>>(HashSet::<u8>::new());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `std::collections::HashSet<[u8; 4]>` to `std::collections::HashSet<u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:41:17
+  --> tests/ui/transmute_collection.rs:42:17
    |
 LL |         let _ = transmute::<_, HashSet<u32>>(HashSet::<[u8; 4]>::new());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `std::collections::BTreeMap<u8, u8>` to `std::collections::BTreeMap<u8, u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:45:17
+  --> tests/ui/transmute_collection.rs:46:17
    |
 LL |         let _ = transmute::<_, BTreeMap<u8, u32>>(BTreeMap::<u8, u8>::new());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `std::collections::BTreeMap<u32, u32>` to `std::collections::BTreeMap<u8, u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:47:17
+  --> tests/ui/transmute_collection.rs:48:17
    |
 LL |         let _ = transmute::<_, BTreeMap<u8, u32>>(BTreeMap::<u32, u32>::new());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `std::collections::BTreeMap<u8, [u8; 4]>` to `std::collections::BTreeMap<u8, u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:50:17
+  --> tests/ui/transmute_collection.rs:51:17
    |
 LL |         let _ = transmute::<_, BTreeMap<u8, u32>>(BTreeMap::<u8, [u8; 4]>::new());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `std::collections::BTreeMap<[u8; 4], u32>` to `std::collections::BTreeMap<u32, u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:52:17
+  --> tests/ui/transmute_collection.rs:53:17
    |
 LL |         let _ = transmute::<_, BTreeMap<u32, u32>>(BTreeMap::<[u8; 4], u32>::new());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `std::collections::HashMap<u8, u8>` to `std::collections::HashMap<u8, u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:56:17
+  --> tests/ui/transmute_collection.rs:57:17
    |
 LL |         let _ = transmute::<_, HashMap<u8, u32>>(HashMap::<u8, u8>::new());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `std::collections::HashMap<u32, u32>` to `std::collections::HashMap<u8, u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:58:17
+  --> tests/ui/transmute_collection.rs:59:17
    |
 LL |         let _ = transmute::<_, HashMap<u8, u32>>(HashMap::<u32, u32>::new());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `std::collections::HashMap<u8, [u8; 4]>` to `std::collections::HashMap<u8, u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:61:17
+  --> tests/ui/transmute_collection.rs:62:17
    |
 LL |         let _ = transmute::<_, HashMap<u8, u32>>(HashMap::<u8, [u8; 4]>::new());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `std::collections::HashMap<[u8; 4], u32>` to `std::collections::HashMap<u32, u32>` with mismatched layout is unsound
-  --> tests/ui/transmute_collection.rs:63:17
+  --> tests/ui/transmute_collection.rs:64:17
    |
 LL |         let _ = transmute::<_, HashMap<u32, u32>>(HashMap::<[u8; 4], u32>::new());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/transmute_float_to_int.fixed b/tests/ui/transmute_float_to_int.fixed
index cef0bcfa623..82d5f7fdca1 100644
--- a/tests/ui/transmute_float_to_int.fixed
+++ b/tests/ui/transmute_float_to_int.fixed
@@ -1,4 +1,5 @@
 #![warn(clippy::transmute_float_to_int)]
+#![allow(clippy::missing_transmute_annotations)]
 
 fn float_to_int() {
     let _: u32 = unsafe { 1f32.to_bits() };
diff --git a/tests/ui/transmute_float_to_int.rs b/tests/ui/transmute_float_to_int.rs
index 3d95bec2a20..9f056330adf 100644
--- a/tests/ui/transmute_float_to_int.rs
+++ b/tests/ui/transmute_float_to_int.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::transmute_float_to_int)]
+#![allow(clippy::missing_transmute_annotations)]
 
 fn float_to_int() {
     let _: u32 = unsafe { std::mem::transmute(1f32) };
diff --git a/tests/ui/transmute_float_to_int.stderr b/tests/ui/transmute_float_to_int.stderr
index e89258d9102..ac3aae5f8b7 100644
--- a/tests/ui/transmute_float_to_int.stderr
+++ b/tests/ui/transmute_float_to_int.stderr
@@ -1,5 +1,5 @@
 error: transmute from a `f32` to a `u32`
-  --> tests/ui/transmute_float_to_int.rs:4:27
+  --> tests/ui/transmute_float_to_int.rs:5:27
    |
 LL |     let _: u32 = unsafe { std::mem::transmute(1f32) };
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits()`
@@ -8,31 +8,31 @@ LL |     let _: u32 = unsafe { std::mem::transmute(1f32) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_float_to_int)]`
 
 error: transmute from a `f32` to a `i32`
-  --> tests/ui/transmute_float_to_int.rs:7:27
+  --> tests/ui/transmute_float_to_int.rs:8:27
    |
 LL |     let _: i32 = unsafe { std::mem::transmute(1f32) };
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits() as i32`
 
 error: transmute from a `f64` to a `u64`
-  --> tests/ui/transmute_float_to_int.rs:9:27
+  --> tests/ui/transmute_float_to_int.rs:10:27
    |
 LL |     let _: u64 = unsafe { std::mem::transmute(1f64) };
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits()`
 
 error: transmute from a `f64` to a `i64`
-  --> tests/ui/transmute_float_to_int.rs:11:27
+  --> tests/ui/transmute_float_to_int.rs:12:27
    |
 LL |     let _: i64 = unsafe { std::mem::transmute(1f64) };
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits() as i64`
 
 error: transmute from a `f64` to a `u64`
-  --> tests/ui/transmute_float_to_int.rs:13:27
+  --> tests/ui/transmute_float_to_int.rs:14:27
    |
 LL |     let _: u64 = unsafe { std::mem::transmute(1.0) };
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1.0f64.to_bits()`
 
 error: transmute from a `f64` to a `u64`
-  --> tests/ui/transmute_float_to_int.rs:15:27
+  --> tests/ui/transmute_float_to_int.rs:16:27
    |
 LL |     let _: u64 = unsafe { std::mem::transmute(-1.0) };
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-1.0f64).to_bits()`
diff --git a/tests/ui/transmute_int_to_char.fixed b/tests/ui/transmute_int_to_char.fixed
index 17080118175..d3277d1b8c7 100644
--- a/tests/ui/transmute_int_to_char.fixed
+++ b/tests/ui/transmute_int_to_char.fixed
@@ -1,4 +1,5 @@
 #![warn(clippy::transmute_int_to_char)]
+#![allow(clippy::missing_transmute_annotations)]
 
 fn int_to_char() {
     let _: char = unsafe { std::char::from_u32(0_u32).unwrap() };
diff --git a/tests/ui/transmute_int_to_char.rs b/tests/ui/transmute_int_to_char.rs
index 5846a97e88a..d21c4fd6fea 100644
--- a/tests/ui/transmute_int_to_char.rs
+++ b/tests/ui/transmute_int_to_char.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::transmute_int_to_char)]
+#![allow(clippy::missing_transmute_annotations)]
 
 fn int_to_char() {
     let _: char = unsafe { std::mem::transmute(0_u32) };
diff --git a/tests/ui/transmute_int_to_char.stderr b/tests/ui/transmute_int_to_char.stderr
index 8444afbd21e..e3a3620f28b 100644
--- a/tests/ui/transmute_int_to_char.stderr
+++ b/tests/ui/transmute_int_to_char.stderr
@@ -1,5 +1,5 @@
 error: transmute from a `u32` to a `char`
-  --> tests/ui/transmute_int_to_char.rs:4:28
+  --> tests/ui/transmute_int_to_char.rs:5:28
    |
 LL |     let _: char = unsafe { std::mem::transmute(0_u32) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()`
@@ -8,7 +8,7 @@ LL |     let _: char = unsafe { std::mem::transmute(0_u32) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_char)]`
 
 error: transmute from a `i32` to a `char`
-  --> tests/ui/transmute_int_to_char.rs:7:28
+  --> tests/ui/transmute_int_to_char.rs:8:28
    |
 LL |     let _: char = unsafe { std::mem::transmute(0_i32) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()`
diff --git a/tests/ui/transmute_int_to_char_no_std.fixed b/tests/ui/transmute_int_to_char_no_std.fixed
index 9ae4e11fb56..32a57645b46 100644
--- a/tests/ui/transmute_int_to_char_no_std.fixed
+++ b/tests/ui/transmute_int_to_char_no_std.fixed
@@ -1,6 +1,7 @@
 #![no_std]
 #![feature(lang_items)]
 #![warn(clippy::transmute_int_to_char)]
+#![allow(clippy::missing_transmute_annotations)]
 
 use core::panic::PanicInfo;
 
diff --git a/tests/ui/transmute_int_to_char_no_std.rs b/tests/ui/transmute_int_to_char_no_std.rs
index 9a2afd5bd2f..942794c32f8 100644
--- a/tests/ui/transmute_int_to_char_no_std.rs
+++ b/tests/ui/transmute_int_to_char_no_std.rs
@@ -1,6 +1,7 @@
 #![no_std]
 #![feature(lang_items)]
 #![warn(clippy::transmute_int_to_char)]
+#![allow(clippy::missing_transmute_annotations)]
 
 use core::panic::PanicInfo;
 
diff --git a/tests/ui/transmute_int_to_char_no_std.stderr b/tests/ui/transmute_int_to_char_no_std.stderr
index d2c3842b684..d94580a84d7 100644
--- a/tests/ui/transmute_int_to_char_no_std.stderr
+++ b/tests/ui/transmute_int_to_char_no_std.stderr
@@ -1,5 +1,5 @@
 error: transmute from a `u32` to a `char`
-  --> tests/ui/transmute_int_to_char_no_std.rs:16:28
+  --> tests/ui/transmute_int_to_char_no_std.rs:17:28
    |
 LL |     let _: char = unsafe { core::mem::transmute(0_u32) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::char::from_u32(0_u32).unwrap()`
@@ -8,7 +8,7 @@ LL |     let _: char = unsafe { core::mem::transmute(0_u32) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_char)]`
 
 error: transmute from a `i32` to a `char`
-  --> tests/ui/transmute_int_to_char_no_std.rs:19:28
+  --> tests/ui/transmute_int_to_char_no_std.rs:20:28
    |
 LL |     let _: char = unsafe { core::mem::transmute(0_i32) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::char::from_u32(0_i32 as u32).unwrap()`
diff --git a/tests/ui/transmute_int_to_non_zero.fixed b/tests/ui/transmute_int_to_non_zero.fixed
index 866c0bbf127..fe8db3dcb0c 100644
--- a/tests/ui/transmute_int_to_non_zero.fixed
+++ b/tests/ui/transmute_int_to_non_zero.fixed
@@ -1,4 +1,5 @@
 #![warn(clippy::transmute_int_to_non_zero)]
+#![allow(clippy::missing_transmute_annotations)]
 
 use core::num::*;
 
diff --git a/tests/ui/transmute_int_to_non_zero.rs b/tests/ui/transmute_int_to_non_zero.rs
index 803c4945c75..a79ed5279b1 100644
--- a/tests/ui/transmute_int_to_non_zero.rs
+++ b/tests/ui/transmute_int_to_non_zero.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::transmute_int_to_non_zero)]
+#![allow(clippy::missing_transmute_annotations)]
 
 use core::num::*;
 
diff --git a/tests/ui/transmute_int_to_non_zero.stderr b/tests/ui/transmute_int_to_non_zero.stderr
index dd37bd21055..bb0b0d0ff4f 100644
--- a/tests/ui/transmute_int_to_non_zero.stderr
+++ b/tests/ui/transmute_int_to_non_zero.stderr
@@ -1,5 +1,5 @@
 error: transmute from a `u8` to a `NonZeroU8`
-  --> tests/ui/transmute_int_to_non_zero.rs:18:33
+  --> tests/ui/transmute_int_to_non_zero.rs:19:33
    |
 LL |     let _: NonZeroU8 = unsafe { std::mem::transmute(int_u8) };
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU8::new_unchecked(int_u8)`
@@ -8,55 +8,55 @@ LL |     let _: NonZeroU8 = unsafe { std::mem::transmute(int_u8) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_non_zero)]`
 
 error: transmute from a `u16` to a `NonZeroU16`
-  --> tests/ui/transmute_int_to_non_zero.rs:21:34
+  --> tests/ui/transmute_int_to_non_zero.rs:22:34
    |
 LL |     let _: NonZeroU16 = unsafe { std::mem::transmute(int_u16) };
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU16::new_unchecked(int_u16)`
 
 error: transmute from a `u32` to a `NonZeroU32`
-  --> tests/ui/transmute_int_to_non_zero.rs:23:34
+  --> tests/ui/transmute_int_to_non_zero.rs:24:34
    |
 LL |     let _: NonZeroU32 = unsafe { std::mem::transmute(int_u32) };
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU32::new_unchecked(int_u32)`
 
 error: transmute from a `u64` to a `NonZeroU64`
-  --> tests/ui/transmute_int_to_non_zero.rs:25:34
+  --> tests/ui/transmute_int_to_non_zero.rs:26:34
    |
 LL |     let _: NonZeroU64 = unsafe { std::mem::transmute(int_u64) };
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU64::new_unchecked(int_u64)`
 
 error: transmute from a `u128` to a `NonZeroU128`
-  --> tests/ui/transmute_int_to_non_zero.rs:27:35
+  --> tests/ui/transmute_int_to_non_zero.rs:28:35
    |
 LL |     let _: NonZeroU128 = unsafe { std::mem::transmute(int_u128) };
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU128::new_unchecked(int_u128)`
 
 error: transmute from a `i8` to a `NonZeroI8`
-  --> tests/ui/transmute_int_to_non_zero.rs:30:33
+  --> tests/ui/transmute_int_to_non_zero.rs:31:33
    |
 LL |     let _: NonZeroI8 = unsafe { std::mem::transmute(int_i8) };
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI8::new_unchecked(int_i8)`
 
 error: transmute from a `i16` to a `NonZeroI16`
-  --> tests/ui/transmute_int_to_non_zero.rs:32:34
+  --> tests/ui/transmute_int_to_non_zero.rs:33:34
    |
 LL |     let _: NonZeroI16 = unsafe { std::mem::transmute(int_i16) };
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI16::new_unchecked(int_i16)`
 
 error: transmute from a `i32` to a `NonZeroI32`
-  --> tests/ui/transmute_int_to_non_zero.rs:34:34
+  --> tests/ui/transmute_int_to_non_zero.rs:35:34
    |
 LL |     let _: NonZeroI32 = unsafe { std::mem::transmute(int_i32) };
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI32::new_unchecked(int_i32)`
 
 error: transmute from a `i64` to a `NonZeroI64`
-  --> tests/ui/transmute_int_to_non_zero.rs:36:34
+  --> tests/ui/transmute_int_to_non_zero.rs:37:34
    |
 LL |     let _: NonZeroI64 = unsafe { std::mem::transmute(int_i64) };
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI64::new_unchecked(int_i64)`
 
 error: transmute from a `i128` to a `NonZeroI128`
-  --> tests/ui/transmute_int_to_non_zero.rs:38:35
+  --> tests/ui/transmute_int_to_non_zero.rs:39:35
    |
 LL |     let _: NonZeroI128 = unsafe { std::mem::transmute(int_i128) };
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI128::new_unchecked(int_i128)`
diff --git a/tests/ui/transmute_null_to_fn.rs b/tests/ui/transmute_null_to_fn.rs
index b07851e864f..c0196ad52d4 100644
--- a/tests/ui/transmute_null_to_fn.rs
+++ b/tests/ui/transmute_null_to_fn.rs
@@ -1,6 +1,6 @@
 #![allow(dead_code)]
 #![warn(clippy::transmute_null_to_fn)]
-#![allow(clippy::zero_ptr)]
+#![allow(clippy::zero_ptr, clippy::missing_transmute_annotations)]
 
 // Easy to lint because these only span one line.
 fn one_liners() {
diff --git a/tests/ui/transmute_ptr_to_ptr.fixed b/tests/ui/transmute_ptr_to_ptr.fixed
index 696def08f14..b696a574ae3 100644
--- a/tests/ui/transmute_ptr_to_ptr.fixed
+++ b/tests/ui/transmute_ptr_to_ptr.fixed
@@ -1,5 +1,5 @@
 #![warn(clippy::transmute_ptr_to_ptr)]
-#![allow(clippy::borrow_as_ptr)]
+#![allow(clippy::borrow_as_ptr, clippy::missing_transmute_annotations)]
 
 // Make sure we can modify lifetimes, which is one of the recommended uses
 // of transmute
diff --git a/tests/ui/transmute_ptr_to_ptr.rs b/tests/ui/transmute_ptr_to_ptr.rs
index 0700d8c1957..85cc1d7802c 100644
--- a/tests/ui/transmute_ptr_to_ptr.rs
+++ b/tests/ui/transmute_ptr_to_ptr.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::transmute_ptr_to_ptr)]
-#![allow(clippy::borrow_as_ptr)]
+#![allow(clippy::borrow_as_ptr, clippy::missing_transmute_annotations)]
 
 // Make sure we can modify lifetimes, which is one of the recommended uses
 // of transmute
diff --git a/tests/ui/transmute_ptr_to_ref.fixed b/tests/ui/transmute_ptr_to_ref.fixed
index acec14ccb6b..56330d71938 100644
--- a/tests/ui/transmute_ptr_to_ref.fixed
+++ b/tests/ui/transmute_ptr_to_ref.fixed
@@ -1,5 +1,9 @@
 #![warn(clippy::transmute_ptr_to_ref)]
-#![allow(clippy::match_single_binding, clippy::unnecessary_cast)]
+#![allow(
+    clippy::match_single_binding,
+    clippy::unnecessary_cast,
+    clippy::missing_transmute_annotations
+)]
 
 unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) {
     let _: &T = &*p;
diff --git a/tests/ui/transmute_ptr_to_ref.rs b/tests/ui/transmute_ptr_to_ref.rs
index 3376401e284..ce1ee8bfbfa 100644
--- a/tests/ui/transmute_ptr_to_ref.rs
+++ b/tests/ui/transmute_ptr_to_ref.rs
@@ -1,5 +1,9 @@
 #![warn(clippy::transmute_ptr_to_ref)]
-#![allow(clippy::match_single_binding, clippy::unnecessary_cast)]
+#![allow(
+    clippy::match_single_binding,
+    clippy::unnecessary_cast,
+    clippy::missing_transmute_annotations
+)]
 
 unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) {
     let _: &T = std::mem::transmute(p);
diff --git a/tests/ui/transmute_ptr_to_ref.stderr b/tests/ui/transmute_ptr_to_ref.stderr
index d7d180398e1..44cda254c3f 100644
--- a/tests/ui/transmute_ptr_to_ref.stderr
+++ b/tests/ui/transmute_ptr_to_ref.stderr
@@ -1,5 +1,5 @@
 error: transmute from a pointer type (`*const T`) to a reference type (`&T`)
-  --> tests/ui/transmute_ptr_to_ref.rs:5:17
+  --> tests/ui/transmute_ptr_to_ref.rs:9:17
    |
 LL |     let _: &T = std::mem::transmute(p);
    |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p`
@@ -8,127 +8,127 @@ LL |     let _: &T = std::mem::transmute(p);
    = help: to override `-D warnings` add `#[allow(clippy::transmute_ptr_to_ref)]`
 
 error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`)
-  --> tests/ui/transmute_ptr_to_ref.rs:8:21
+  --> tests/ui/transmute_ptr_to_ref.rs:12:21
    |
 LL |     let _: &mut T = std::mem::transmute(m);
    |                     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m`
 
 error: transmute from a pointer type (`*mut T`) to a reference type (`&T`)
-  --> tests/ui/transmute_ptr_to_ref.rs:11:17
+  --> tests/ui/transmute_ptr_to_ref.rs:15:17
    |
 LL |     let _: &T = std::mem::transmute(m);
    |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m`
 
 error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`)
-  --> tests/ui/transmute_ptr_to_ref.rs:14:21
+  --> tests/ui/transmute_ptr_to_ref.rs:18:21
    |
 LL |     let _: &mut T = std::mem::transmute(p as *mut T);
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut T)`
 
 error: transmute from a pointer type (`*const U`) to a reference type (`&T`)
-  --> tests/ui/transmute_ptr_to_ref.rs:17:17
+  --> tests/ui/transmute_ptr_to_ref.rs:21:17
    |
 LL |     let _: &T = std::mem::transmute(o);
    |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const T)`
 
 error: transmute from a pointer type (`*mut U`) to a reference type (`&mut T`)
-  --> tests/ui/transmute_ptr_to_ref.rs:20:21
+  --> tests/ui/transmute_ptr_to_ref.rs:24:21
    |
 LL |     let _: &mut T = std::mem::transmute(om);
    |                     ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut T)`
 
 error: transmute from a pointer type (`*mut U`) to a reference type (`&T`)
-  --> tests/ui/transmute_ptr_to_ref.rs:23:17
+  --> tests/ui/transmute_ptr_to_ref.rs:27:17
    |
 LL |     let _: &T = std::mem::transmute(om);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)`
 
 error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, u8>`)
-  --> tests/ui/transmute_ptr_to_ref.rs:33:32
+  --> tests/ui/transmute_ptr_to_ref.rs:37:32
    |
 LL |     let _: &Foo<u8> = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::<Foo<_>>()`
 
 error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, &u8>`)
-  --> tests/ui/transmute_ptr_to_ref.rs:35:33
+  --> tests/ui/transmute_ptr_to_ref.rs:39:33
    |
 LL |     let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) };
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::<Foo<&_>>()`
 
 error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`)
-  --> tests/ui/transmute_ptr_to_ref.rs:39:14
+  --> tests/ui/transmute_ptr_to_ref.rs:43:14
    |
 LL |     unsafe { std::mem::transmute::<_, Bar>(raw) };
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:44:14
+  --> tests/ui/transmute_ptr_to_ref.rs:48:14
    |
 LL |         0 => std::mem::transmute(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:45:14
+  --> tests/ui/transmute_ptr_to_ref.rs:49:14
    |
 LL |         1 => std::mem::transmute(y),
    |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:46:14
+  --> tests/ui/transmute_ptr_to_ref.rs:50:14
    |
 LL |         2 => std::mem::transmute::<_, &&'b u32>(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:47:14
+  --> tests/ui/transmute_ptr_to_ref.rs:51:14
    |
 LL |         _ => std::mem::transmute::<_, &&'b u32>(y),
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&'b u32>()`
 
 error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:55:19
+  --> tests/ui/transmute_ptr_to_ref.rs:59:19
    |
 LL |     let _: &u32 = std::mem::transmute(a);
    |                   ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a`
 
 error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:56:19
+  --> tests/ui/transmute_ptr_to_ref.rs:60:19
    |
 LL |     let _: &u32 = std::mem::transmute::<_, &u32>(a);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a.cast::<u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:58:14
+  --> tests/ui/transmute_ptr_to_ref.rs:62:14
    |
 LL |         0 => std::mem::transmute(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:59:14
+  --> tests/ui/transmute_ptr_to_ref.rs:63:14
    |
 LL |         _ => std::mem::transmute::<_, &&'b u32>(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()`
 
 error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:67:19
+  --> tests/ui/transmute_ptr_to_ref.rs:71:19
    |
 LL |     let _: &u32 = std::mem::transmute(a);
    |                   ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a`
 
 error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:68:19
+  --> tests/ui/transmute_ptr_to_ref.rs:72:19
    |
 LL |     let _: &u32 = std::mem::transmute::<_, &u32>(a);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const u32)`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:70:14
+  --> tests/ui/transmute_ptr_to_ref.rs:74:14
    |
 LL |         0 => std::mem::transmute(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &u32)`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> tests/ui/transmute_ptr_to_ref.rs:71:14
+  --> tests/ui/transmute_ptr_to_ref.rs:75:14
    |
 LL |         _ => std::mem::transmute::<_, &&'b u32>(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &'b u32)`
diff --git a/tests/ui/transmute_ref_to_ref.rs b/tests/ui/transmute_ref_to_ref.rs
index bdc7b9f6478..44d7af44a80 100644
--- a/tests/ui/transmute_ref_to_ref.rs
+++ b/tests/ui/transmute_ref_to_ref.rs
@@ -1,7 +1,7 @@
 //@no-rustfix
 
 #![deny(clippy::transmute_ptr_to_ptr)]
-#![allow(dead_code)]
+#![allow(dead_code, clippy::missing_transmute_annotations)]
 
 fn main() {
     unsafe {
diff --git a/tests/ui/transmute_ref_to_ref_no_std.rs b/tests/ui/transmute_ref_to_ref_no_std.rs
index b67386f8588..59177058754 100644
--- a/tests/ui/transmute_ref_to_ref_no_std.rs
+++ b/tests/ui/transmute_ref_to_ref_no_std.rs
@@ -1,7 +1,7 @@
 //@no-rustfix
 
 #![deny(clippy::transmute_ptr_to_ptr)]
-#![allow(dead_code)]
+#![allow(dead_code, clippy::missing_transmute_annotations)]
 #![feature(lang_items)]
 #![no_std]
 
diff --git a/tests/ui/transmute_undefined_repr.rs b/tests/ui/transmute_undefined_repr.rs
index a087d09c120..dd4bac7f1ed 100644
--- a/tests/ui/transmute_undefined_repr.rs
+++ b/tests/ui/transmute_undefined_repr.rs
@@ -1,5 +1,10 @@
 #![warn(clippy::transmute_undefined_repr)]
-#![allow(clippy::unit_arg, clippy::transmute_ptr_to_ref, clippy::useless_transmute)]
+#![allow(
+    clippy::unit_arg,
+    clippy::transmute_ptr_to_ref,
+    clippy::useless_transmute,
+    clippy::missing_transmute_annotations
+)]
 
 use core::any::TypeId;
 use core::ffi::c_void;
diff --git a/tests/ui/transmute_undefined_repr.stderr b/tests/ui/transmute_undefined_repr.stderr
index 5504fbe16e4..b41d37a5cd1 100644
--- a/tests/ui/transmute_undefined_repr.stderr
+++ b/tests/ui/transmute_undefined_repr.stderr
@@ -1,5 +1,5 @@
 error: transmute from `Ty2<u32, i32>` which has an undefined layout
-  --> tests/ui/transmute_undefined_repr.rs:29:33
+  --> tests/ui/transmute_undefined_repr.rs:34:33
    |
 LL |         let _: Ty2C<u32, i32> = transmute(value::<Ty2<u32, i32>>());
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,13 +8,13 @@ LL |         let _: Ty2C<u32, i32> = transmute(value::<Ty2<u32, i32>>());
    = help: to override `-D warnings` add `#[allow(clippy::transmute_undefined_repr)]`
 
 error: transmute into `Ty2<u32, i32>` which has an undefined layout
-  --> tests/ui/transmute_undefined_repr.rs:33:32
+  --> tests/ui/transmute_undefined_repr.rs:38:32
    |
 LL |         let _: Ty2<u32, i32> = transmute(value::<Ty2C<u32, i32>>());
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from `Ty<Ty2<u32, i32>>` to `Ty2<u32, f32>`, both of which have an undefined layout
-  --> tests/ui/transmute_undefined_repr.rs:42:32
+  --> tests/ui/transmute_undefined_repr.rs:47:32
    |
 LL |         let _: Ty2<u32, f32> = transmute(value::<Ty<Ty2<u32, i32>>>());
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL |         let _: Ty2<u32, f32> = transmute(value::<Ty<Ty2<u32, i32>>>());
    = note: two instances of the same generic type (`Ty2`) may have different layouts
 
 error: transmute from `Ty2<u32, f32>` to `Ty<Ty2<u32, i32>>`, both of which have an undefined layout
-  --> tests/ui/transmute_undefined_repr.rs:46:36
+  --> tests/ui/transmute_undefined_repr.rs:51:36
    |
 LL |         let _: Ty<Ty2<u32, i32>> = transmute(value::<Ty2<u32, f32>>());
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -30,7 +30,7 @@ LL |         let _: Ty<Ty2<u32, i32>> = transmute(value::<Ty2<u32, f32>>());
    = note: two instances of the same generic type (`Ty2`) may have different layouts
 
 error: transmute from `Ty<&Ty2<u32, i32>>` to `&Ty2<u32, f32>`, both of which have an undefined layout
-  --> tests/ui/transmute_undefined_repr.rs:54:33
+  --> tests/ui/transmute_undefined_repr.rs:59:33
    |
 LL |         let _: &Ty2<u32, f32> = transmute(value::<Ty<&Ty2<u32, i32>>>());
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -38,7 +38,7 @@ LL |         let _: &Ty2<u32, f32> = transmute(value::<Ty<&Ty2<u32, i32>>>());
    = note: two instances of the same generic type (`Ty2`) may have different layouts
 
 error: transmute from `&Ty2<u32, f32>` to `Ty<&Ty2<u32, i32>>`, both of which have an undefined layout
-  --> tests/ui/transmute_undefined_repr.rs:58:37
+  --> tests/ui/transmute_undefined_repr.rs:63:37
    |
 LL |         let _: Ty<&Ty2<u32, i32>> = transmute(value::<&Ty2<u32, f32>>());
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -46,7 +46,7 @@ LL |         let _: Ty<&Ty2<u32, i32>> = transmute(value::<&Ty2<u32, f32>>());
    = note: two instances of the same generic type (`Ty2`) may have different layouts
 
 error: transmute from `std::boxed::Box<Ty2<u32, u32>>` to `&mut Ty2<u32, f32>`, both of which have an undefined layout
-  --> tests/ui/transmute_undefined_repr.rs:88:45
+  --> tests/ui/transmute_undefined_repr.rs:93:45
    |
 LL |         let _: &'static mut Ty2<u32, f32> = transmute(value::<Box<Ty2<u32, u32>>>());
    |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -54,7 +54,7 @@ LL |         let _: &'static mut Ty2<u32, f32> = transmute(value::<Box<Ty2<u32,
    = note: two instances of the same generic type (`Ty2`) may have different layouts
 
 error: transmute from `&mut Ty2<u32, f32>` to `std::boxed::Box<Ty2<u32, u32>>`, both of which have an undefined layout
-  --> tests/ui/transmute_undefined_repr.rs:92:37
+  --> tests/ui/transmute_undefined_repr.rs:97:37
    |
 LL |         let _: Box<Ty2<u32, u32>> = transmute(value::<&'static mut Ty2<u32, f32>>());
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -62,7 +62,7 @@ LL |         let _: Box<Ty2<u32, u32>> = transmute(value::<&'static mut Ty2<u32,
    = note: two instances of the same generic type (`Ty2`) may have different layouts
 
 error: transmute into `*const Ty2<u32, u32>` which has an undefined layout
-  --> tests/ui/transmute_undefined_repr.rs:189:39
+  --> tests/ui/transmute_undefined_repr.rs:194:39
    |
 LL |         let _: *const Ty2<u32, u32> = transmute(value::<*const Ty2C<u32, Ty2<u32, u32>>>());
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -70,7 +70,7 @@ LL |         let _: *const Ty2<u32, u32> = transmute(value::<*const Ty2C<u32, Ty
    = note: the contained type `Ty2<u32, u32>` has an undefined layout
 
 error: transmute from `*const Ty2<u32, u32>` which has an undefined layout
-  --> tests/ui/transmute_undefined_repr.rs:193:50
+  --> tests/ui/transmute_undefined_repr.rs:198:50
    |
 LL |         let _: *const Ty2C<u32, Ty2<u32, u32>> = transmute(value::<*const Ty2<u32, u32>>());
    |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -78,7 +78,7 @@ LL |         let _: *const Ty2C<u32, Ty2<u32, u32>> = transmute(value::<*const T
    = note: the contained type `Ty2<u32, u32>` has an undefined layout
 
 error: transmute from `std::vec::Vec<Ty2<U, i32>>` to `std::vec::Vec<Ty2<T, u32>>`, both of which have an undefined layout
-  --> tests/ui/transmute_undefined_repr.rs:240:35
+  --> tests/ui/transmute_undefined_repr.rs:245:35
    |
 LL |         let _: Vec<Ty2<T, u32>> = transmute(value::<Vec<Ty2<U, i32>>>());
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -86,7 +86,7 @@ LL |         let _: Vec<Ty2<T, u32>> = transmute(value::<Vec<Ty2<U, i32>>>());
    = note: two instances of the same generic type (`Vec`) may have different layouts
 
 error: transmute from `std::vec::Vec<Ty2<T, u32>>` to `std::vec::Vec<Ty2<U, i32>>`, both of which have an undefined layout
-  --> tests/ui/transmute_undefined_repr.rs:244:35
+  --> tests/ui/transmute_undefined_repr.rs:249:35
    |
 LL |         let _: Vec<Ty2<U, i32>> = transmute(value::<Vec<Ty2<T, u32>>>());
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/tests/ui/transmutes_expressible_as_ptr_casts.fixed
index 2365695d691..51682da4a98 100644
--- a/tests/ui/transmutes_expressible_as_ptr_casts.fixed
+++ b/tests/ui/transmutes_expressible_as_ptr_casts.fixed
@@ -3,7 +3,7 @@
 // would otherwise be responsible for
 #![warn(clippy::useless_transmute)]
 #![warn(clippy::transmute_ptr_to_ptr)]
-#![allow(unused, clippy::borrow_as_ptr)]
+#![allow(unused, clippy::borrow_as_ptr, clippy::missing_transmute_annotations)]
 
 use std::mem::{size_of, transmute};
 
diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.rs b/tests/ui/transmutes_expressible_as_ptr_casts.rs
index cd1607b4c19..e5fcdef7a1c 100644
--- a/tests/ui/transmutes_expressible_as_ptr_casts.rs
+++ b/tests/ui/transmutes_expressible_as_ptr_casts.rs
@@ -3,7 +3,7 @@
 // would otherwise be responsible for
 #![warn(clippy::useless_transmute)]
 #![warn(clippy::transmute_ptr_to_ptr)]
-#![allow(unused, clippy::borrow_as_ptr)]
+#![allow(unused, clippy::borrow_as_ptr, clippy::missing_transmute_annotations)]
 
 use std::mem::{size_of, transmute};
 
diff --git a/tests/ui/transmuting_null.rs b/tests/ui/transmuting_null.rs
index 88b8c996523..c2deb6b6c46 100644
--- a/tests/ui/transmuting_null.rs
+++ b/tests/ui/transmuting_null.rs
@@ -2,7 +2,7 @@
 #![warn(clippy::transmuting_null)]
 #![allow(clippy::zero_ptr)]
 #![allow(clippy::transmute_ptr_to_ref)]
-#![allow(clippy::eq_op)]
+#![allow(clippy::eq_op, clippy::missing_transmute_annotations)]
 
 // Easy to lint because these only span one line.
 fn one_liners() {
diff --git a/tests/ui/type_id_on_box.fixed b/tests/ui/type_id_on_box.fixed
index 538c38b70e6..3656043700f 100644
--- a/tests/ui/type_id_on_box.fixed
+++ b/tests/ui/type_id_on_box.fixed
@@ -19,19 +19,37 @@ fn existential() -> impl Any {
     Box::new(1) as Box<dyn Any>
 }
 
+trait AnySubTrait: Any {}
+impl<T: Any> AnySubTrait for T {}
+
 fn main() {
+    // Don't lint, calling `.type_id()` on a `&dyn Any` does the expected thing
+    let ref_dyn: &dyn Any = &42;
+    let _ = ref_dyn.type_id();
+
     let any_box: Box<dyn Any> = Box::new(0usize);
     let _ = (*any_box).type_id();
-    let _ = TypeId::of::<Box<dyn Any>>(); // Don't lint. We explicitly say "do this instead" if this is intentional
+    //~^ ERROR: calling `.type_id()` on
+
+    // Don't lint. We explicitly say "do this instead" if this is intentional
+    let _ = TypeId::of::<Box<dyn Any>>();
     let _ = (*any_box).type_id();
+
+    // 2 derefs are needed here to get to the `dyn Any`
     let any_box: &Box<dyn Any> = &(Box::new(0usize) as Box<dyn Any>);
-    let _ = (**any_box).type_id(); // 2 derefs are needed here to get to the `dyn Any`
+    let _ = (**any_box).type_id();
+    //~^ ERROR: calling `.type_id()` on
 
     let b = existential();
-    let _ = b.type_id(); // Don't lint.
+    let _ = b.type_id(); // Don't
+
+    let b: Box<dyn AnySubTrait> = Box::new(1);
+    let _ = (*b).type_id();
+    //~^ ERROR: calling `.type_id()` on
 
     let b: SomeBox = Box::new(0usize);
     let _ = (*b).type_id();
+    //~^ ERROR: calling `.type_id()` on
 
     let b = BadBox(Box::new(0usize));
     let _ = b.type_id(); // Don't lint. This is a call to `<BadBox as Any>::type_id`. Not `std::boxed::Box`!
diff --git a/tests/ui/type_id_on_box.rs b/tests/ui/type_id_on_box.rs
index f224d273bc2..4bd9e73f2da 100644
--- a/tests/ui/type_id_on_box.rs
+++ b/tests/ui/type_id_on_box.rs
@@ -19,19 +19,37 @@ fn existential() -> impl Any {
     Box::new(1) as Box<dyn Any>
 }
 
+trait AnySubTrait: Any {}
+impl<T: Any> AnySubTrait for T {}
+
 fn main() {
+    // Don't lint, calling `.type_id()` on a `&dyn Any` does the expected thing
+    let ref_dyn: &dyn Any = &42;
+    let _ = ref_dyn.type_id();
+
     let any_box: Box<dyn Any> = Box::new(0usize);
     let _ = any_box.type_id();
-    let _ = TypeId::of::<Box<dyn Any>>(); // Don't lint. We explicitly say "do this instead" if this is intentional
+    //~^ ERROR: calling `.type_id()` on
+
+    // Don't lint. We explicitly say "do this instead" if this is intentional
+    let _ = TypeId::of::<Box<dyn Any>>();
     let _ = (*any_box).type_id();
+
+    // 2 derefs are needed here to get to the `dyn Any`
     let any_box: &Box<dyn Any> = &(Box::new(0usize) as Box<dyn Any>);
-    let _ = any_box.type_id(); // 2 derefs are needed here to get to the `dyn Any`
+    let _ = any_box.type_id();
+    //~^ ERROR: calling `.type_id()` on
 
     let b = existential();
-    let _ = b.type_id(); // Don't lint.
+    let _ = b.type_id(); // Don't
+
+    let b: Box<dyn AnySubTrait> = Box::new(1);
+    let _ = b.type_id();
+    //~^ ERROR: calling `.type_id()` on
 
     let b: SomeBox = Box::new(0usize);
     let _ = b.type_id();
+    //~^ ERROR: calling `.type_id()` on
 
     let b = BadBox(Box::new(0usize));
     let _ = b.type_id(); // Don't lint. This is a call to `<BadBox as Any>::type_id`. Not `std::boxed::Box`!
diff --git a/tests/ui/type_id_on_box.stderr b/tests/ui/type_id_on_box.stderr
index 0fce6a37c00..4528195607d 100644
--- a/tests/ui/type_id_on_box.stderr
+++ b/tests/ui/type_id_on_box.stderr
@@ -1,37 +1,48 @@
-error: calling `.type_id()` on a `Box<dyn Any>`
-  --> tests/ui/type_id_on_box.rs:24:13
+error: calling `.type_id()` on `Box<dyn Any>`
+  --> tests/ui/type_id_on_box.rs:31:13
    |
 LL |     let _ = any_box.type_id();
    |             -------^^^^^^^^^^
    |             |
    |             help: consider dereferencing first: `(*any_box)`
    |
-   = note: this returns the type id of the literal type `Box<dyn Any>` instead of the type id of the boxed value, which is most likely not what you want
+   = note: this returns the type id of the literal type `Box<_>` instead of the type id of the boxed value, which is most likely not what you want
    = note: if this is intentional, use `TypeId::of::<Box<dyn Any>>()` instead, which makes it more clear
    = note: `-D clippy::type-id-on-box` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::type_id_on_box)]`
 
-error: calling `.type_id()` on a `Box<dyn Any>`
-  --> tests/ui/type_id_on_box.rs:28:13
+error: calling `.type_id()` on `Box<dyn Any>`
+  --> tests/ui/type_id_on_box.rs:40:13
    |
-LL |     let _ = any_box.type_id(); // 2 derefs are needed here to get to the `dyn Any`
+LL |     let _ = any_box.type_id();
    |             -------^^^^^^^^^^
    |             |
    |             help: consider dereferencing first: `(**any_box)`
    |
-   = note: this returns the type id of the literal type `Box<dyn Any>` instead of the type id of the boxed value, which is most likely not what you want
+   = note: this returns the type id of the literal type `Box<_>` instead of the type id of the boxed value, which is most likely not what you want
    = note: if this is intentional, use `TypeId::of::<Box<dyn Any>>()` instead, which makes it more clear
 
-error: calling `.type_id()` on a `Box<dyn Any>`
-  --> tests/ui/type_id_on_box.rs:34:13
+error: calling `.type_id()` on `Box<dyn AnySubTrait>`
+  --> tests/ui/type_id_on_box.rs:47:13
    |
 LL |     let _ = b.type_id();
    |             -^^^^^^^^^^
    |             |
    |             help: consider dereferencing first: `(*b)`
    |
-   = note: this returns the type id of the literal type `Box<dyn Any>` instead of the type id of the boxed value, which is most likely not what you want
+   = note: this returns the type id of the literal type `Box<_>` instead of the type id of the boxed value, which is most likely not what you want
+   = note: if this is intentional, use `TypeId::of::<Box<dyn AnySubTrait>>()` instead, which makes it more clear
+
+error: calling `.type_id()` on `Box<dyn Any>`
+  --> tests/ui/type_id_on_box.rs:51:13
+   |
+LL |     let _ = b.type_id();
+   |             -^^^^^^^^^^
+   |             |
+   |             help: consider dereferencing first: `(*b)`
+   |
+   = note: this returns the type id of the literal type `Box<_>` instead of the type id of the boxed value, which is most likely not what you want
    = note: if this is intentional, use `TypeId::of::<Box<dyn Any>>()` instead, which makes it more clear
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/type_id_on_box_unfixable.rs b/tests/ui/type_id_on_box_unfixable.rs
new file mode 100644
index 00000000000..f6d09834adb
--- /dev/null
+++ b/tests/ui/type_id_on_box_unfixable.rs
@@ -0,0 +1,31 @@
+#![warn(clippy::type_id_on_box)]
+
+use std::any::{Any, TypeId};
+use std::ops::Deref;
+
+trait AnySubTrait: Any {}
+impl<T: Any> AnySubTrait for T {}
+
+// `Any` is an indirect supertrait
+trait AnySubSubTrait: AnySubTrait {}
+impl<T: AnySubTrait> AnySubSubTrait for T {}
+
+// This trait mentions `Any` in its predicates, but it is not a subtrait of `Any`.
+trait NormalTrait
+where
+    i32: Any,
+{
+}
+impl<T> NormalTrait for T {}
+
+fn main() {
+    // (currently we don't look deeper than one level into the supertrait hierachy, but we probably
+    // could)
+    let b: Box<dyn AnySubSubTrait> = Box::new(1);
+    let _ = b.type_id();
+    //~^ ERROR: calling `.type_id()` on
+
+    let b: Box<dyn NormalTrait> = Box::new(1);
+    let _ = b.type_id();
+    //~^ ERROR: calling `.type_id()` on
+}
diff --git a/tests/ui/type_id_on_box_unfixable.stderr b/tests/ui/type_id_on_box_unfixable.stderr
new file mode 100644
index 00000000000..539ed481ec1
--- /dev/null
+++ b/tests/ui/type_id_on_box_unfixable.stderr
@@ -0,0 +1,22 @@
+error: calling `.type_id()` on `Box<dyn AnySubSubTrait>`
+  --> tests/ui/type_id_on_box_unfixable.rs:25:13
+   |
+LL |     let _ = b.type_id();
+   |             ^^^^^^^^^^^
+   |
+   = note: this returns the type id of the literal type `Box<_>` instead of the type id of the boxed value, which is most likely not what you want
+   = note: if this is intentional, use `TypeId::of::<Box<dyn AnySubSubTrait>>()` instead, which makes it more clear
+   = note: `-D clippy::type-id-on-box` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::type_id_on_box)]`
+
+error: calling `.type_id()` on `Box<dyn NormalTrait>`
+  --> tests/ui/type_id_on_box_unfixable.rs:29:13
+   |
+LL |     let _ = b.type_id();
+   |             ^^^^^^^^^^^
+   |
+   = note: this returns the type id of the literal type `Box<_>` instead of the type id of the boxed value, which is most likely not what you want
+   = note: if this is intentional, use `TypeId::of::<Box<dyn NormalTrait>>()` instead, which makes it more clear
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/uninhabited_references.rs b/tests/ui/uninhabited_references.rs
index cd07b590a61..3569366ed05 100644
--- a/tests/ui/uninhabited_references.rs
+++ b/tests/ui/uninhabited_references.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::uninhabited_references)]
+#![allow(clippy::missing_transmute_annotations)]
 #![feature(never_type)]
 
 fn ret_uninh_ref() -> &'static std::convert::Infallible {
diff --git a/tests/ui/uninhabited_references.stderr b/tests/ui/uninhabited_references.stderr
index 446d4e75557..8c9b206f429 100644
--- a/tests/ui/uninhabited_references.stderr
+++ b/tests/ui/uninhabited_references.stderr
@@ -1,5 +1,5 @@
 error: dereferencing a reference to an uninhabited type would be undefined behavior
-  --> tests/ui/uninhabited_references.rs:4:23
+  --> tests/ui/uninhabited_references.rs:5:23
    |
 LL | fn ret_uninh_ref() -> &'static std::convert::Infallible {
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | fn ret_uninh_ref() -> &'static std::convert::Infallible {
    = help: to override `-D warnings` add `#[allow(clippy::uninhabited_references)]`
 
 error: dereferencing a reference to an uninhabited type would be undefined behavior
-  --> tests/ui/uninhabited_references.rs:10:30
+  --> tests/ui/uninhabited_references.rs:11:30
    |
 LL |         fn $name(x: &$ty) -> &$ty {
    |                              ^^^^
@@ -19,7 +19,7 @@ LL | ret_something!(id_never, !);
    = note: this error originates in the macro `ret_something` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: dereferencing a reference to an uninhabited type is undefined behavior
-  --> tests/ui/uninhabited_references.rs:11:14
+  --> tests/ui/uninhabited_references.rs:12:14
    |
 LL |             &*x
    |              ^^
@@ -30,7 +30,7 @@ LL | ret_something!(id_never, !);
    = note: this error originates in the macro `ret_something` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: dereferencing a reference to an uninhabited type is undefined behavior
-  --> tests/ui/uninhabited_references.rs:21:13
+  --> tests/ui/uninhabited_references.rs:22:13
    |
 LL |     let _ = *x;
    |             ^^
diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed
index 6ea7857a238..ffc5b74d7bd 100644
--- a/tests/ui/use_self.fixed
+++ b/tests/ui/use_self.fixed
@@ -7,7 +7,8 @@
     clippy::upper_case_acronyms,
     clippy::from_over_into,
     clippy::self_named_constructors,
-    clippy::needless_lifetimes
+    clippy::needless_lifetimes,
+    clippy::missing_transmute_annotations
 )]
 
 #[macro_use]
diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs
index 338cc00e45a..eb9d96168bc 100644
--- a/tests/ui/use_self.rs
+++ b/tests/ui/use_self.rs
@@ -7,7 +7,8 @@
     clippy::upper_case_acronyms,
     clippy::from_over_into,
     clippy::self_named_constructors,
-    clippy::needless_lifetimes
+    clippy::needless_lifetimes,
+    clippy::missing_transmute_annotations
 )]
 
 #[macro_use]
diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr
index d7aa8410a47..bd5b685b45d 100644
--- a/tests/ui/use_self.stderr
+++ b/tests/ui/use_self.stderr
@@ -1,5 +1,5 @@
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:22:21
+  --> tests/ui/use_self.rs:23:21
    |
 LL |         fn new() -> Foo {
    |                     ^^^ help: use the applicable keyword: `Self`
@@ -8,253 +8,253 @@ LL |         fn new() -> Foo {
    = help: to override `-D warnings` add `#[allow(clippy::use_self)]`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:23:13
+  --> tests/ui/use_self.rs:24:13
    |
 LL |             Foo {}
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:25:22
+  --> tests/ui/use_self.rs:26:22
    |
 LL |         fn test() -> Foo {
    |                      ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:26:13
+  --> tests/ui/use_self.rs:27:13
    |
 LL |             Foo::new()
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:31:25
+  --> tests/ui/use_self.rs:32:25
    |
 LL |         fn default() -> Foo {
    |                         ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:32:13
+  --> tests/ui/use_self.rs:33:13
    |
 LL |             Foo::new()
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:73:28
+  --> tests/ui/use_self.rs:74:28
    |
 LL |         fn clone(&self) -> Foo<'a> {
    |                            ^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:106:24
+  --> tests/ui/use_self.rs:107:24
    |
 LL |         fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
    |                        ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:106:55
+  --> tests/ui/use_self.rs:107:55
    |
 LL |         fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
    |                                                       ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:121:13
+  --> tests/ui/use_self.rs:122:13
    |
 LL |             TS(0)
    |             ^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:156:29
+  --> tests/ui/use_self.rs:157:29
    |
 LL |                 fn bar() -> Bar {
    |                             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:157:21
+  --> tests/ui/use_self.rs:158:21
    |
 LL |                     Bar { foo: Foo {} }
    |                     ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:168:21
+  --> tests/ui/use_self.rs:169:21
    |
 LL |         fn baz() -> Foo {
    |                     ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:169:13
+  --> tests/ui/use_self.rs:170:13
    |
 LL |             Foo {}
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:186:21
+  --> tests/ui/use_self.rs:187:21
    |
 LL |             let _ = Enum::B(42);
    |                     ^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:187:21
+  --> tests/ui/use_self.rs:188:21
    |
 LL |             let _ = Enum::C { field: true };
    |                     ^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:188:21
+  --> tests/ui/use_self.rs:189:21
    |
 LL |             let _ = Enum::A;
    |                     ^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:230:13
+  --> tests/ui/use_self.rs:231:13
    |
 LL |             nested::A::fun_1();
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:231:13
+  --> tests/ui/use_self.rs:232:13
    |
 LL |             nested::A::A;
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:233:13
+  --> tests/ui/use_self.rs:234:13
    |
 LL |             nested::A {};
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:252:13
+  --> tests/ui/use_self.rs:253:13
    |
 LL |             TestStruct::from_something()
    |             ^^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:266:25
+  --> tests/ui/use_self.rs:267:25
    |
 LL |         async fn g() -> S {
    |                         ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:267:13
+  --> tests/ui/use_self.rs:268:13
    |
 LL |             S {}
    |             ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:271:16
+  --> tests/ui/use_self.rs:272:16
    |
 LL |             &p[S::A..S::B]
    |                ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:271:22
+  --> tests/ui/use_self.rs:272:22
    |
 LL |             &p[S::A..S::B]
    |                      ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:294:29
+  --> tests/ui/use_self.rs:295:29
    |
 LL |         fn foo(value: T) -> Foo<T> {
    |                             ^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:295:13
+  --> tests/ui/use_self.rs:296:13
    |
 LL |             Foo::<T> { value }
    |             ^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:467:13
+  --> tests/ui/use_self.rs:468:13
    |
 LL |             A::new::<submod::B>(submod::B {})
    |             ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:504:13
+  --> tests/ui/use_self.rs:505:13
    |
 LL |             S2::new()
    |             ^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:541:17
+  --> tests/ui/use_self.rs:542:17
    |
 LL |                 Foo::Bar => unimplemented!(),
    |                 ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:542:17
+  --> tests/ui/use_self.rs:543:17
    |
 LL |                 Foo::Baz => unimplemented!(),
    |                 ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:548:20
+  --> tests/ui/use_self.rs:549:20
    |
 LL |             if let Foo::Bar = self {
    |                    ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:572:17
+  --> tests/ui/use_self.rs:573:17
    |
 LL |                 Something::Num(n) => *n,
    |                 ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:573:17
+  --> tests/ui/use_self.rs:574:17
    |
 LL |                 Something::TupleNums(n, _m) => *n,
    |                 ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:574:17
+  --> tests/ui/use_self.rs:575:17
    |
 LL |                 Something::StructNums { one, two: _ } => *one,
    |                 ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:580:17
+  --> tests/ui/use_self.rs:581:17
    |
 LL |                 crate::issue8845::Something::Num(n) => *n,
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:581:17
+  --> tests/ui/use_self.rs:582:17
    |
 LL |                 crate::issue8845::Something::TupleNums(n, _m) => *n,
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:582:17
+  --> tests/ui/use_self.rs:583:17
    |
 LL |                 crate::issue8845::Something::StructNums { one, two: _ } => *one,
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:598:17
+  --> tests/ui/use_self.rs:599:17
    |
 LL |             let Foo(x) = self;
    |                 ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:603:17
+  --> tests/ui/use_self.rs:604:17
    |
 LL |             let crate::issue8845::Foo(x) = self;
    |                 ^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:610:17
+  --> tests/ui/use_self.rs:611:17
    |
 LL |             let Bar { x, .. } = self;
    |                 ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:615:17
+  --> tests/ui/use_self.rs:616:17
    |
 LL |             let crate::issue8845::Bar { x, .. } = self;
    |                 ^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:654:17
+  --> tests/ui/use_self.rs:655:17
    |
 LL |                 E::A => {},
    |                 ^ help: use the applicable keyword: `Self`
diff --git a/tests/ui/useless_asref.fixed b/tests/ui/useless_asref.fixed
index c98f2928e03..ddbb9255b46 100644
--- a/tests/ui/useless_asref.fixed
+++ b/tests/ui/useless_asref.fixed
@@ -8,6 +8,8 @@
 )]
 
 use std::fmt::Debug;
+use std::rc::{Rc, Weak as RcWeak};
+use std::sync::{Arc, Weak as ArcWeak};
 
 struct FakeAsRef;
 
@@ -180,6 +182,22 @@ mod issue12135 {
     }
 }
 
+fn issue_12528() {
+    struct Foo;
+
+    let opt = Some(Arc::new(Foo));
+    let _ = opt.as_ref().map(Arc::clone);
+
+    let opt = Some(Rc::new(Foo));
+    let _ = opt.as_ref().map(Rc::clone);
+
+    let opt = Some(Arc::downgrade(&Arc::new(Foo)));
+    let _ = opt.as_ref().map(ArcWeak::clone);
+
+    let opt = Some(Rc::downgrade(&Rc::new(Foo)));
+    let _ = opt.as_ref().map(RcWeak::clone);
+}
+
 fn main() {
     not_ok();
     ok();
diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs
index f9d603f116d..b0405e930a2 100644
--- a/tests/ui/useless_asref.rs
+++ b/tests/ui/useless_asref.rs
@@ -8,6 +8,8 @@
 )]
 
 use std::fmt::Debug;
+use std::rc::{Rc, Weak as RcWeak};
+use std::sync::{Arc, Weak as ArcWeak};
 
 struct FakeAsRef;
 
@@ -180,6 +182,22 @@ mod issue12135 {
     }
 }
 
+fn issue_12528() {
+    struct Foo;
+
+    let opt = Some(Arc::new(Foo));
+    let _ = opt.as_ref().map(Arc::clone);
+
+    let opt = Some(Rc::new(Foo));
+    let _ = opt.as_ref().map(Rc::clone);
+
+    let opt = Some(Arc::downgrade(&Arc::new(Foo)));
+    let _ = opt.as_ref().map(ArcWeak::clone);
+
+    let opt = Some(Rc::downgrade(&Rc::new(Foo)));
+    let _ = opt.as_ref().map(RcWeak::clone);
+}
+
 fn main() {
     not_ok();
     ok();
diff --git a/tests/ui/useless_asref.stderr b/tests/ui/useless_asref.stderr
index c7d622ec2dc..5f495c39670 100644
--- a/tests/ui/useless_asref.stderr
+++ b/tests/ui/useless_asref.stderr
@@ -1,5 +1,5 @@
 error: this call to `as_ref` does nothing
-  --> tests/ui/useless_asref.rs:48:18
+  --> tests/ui/useless_asref.rs:50:18
    |
 LL |         foo_rstr(rstr.as_ref());
    |                  ^^^^^^^^^^^^^ help: try: `rstr`
@@ -11,103 +11,103 @@ LL | #![deny(clippy::useless_asref)]
    |         ^^^^^^^^^^^^^^^^^^^^^
 
 error: this call to `as_ref` does nothing
-  --> tests/ui/useless_asref.rs:50:20
+  --> tests/ui/useless_asref.rs:52:20
    |
 LL |         foo_rslice(rslice.as_ref());
    |                    ^^^^^^^^^^^^^^^ help: try: `rslice`
 
 error: this call to `as_mut` does nothing
-  --> tests/ui/useless_asref.rs:54:21
+  --> tests/ui/useless_asref.rs:56:21
    |
 LL |         foo_mrslice(mrslice.as_mut());
    |                     ^^^^^^^^^^^^^^^^ help: try: `mrslice`
 
 error: this call to `as_ref` does nothing
-  --> tests/ui/useless_asref.rs:56:20
+  --> tests/ui/useless_asref.rs:58:20
    |
 LL |         foo_rslice(mrslice.as_ref());
    |                    ^^^^^^^^^^^^^^^^ help: try: `mrslice`
 
 error: this call to `as_ref` does nothing
-  --> tests/ui/useless_asref.rs:63:20
+  --> tests/ui/useless_asref.rs:65:20
    |
 LL |         foo_rslice(rrrrrslice.as_ref());
    |                    ^^^^^^^^^^^^^^^^^^^ help: try: `rrrrrslice`
 
 error: this call to `as_ref` does nothing
-  --> tests/ui/useless_asref.rs:65:18
+  --> tests/ui/useless_asref.rs:67:18
    |
 LL |         foo_rstr(rrrrrstr.as_ref());
    |                  ^^^^^^^^^^^^^^^^^ help: try: `rrrrrstr`
 
 error: this call to `as_mut` does nothing
-  --> tests/ui/useless_asref.rs:70:21
+  --> tests/ui/useless_asref.rs:72:21
    |
 LL |         foo_mrslice(mrrrrrslice.as_mut());
    |                     ^^^^^^^^^^^^^^^^^^^^ help: try: `mrrrrrslice`
 
 error: this call to `as_ref` does nothing
-  --> tests/ui/useless_asref.rs:72:20
+  --> tests/ui/useless_asref.rs:74:20
    |
 LL |         foo_rslice(mrrrrrslice.as_ref());
    |                    ^^^^^^^^^^^^^^^^^^^^ help: try: `mrrrrrslice`
 
 error: this call to `as_ref` does nothing
-  --> tests/ui/useless_asref.rs:76:16
+  --> tests/ui/useless_asref.rs:78:16
    |
 LL |     foo_rrrrmr((&&&&MoreRef).as_ref());
    |                ^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&&&&MoreRef)`
 
 error: this call to `as_mut` does nothing
-  --> tests/ui/useless_asref.rs:126:13
+  --> tests/ui/useless_asref.rs:128:13
    |
 LL |     foo_mrt(mrt.as_mut());
    |             ^^^^^^^^^^^^ help: try: `mrt`
 
 error: this call to `as_ref` does nothing
-  --> tests/ui/useless_asref.rs:128:12
+  --> tests/ui/useless_asref.rs:130:12
    |
 LL |     foo_rt(mrt.as_ref());
    |            ^^^^^^^^^^^^ help: try: `mrt`
 
 error: this call to `as_ref.map(...)` does nothing
-  --> tests/ui/useless_asref.rs:139:13
+  --> tests/ui/useless_asref.rs:141:13
    |
 LL |     let z = x.as_ref().map(String::clone);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()`
 
 error: this call to `as_ref.map(...)` does nothing
-  --> tests/ui/useless_asref.rs:141:13
+  --> tests/ui/useless_asref.rs:143:13
    |
 LL |     let z = x.as_ref().map(|z| z.clone());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()`
 
 error: this call to `as_ref.map(...)` does nothing
-  --> tests/ui/useless_asref.rs:143:13
+  --> tests/ui/useless_asref.rs:145:13
    |
 LL |     let z = x.as_ref().map(|z| String::clone(z));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()`
 
 error: this call to `as_ref.map(...)` does nothing
-  --> tests/ui/useless_asref.rs:167:9
+  --> tests/ui/useless_asref.rs:169:9
    |
 LL |         x.field.as_ref().map(|v| v.clone());
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.field.clone()`
 
 error: this call to `as_ref.map(...)` does nothing
-  --> tests/ui/useless_asref.rs:169:9
+  --> tests/ui/useless_asref.rs:171:9
    |
 LL |         x.field.as_ref().map(Clone::clone);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.field.clone()`
 
 error: this call to `as_ref.map(...)` does nothing
-  --> tests/ui/useless_asref.rs:171:9
+  --> tests/ui/useless_asref.rs:173:9
    |
 LL |         x.field.as_ref().map(|v| Clone::clone(v));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.field.clone()`
 
 error: this call to `as_ref.map(...)` does nothing
-  --> tests/ui/useless_asref.rs:176:9
+  --> tests/ui/useless_asref.rs:178:9
    |
 LL |         Some(1).as_ref().map(|&x| x.clone());
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(1).clone()`
diff --git a/triagebot.toml b/triagebot.toml
index d455d967e30..d8131044ff2 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -19,7 +19,7 @@ new_pr = true
 
 [assign]
 contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md"
-users_on_vacation = []
+users_on_vacation = ["y21"]
 
 [assign.owners]
 "/.github" = ["@flip1995"]

From 71e02a01a14b00c8bbc4a679d258c07270bfe226 Mon Sep 17 00:00:00 2001
From: y21 <30553356+y21@users.noreply.github.com>
Date: Fri, 5 Apr 2024 00:17:27 +0200
Subject: [PATCH 17/47] use `Lrc` instead of the aliased type `Arc` directly

---
 clippy_lints/src/attrs/mixed_attributes_style.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clippy_lints/src/attrs/mixed_attributes_style.rs b/clippy_lints/src/attrs/mixed_attributes_style.rs
index 75a3d7a9ac3..5d2ea36b366 100644
--- a/clippy_lints/src/attrs/mixed_attributes_style.rs
+++ b/clippy_lints/src/attrs/mixed_attributes_style.rs
@@ -2,10 +2,10 @@ use super::MIXED_ATTRIBUTES_STYLE;
 use clippy_utils::diagnostics::span_lint;
 use rustc_ast::{AttrKind, AttrStyle, Attribute};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sync::Lrc;
 use rustc_lint::{LateContext, LintContext};
 use rustc_span::source_map::SourceMap;
 use rustc_span::{SourceFile, Span, Symbol};
-use std::sync::Arc;
 
 #[derive(Hash, PartialEq, Eq)]
 enum SimpleAttrKind {
@@ -79,7 +79,7 @@ fn lint_mixed_attrs(cx: &LateContext<'_>, attrs: &[Attribute]) {
     );
 }
 
-fn attr_in_same_src_as_item(source_map: &SourceMap, item_src: &Arc<SourceFile>, attr_span: Span) -> bool {
+fn attr_in_same_src_as_item(source_map: &SourceMap, item_src: &Lrc<SourceFile>, attr_span: Span) -> bool {
     let attr_src = source_map.lookup_source_file(attr_span.lo());
-    Arc::ptr_eq(item_src, &attr_src)
+    Lrc::ptr_eq(item_src, &attr_src)
 }

From d4a8f61eb321faf9966ba09e4bb777347a70655d Mon Sep 17 00:00:00 2001
From: Alex Macleod <alex@macleod.io>
Date: Fri, 5 Apr 2024 16:12:07 +0000
Subject: [PATCH 18/47] Use check_attributes in doc lints

---
 clippy_lints/src/doc/missing_headers.rs |   2 +-
 clippy_lints/src/doc/mod.rs             | 151 ++++++++++--------------
 tests/ui/doc/doc-fixable.fixed          |   5 +
 tests/ui/doc/doc-fixable.rs             |   5 +
 tests/ui/doc/doc-fixable.stderr         |  13 +-
 5 files changed, 85 insertions(+), 91 deletions(-)

diff --git a/clippy_lints/src/doc/missing_headers.rs b/clippy_lints/src/doc/missing_headers.rs
index 26f120cb33f..f935ae2e3e4 100644
--- a/clippy_lints/src/doc/missing_headers.rs
+++ b/clippy_lints/src/doc/missing_headers.rs
@@ -11,7 +11,7 @@ use super::{DocHeaders, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, MISSING_SAFETY_D
 pub fn check(
     cx: &LateContext<'_>,
     owner_id: OwnerId,
-    sig: &FnSig<'_>,
+    sig: FnSig<'_>,
     headers: DocHeaders,
     body_id: Option<BodyId>,
     panic_span: Option<Span>,
diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs
index b135e4e3577..4bced104d3b 100644
--- a/clippy_lints/src/doc/mod.rs
+++ b/clippy_lints/src/doc/mod.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
 use clippy_utils::macros::{is_panic, root_macro_call_first_node};
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::Visitable;
-use clippy_utils::{is_entrypoint_fn, method_chain_args};
+use clippy_utils::{is_entrypoint_fn, is_trait_impl_item, method_chain_args};
 use pulldown_cmark::Event::{
     Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text,
 };
@@ -11,9 +11,8 @@ use pulldown_cmark::Tag::{BlockQuote, CodeBlock, Heading, Item, Link, Paragraph}
 use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options};
 use rustc_ast::ast::Attribute;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{AnonConst, Expr};
+use rustc_hir::{AnonConst, Expr, ImplItemKind, ItemKind, Node, TraitItemKind, Unsafety};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::lint::in_external_macro;
@@ -366,7 +365,6 @@ declare_clippy_lint! {
 #[derive(Clone)]
 pub struct Documentation {
     valid_idents: FxHashSet<String>,
-    in_trait_impl: bool,
     check_private_items: bool,
 }
 
@@ -374,7 +372,6 @@ impl Documentation {
     pub fn new(valid_idents: &[String], check_private_items: bool) -> Self {
         Self {
             valid_idents: valid_idents.iter().cloned().collect(),
-            in_trait_impl: false,
             check_private_items,
         }
     }
@@ -394,36 +391,72 @@ impl_lint_pass!(Documentation => [
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for Documentation {
-    fn check_crate(&mut self, cx: &LateContext<'tcx>) {
-        let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID);
-        check_attrs(cx, &self.valid_idents, attrs);
-    }
-
-    fn check_variant(&mut self, cx: &LateContext<'tcx>, variant: &'tcx hir::Variant<'tcx>) {
-        let attrs = cx.tcx.hir().attrs(variant.hir_id);
-        check_attrs(cx, &self.valid_idents, attrs);
-    }
-
-    fn check_field_def(&mut self, cx: &LateContext<'tcx>, variant: &'tcx hir::FieldDef<'tcx>) {
-        let attrs = cx.tcx.hir().attrs(variant.hir_id);
-        check_attrs(cx, &self.valid_idents, attrs);
-    }
-
-    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
-        let attrs = cx.tcx.hir().attrs(item.hir_id());
+    fn check_attributes(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
         let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else {
             return;
         };
 
-        match item.kind {
-            hir::ItemKind::Fn(ref sig, _, body_id) => {
-                if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) {
-                    let body = cx.tcx.hir().body(body_id);
+        match cx.tcx.hir_node(cx.last_node_with_lint_attrs) {
+            Node::Item(item) => match item.kind {
+                ItemKind::Fn(sig, _, body_id) => {
+                    if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) {
+                        let body = cx.tcx.hir().body(body_id);
 
-                    let panic_span = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value);
+                        let panic_span = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value);
+                        missing_headers::check(
+                            cx,
+                            item.owner_id,
+                            sig,
+                            headers,
+                            Some(body_id),
+                            panic_span,
+                            self.check_private_items,
+                        );
+                    }
+                },
+                ItemKind::Trait(_, unsafety, ..) => match (headers.safety, unsafety) {
+                    (false, Unsafety::Unsafe) => span_lint(
+                        cx,
+                        MISSING_SAFETY_DOC,
+                        cx.tcx.def_span(item.owner_id),
+                        "docs for unsafe trait missing `# Safety` section",
+                    ),
+                    (true, Unsafety::Normal) => span_lint(
+                        cx,
+                        UNNECESSARY_SAFETY_DOC,
+                        cx.tcx.def_span(item.owner_id),
+                        "docs for safe trait have unnecessary `# Safety` section",
+                    ),
+                    _ => (),
+                },
+                _ => (),
+            },
+            Node::TraitItem(trait_item) => {
+                if let TraitItemKind::Fn(sig, ..) = trait_item.kind
+                    && !in_external_macro(cx.tcx.sess, trait_item.span)
+                {
                     missing_headers::check(
                         cx,
-                        item.owner_id,
+                        trait_item.owner_id,
+                        sig,
+                        headers,
+                        None,
+                        None,
+                        self.check_private_items,
+                    );
+                }
+            },
+            Node::ImplItem(impl_item) => {
+                if let ImplItemKind::Fn(sig, body_id) = impl_item.kind
+                    && !in_external_macro(cx.tcx.sess, impl_item.span)
+                    && !is_trait_impl_item(cx, impl_item.hir_id())
+                {
+                    let body = cx.tcx.hir().body(body_id);
+
+                    let panic_span = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(impl_item.owner_id), body.value);
+                    missing_headers::check(
+                        cx,
+                        impl_item.owner_id,
                         sig,
                         headers,
                         Some(body_id),
@@ -432,67 +465,7 @@ impl<'tcx> LateLintPass<'tcx> for Documentation {
                     );
                 }
             },
-            hir::ItemKind::Impl(impl_) => {
-                self.in_trait_impl = impl_.of_trait.is_some();
-            },
-            hir::ItemKind::Trait(_, unsafety, ..) => match (headers.safety, unsafety) {
-                (false, hir::Unsafety::Unsafe) => span_lint(
-                    cx,
-                    MISSING_SAFETY_DOC,
-                    cx.tcx.def_span(item.owner_id),
-                    "docs for unsafe trait missing `# Safety` section",
-                ),
-                (true, hir::Unsafety::Normal) => span_lint(
-                    cx,
-                    UNNECESSARY_SAFETY_DOC,
-                    cx.tcx.def_span(item.owner_id),
-                    "docs for safe trait have unnecessary `# Safety` section",
-                ),
-                _ => (),
-            },
-            _ => (),
-        }
-    }
-
-    fn check_item_post(&mut self, _cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
-        if let hir::ItemKind::Impl { .. } = item.kind {
-            self.in_trait_impl = false;
-        }
-    }
-
-    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
-        let attrs = cx.tcx.hir().attrs(item.hir_id());
-        let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else {
-            return;
-        };
-        if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
-            if !in_external_macro(cx.tcx.sess, item.span) {
-                missing_headers::check(cx, item.owner_id, sig, headers, None, None, self.check_private_items);
-            }
-        }
-    }
-
-    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
-        let attrs = cx.tcx.hir().attrs(item.hir_id());
-        let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else {
-            return;
-        };
-        if self.in_trait_impl || in_external_macro(cx.tcx.sess, item.span) {
-            return;
-        }
-        if let hir::ImplItemKind::Fn(ref sig, body_id) = item.kind {
-            let body = cx.tcx.hir().body(body_id);
-
-            let panic_span = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value);
-            missing_headers::check(
-                cx,
-                item.owner_id,
-                sig,
-                headers,
-                Some(body_id),
-                panic_span,
-                self.check_private_items,
-            );
+            _ => {},
         }
     }
 }
diff --git a/tests/ui/doc/doc-fixable.fixed b/tests/ui/doc/doc-fixable.fixed
index 178d4a1aa2b..7e22c847b1b 100644
--- a/tests/ui/doc/doc-fixable.fixed
+++ b/tests/ui/doc/doc-fixable.fixed
@@ -235,3 +235,8 @@ fn parenthesized_word() {}
 /// OSes
 /// UXes
 fn plural_acronym_test() {}
+
+extern {
+    /// `foo()`
+    fn in_extern();
+}
diff --git a/tests/ui/doc/doc-fixable.rs b/tests/ui/doc/doc-fixable.rs
index 01edb44c64c..3e2cb0df54b 100644
--- a/tests/ui/doc/doc-fixable.rs
+++ b/tests/ui/doc/doc-fixable.rs
@@ -235,3 +235,8 @@ fn parenthesized_word() {}
 /// OSes
 /// UXes
 fn plural_acronym_test() {}
+
+extern {
+    /// foo()
+    fn in_extern();
+}
diff --git a/tests/ui/doc/doc-fixable.stderr b/tests/ui/doc/doc-fixable.stderr
index ac876306b39..cd2228c47e3 100644
--- a/tests/ui/doc/doc-fixable.stderr
+++ b/tests/ui/doc/doc-fixable.stderr
@@ -352,5 +352,16 @@ help: try
 LL | /// `ABes`
    |     ~~~~~~
 
-error: aborting due to 32 previous errors
+error: item in documentation is missing backticks
+  --> tests/ui/doc/doc-fixable.rs:240:9
+   |
+LL |     /// foo()
+   |         ^^^^^
+   |
+help: try
+   |
+LL |     /// `foo()`
+   |         ~~~~~~~
+
+error: aborting due to 33 previous errors
 

From 42d09703b4d11935225e4c707a86da65afc5e667 Mon Sep 17 00:00:00 2001
From: Jacherr <jwc2002@outlook.com>
Date: Fri, 8 Mar 2024 18:32:29 +0000
Subject: [PATCH 19/47] Add support for ICE reporting in lintcheck

---
 lintcheck/src/main.rs | 96 +++++++++++++++++++++++++++++++------------
 1 file changed, 69 insertions(+), 27 deletions(-)

diff --git a/lintcheck/src/main.rs b/lintcheck/src/main.rs
index 66442998161..f6e1abaccd6 100644
--- a/lintcheck/src/main.rs
+++ b/lintcheck/src/main.rs
@@ -19,12 +19,12 @@ use std::env::consts::EXE_SUFFIX;
 use std::fmt::{self, Write as _};
 use std::io::{self, ErrorKind};
 use std::path::{Path, PathBuf};
-use std::process::Command;
+use std::process::{Command, ExitStatus};
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::time::Duration;
 use std::{env, fs, thread};
 
-use cargo_metadata::diagnostic::{Diagnostic, DiagnosticLevel};
+use cargo_metadata::diagnostic::Diagnostic;
 use cargo_metadata::Message;
 use rayon::prelude::*;
 use serde::{Deserialize, Serialize};
@@ -90,16 +90,43 @@ struct Crate {
     options: Option<Vec<String>>,
 }
 
+/// A single emitted output from clippy being executed on a crate. It may either be a
+/// `ClippyWarning`, or a `RustcIce` caused by a panic within clippy. A crate may have many
+/// `ClippyWarning`s but a maximum of one `RustcIce` (at which point clippy halts execution).
+#[derive(Debug)]
+enum ClippyCheckOutput {
+    ClippyWarning(ClippyWarning),
+    RustcIce(RustcIce),
+}
+
+#[derive(Debug)]
+struct RustcIce {
+    pub crate_name: String,
+    pub ice_content: String,
+}
+impl RustcIce {
+    pub fn from_stderr_and_status(crate_name: &str, status: ExitStatus, stderr: &str) -> Option<Self> {
+        if status.code().unwrap_or(0) == 101
+        /* ice exit status */
+        {
+            Some(Self {
+                crate_name: crate_name.to_owned(),
+                ice_content: stderr.to_owned(),
+            })
+        } else {
+            None
+        }
+    }
+}
+
 /// A single warning that clippy issued while checking a `Crate`
 #[derive(Debug)]
 struct ClippyWarning {
-    crate_name: String,
     file: String,
     line: usize,
     column: usize,
     lint_type: String,
     message: String,
-    is_ice: bool,
 }
 
 #[allow(unused)]
@@ -124,13 +151,11 @@ impl ClippyWarning {
         };
 
         Some(Self {
-            crate_name: crate_name.to_owned(),
             file,
             line: span.line_start,
             column: span.column_start,
             lint_type,
             message: diag.message,
-            is_ice: diag.level == DiagnosticLevel::Ice,
         })
     }
 
@@ -311,7 +336,7 @@ impl Crate {
         config: &LintcheckConfig,
         lint_filter: &[String],
         server: &Option<LintcheckServer>,
-    ) -> Vec<ClippyWarning> {
+    ) -> Vec<ClippyCheckOutput> {
         // advance the atomic index by one
         let index = target_dir_index.fetch_add(1, Ordering::SeqCst);
         // "loop" the index within 0..thread_limit
@@ -335,9 +360,9 @@ impl Crate {
         let shared_target_dir = clippy_project_root().join("target/lintcheck/shared_target_dir");
 
         let mut cargo_clippy_args = if config.fix {
-            vec!["--fix", "--"]
+            vec!["--quiet", "--fix", "--"]
         } else {
-            vec!["--", "--message-format=json", "--"]
+            vec!["--quiet", "--message-format=json", "--"]
         };
 
         let mut clippy_args = Vec::<&str>::new();
@@ -428,14 +453,21 @@ impl Crate {
         }
 
         // get all clippy warnings and ICEs
-        let warnings: Vec<ClippyWarning> = Message::parse_stream(stdout.as_bytes())
+        let mut entries: Vec<ClippyCheckOutput> = Message::parse_stream(stdout.as_bytes())
             .filter_map(|msg| match msg {
                 Ok(Message::CompilerMessage(message)) => ClippyWarning::new(message.message, &self.name, &self.version),
                 _ => None,
             })
+            .map(ClippyCheckOutput::ClippyWarning)
             .collect();
 
-        warnings
+        if let Some(ice) = RustcIce::from_stderr_and_status(&self.name, *status, &stderr) {
+            entries.push(ClippyCheckOutput::RustcIce(ice));
+        } else if !status.success() {
+            println!("non-ICE bad exit status for {} {}: {}", self.name, self.version, stderr);
+        }
+
+        entries
     }
 }
 
@@ -635,7 +667,7 @@ fn main() {
         LintcheckServer::spawn(recursive_options)
     });
 
-    let mut clippy_warnings: Vec<ClippyWarning> = crates
+    let mut clippy_entries: Vec<ClippyCheckOutput> = crates
         .par_iter()
         .flat_map(|krate| {
             krate.run_clippy_lints(
@@ -651,7 +683,9 @@ fn main() {
         .collect();
 
     if let Some(server) = server {
-        clippy_warnings.extend(server.warnings());
+        let server_clippy_entries = server.warnings().map(ClippyCheckOutput::ClippyWarning);
+
+        clippy_entries.extend(server_clippy_entries);
     }
 
     // if we are in --fix mode, don't change the log files, terminate here
@@ -659,20 +693,21 @@ fn main() {
         return;
     }
 
+    // split up warnings and ices
+    let mut warnings: Vec<ClippyWarning> = vec![];
+    let mut raw_ices: Vec<RustcIce> = vec![];
+    for entry in clippy_entries {
+        if let ClippyCheckOutput::ClippyWarning(x) = entry {
+            warnings.push(x);
+        } else if let ClippyCheckOutput::RustcIce(x) = entry {
+            raw_ices.push(x);
+        }
+    }
+
     // generate some stats
-    let (stats_formatted, new_stats) = gather_stats(&clippy_warnings);
+    let (stats_formatted, new_stats) = gather_stats(&warnings);
 
-    // grab crashes/ICEs, save the crate name and the ice message
-    let ices: Vec<(&String, &String)> = clippy_warnings
-        .iter()
-        .filter(|warning| warning.is_ice)
-        .map(|w| (&w.crate_name, &w.message))
-        .collect();
-
-    let mut all_msgs: Vec<String> = clippy_warnings
-        .iter()
-        .map(|warn| warn.to_output(config.markdown))
-        .collect();
+    let mut all_msgs: Vec<String> = warnings.iter().map(|warn| warn.to_output(config.markdown)).collect();
     all_msgs.sort();
     all_msgs.push("\n\n### Stats:\n\n".into());
     all_msgs.push(stats_formatted);
@@ -686,11 +721,18 @@ fn main() {
     }
     write!(text, "{}", all_msgs.join("")).unwrap();
     text.push_str("\n\n### ICEs:\n");
-    for (cratename, msg) in &ices {
-        let _: fmt::Result = write!(text, "{cratename}: '{msg}'");
+    for ice in &raw_ices {
+        let _: fmt::Result = write!(
+            text,
+            "{}:\n{}\n========================================\n\n",
+            ice.crate_name, ice.ice_content
+        );
     }
 
     println!("Writing logs to {}", config.lintcheck_results_path.display());
+    if !raw_ices.is_empty() {
+        println!("WARNING: at least one ICE reported, check log file");
+    }
     fs::create_dir_all(config.lintcheck_results_path.parent().unwrap()).unwrap();
     fs::write(&config.lintcheck_results_path, text).unwrap();
 

From 2a34f231e9f8a54dd19515db5639600339e357f9 Mon Sep 17 00:00:00 2001
From: xFrednet <xFrednet@gmail.com>
Date: Mon, 1 Apr 2024 12:06:29 +0200
Subject: [PATCH 20/47] Prevent PR assignments to `@matthiaskrgr`,
 `@giraffate`, and `@Centri3`

---
 triagebot.toml | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/triagebot.toml b/triagebot.toml
index d8131044ff2..901977da25b 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -19,7 +19,12 @@ new_pr = true
 
 [assign]
 contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md"
-users_on_vacation = ["y21"]
+users_on_vacation = [
+    "y21",
+    "matthiaskrgr",
+    "giraffate",
+    "Centri3",
+]
 
 [assign.owners]
 "/.github" = ["@flip1995"]

From 6a2cb33029928650700d94fd6b257f1029bb7eea Mon Sep 17 00:00:00 2001
From: Folkert <folkert@folkertdev.nl>
Date: Wed, 3 Apr 2024 10:10:00 +0200
Subject: [PATCH 21/47] fix incorrect suggestion for `!(a as type >= b)`

---
 clippy_lints/src/booleans.rs            | 17 ++++++++++++-----
 tests/ui/nonminimal_bool_methods.fixed  |  8 ++++++++
 tests/ui/nonminimal_bool_methods.rs     |  8 ++++++++
 tests/ui/nonminimal_bool_methods.stderr | 20 +++++++++++++++++++-
 4 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs
index 6edfebb5534..b6341b3fe8e 100644
--- a/clippy_lints/src/booleans.rs
+++ b/clippy_lints/src/booleans.rs
@@ -346,11 +346,18 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
                 _ => None,
             }
             .and_then(|op| {
-                Some(format!(
-                    "{}{op}{}",
-                    snippet_opt(cx, lhs.span)?,
-                    snippet_opt(cx, rhs.span)?
-                ))
+                let lhs_snippet = snippet_opt(cx, lhs.span)?;
+                let rhs_snippet = snippet_opt(cx, rhs.span)?;
+
+                if !(lhs_snippet.starts_with('(') && lhs_snippet.ends_with(')')) {
+                    if let (ExprKind::Cast(..), BinOpKind::Ge) = (&lhs.kind, binop.node) {
+                        // e.g. `(a as u64) < b`. Without the parens the `<` is
+                        // interpreted as a start of generic arguments for `u64`
+                        return Some(format!("({lhs_snippet}){op}{rhs_snippet}"));
+                    }
+                }
+
+                Some(format!("{lhs_snippet}{op}{rhs_snippet}"))
             })
         },
         ExprKind::MethodCall(path, receiver, [], _) => {
diff --git a/tests/ui/nonminimal_bool_methods.fixed b/tests/ui/nonminimal_bool_methods.fixed
index bd4be3e5a44..aba599678e3 100644
--- a/tests/ui/nonminimal_bool_methods.fixed
+++ b/tests/ui/nonminimal_bool_methods.fixed
@@ -109,4 +109,12 @@ fn dont_warn_for_negated_partial_ord_comparison() {
     let _ = !(a >= b);
 }
 
+fn issue_12625() {
+    let a = 0;
+    let b = 0;
+    if (a as u64) < b {} //~ ERROR: this boolean expression can be simplified
+    if (a as u64) < b {} //~ ERROR: this boolean expression can be simplified
+    if a as u64 > b {} //~ ERROR: this boolean expression can be simplified
+}
+
 fn main() {}
diff --git a/tests/ui/nonminimal_bool_methods.rs b/tests/ui/nonminimal_bool_methods.rs
index 4523c7385df..35f22db1d36 100644
--- a/tests/ui/nonminimal_bool_methods.rs
+++ b/tests/ui/nonminimal_bool_methods.rs
@@ -109,4 +109,12 @@ fn dont_warn_for_negated_partial_ord_comparison() {
     let _ = !(a >= b);
 }
 
+fn issue_12625() {
+    let a = 0;
+    let b = 0;
+    if !(a as u64 >= b) {} //~ ERROR: this boolean expression can be simplified
+    if !((a as u64) >= b) {} //~ ERROR: this boolean expression can be simplified
+    if !(a as u64 <= b) {} //~ ERROR: this boolean expression can be simplified
+}
+
 fn main() {}
diff --git a/tests/ui/nonminimal_bool_methods.stderr b/tests/ui/nonminimal_bool_methods.stderr
index e32c8dacd2f..18da4e0d380 100644
--- a/tests/ui/nonminimal_bool_methods.stderr
+++ b/tests/ui/nonminimal_bool_methods.stderr
@@ -79,5 +79,23 @@ error: this boolean expression can be simplified
 LL |     if !res.is_none() {}
    |        ^^^^^^^^^^^^^^ help: try: `res.is_some()`
 
-error: aborting due to 13 previous errors
+error: this boolean expression can be simplified
+  --> tests/ui/nonminimal_bool_methods.rs:115:8
+   |
+LL |     if !(a as u64 >= b) {}
+   |        ^^^^^^^^^^^^^^^^ help: try: `(a as u64) < b`
+
+error: this boolean expression can be simplified
+  --> tests/ui/nonminimal_bool_methods.rs:116:8
+   |
+LL |     if !((a as u64) >= b) {}
+   |        ^^^^^^^^^^^^^^^^^^ help: try: `(a as u64) < b`
+
+error: this boolean expression can be simplified
+  --> tests/ui/nonminimal_bool_methods.rs:117:8
+   |
+LL |     if !(a as u64 <= b) {}
+   |        ^^^^^^^^^^^^^^^^ help: try: `a as u64 > b`
+
+error: aborting due to 16 previous errors
 

From 02b5e1a1592df408c7bd73f80479c6180763c172 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 8 Apr 2024 10:36:15 +0000
Subject: [PATCH 22/47] Stop exporting `TypeckRootCtxt` and `FnCtxt`.

While they have many convenient APIs, it is better to expose dedicated functions for them
---
 .../src/methods/unnecessary_to_owned.rs       |  5 +--
 .../transmutes_expressible_as_ptr_casts.rs    |  4 +-
 clippy_lints/src/transmute/utils.rs           | 37 -------------------
 3 files changed, 3 insertions(+), 43 deletions(-)

diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs
index 23fc323446e..d3347466be9 100644
--- a/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -12,7 +12,6 @@ use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node};
-use rustc_hir_typeck::{FnCtxt, TypeckRootCtxt};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::mir::Mutability;
@@ -437,9 +436,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
             Node::Item(item) => {
                 if let ItemKind::Fn(_, _, body_id) = &item.kind
                     && let output_ty = return_ty(cx, item.owner_id)
-                    && let root_ctxt = TypeckRootCtxt::new(cx.tcx, item.owner_id.def_id)
-                    && let fn_ctxt = FnCtxt::new(&root_ctxt, cx.param_env, item.owner_id.def_id)
-                    && fn_ctxt.can_coerce(ty, output_ty)
+                    && rustc_hir_typeck::can_coerce(cx.tcx, cx.param_env, item.owner_id.def_id, ty, output_ty)
                 {
                     if has_lifetime(output_ty) && has_lifetime(ty) {
                         return false;
diff --git a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
index 6f5ac625e35..a6a6e9a3bac 100644
--- a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
+++ b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
@@ -1,4 +1,4 @@
-use super::utils::check_cast;
+use rustc_hir_typeck::cast::check_cast;
 use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::sugg::Sugg;
@@ -22,7 +22,7 @@ pub(super) fn check<'tcx>(
 ) -> bool {
     use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast};
     let mut app = Applicability::MachineApplicable;
-    let mut sugg = match check_cast(cx, e, from_ty, to_ty) {
+    let mut sugg = match check_cast(cx.tcx, cx.param_env, e, from_ty, to_ty) {
         Some(FnPtrAddrCast | PtrAddrCast) if const_context => return false,
         Some(PtrPtrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) => {
             Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app)
diff --git a/clippy_lints/src/transmute/utils.rs b/clippy_lints/src/transmute/utils.rs
index 15f1890aa39..e8ccd35b4da 100644
--- a/clippy_lints/src/transmute/utils.rs
+++ b/clippy_lints/src/transmute/utils.rs
@@ -1,10 +1,5 @@
-use rustc_hir as hir;
-use rustc_hir::Expr;
-use rustc_hir_typeck::{cast, FnCtxt, TypeckRootCtxt};
 use rustc_lint::LateContext;
-use rustc_middle::ty::cast::CastKind;
 use rustc_middle::ty::Ty;
-use rustc_span::DUMMY_SP;
 
 // check if the component types of the transmuted collection and the result have different ABI,
 // size or alignment
@@ -20,35 +15,3 @@ pub(super) fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx
         false
     }
 }
-
-/// If a cast from `from_ty` to `to_ty` is valid, returns an Ok containing the kind of
-/// the cast. In certain cases, including some invalid casts from array references
-/// to pointers, this may cause additional errors to be emitted and/or ICE error
-/// messages. This function will panic if that occurs.
-pub(super) fn check_cast<'tcx>(
-    cx: &LateContext<'tcx>,
-    e: &'tcx Expr<'_>,
-    from_ty: Ty<'tcx>,
-    to_ty: Ty<'tcx>,
-) -> Option<CastKind> {
-    let hir_id = e.hir_id;
-    let local_def_id = hir_id.owner.def_id;
-
-    let root_ctxt = TypeckRootCtxt::new(cx.tcx, local_def_id);
-    let fn_ctxt = FnCtxt::new(&root_ctxt, cx.param_env, local_def_id);
-
-    if let Ok(check) = cast::CastCheck::new(
-        &fn_ctxt,
-        e,
-        from_ty,
-        to_ty,
-        // We won't show any error to the user, so we don't care what the span is here.
-        DUMMY_SP,
-        DUMMY_SP,
-        hir::Constness::NotConst,
-    ) {
-        check.do_check(&fn_ctxt).ok()
-    } else {
-        None
-    }
-}

From 89b48a2e22fe4b5f3289e349ae0af81c530f7630 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Tue, 31 Jan 2023 11:54:06 +0000
Subject: [PATCH 23/47] Thread pattern types through the HIR

---
 clippy_lints/src/dereference.rs | 1 +
 clippy_utils/src/hir_utils.rs   | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs
index 560b2acc1c7..eb317c70926 100644
--- a/clippy_lints/src/dereference.rs
+++ b/clippy_lints/src/dereference.rs
@@ -821,6 +821,7 @@ impl TyCoercionStability {
                 | TyKind::Array(..)
                 | TyKind::Ptr(_)
                 | TyKind::BareFn(_)
+                | TyKind::Pat(..)
                 | TyKind::Never
                 | TyKind::Tup(_)
                 | TyKind::Path(_) => Self::Deref,
diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs
index f8bbe997774..6c3d9329932 100644
--- a/clippy_utils/src/hir_utils.rs
+++ b/clippy_utils/src/hir_utils.rs
@@ -1068,6 +1068,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 self.hash_ty(ty);
                 self.hash_array_length(len);
             },
+            TyKind::Pat(ty, pat) => {
+                self.hash_ty(ty);
+                self.hash_pat(pat);
+            },
             TyKind::Ptr(ref mut_ty) => {
                 self.hash_ty(mut_ty.ty);
                 mut_ty.mutbl.hash(&mut self.s);

From c8388033f3e5dba47531be66d3b80b45eecee46a Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Thu, 2 Feb 2023 13:57:36 +0000
Subject: [PATCH 24/47] Actually create ranged int types in the type system.

---
 clippy_lints/src/dereference.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs
index eb317c70926..f83fb1b9019 100644
--- a/clippy_lints/src/dereference.rs
+++ b/clippy_lints/src/dereference.rs
@@ -870,6 +870,7 @@ impl TyCoercionStability {
                 | ty::Int(_)
                 | ty::Uint(_)
                 | ty::Array(..)
+                | ty::Pat(..)
                 | ty::Float(_)
                 | ty::RawPtr(..)
                 | ty::FnPtr(_)

From db3a927432586c33a4aaad54951056b8ced30439 Mon Sep 17 00:00:00 2001
From: Wilfred Hughes <me@wilfred.me.uk>
Date: Mon, 8 Apr 2024 12:50:28 -0700
Subject: [PATCH 25/47] Fix markdown syntax in str_split_at_newline docs

---
 clippy_lints/src/methods/mod.rs | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 2fb317c8c68..0939c028564 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -3938,7 +3938,6 @@ declare_clippy_lint! {
     /// This lint cannot detect if the split is intentionally restricted to a single type of newline (`"\n"` or
     /// `"\r\n"`), for example during the parsing of a specific file format in which precisely one newline type is
     /// valid.
-    /// ```
     #[clippy::version = "1.77.0"]
     pub STR_SPLIT_AT_NEWLINE,
     pedantic,

From 8ae7eaefdc27b224c074649aea13955c21593777 Mon Sep 17 00:00:00 2001
From: Mariana Miranda <mariana.almeida.miranda@tecnico.ulisboa.pt>
Date: Mon, 8 Apr 2024 23:35:19 +0100
Subject: [PATCH 26/47] fix: Refactor dereference code and fix test

---
 clippy_lints/src/dereference.rs | 11 +++++++----
 tests/ui/needless_borrow.fixed  |  3 ++-
 tests/ui/needless_borrow.rs     |  3 ++-
 tests/ui/needless_borrow.stderr |  2 +-
 4 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs
index f63413bd575..3fd4d6383b1 100644
--- a/clippy_lints/src/dereference.rs
+++ b/clippy_lints/src/dereference.rs
@@ -1014,10 +1014,13 @@ fn report<'tcx>(
                         },
                         _ => (0, false),
                     };
-                    let is_in_tuple = match cx.tcx.parent_hir_node(data.first_expr.hir_id) {
-                        Node::Expr(e) => matches!(e.kind, ExprKind::Tup(_)),
-                        _ => false,
-                    };
+                    let is_in_tuple = matches!(
+                        get_parent_expr(cx, data.first_expr),
+                        Some(Expr {
+                            kind: ExprKind::Tup(..),
+                            ..
+                        })
+                    );
 
                     let sugg = if !snip_is_macro
                         && (calls_field || expr.precedence().order() < precedence)
diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed
index adc92be0e1a..5121077b4ca 100644
--- a/tests/ui/needless_borrow.fixed
+++ b/tests/ui/needless_borrow.fixed
@@ -255,6 +255,7 @@ mod issue_10253 {
 fn issue_12268() {
     let option = Some((&1,));
     let x = (&1,);
-    // Lint here.
     option.unwrap_or((x.0,));
+    //~^ ERROR: this expression creates a reference which is immediately dereferenced by the
+    // compiler
 }
diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs
index b1f51a29978..e3a5cb280ba 100644
--- a/tests/ui/needless_borrow.rs
+++ b/tests/ui/needless_borrow.rs
@@ -255,6 +255,7 @@ mod issue_10253 {
 fn issue_12268() {
     let option = Some((&1,));
     let x = (&1,);
-    // Lint here.
     option.unwrap_or((&x.0,));
+    //~^ ERROR: this expression creates a reference which is immediately dereferenced by the
+    // compiler
 }
diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr
index 56fcf1268a1..4b2b17e7e57 100644
--- a/tests/ui/needless_borrow.stderr
+++ b/tests/ui/needless_borrow.stderr
@@ -164,7 +164,7 @@ 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:259:23
+  --> tests/ui/needless_borrow.rs:258:23
    |
 LL |     option.unwrap_or((&x.0,));
    |                       ^^^^ help: change this to: `x.0`

From 3705073a71648cff81bdb3eadeeacacc8d65123c Mon Sep 17 00:00:00 2001
From: modelflat <zhykreg@gmail.com>
Date: Wed, 27 Mar 2024 12:58:26 +0100
Subject: [PATCH 27/47] Recognize common prefixes when checking for items with
 module name suffix

Fixes #12544.

- don't report an item name if it consists only of a prefix from `allowed-prefixes` list and a module name (e.g. `AsFoo` in module `foo`).
- configured by `allowed-prefixes` config entry
- prefixes allowed by default: [`to`, `from`, `into`, `as`, `try_into`, `try_from`]
- update docs
---
 CHANGELOG.md                                  |  1 +
 book/src/lint_configuration.md                | 26 +++++++++++++++++++
 clippy_config/src/conf.rs                     | 22 ++++++++++++++++
 clippy_lints/src/item_name_repetitions.rs     | 12 ++++++++-
 clippy_lints/src/lib.rs                       |  2 ++
 .../allowed_prefixes/clippy.toml              |  1 +
 .../allowed_prefixes/item_name_repetitions.rs | 15 +++++++++++
 .../item_name_repetitions.stderr              | 11 ++++++++
 .../allowed_prefixes_extend/clippy.toml       |  1 +
 .../item_name_repetitions.rs                  | 21 +++++++++++++++
 .../item_name_repetitions.stderr              | 11 ++++++++
 .../toml_unknown_key/conf_unknown_key.stderr  |  3 +++
 tests/ui/module_name_repetitions.rs           | 14 ++++++++++
 13 files changed, 139 insertions(+), 1 deletion(-)
 create mode 100644 tests/ui-toml/item_name_repetitions/allowed_prefixes/clippy.toml
 create mode 100644 tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs
 create mode 100644 tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.stderr
 create mode 100644 tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/clippy.toml
 create mode 100644 tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs
 create mode 100644 tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.stderr

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f7e7ed86eed..bd3a04e34ae 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5894,6 +5894,7 @@ Released 2018-09-13
 [`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles
 [`allowed-duplicate-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-duplicate-crates
 [`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars
+[`allowed-prefixes`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-prefixes
 [`allowed-scripts`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-scripts
 [`allowed-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-wildcard-imports
 [`arithmetic-side-effects-allowed`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed
diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md
index 4a2727c5197..7cefa685264 100644
--- a/book/src/lint_configuration.md
+++ b/book/src/lint_configuration.md
@@ -164,6 +164,32 @@ configuration of Clippy. By default, any configuration will replace the default
 * [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars)
 
 
+## `allowed-prefixes`
+List of prefixes to allow when determining whether an item's name ends with the module's name.
+If the rest of an item's name is an allowed prefix (e.g. item `ToFoo` or `to_foo` in module `foo`),
+then don't emit a warning.
+
+#### Example
+
+```toml
+allowed-prefixes = [ "to", "from" ]
+```
+
+#### Noteworthy
+
+- By default, the following prefixes are allowed: `to`, `as`, `into`, `from`, `try_into` and `try_from`
+- PascalCase variant is included automatically for each snake_case variant (e.g. if `try_into` is included,
+  `TryInto` will also be included)
+- Use `".."` as part of the list to indicate that the configured values should be appended to the
+default configuration of Clippy. By default, any configuration will replace the default value
+
+**Default Value:** `["to", "as", "into", "from", "try_into", "try_from"]`
+
+---
+**Affected lints:**
+* [`module_name_repetitions`](https://rust-lang.github.io/rust-clippy/master/index.html#module_name_repetitions)
+
+
 ## `allowed-scripts`
 The list of unicode scripts allowed to be used in the scope.
 
diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs
index 3b5de2c16ff..9cfedbdd53b 100644
--- a/clippy_config/src/conf.rs
+++ b/clippy_config/src/conf.rs
@@ -39,6 +39,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[
 ];
 const DEFAULT_DISALLOWED_NAMES: &[&str] = &["foo", "baz", "quux"];
 const DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z", "w", "n"];
+const DEFAULT_ALLOWED_PREFIXES: &[&str] = &["to", "as", "into", "from", "try_into", "try_from"];
 
 /// Conf with parse errors
 #[derive(Default)]
@@ -589,6 +590,26 @@ define_Conf! {
     /// 2. Paths with any segment that containing the word 'prelude'
     /// are already allowed by default.
     (allowed_wildcard_imports: FxHashSet<String> = FxHashSet::default()),
+    /// Lint: MODULE_NAME_REPETITIONS.
+    ///
+    /// List of prefixes to allow when determining whether an item's name ends with the module's name.
+    /// If the rest of an item's name is an allowed prefix (e.g. item `ToFoo` or `to_foo` in module `foo`),
+    /// then don't emit a warning.
+    ///
+    /// #### Example
+    ///
+    /// ```toml
+    /// allowed-prefixes = [ "to", "from" ]
+    /// ```
+    ///
+    /// #### Noteworthy
+    ///
+    /// - By default, the following prefixes are allowed: `to`, `as`, `into`, `from`, `try_into` and `try_from`
+    /// - PascalCase variant is included automatically for each snake_case variant (e.g. if `try_into` is included,
+    ///   `TryInto` will also be included)
+    /// - Use `".."` as part of the list to indicate that the configured values should be appended to the
+    /// default configuration of Clippy. By default, any configuration will replace the default value
+    (allowed_prefixes: Vec<String> = DEFAULT_ALLOWED_PREFIXES.iter().map(ToString::to_string).collect()),
 }
 
 /// Search for the configuration file.
@@ -649,6 +670,7 @@ fn deserialize(file: &SourceFile) -> TryConf {
         Ok(mut conf) => {
             extend_vec_if_indicator_present(&mut conf.conf.doc_valid_idents, DEFAULT_DOC_VALID_IDENTS);
             extend_vec_if_indicator_present(&mut conf.conf.disallowed_names, DEFAULT_DISALLOWED_NAMES);
+            extend_vec_if_indicator_present(&mut conf.conf.allowed_prefixes, DEFAULT_ALLOWED_PREFIXES);
             // TODO: THIS SHOULD BE TESTED, this comment will be gone soon
             if conf.conf.allowed_idents_below_min_chars.contains("..") {
                 conf.conf
diff --git a/clippy_lints/src/item_name_repetitions.rs b/clippy_lints/src/item_name_repetitions.rs
index 0b4c416d94d..ffd487cf576 100644
--- a/clippy_lints/src/item_name_repetitions.rs
+++ b/clippy_lints/src/item_name_repetitions.rs
@@ -5,6 +5,7 @@ use clippy_utils::is_bool;
 use clippy_utils::macros::span_is_local;
 use clippy_utils::source::is_present_in_source;
 use clippy_utils::str_utils::{camel_case_split, count_match_end, count_match_start, to_camel_case, to_snake_case};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::{EnumDef, FieldDef, Item, ItemKind, OwnerId, Variant, VariantData};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
@@ -147,6 +148,7 @@ pub struct ItemNameRepetitions {
     struct_threshold: u64,
     avoid_breaking_exported_api: bool,
     allow_private_module_inception: bool,
+    allowed_prefixes: FxHashSet<String>,
 }
 
 impl ItemNameRepetitions {
@@ -156,6 +158,7 @@ impl ItemNameRepetitions {
         struct_threshold: u64,
         avoid_breaking_exported_api: bool,
         allow_private_module_inception: bool,
+        allowed_prefixes: &[String],
     ) -> Self {
         Self {
             modules: Vec::new(),
@@ -163,8 +166,13 @@ impl ItemNameRepetitions {
             struct_threshold,
             avoid_breaking_exported_api,
             allow_private_module_inception,
+            allowed_prefixes: allowed_prefixes.iter().map(|s| to_camel_case(s)).collect(),
         }
     }
+
+    fn is_allowed_prefix(&self, prefix: &str) -> bool {
+        self.allowed_prefixes.contains(prefix)
+    }
 }
 
 impl_lint_pass!(ItemNameRepetitions => [
@@ -423,7 +431,9 @@ impl LateLintPass<'_> for ItemNameRepetitions {
                                 _ => (),
                             }
                         }
-                        if rmatching.char_count == nchars {
+                        if rmatching.char_count == nchars
+                            && !self.is_allowed_prefix(&item_camel[..item_camel.len() - rmatching.byte_count])
+                        {
                             span_lint(
                                 cx,
                                 MODULE_NAME_REPETITIONS,
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index b92364a9d14..e2aac58bf97 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -594,6 +594,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
         pub_underscore_fields_behavior,
         ref allowed_duplicate_crates,
         allow_comparison_to_zero,
+        ref allowed_prefixes,
 
         blacklisted_names: _,
         cyclomatic_complexity_threshold: _,
@@ -864,6 +865,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
             struct_field_name_threshold,
             avoid_breaking_exported_api,
             allow_private_module_inception,
+            allowed_prefixes,
         ))
     });
     store.register_early_pass(|| Box::new(tabs_in_doc_comments::TabsInDocComments));
diff --git a/tests/ui-toml/item_name_repetitions/allowed_prefixes/clippy.toml b/tests/ui-toml/item_name_repetitions/allowed_prefixes/clippy.toml
new file mode 100644
index 00000000000..35145551b60
--- /dev/null
+++ b/tests/ui-toml/item_name_repetitions/allowed_prefixes/clippy.toml
@@ -0,0 +1 @@
+allowed-prefixes = ["bar"]
diff --git a/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs b/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs
new file mode 100644
index 00000000000..4142ced5f6b
--- /dev/null
+++ b/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs
@@ -0,0 +1,15 @@
+#![warn(clippy::module_name_repetitions)]
+#![allow(dead_code)]
+
+mod foo {
+    // #12544 - shouldn't warn if item name consists only of an allowed prefix and a module name.
+    // In this test, allowed prefixes are configured to be ["bar"].
+
+    // this line should produce a warning:
+    pub fn to_foo() {}
+
+    // but this line shouldn't
+    pub fn bar_foo() {}
+}
+
+fn main() {}
diff --git a/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.stderr b/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.stderr
new file mode 100644
index 00000000000..6cfe0eab479
--- /dev/null
+++ b/tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.stderr
@@ -0,0 +1,11 @@
+error: item name ends with its containing module's name
+  --> tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs:9:12
+   |
+LL |     pub fn to_foo() {}
+   |            ^^^^^^
+   |
+   = note: `-D clippy::module-name-repetitions` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::module_name_repetitions)]`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/clippy.toml b/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/clippy.toml
new file mode 100644
index 00000000000..31ef524671d
--- /dev/null
+++ b/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/clippy.toml
@@ -0,0 +1 @@
+allowed-prefixes = ["..", "bar"]
diff --git a/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs b/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs
new file mode 100644
index 00000000000..b132305d01c
--- /dev/null
+++ b/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs
@@ -0,0 +1,21 @@
+#![warn(clippy::module_name_repetitions)]
+#![allow(dead_code)]
+
+mod foo {
+    // #12544 - shouldn't warn if item name consists only of an allowed prefix and a module name.
+    // In this test, allowed prefixes are configured to be all of the default prefixes and ["bar"].
+
+    // this line should produce a warning:
+    pub fn something_foo() {}
+
+    // but none of the following should:
+    pub fn bar_foo() {}
+    pub fn to_foo() {}
+    pub fn as_foo() {}
+    pub fn into_foo() {}
+    pub fn from_foo() {}
+    pub fn try_into_foo() {}
+    pub fn try_from_foo() {}
+}
+
+fn main() {}
diff --git a/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.stderr b/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.stderr
new file mode 100644
index 00000000000..f495ec42184
--- /dev/null
+++ b/tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.stderr
@@ -0,0 +1,11 @@
+error: item name ends with its containing module's name
+  --> tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs:9:12
+   |
+LL |     pub fn something_foo() {}
+   |            ^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::module-name-repetitions` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::module_name_repetitions)]`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index 737c062ea56..24645b61fdb 100644
--- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -14,6 +14,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
            allowed-dotfiles
            allowed-duplicate-crates
            allowed-idents-below-min-chars
+           allowed-prefixes
            allowed-scripts
            allowed-wildcard-imports
            arithmetic-side-effects-allowed
@@ -93,6 +94,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
            allowed-dotfiles
            allowed-duplicate-crates
            allowed-idents-below-min-chars
+           allowed-prefixes
            allowed-scripts
            allowed-wildcard-imports
            arithmetic-side-effects-allowed
@@ -172,6 +174,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
            allowed-dotfiles
            allowed-duplicate-crates
            allowed-idents-below-min-chars
+           allowed-prefixes
            allowed-scripts
            allowed-wildcard-imports
            arithmetic-side-effects-allowed
diff --git a/tests/ui/module_name_repetitions.rs b/tests/ui/module_name_repetitions.rs
index a6cf0389098..b75ef87ab36 100644
--- a/tests/ui/module_name_repetitions.rs
+++ b/tests/ui/module_name_repetitions.rs
@@ -19,6 +19,20 @@ mod foo {
 
     // Should not warn
     pub struct Foobar;
+
+    // #12544 - shouldn't warn if item name consists only of an allowed prefix and a module name.
+    pub fn to_foo() {}
+    pub fn into_foo() {}
+    pub fn as_foo() {}
+    pub fn from_foo() {}
+    pub fn try_into_foo() {}
+    pub fn try_from_foo() {}
+    pub trait IntoFoo {}
+    pub trait ToFoo {}
+    pub trait AsFoo {}
+    pub trait FromFoo {}
+    pub trait TryIntoFoo {}
+    pub trait TryFromFoo {}
 }
 
 fn main() {}

From 23225e15d0482e2781c06f462a2b8f57d6fb824c Mon Sep 17 00:00:00 2001
From: Philipp Krones <hello@philkrones.com>
Date: Mon, 8 Apr 2024 16:13:56 +0200
Subject: [PATCH 28/47] Consistent lint group table in book and README

The lint table and the restriction group description was improved in #10385,
but only in the README. Apply the same changes to the book.
---
 book/src/README.md | 28 +++++++++++++++++++---------
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/book/src/README.md b/book/src/README.md
index e7972b0db19..7bdfb97c3ac 100644
--- a/book/src/README.md
+++ b/book/src/README.md
@@ -18,17 +18,27 @@ category.
 | `clippy::all`         | all lints that are on by default (correctness, suspicious, style, complexity, perf) | **warn/deny** |
 | `clippy::correctness` | code that is outright wrong or useless                                              | **deny**      |
 | `clippy::suspicious`  | code that is most likely wrong or useless                                           | **warn**      |
+| `clippy::style`       | code that should be written in a more idiomatic way                                 | **warn**      |
 | `clippy::complexity`  | code that does something simple but in a complex way                                | **warn**      |
 | `clippy::perf`        | code that can be written to run faster                                              | **warn**      |
-| `clippy::style`       | code that should be written in a more idiomatic way                                 | **warn**      |
-| `clippy::pedantic`    | lints which are rather strict or might have false positives                         | allow         |
+| `clippy::pedantic`    | lints which are rather strict or have occasional false positives                    | allow         |
+| `clippy::restriction` | lints which prevent the use of language and library features[^restrict]             | allow         |
 | `clippy::nursery`     | new lints that are still under development                                          | allow         |
-| `clippy::cargo`       | lints for the cargo manifest                                                        | allow         |                                   | allow         |
+| `clippy::cargo`       | lints for the cargo manifest                                                        | allow         |
 
-More to come, please [file an
-issue](https://github.com/rust-lang/rust-clippy/issues) if you have ideas!
+More to come, please [file an issue](https://github.com/rust-lang/rust-clippy/issues) if you have ideas!
 
-The [lint list](https://rust-lang.github.io/rust-clippy/master/index.html) also
-contains "restriction lints", which are for things which are usually not
-considered "bad", but may be useful to turn on in specific cases. These should
-be used very selectively, if at all.
+The `restriction` category should, *emphatically*, not be enabled as a whole. The contained
+lints may lint against perfectly reasonable code, may not have an alternative suggestion,
+and may contradict any other lints (including other categories). Lints should be considered
+on a case-by-case basis before enabling.
+
+[^restrict]: Some use cases for `restriction` lints include:
+    - Strict coding styles (e.g. [`clippy::else_if_without_else`]).
+    - Additional restrictions on CI (e.g. [`clippy::todo`]).
+    - Preventing panicking in certain functions (e.g. [`clippy::unwrap_used`]).
+    - Running a lint only on a subset of code (e.g. `#[forbid(clippy::float_arithmetic)]` on a module).
+
+[`clippy::else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
+[`clippy::todo`]: https://rust-lang.github.io/rust-clippy/master/index.html#todo
+[`clippy::unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used

From f7d49a340d63da0bcf9011f7e2f30be2ca88fdf6 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Mon, 8 Apr 2024 14:12:32 +0200
Subject: [PATCH 29/47] Turn `duplicated_attributes` into a late lint

---
 .../src/attrs/duplicated_attributes.rs        |  8 ++--
 clippy_lints/src/attrs/mod.rs                 | 11 ++----
 tests/ui/auxiliary/proc_macro_attr.rs         | 14 +++++++
 tests/ui/duplicated_attributes.rs             | 10 ++++-
 tests/ui/duplicated_attributes.stderr         | 31 ++++-----------
 tests/ui/unnecessary_clippy_cfg.stderr        | 38 ++++++++++++++++++-
 tests/ui/useless_attribute.fixed              |  2 +-
 tests/ui/useless_attribute.rs                 |  2 +-
 8 files changed, 77 insertions(+), 39 deletions(-)

diff --git a/clippy_lints/src/attrs/duplicated_attributes.rs b/clippy_lints/src/attrs/duplicated_attributes.rs
index 3a8844d0754..736ee48641d 100644
--- a/clippy_lints/src/attrs/duplicated_attributes.rs
+++ b/clippy_lints/src/attrs/duplicated_attributes.rs
@@ -2,12 +2,12 @@ use super::DUPLICATED_ATTRIBUTES;
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_ast::{Attribute, MetaItem};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_lint::EarlyContext;
+use rustc_lint::LateContext;
 use rustc_span::{sym, Span};
 use std::collections::hash_map::Entry;
 
 fn emit_if_duplicated(
-    cx: &EarlyContext<'_>,
+    cx: &LateContext<'_>,
     attr: &MetaItem,
     attr_paths: &mut FxHashMap<String, Span>,
     complete_path: String,
@@ -26,7 +26,7 @@ fn emit_if_duplicated(
 }
 
 fn check_duplicated_attr(
-    cx: &EarlyContext<'_>,
+    cx: &LateContext<'_>,
     attr: &MetaItem,
     attr_paths: &mut FxHashMap<String, Span>,
     parent: &mut Vec<String>,
@@ -64,7 +64,7 @@ fn check_duplicated_attr(
     }
 }
 
-pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
+pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
     let mut attr_paths = FxHashMap::default();
 
     for attr in attrs {
diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs
index 684ad7de2f0..8f47bc7653b 100644
--- a/clippy_lints/src/attrs/mod.rs
+++ b/clippy_lints/src/attrs/mod.rs
@@ -17,7 +17,7 @@ mod useless_attribute;
 mod utils;
 
 use clippy_config::msrvs::Msrv;
-use rustc_ast::{Attribute, Crate, MetaItemKind, NestedMetaItem};
+use rustc_ast::{Attribute, MetaItemKind, NestedMetaItem};
 use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
 use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, impl_lint_pass};
@@ -534,11 +534,13 @@ declare_lint_pass!(Attributes => [
     BLANKET_CLIPPY_RESTRICTION_LINTS,
     SHOULD_PANIC_WITHOUT_EXPECT,
     MIXED_ATTRIBUTES_STYLE,
+    DUPLICATED_ATTRIBUTES,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for Attributes {
     fn check_crate(&mut self, cx: &LateContext<'tcx>) {
         blanket_clippy_restriction_lints::check_command_line(cx);
+        duplicated_attributes::check(cx, cx.tcx.hir().krate_attrs());
     }
 
     fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) {
@@ -578,6 +580,7 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
             _ => {},
         }
         mixed_attributes_style::check(cx, item.span, attrs);
+        duplicated_attributes::check(cx, attrs);
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
@@ -606,17 +609,11 @@ impl_lint_pass!(EarlyAttributes => [
     MAYBE_MISUSED_CFG,
     DEPRECATED_CLIPPY_CFG_ATTR,
     UNNECESSARY_CLIPPY_CFG,
-    DUPLICATED_ATTRIBUTES,
 ]);
 
 impl EarlyLintPass for EarlyAttributes {
-    fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) {
-        duplicated_attributes::check(cx, &krate.attrs);
-    }
-
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
         empty_line_after::check(cx, item);
-        duplicated_attributes::check(cx, &item.attrs);
     }
 
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
diff --git a/tests/ui/auxiliary/proc_macro_attr.rs b/tests/ui/auxiliary/proc_macro_attr.rs
index a6f3b164c9b..f6fdebaf252 100644
--- a/tests/ui/auxiliary/proc_macro_attr.rs
+++ b/tests/ui/auxiliary/proc_macro_attr.rs
@@ -176,3 +176,17 @@ pub fn with_empty_docs(_attr: TokenStream, input: TokenStream) -> TokenStream {
     }
     .into()
 }
+
+#[proc_macro_attribute]
+pub fn duplicated_attr(_attr: TokenStream, input: TokenStream) -> TokenStream {
+    let item = parse_macro_input!(input as syn::Item);
+    let attrs: Vec<syn::Attribute> = vec![];
+    quote! {
+        #(#attrs)*
+        #[allow(unused)]
+        #[allow(unused)]
+        #[allow(unused)]
+        #item
+    }
+    .into()
+}
diff --git a/tests/ui/duplicated_attributes.rs b/tests/ui/duplicated_attributes.rs
index d051c881f15..d51e7e37beb 100644
--- a/tests/ui/duplicated_attributes.rs
+++ b/tests/ui/duplicated_attributes.rs
@@ -1,9 +1,14 @@
+//@aux-build:proc_macro_attr.rs
+
 #![warn(clippy::duplicated_attributes)]
 #![cfg(any(unix, windows))]
 #![allow(dead_code)]
 #![allow(dead_code)] //~ ERROR: duplicated attribute
 #![cfg(any(unix, windows))] // Should not warn!
 
+#[macro_use]
+extern crate proc_macro_attr;
+
 #[cfg(any(unix, windows, target_os = "linux"))]
 #[allow(dead_code)]
 #[allow(dead_code)] //~ ERROR: duplicated attribute
@@ -12,7 +17,10 @@ fn foo() {}
 
 #[cfg(unix)]
 #[cfg(windows)]
-#[cfg(unix)] //~ ERROR: duplicated attribute
+#[cfg(unix)] // cfgs are not handled
 fn bar() {}
 
+#[proc_macro_attr::duplicated_attr()] // Should not warn!
+fn babar() {}
+
 fn main() {}
diff --git a/tests/ui/duplicated_attributes.stderr b/tests/ui/duplicated_attributes.stderr
index 9e26ba990ac..0903617a8d1 100644
--- a/tests/ui/duplicated_attributes.stderr
+++ b/tests/ui/duplicated_attributes.stderr
@@ -1,16 +1,16 @@
 error: duplicated attribute
-  --> tests/ui/duplicated_attributes.rs:4:10
+  --> tests/ui/duplicated_attributes.rs:6:10
    |
 LL | #![allow(dead_code)]
    |          ^^^^^^^^^
    |
 note: first defined here
-  --> tests/ui/duplicated_attributes.rs:3:10
+  --> tests/ui/duplicated_attributes.rs:5:10
    |
 LL | #![allow(dead_code)]
    |          ^^^^^^^^^
 help: remove this attribute
-  --> tests/ui/duplicated_attributes.rs:4:10
+  --> tests/ui/duplicated_attributes.rs:6:10
    |
 LL | #![allow(dead_code)]
    |          ^^^^^^^^^
@@ -18,38 +18,21 @@ LL | #![allow(dead_code)]
    = help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]`
 
 error: duplicated attribute
-  --> tests/ui/duplicated_attributes.rs:9:9
+  --> tests/ui/duplicated_attributes.rs:14:9
    |
 LL | #[allow(dead_code)]
    |         ^^^^^^^^^
    |
 note: first defined here
-  --> tests/ui/duplicated_attributes.rs:8:9
+  --> tests/ui/duplicated_attributes.rs:13:9
    |
 LL | #[allow(dead_code)]
    |         ^^^^^^^^^
 help: remove this attribute
-  --> tests/ui/duplicated_attributes.rs:9:9
+  --> tests/ui/duplicated_attributes.rs:14:9
    |
 LL | #[allow(dead_code)]
    |         ^^^^^^^^^
 
-error: duplicated attribute
-  --> tests/ui/duplicated_attributes.rs:15:7
-   |
-LL | #[cfg(unix)]
-   |       ^^^^
-   |
-note: first defined here
-  --> tests/ui/duplicated_attributes.rs:13:7
-   |
-LL | #[cfg(unix)]
-   |       ^^^^
-help: remove this attribute
-  --> tests/ui/duplicated_attributes.rs:15:7
-   |
-LL | #[cfg(unix)]
-   |       ^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/unnecessary_clippy_cfg.stderr b/tests/ui/unnecessary_clippy_cfg.stderr
index fbc05743ca7..3d58c9eb5da 100644
--- a/tests/ui/unnecessary_clippy_cfg.stderr
+++ b/tests/ui/unnecessary_clippy_cfg.stderr
@@ -57,5 +57,41 @@ error: no need to put clippy lints behind a `clippy` cfg
 LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#![deny(clippy::non_minimal_cfg, clippy::maybe_misused_cfg)]`
 
-error: aborting due to 8 previous errors
+error: duplicated attribute
+  --> tests/ui/unnecessary_clippy_cfg.rs:8:26
+   |
+LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
+   |                          ^^^^^^^^^
+   |
+note: first defined here
+  --> tests/ui/unnecessary_clippy_cfg.rs:6:26
+   |
+LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
+   |                          ^^^^^^^^^
+help: remove this attribute
+  --> tests/ui/unnecessary_clippy_cfg.rs:8:26
+   |
+LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
+   |                          ^^^^^^^^^
+   = note: `-D clippy::duplicated-attributes` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]`
+
+error: duplicated attribute
+  --> tests/ui/unnecessary_clippy_cfg.rs:17:25
+   |
+LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
+   |                         ^^^^^^^^^
+   |
+note: first defined here
+  --> tests/ui/unnecessary_clippy_cfg.rs:15:25
+   |
+LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
+   |                         ^^^^^^^^^
+help: remove this attribute
+  --> tests/ui/unnecessary_clippy_cfg.rs:17:25
+   |
+LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
+   |                         ^^^^^^^^^
+
+error: aborting due to 10 previous errors
 
diff --git a/tests/ui/useless_attribute.fixed b/tests/ui/useless_attribute.fixed
index d1cdf73d559..81759086f79 100644
--- a/tests/ui/useless_attribute.fixed
+++ b/tests/ui/useless_attribute.fixed
@@ -1,6 +1,6 @@
 //@aux-build:proc_macro_derive.rs
 
-#![allow(unused)]
+#![allow(unused, clippy::duplicated_attributes)]
 #![warn(clippy::useless_attribute)]
 #![warn(unreachable_pub)]
 #![feature(rustc_private)]
diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs
index d6aa7fa242c..59a9dcf093b 100644
--- a/tests/ui/useless_attribute.rs
+++ b/tests/ui/useless_attribute.rs
@@ -1,6 +1,6 @@
 //@aux-build:proc_macro_derive.rs
 
-#![allow(unused)]
+#![allow(unused, clippy::duplicated_attributes)]
 #![warn(clippy::useless_attribute)]
 #![warn(unreachable_pub)]
 #![feature(rustc_private)]

From d13ccf3392283ec7c527a78093e1c6e9d627d186 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 7 Apr 2024 19:38:05 -0400
Subject: [PATCH 30/47] Add a helper for extending a span to include any
 trailing whitespace

---
 clippy_lints/src/lifetimes.rs | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs
index a60a40a2a47..2bb63ec2b04 100644
--- a/clippy_lints/src/lifetimes.rs
+++ b/clippy_lints/src/lifetimes.rs
@@ -294,8 +294,7 @@ fn elision_suggestions(
                         let span = cx
                             .sess()
                             .source_map()
-                            .span_extend_while(usage.ident.span, |ch| ch.is_ascii_whitespace())
-                            .unwrap_or(usage.ident.span);
+                            .span_extend_while_whitespace(usage.ident.span);
 
                         (span, String::new())
                     },

From e5b6d433fbff84875336a5d58fc18da5a7004847 Mon Sep 17 00:00:00 2001
From: Joel Natividad <1980690+jqnatividad@users.noreply.github.com>
Date: Wed, 10 Apr 2024 08:37:02 -0400
Subject: [PATCH 31/47] fix various comment typos

---
 clippy_lints/src/legacy_numeric_constants.rs | 2 +-
 clippy_utils/src/lib.rs                      | 2 +-
 tests/ui/unconditional_recursion.rs          | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/clippy_lints/src/legacy_numeric_constants.rs b/clippy_lints/src/legacy_numeric_constants.rs
index c5f1afe68c3..00124dcdd91 100644
--- a/clippy_lints/src/legacy_numeric_constants.rs
+++ b/clippy_lints/src/legacy_numeric_constants.rs
@@ -17,7 +17,7 @@ declare_clippy_lint! {
     /// `std::<float>::EPSILON`, etc.
     ///
     /// ### Why is this bad?
-    /// All of these have been superceded by the associated constants on their respective types,
+    /// All of these have been superseded by the associated constants on their respective types,
     /// such as `i128::MAX`. These legacy items may be deprecated in a future version of rust.
     ///
     /// ### Example
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 37c12dd850c..a13885b022f 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -3285,7 +3285,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
             Right(r) => Right(r.data),
         });
 
-    // 2. for the remaning segments, construct relative path using only mod names and `super`
+    // 2. for the remaining segments, construct relative path using only mod names and `super`
     let mut go_up_by = 0;
     let mut path = Vec::new();
     for el in unique_parts {
diff --git a/tests/ui/unconditional_recursion.rs b/tests/ui/unconditional_recursion.rs
index 70b390b00e2..a51fc567f50 100644
--- a/tests/ui/unconditional_recursion.rs
+++ b/tests/ui/unconditional_recursion.rs
@@ -266,7 +266,7 @@ struct S13 {
 
 impl S13 {
     fn new() -> Self {
-        // Shoud not warn!
+        // Should not warn!
         Self::default()
     }
 }

From 8de0a1bdbd0d35640acaa4cf0d677b1cc7dcf50e Mon Sep 17 00:00:00 2001
From: Joel Natividad <1980690+jqnatividad@users.noreply.github.com>
Date: Wed, 10 Apr 2024 08:37:30 -0400
Subject: [PATCH 32/47] fix varname typo

---
 clippy_lints/src/transmute/transmute_int_to_non_zero.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clippy_lints/src/transmute/transmute_int_to_non_zero.rs b/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
index 234021f0f47..2bea3be3d60 100644
--- a/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
+++ b/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
@@ -27,7 +27,7 @@ pub(super) fn check<'tcx>(
     };
 
     // FIXME: This can be simplified once `NonZero<T>` is stable.
-    let coercable_types = [
+    let coercible_types = [
         ("NonZeroU8", tcx.types.u8),
         ("NonZeroU16", tcx.types.u16),
         ("NonZeroU32", tcx.types.u32),
@@ -44,7 +44,7 @@ pub(super) fn check<'tcx>(
 
     let int_type = substs.type_at(0);
 
-    let Some(nonzero_alias) = coercable_types.iter().find_map(|(nonzero_alias, t)| {
+    let Some(nonzero_alias) = coercible_types.iter().find_map(|(nonzero_alias, t)| {
         if *t == int_type && *t == from_ty {
             Some(nonzero_alias)
         } else {

From d7a8622bf41a149cab0c464b70229632bf8a4f7e Mon Sep 17 00:00:00 2001
From: Joel Natividad <1980690+jqnatividad@users.noreply.github.com>
Date: Wed, 10 Apr 2024 08:46:03 -0400
Subject: [PATCH 33/47] Why is this bad explanation typo

---
 clippy_lints/src/derive.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs
index 5f9700b76d9..42cd19fb8ec 100644
--- a/clippy_lints/src/derive.rs
+++ b/clippy_lints/src/derive.rs
@@ -132,7 +132,7 @@ declare_clippy_lint! {
     ///
     /// ### Why is this bad?
     /// Deriving `serde::Deserialize` will create a constructor
-    /// that may violate invariants hold by another constructor.
+    /// that may violate invariants held by another constructor.
     ///
     /// ### Example
     /// ```rust,ignore

From 8b5447c622ffe8804ec2d395a5f43e01b93455e9 Mon Sep 17 00:00:00 2001
From: cowlicks <cowlicks@riseup.net>
Date: Wed, 10 Apr 2024 12:57:24 -0500
Subject: [PATCH 34/47] Fix typo in needless_borrows_for_generic_args.rs

---
 clippy_lints/src/needless_borrows_for_generic_args.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clippy_lints/src/needless_borrows_for_generic_args.rs b/clippy_lints/src/needless_borrows_for_generic_args.rs
index c555fc8675c..a24cd4f9c8a 100644
--- a/clippy_lints/src/needless_borrows_for_generic_args.rs
+++ b/clippy_lints/src/needless_borrows_for_generic_args.rs
@@ -23,7 +23,7 @@ use std::collections::VecDeque;
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for borrow operations (`&`) that used as a generic argument to a
+    /// Checks for borrow operations (`&`) that are used as a generic argument to a
     /// function when the borrowed value could be used.
     ///
     /// ### Why is this bad?

From fb2e827c648a78d9e614dc47bc2c4a7c7a9e40b6 Mon Sep 17 00:00:00 2001
From: Alex Macleod <alex@macleod.io>
Date: Thu, 11 Apr 2024 14:17:10 +0000
Subject: [PATCH 35/47] Pin remark-lint-maximum-line-length version

---
 .github/workflows/remark.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/remark.yml b/.github/workflows/remark.yml
index 05e1b3b9202..348d52020fd 100644
--- a/.github/workflows/remark.yml
+++ b/.github/workflows/remark.yml
@@ -24,7 +24,7 @@ jobs:
         node-version: '18.x'
 
     - name: Install remark
-      run: npm install remark-cli remark-lint remark-lint-maximum-line-length remark-preset-lint-recommended remark-gfm
+      run: npm install remark-cli remark-lint remark-lint-maximum-line-length@^3.1.3 remark-preset-lint-recommended remark-gfm
 
     - name: Install mdbook
       run: |

From da0ae33c15a85472985ca0e3630cbe88859bb845 Mon Sep 17 00:00:00 2001
From: Luv-Ray <zhuoxun.yang777@outlook.com>
Date: Sat, 13 Apr 2024 14:35:44 +0800
Subject: [PATCH 36/47] [`ptr_as_ptr`]: Fix duplicate errors

---
 clippy_lints/src/casts/mod.rs     |  1 -
 tests/ui/crashes/ice-12616.stderr | 10 +----
 tests/ui/ptr_as_ptr.fixed         |  1 -
 tests/ui/ptr_as_ptr.rs            |  1 -
 tests/ui/ptr_as_ptr.stderr        | 66 +++++++++++++++----------------
 5 files changed, 34 insertions(+), 45 deletions(-)

diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index a87102b6bf4..d14898a8196 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -757,7 +757,6 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
         if in_external_macro(cx.sess(), expr.span) {
             return;
         }
-        ptr_as_ptr::check(cx, expr, &self.msrv);
 
         if let ExprKind::Cast(cast_expr, cast_to_hir) = expr.kind {
             if is_hir_ty_cfg_dependant(cx, cast_to_hir) {
diff --git a/tests/ui/crashes/ice-12616.stderr b/tests/ui/crashes/ice-12616.stderr
index ef573f55cf3..c7cf5cf5483 100644
--- a/tests/ui/crashes/ice-12616.stderr
+++ b/tests/ui/crashes/ice-12616.stderr
@@ -7,13 +7,5 @@ LL |     s() as *const ();
    = note: `-D clippy::ptr-as-ptr` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::ptr_as_ptr)]`
 
-error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/crashes/ice-12616.rs:6:5
-   |
-LL |     s() as *const ();
-   |     ^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `s().cast::<()>()`
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/ptr_as_ptr.fixed b/tests/ui/ptr_as_ptr.fixed
index 61d37b8ba3a..fa15c323540 100644
--- a/tests/ui/ptr_as_ptr.fixed
+++ b/tests/ui/ptr_as_ptr.fixed
@@ -1,5 +1,4 @@
 //@aux-build:proc_macros.rs
-//@compile-flags: -Zdeduplicate-diagnostics=yes
 
 #![warn(clippy::ptr_as_ptr)]
 
diff --git a/tests/ui/ptr_as_ptr.rs b/tests/ui/ptr_as_ptr.rs
index 8f2068cd268..7ab52e63da5 100644
--- a/tests/ui/ptr_as_ptr.rs
+++ b/tests/ui/ptr_as_ptr.rs
@@ -1,5 +1,4 @@
 //@aux-build:proc_macros.rs
-//@compile-flags: -Zdeduplicate-diagnostics=yes
 
 #![warn(clippy::ptr_as_ptr)]
 
diff --git a/tests/ui/ptr_as_ptr.stderr b/tests/ui/ptr_as_ptr.stderr
index e6cd697c7ba..e162f35baf5 100644
--- a/tests/ui/ptr_as_ptr.stderr
+++ b/tests/ui/ptr_as_ptr.stderr
@@ -1,5 +1,5 @@
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:19:33
+  --> tests/ui/ptr_as_ptr.rs:18:33
    |
 LL |         *unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::issue_11278_a::T<String>) }
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `Box::into_raw(Box::new(o)).cast::<super::issue_11278_a::T<String>>()`
@@ -8,37 +8,37 @@ LL |         *unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::i
    = help: to override `-D warnings` add `#[allow(clippy::ptr_as_ptr)]`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:28:13
+  --> tests/ui/ptr_as_ptr.rs:27:13
    |
 LL |     let _ = ptr as *const i32;
    |             ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:29:13
+  --> tests/ui/ptr_as_ptr.rs:28:13
    |
 LL |     let _ = mut_ptr as *mut i32;
    |             ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:34:17
+  --> tests/ui/ptr_as_ptr.rs:33:17
    |
 LL |         let _ = *ptr_ptr as *const i32;
    |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `(*ptr_ptr).cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:47:25
+  --> tests/ui/ptr_as_ptr.rs:46:25
    |
 LL |     let _: *const i32 = ptr as *const _;
    |                         ^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:48:23
+  --> tests/ui/ptr_as_ptr.rs:47:23
    |
 LL |     let _: *mut i32 = mut_ptr as _;
    |                       ^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:51:21
+  --> tests/ui/ptr_as_ptr.rs:50:21
    |
 LL |     let _ = inline!($ptr as *const i32);
    |                     ^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `$ptr.cast::<i32>()`
@@ -46,157 +46,157 @@ LL |     let _ = inline!($ptr as *const i32);
    = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:72:13
+  --> tests/ui/ptr_as_ptr.rs:71:13
    |
 LL |     let _ = ptr as *const i32;
    |             ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:73:13
+  --> tests/ui/ptr_as_ptr.rs:72:13
    |
 LL |     let _ = mut_ptr as *mut i32;
    |             ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:80:9
+  --> tests/ui/ptr_as_ptr.rs:79:9
    |
 LL |         ptr::null_mut() as *mut u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:84:9
+  --> tests/ui/ptr_as_ptr.rs:83:9
    |
 LL |         std::ptr::null_mut() as *mut u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut::<u32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:89:9
+  --> tests/ui/ptr_as_ptr.rs:88:9
    |
 LL |         ptr::null_mut() as *mut u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:93:9
+  --> tests/ui/ptr_as_ptr.rs:92:9
    |
 LL |         core::ptr::null_mut() as *mut u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut::<u32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:98:9
+  --> tests/ui/ptr_as_ptr.rs:97:9
    |
 LL |         ptr::null() as *const u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:102:9
+  --> tests/ui/ptr_as_ptr.rs:101:9
    |
 LL |         std::ptr::null() as *const u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null::<u32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:107:9
+  --> tests/ui/ptr_as_ptr.rs:106:9
    |
 LL |         ptr::null() as *const u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:111:9
+  --> tests/ui/ptr_as_ptr.rs:110:9
    |
 LL |         core::ptr::null() as *const u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null::<u32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:118:9
+  --> tests/ui/ptr_as_ptr.rs:117:9
    |
 LL |         ptr::null_mut() as *mut _
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:122:9
+  --> tests/ui/ptr_as_ptr.rs:121:9
    |
 LL |         std::ptr::null_mut() as *mut _
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:127:9
+  --> tests/ui/ptr_as_ptr.rs:126:9
    |
 LL |         ptr::null_mut() as *mut _
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:131:9
+  --> tests/ui/ptr_as_ptr.rs:130:9
    |
 LL |         core::ptr::null_mut() as *mut _
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:136:9
+  --> tests/ui/ptr_as_ptr.rs:135:9
    |
 LL |         ptr::null() as *const _
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:140:9
+  --> tests/ui/ptr_as_ptr.rs:139:9
    |
 LL |         std::ptr::null() as *const _
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:145:9
+  --> tests/ui/ptr_as_ptr.rs:144:9
    |
 LL |         ptr::null() as *const _
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:149:9
+  --> tests/ui/ptr_as_ptr.rs:148:9
    |
 LL |         core::ptr::null() as *const _
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:156:9
+  --> tests/ui/ptr_as_ptr.rs:155:9
    |
 LL |         ptr::null_mut() as _
    |         ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:160:9
+  --> tests/ui/ptr_as_ptr.rs:159:9
    |
 LL |         std::ptr::null_mut() as _
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:165:9
+  --> tests/ui/ptr_as_ptr.rs:164:9
    |
 LL |         ptr::null_mut() as _
    |         ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:169:9
+  --> tests/ui/ptr_as_ptr.rs:168:9
    |
 LL |         core::ptr::null_mut() as _
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:174:9
+  --> tests/ui/ptr_as_ptr.rs:173:9
    |
 LL |         ptr::null() as _
    |         ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:178:9
+  --> tests/ui/ptr_as_ptr.rs:177:9
    |
 LL |         std::ptr::null() as _
    |         ^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:183:9
+  --> tests/ui/ptr_as_ptr.rs:182:9
    |
 LL |         ptr::null() as _
    |         ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:187:9
+  --> tests/ui/ptr_as_ptr.rs:186:9
    |
 LL |         core::ptr::null() as _
    |         ^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()`

From 735f2c6f92dc4dfd23b41550342f91d61b62b5da Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Thu, 4 Apr 2024 20:52:56 -0400
Subject: [PATCH 37/47] Rustfmt, clippy

---
 clippy_utils/src/ast_utils.rs | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs
index f594a40ff59..9f0bd4ea7e2 100644
--- a/clippy_utils/src/ast_utils.rs
+++ b/clippy_utils/src/ast_utils.rs
@@ -709,7 +709,8 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool {
         (Tup(l), Tup(r)) => over(l, r, |l, r| eq_ty(l, r)),
         (Path(lq, lp), Path(rq, rp)) => both(lq, rq, eq_qself) && eq_path(lp, rp),
         (TraitObject(lg, ls), TraitObject(rg, rs)) => ls == rs && over(lg, rg, eq_generic_bound),
-        (ImplTrait(_, lg), ImplTrait(_, rg)) => over(lg, rg, eq_generic_bound),
+        (ImplTrait(_, lg, lc), ImplTrait(_, rg, rc)) =>
+            over(lg, rg, eq_generic_bound) && both(lc, rc, |lc, rc| over(lc.0.as_slice(), rc.0.as_slice(), eq_precise_capture)),
         (Typeof(l), Typeof(r)) => eq_expr(&l.value, &r.value),
         (MacCall(l), MacCall(r)) => eq_mac_call(l, r),
         _ => false,
@@ -770,6 +771,14 @@ pub fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool {
     }
 }
 
+pub fn eq_precise_capture(l: &PreciseCapturingArg, r: &PreciseCapturingArg) -> bool {
+    match (l, r) {
+        (PreciseCapturingArg::Lifetime(l), PreciseCapturingArg::Lifetime(r)) => l.ident == r.ident,
+        (PreciseCapturingArg::Arg(l, _), PreciseCapturingArg::Arg(r, _)) => l.segments[0].ident == r.segments[0].ident,
+        _ => false,
+    }
+}
+
 fn eq_term(l: &Term, r: &Term) -> bool {
     match (l, r) {
         (Term::Ty(l), Term::Ty(r)) => eq_ty(l, r),

From febf858c23a221977c80b1ff89443fc2229f94fd Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 24 Mar 2024 12:47:01 -0400
Subject: [PATCH 38/47] Remove TypeVariableOriginKind

---
 clippy_utils/src/ty.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs
index ab1be66dc78..1afc5ed0157 100644
--- a/clippy_utils/src/ty.rs
+++ b/clippy_utils/src/ty.rs
@@ -10,7 +10,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety};
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::type_variable::{TypeVariableOrigin};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::mir::interpret::Scalar;
@@ -276,8 +276,8 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
         .map(|arg| {
             arg.into().unwrap_or_else(|| {
                 let orig = TypeVariableOrigin {
-                    kind: TypeVariableOriginKind::MiscVariable,
                     span: DUMMY_SP,
+                    param_def_id: None,
                 };
                 infcx.next_ty_var(orig).into()
             })

From 1703109ba0e48505e50273c4309b97fd2dc8c86e Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 14 Apr 2024 11:04:18 -0400
Subject: [PATCH 39/47] Fix clippy

---
 clippy_lints/src/casts/ptr_as_ptr.rs           | 2 +-
 clippy_lints/src/matches/match_wild_err_arm.rs | 2 +-
 clippy_lints/src/mut_reference.rs              | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/clippy_lints/src/casts/ptr_as_ptr.rs b/clippy_lints/src/casts/ptr_as_ptr.rs
index 68841076f77..2c168405ee2 100644
--- a/clippy_lints/src/casts/ptr_as_ptr.rs
+++ b/clippy_lints/src/casts/ptr_as_ptr.rs
@@ -77,7 +77,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
 
         let (help, final_suggestion) = if let Some(method) = omit_cast.corresponding_item() {
             // don't force absolute path
-            let method = qpath_to_string(method);
+            let method = qpath_to_string(&cx.tcx, method);
             ("try call directly", format!("{method}{turbofish}()"))
         } else {
             let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app);
diff --git a/clippy_lints/src/matches/match_wild_err_arm.rs b/clippy_lints/src/matches/match_wild_err_arm.rs
index d1f637ec78c..310675d01a2 100644
--- a/clippy_lints/src/matches/match_wild_err_arm.rs
+++ b/clippy_lints/src/matches/match_wild_err_arm.rs
@@ -19,7 +19,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'
     if is_type_diagnostic_item(cx, ex_ty, sym::Result) {
         for arm in arms {
             if let PatKind::TupleStruct(ref path, inner, _) = arm.pat.kind {
-                let path_str = rustc_hir_pretty::qpath_to_string(path);
+                let path_str = rustc_hir_pretty::qpath_to_string(&cx.tcx, path);
                 if path_str == "Err" {
                     let mut matching_wild = inner.iter().any(is_wild);
                     let mut ident_bind_name = kw::Underscore;
diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs
index 6867f76a723..0a3b769c3e6 100644
--- a/clippy_lints/src/mut_reference.rs
+++ b/clippy_lints/src/mut_reference.rs
@@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed {
                         cx,
                         arguments.iter().collect(),
                         cx.typeck_results().expr_ty(fn_expr),
-                        &rustc_hir_pretty::qpath_to_string(path),
+                        &rustc_hir_pretty::qpath_to_string(&cx.tcx, path),
                         "function",
                     );
                 }

From 3e1136049706c90ae6ab30bfaf8c63839059aa36 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <n.nethercote@gmail.com>
Date: Thu, 21 Mar 2024 14:17:00 +1100
Subject: [PATCH 40/47] Construct `SourceMap` at the same time as
 `SessionGlobals`.

Currently `SourceMap` is constructed slightly later than
`SessionGlobals`, and inserted. This commit changes things so they are
done at the same time.

Benefits:
- `SessionGlobals::source_map` changes from
  `Lock<Option<Lrc<SourceMap>>>` to `Option<Lrc<SourceMap>>`. It's still
  optional, but mutability isn't required because it's initialized at
  construction.
- `set_source_map` is removed, simplifying `run_compiler`, which is
  good because that's a critical function and it's nice to make it
  simpler.

This requires moving things around a bit, so the necessary inputs are
available when `SessionGlobals` is created, in particular the `loader`
and `hash_kind`, which are no longer computed by `build_session`. These
inputs are captured by the new `SourceMapInputs` type, which is threaded
through various places.
---
 clippy_lints/src/doc/needless_doctest_main.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clippy_lints/src/doc/needless_doctest_main.rs b/clippy_lints/src/doc/needless_doctest_main.rs
index e55a988321b..651f2ebaee6 100644
--- a/clippy_lints/src/doc/needless_doctest_main.rs
+++ b/clippy_lints/src/doc/needless_doctest_main.rs
@@ -38,7 +38,7 @@ pub fn check(
     // of all `#[test]` attributes in not ignored code examples
     fn check_code_sample(code: String, edition: Edition, ignore: bool) -> (bool, Vec<Range<usize>>) {
         rustc_driver::catch_fatal_errors(|| {
-            rustc_span::create_session_globals_then(edition, || {
+            rustc_span::create_session_globals_then(edition, None, || {
                 let mut test_attr_spans = vec![];
                 let filename = FileName::anon_source_code(&code);
 

From b64c5f991c0d9c84f7ca6c61fba561d150d5ac4c Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <n.nethercote@gmail.com>
Date: Wed, 6 Mar 2024 16:39:02 +1100
Subject: [PATCH 41/47] Avoid unnecessary `rustc_span::DUMMY_SP` usage.

In some cases `DUMMY_SP` is already imported. In other cases this commit
adds the necessary import, in files where `DUMMY_SP` is used more than
once.
---
 clippy_lints/src/non_copy_const.rs | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs
index 73fc34c2450..5ca388d67a1 100644
--- a/clippy_lints/src/non_copy_const.rs
+++ b/clippy_lints/src/non_copy_const.rs
@@ -18,7 +18,7 @@ use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult, GlobalId};
 use rustc_middle::ty::adjustment::Adjust;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, InnerSpan, Span};
+use rustc_span::{sym, DUMMY_SP, InnerSpan, Span};
 use rustc_target::abi::VariantIdx;
 
 // FIXME: this is a correctness problem but there's no suitable
@@ -290,9 +290,7 @@ impl NonCopyConst {
             promoted: None,
         };
         let param_env = cx.tcx.param_env(def_id).with_reveal_all_normalized(cx.tcx);
-        let result = cx
-            .tcx
-            .const_eval_global_id_for_typeck(param_env, cid, rustc_span::DUMMY_SP);
+        let result = cx.tcx.const_eval_global_id_for_typeck(param_env, cid, DUMMY_SP);
         self.is_value_unfrozen_raw(cx, result, ty)
     }
 
@@ -303,7 +301,7 @@ impl NonCopyConst {
             cx.tcx,
             cx.param_env,
             ty::UnevaluatedConst::new(def_id, args),
-            rustc_span::DUMMY_SP,
+            DUMMY_SP,
         );
         self.is_value_unfrozen_raw(cx, result, ty)
     }

From c0bc81222785d078cbd29efeb2086ff2638ef819 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <n.nethercote@gmail.com>
Date: Wed, 6 Mar 2024 16:54:36 +1100
Subject: [PATCH 42/47] Always use `ty::` qualifier for `TyKind` enum variants.

Because that's the way it should be done.
---
 clippy_lints/src/derivable_impls.rs          | 6 +++---
 clippy_lints/src/from_raw_with_void_ptr.rs   | 4 ++--
 clippy_lints/src/functions/result.rs         | 6 +++---
 clippy_lints/src/implicit_saturating_add.rs  | 3 ++-
 clippy_lints/src/large_enum_variant.rs       | 6 +++---
 clippy_lints/src/methods/unnecessary_join.rs | 6 +++---
 clippy_lints/src/mut_key.rs                  | 4 ++--
 clippy_lints/src/zero_sized_map_values.rs    | 4 ++--
 8 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs
index 80327586fed..0c9ad5e8d00 100644
--- a/clippy_lints/src/derivable_impls.rs
+++ b/clippy_lints/src/derivable_impls.rs
@@ -9,7 +9,7 @@ use rustc_hir::{
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::adjustment::{Adjust, PointerCoercion};
-use rustc_middle::ty::{self, Adt, AdtDef, GenericArgsRef, Ty, TypeckResults};
+use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty, TypeckResults};
 use rustc_session::impl_lint_pass;
 use rustc_span::sym;
 
@@ -79,7 +79,7 @@ fn is_path_self(e: &Expr<'_>) -> bool {
 fn contains_trait_object(ty: Ty<'_>) -> bool {
     match ty.kind() {
         ty::Ref(_, ty, _) => contains_trait_object(*ty),
-        Adt(def, args) => def.is_box() && args[0].as_type().map_or(false, contains_trait_object),
+        ty::Adt(def, args) => def.is_box() && args[0].as_type().map_or(false, contains_trait_object),
         ty::Dynamic(..) => true,
         _ => false,
     }
@@ -198,7 +198,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
             && let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir)
             && let ImplItemKind::Fn(_, b) = &impl_item.kind
             && let Body { value: func_expr, .. } = cx.tcx.hir().body(*b)
-            && let &Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
+            && let &ty::Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
             && let attrs = cx.tcx.hir().attrs(item.hir_id())
             && !attrs.iter().any(|attr| attr.doc_str().is_some())
             && cx.tcx.hir().attrs(impl_item_hir).is_empty()
diff --git a/clippy_lints/src/from_raw_with_void_ptr.rs b/clippy_lints/src/from_raw_with_void_ptr.rs
index ba2495c17a2..d62d008d480 100644
--- a/clippy_lints/src/from_raw_with_void_ptr.rs
+++ b/clippy_lints/src/from_raw_with_void_ptr.rs
@@ -4,7 +4,7 @@ use clippy_utils::ty::is_c_void;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::RawPtr;
+use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
 use rustc_span::sym;
 
@@ -44,7 +44,7 @@ impl LateLintPass<'_> for FromRawWithVoidPtr {
             && seg.ident.name == sym!(from_raw)
             && let Some(type_str) = path_def_id(cx, ty).and_then(|id| def_id_matches_type(cx, id))
             && let arg_kind = cx.typeck_results().expr_ty(arg).kind()
-            && let RawPtr(ty, _) = arg_kind
+            && let ty::RawPtr(ty, _) = arg_kind
             && is_c_void(cx, *ty)
         {
             let msg = format!("creating a `{type_str}` from a void raw pointer");
diff --git a/clippy_lints/src/functions/result.rs b/clippy_lints/src/functions/result.rs
index 93f088d3e33..c3a0b40a677 100644
--- a/clippy_lints/src/functions/result.rs
+++ b/clippy_lints/src/functions/result.rs
@@ -2,7 +2,7 @@ use rustc_errors::Diag;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{Adt, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_span::{sym, Span};
 
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
@@ -25,7 +25,7 @@ fn result_err_ty<'tcx>(
             .tcx
             .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(id).instantiate_identity().output())
         && is_type_diagnostic_item(cx, ty, sym::Result)
-        && let Adt(_, args) = ty.kind()
+        && let ty::Adt(_, args) = ty.kind()
     {
         let err_ty = args.type_at(1);
         Some((hir_ty, err_ty))
@@ -86,7 +86,7 @@ fn check_result_unit_err(cx: &LateContext<'_>, err_ty: Ty<'_>, fn_header_span: S
 }
 
 fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty_span: Span, large_err_threshold: u64) {
-    if let Adt(adt, subst) = err_ty.kind()
+    if let ty::Adt(adt, subst) = err_ty.kind()
         && let Some(local_def_id) = err_ty
             .ty_adt_def()
             .expect("already checked this is adt")
diff --git a/clippy_lints/src/implicit_saturating_add.rs b/clippy_lints/src/implicit_saturating_add.rs
index b8d7e8f3b07..f225c6e7f04 100644
--- a/clippy_lints/src/implicit_saturating_add.rs
+++ b/clippy_lints/src/implicit_saturating_add.rs
@@ -7,7 +7,7 @@ use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{Int, IntTy, Ty, Uint, UintTy};
+use rustc_middle::ty::{IntTy, Ty, UintTy};
 use rustc_session::declare_lint_pass;
 
 declare_clippy_lint! {
@@ -97,6 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingAdd {
 }
 
 fn get_int_max(ty: Ty<'_>) -> Option<u128> {
+    use rustc_middle::ty::{Int, Uint};
     match ty.peel_refs().kind() {
         Int(IntTy::I8) => i8::MAX.try_into().ok(),
         Int(IntTy::I16) => i16::MAX.try_into().ok(),
diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs
index 6feb1885576..0bf7389ef9c 100644
--- a/clippy_lints/src/large_enum_variant.rs
+++ b/clippy_lints/src/large_enum_variant.rs
@@ -7,7 +7,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{Adt, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_session::impl_lint_pass;
 use rustc_span::Span;
 
@@ -82,7 +82,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
         }
         if let ItemKind::Enum(ref def, _) = item.kind {
             let ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
-            let Adt(adt, subst) = ty.kind() else {
+            let ty::Adt(adt, subst) = ty.kind() else {
                 panic!("already checked whether this is an enum")
             };
             if adt.variants().len() <= 1 {
@@ -167,7 +167,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
 }
 
 fn maybe_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
-    if let Adt(_def, args) = ty.kind()
+    if let ty::Adt(_def, args) = ty.kind()
         && args.types().next().is_some()
         && let Some(copy_trait) = cx.tcx.lang_items().copy_trait()
     {
diff --git a/clippy_lints/src/methods/unnecessary_join.rs b/clippy_lints/src/methods/unnecessary_join.rs
index c3ad4db3875..efd1a718504 100644
--- a/clippy_lints/src/methods/unnecessary_join.rs
+++ b/clippy_lints/src/methods/unnecessary_join.rs
@@ -4,7 +4,7 @@ use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem};
 use rustc_lint::LateContext;
-use rustc_middle::ty::{Ref, Slice};
+use rustc_middle::ty;
 use rustc_span::Span;
 
 use super::UNNECESSARY_JOIN;
@@ -18,9 +18,9 @@ pub(super) fn check<'tcx>(
 ) {
     let applicability = Applicability::MachineApplicable;
     let collect_output_adjusted_type = cx.typeck_results().expr_ty_adjusted(join_self_arg);
-    if let Ref(_, ref_type, _) = collect_output_adjusted_type.kind()
+    if let ty::Ref(_, ref_type, _) = collect_output_adjusted_type.kind()
         // the turbofish for collect is ::<Vec<String>>
-        && let Slice(slice) = ref_type.kind()
+        && let ty::Slice(slice) = ref_type.kind()
         && is_type_lang_item(cx, *slice, LangItem::String)
         // the argument for join is ""
         && let ExprKind::Lit(spanned) = &join_arg.kind
diff --git a/clippy_lints/src/mut_key.rs b/clippy_lints/src/mut_key.rs
index 79f0a398d55..8c2f43c97f4 100644
--- a/clippy_lints/src/mut_key.rs
+++ b/clippy_lints/src/mut_key.rs
@@ -4,7 +4,7 @@ use clippy_utils::{def_path_def_ids, trait_ref_of_method};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{Adt, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::sym;
@@ -153,7 +153,7 @@ impl MutableKeyType {
     // generics (because the compiler cannot ensure immutability for unknown types).
     fn check_ty_<'tcx>(&self, cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) {
         let ty = ty.peel_refs();
-        if let Adt(def, args) = ty.kind() {
+        if let ty::Adt(def, args) = ty.kind() {
             let is_keyed_type = [sym::HashMap, sym::BTreeMap, sym::HashSet, sym::BTreeSet]
                 .iter()
                 .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did()));
diff --git a/clippy_lints/src/zero_sized_map_values.rs b/clippy_lints/src/zero_sized_map_values.rs
index d1f7c6417c7..e14480b8655 100644
--- a/clippy_lints/src/zero_sized_map_values.rs
+++ b/clippy_lints/src/zero_sized_map_values.rs
@@ -4,7 +4,7 @@ use rustc_hir::{self as hir, HirId, ItemKind, Node};
 use rustc_hir_analysis::lower_ty;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::layout::LayoutOf as _;
-use rustc_middle::ty::{Adt, Ty, TypeVisitableExt};
+use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_session::declare_lint_pass;
 use rustc_span::sym;
 
@@ -49,7 +49,7 @@ impl LateLintPass<'_> for ZeroSizedMapValues {
             && !in_trait_impl(cx, hir_ty.hir_id)
             && let ty = ty_from_hir_ty(cx, hir_ty)
             && (is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap))
-            && let Adt(_, args) = ty.kind()
+            && let ty::Adt(_, args) = ty.kind()
             && let ty = args.type_at(1)
             // Fixes https://github.com/rust-lang/rust-clippy/issues/7447 because of
             // https://github.com/rust-lang/rust/blob/master/compiler/rustc_middle/src/ty/sty.rs#L968

From 0aea3edb3864c25dd80987810653f96118770a3e Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <n.nethercote@gmail.com>
Date: Wed, 6 Mar 2024 17:24:13 +1100
Subject: [PATCH 43/47] Avoid lots of `hir::HirId{,Map,Set}` qualifiers.

Because they're a bit redundant.
---
 .../src/functions/not_unsafe_ptr_arg_deref.rs |  4 +--
 clippy_lints/src/index_refutable_slice.rs     | 13 ++++----
 .../src/operators/assign_op_pattern.rs        | 33 ++++++++++---------
 clippy_lints/src/ptr.rs                       |  4 +--
 .../src/significant_drop_tightening.rs        | 18 +++++-----
 5 files changed, 37 insertions(+), 35 deletions(-)

diff --git a/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
index 2d757883f26..995dd782cbb 100644
--- a/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
+++ b/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
@@ -1,4 +1,4 @@
-use rustc_hir::{self as hir, intravisit, HirIdSet};
+use rustc_hir::{self as hir, intravisit, HirId, HirIdSet};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_span::def_id::LocalDefId;
@@ -74,7 +74,7 @@ fn check_raw_ptr<'tcx>(
     }
 }
 
-fn raw_ptr_arg(cx: &LateContext<'_>, arg: &hir::Param<'_>) -> Option<hir::HirId> {
+fn raw_ptr_arg(cx: &LateContext<'_>, arg: &hir::Param<'_>) -> Option<HirId> {
     if let (&hir::PatKind::Binding(_, id, _, _), Some(&ty::RawPtr(_, _))) = (
         &arg.pat.kind,
         cx.maybe_typeck_results()
diff --git a/clippy_lints/src/index_refutable_slice.rs b/clippy_lints/src/index_refutable_slice.rs
index 4d1f89b1d9d..6ddc8346511 100644
--- a/clippy_lints/src/index_refutable_slice.rs
+++ b/clippy_lints/src/index_refutable_slice.rs
@@ -7,6 +7,7 @@ use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_hir::HirId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
@@ -87,9 +88,9 @@ impl<'tcx> LateLintPass<'tcx> for IndexRefutableSlice {
     extract_msrv_attr!(LateContext);
 }
 
-fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap<hir::HirId, SliceLintInformation> {
-    let mut removed_pat: FxHashSet<hir::HirId> = FxHashSet::default();
-    let mut slices: FxIndexMap<hir::HirId, SliceLintInformation> = FxIndexMap::default();
+fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap<HirId, SliceLintInformation> {
+    let mut removed_pat: FxHashSet<HirId> = FxHashSet::default();
+    let mut slices: FxIndexMap<HirId, SliceLintInformation> = FxIndexMap::default();
     pat.walk_always(|pat| {
         // We'll just ignore mut and ref mut for simplicity sake right now
         if let hir::PatKind::Binding(
@@ -206,10 +207,10 @@ impl SliceLintInformation {
 
 fn filter_lintable_slices<'tcx>(
     cx: &LateContext<'tcx>,
-    slice_lint_info: FxIndexMap<hir::HirId, SliceLintInformation>,
+    slice_lint_info: FxIndexMap<HirId, SliceLintInformation>,
     max_suggested_slice: u64,
     scope: &'tcx hir::Expr<'tcx>,
-) -> FxIndexMap<hir::HirId, SliceLintInformation> {
+) -> FxIndexMap<HirId, SliceLintInformation> {
     let mut visitor = SliceIndexLintingVisitor {
         cx,
         slice_lint_info,
@@ -223,7 +224,7 @@ fn filter_lintable_slices<'tcx>(
 
 struct SliceIndexLintingVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
-    slice_lint_info: FxIndexMap<hir::HirId, SliceLintInformation>,
+    slice_lint_info: FxIndexMap<HirId, SliceLintInformation>,
     max_suggested_slice: u64,
 }
 
diff --git a/clippy_lints/src/operators/assign_op_pattern.rs b/clippy_lints/src/operators/assign_op_pattern.rs
index 2f85130fba1..435eb9048f5 100644
--- a/clippy_lints/src/operators/assign_op_pattern.rs
+++ b/clippy_lints/src/operators/assign_op_pattern.rs
@@ -6,6 +6,7 @@ use clippy_utils::{binop_traits, eq_expr_value, trait_ref_of_method};
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_hir::{HirId, HirIdSet};
 use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 use rustc_lint::LateContext;
 use rustc_middle::mir::FakeReadCause;
@@ -98,10 +99,10 @@ pub(super) fn check<'tcx>(
     }
 }
 
-fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet {
-    struct S(hir::HirIdSet);
+fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
+    struct S(HirIdSet);
     impl Delegate<'_> for S {
-        fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: hir::HirId, kind: BorrowKind) {
+        fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: HirId, kind: BorrowKind) {
             if matches!(kind, BorrowKind::ImmBorrow | BorrowKind::UniqueImmBorrow) {
                 self.0.insert(match place.place.base {
                     PlaceBase::Local(id) => id,
@@ -111,13 +112,13 @@ fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet
             }
         }
 
-        fn consume(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
-        fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
-        fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: hir::HirId) {}
-        fn copy(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
+        fn consume(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
+        fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
+        fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: HirId) {}
+        fn copy(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
     }
 
-    let mut s = S(hir::HirIdSet::default());
+    let mut s = S(HirIdSet::default());
     let infcx = cx.tcx.infer_ctxt().build();
     let mut v = ExprUseVisitor::new(
         &mut s,
@@ -130,10 +131,10 @@ fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet
     s.0
 }
 
-fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet {
-    struct S(hir::HirIdSet);
+fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
+    struct S(HirIdSet);
     impl Delegate<'_> for S {
-        fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: hir::HirId, kind: BorrowKind) {
+        fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: HirId, kind: BorrowKind) {
             if matches!(kind, BorrowKind::MutBorrow) {
                 self.0.insert(match place.place.base {
                     PlaceBase::Local(id) => id,
@@ -143,13 +144,13 @@ fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet
             }
         }
 
-        fn consume(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
-        fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
-        fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: hir::HirId) {}
-        fn copy(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
+        fn consume(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
+        fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
+        fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: HirId) {}
+        fn copy(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
     }
 
-    let mut s = S(hir::HirIdSet::default());
+    let mut s = S(HirIdSet::default());
     let infcx = cx.tcx.infer_ctxt().build();
     let mut v = ExprUseVisitor::new(
         &mut s,
diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs
index 83b32000a9f..d6592622f0b 100644
--- a/clippy_lints/src/ptr.rs
+++ b/clippy_lints/src/ptr.rs
@@ -8,7 +8,7 @@ use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_i
 use hir::LifetimeName;
 use rustc_errors::{Applicability, MultiSpan};
 use rustc_hir::def_id::DefId;
-use rustc_hir::hir_id::HirIdMap;
+use rustc_hir::hir_id::{HirId, HirIdMap};
 use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{
     self as hir, AnonConst, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg,
@@ -324,7 +324,7 @@ struct PtrArgReplacement {
 
 struct PtrArg<'tcx> {
     idx: usize,
-    emission_id: hir::HirId,
+    emission_id: HirId,
     span: Span,
     ty_did: DefId,
     ty_name: Symbol,
diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs
index d3540bc8e1c..038eb92d652 100644
--- a/clippy_lints/src/significant_drop_tightening.rs
+++ b/clippy_lints/src/significant_drop_tightening.rs
@@ -5,7 +5,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::{self as hir};
+use rustc_hir::{self as hir, HirId};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty::{GenericArgKind, Ty};
 use rustc_session::impl_lint_pass;
@@ -55,7 +55,7 @@ impl_lint_pass!(SignificantDropTightening<'_> => [SIGNIFICANT_DROP_TIGHTENING]);
 
 #[derive(Default)]
 pub struct SignificantDropTightening<'tcx> {
-    apas: FxIndexMap<hir::HirId, AuxParamsAttr>,
+    apas: FxIndexMap<HirId, AuxParamsAttr>,
     /// Auxiliary structure used to avoid having to verify the same type multiple times.
     seen_types: FxHashSet<Ty<'tcx>>,
     type_cache: FxHashMap<Ty<'tcx>, bool>,
@@ -359,9 +359,9 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'o
 /// Auxiliary parameters used on each block check of an item
 struct AuxParams<'others, 'stmt, 'tcx> {
     //// See [AuxParamsAttr].
-    apas: &'others mut FxIndexMap<hir::HirId, AuxParamsAttr>,
+    apas: &'others mut FxIndexMap<HirId, AuxParamsAttr>,
     /// The current block identifier that is being visited.
-    curr_block_hir_id: hir::HirId,
+    curr_block_hir_id: HirId,
     /// The current block span that is being visited.
     curr_block_span: Span,
     /// The current statement that is being visited.
@@ -369,10 +369,10 @@ struct AuxParams<'others, 'stmt, 'tcx> {
 }
 
 impl<'others, 'stmt, 'tcx> AuxParams<'others, 'stmt, 'tcx> {
-    fn new(apas: &'others mut FxIndexMap<hir::HirId, AuxParamsAttr>, curr_stmt: &'stmt hir::Stmt<'tcx>) -> Self {
+    fn new(apas: &'others mut FxIndexMap<HirId, AuxParamsAttr>, curr_stmt: &'stmt hir::Stmt<'tcx>) -> Self {
         Self {
             apas,
-            curr_block_hir_id: hir::HirId::INVALID,
+            curr_block_hir_id: HirId::INVALID,
             curr_block_span: DUMMY_SP,
             curr_stmt: Cow::Borrowed(curr_stmt),
         }
@@ -389,7 +389,7 @@ struct AuxParamsAttr {
     has_expensive_expr_after_last_attr: bool,
 
     /// The identifier of the block that involves the first `#[has_significant_drop]`.
-    first_block_hir_id: hir::HirId,
+    first_block_hir_id: HirId,
     /// The span of the block that involves the first `#[has_significant_drop]`.
     first_block_span: Span,
     /// The binding or variable that references the initial construction of the type marked with
@@ -414,7 +414,7 @@ impl Default for AuxParamsAttr {
         Self {
             counter: 0,
             has_expensive_expr_after_last_attr: false,
-            first_block_hir_id: hir::HirId::INVALID,
+            first_block_hir_id: HirId::INVALID,
             first_bind_ident: Ident::empty(),
             first_block_span: DUMMY_SP,
             first_method_span: DUMMY_SP,
@@ -428,7 +428,7 @@ impl Default for AuxParamsAttr {
 
 fn dummy_stmt_expr<'any>(expr: &'any hir::Expr<'any>) -> hir::Stmt<'any> {
     hir::Stmt {
-        hir_id: hir::HirId::INVALID,
+        hir_id: HirId::INVALID,
         kind: hir::StmtKind::Expr(expr),
         span: DUMMY_SP,
     }

From ae37fa89b458475a8f724bde8432afd19b4951a4 Mon Sep 17 00:00:00 2001
From: Philipp Krones <hello@philkrones.com>
Date: Tue, 16 Apr 2024 17:46:43 +0200
Subject: [PATCH 44/47] Bump nightly version -> 2024-04-05

---
 rust-toolchain | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rust-toolchain b/rust-toolchain
index b2fe5c8bee7..fc476c50ee6 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2024-04-04"
+channel = "nightly-2024-04-05"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]

From 1fff3bef4de408bdea2dd005755770ed3a92bb3d Mon Sep 17 00:00:00 2001
From: Alex Macleod <alex@macleod.io>
Date: Tue, 16 Apr 2024 16:36:38 +0000
Subject: [PATCH 45/47] Add `cargo dev setup toolchain`

---
 book/src/development/adding_lints.md | 26 +++++-----
 clippy_dev/src/fmt.rs                |  1 -
 clippy_dev/src/lib.rs                |  1 +
 clippy_dev/src/main.rs               | 55 ++++++++++++++------
 clippy_dev/src/new_lint.rs           |  1 -
 clippy_dev/src/setup/mod.rs          |  1 +
 clippy_dev/src/setup/toolchain.rs    | 75 ++++++++++++++++++++++++++++
 7 files changed, 131 insertions(+), 29 deletions(-)
 create mode 100644 clippy_dev/src/setup/toolchain.rs

diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md
index e30a5f9fe10..b80ac6370e7 100644
--- a/book/src/development/adding_lints.md
+++ b/book/src/development/adding_lints.md
@@ -18,7 +18,6 @@ because that's clearly a non-descriptive name.
     - [Cargo lints](#cargo-lints)
   - [Rustfix tests](#rustfix-tests)
   - [Testing manually](#testing-manually)
-  - [Running directly](#running-directly)
   - [Lint declaration](#lint-declaration)
   - [Lint registration](#lint-registration)
   - [Lint passes](#lint-passes)
@@ -176,23 +175,26 @@ the tests.
 
 Manually testing against an example file can be useful if you have added some
 `println!`s and the test suite output becomes unreadable. To try Clippy with
-your local modifications, run
+your local modifications, run the following from the Clippy directory:
 
-```
+```bash
 cargo dev lint input.rs
 ```
 
-from the working copy root. With tests in place, let's have a look at
-implementing our lint now.
+To run Clippy on an existing project rather than a single file you can use
 
-## Running directly
+```bash
+cargo dev lint /path/to/project
+```
 
-While it's easier to just use `cargo dev lint`, it might be desirable to get
-`target/release/cargo-clippy` and `target/release/clippy-driver` to work as well in some cases.
-By default, they don't work because clippy dynamically links rustc. To help them find rustc,
-add the path printed by`rustc --print target-libdir` (ran inside this workspace so that the rustc version matches)
-to your library search path.
-On linux, this can be done by setting the `LD_LIBRARY_PATH` environment variable to that path.
+Or set up a rustup toolchain that points to the local Clippy binaries
+
+```bash
+cargo dev setup toolchain
+
+# Then in `/path/to/project` you can run
+cargo +clippy clippy
+```
 
 ## Lint declaration
 
diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs
index ee559d45dd1..25623144181 100644
--- a/clippy_dev/src/fmt.rs
+++ b/clippy_dev/src/fmt.rs
@@ -35,7 +35,6 @@ struct FmtContext {
 }
 
 // the "main" function of cargo dev fmt
-#[allow(clippy::missing_panics_doc)]
 pub fn run(check: bool, verbose: bool) {
     fn try_run(context: &FmtContext) -> Result<bool, CliError> {
         let mut success = true;
diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs
index bb62e902cd5..385191e0361 100644
--- a/clippy_dev/src/lib.rs
+++ b/clippy_dev/src/lib.rs
@@ -9,6 +9,7 @@
     unused_lifetimes,
     unused_qualifications
 )]
+#![allow(clippy::missing_panics_doc)]
 
 // The `rustc_driver` crate seems to be required in order to use the `rust_lexer` crate.
 #[allow(unused_extern_crates)]
diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs
index 5bd9994e18d..397a0e99082 100644
--- a/clippy_dev/src/main.rs
+++ b/clippy_dev/src/main.rs
@@ -46,6 +46,13 @@ fn main() {
             }
         },
         Some(("setup", sub_command)) => match sub_command.subcommand() {
+            Some(("git-hook", matches)) => {
+                if matches.get_flag("remove") {
+                    setup::git_hook::remove_hook();
+                } else {
+                    setup::git_hook::install_hook(matches.get_flag("force-override"));
+                }
+            },
             Some(("intellij", matches)) => {
                 if matches.get_flag("remove") {
                     setup::intellij::remove_rustc_src();
@@ -57,12 +64,12 @@ fn main() {
                     );
                 }
             },
-            Some(("git-hook", matches)) => {
-                if matches.get_flag("remove") {
-                    setup::git_hook::remove_hook();
-                } else {
-                    setup::git_hook::install_hook(matches.get_flag("force-override"));
-                }
+            Some(("toolchain", matches)) => {
+                setup::toolchain::create(
+                    matches.get_flag("force"),
+                    matches.get_flag("release"),
+                    matches.get_one::<String>("name").unwrap(),
+                );
             },
             Some(("vscode-tasks", matches)) => {
                 if matches.get_flag("remove") {
@@ -210,6 +217,19 @@ fn get_clap_config() -> ArgMatches {
                 .about("Support for setting up your personal development environment")
                 .arg_required_else_help(true)
                 .subcommands([
+                    Command::new("git-hook")
+                        .about("Add a pre-commit git hook that formats your code to make it look pretty")
+                        .args([
+                            Arg::new("remove")
+                                .long("remove")
+                                .action(ArgAction::SetTrue)
+                                .help("Remove the pre-commit hook added with 'cargo dev setup git-hook'"),
+                            Arg::new("force-override")
+                                .long("force-override")
+                                .short('f')
+                                .action(ArgAction::SetTrue)
+                                .help("Forces the override of an existing git pre-commit hook"),
+                        ]),
                     Command::new("intellij")
                         .about("Alter dependencies so Intellij Rust can find rustc internals")
                         .args([
@@ -225,18 +245,23 @@ fn get_clap_config() -> ArgMatches {
                                 .conflicts_with("remove")
                                 .required(true),
                         ]),
-                    Command::new("git-hook")
-                        .about("Add a pre-commit git hook that formats your code to make it look pretty")
+                    Command::new("toolchain")
+                        .about("Install a rustup toolchain pointing to the local clippy build")
                         .args([
-                            Arg::new("remove")
-                                .long("remove")
-                                .action(ArgAction::SetTrue)
-                                .help("Remove the pre-commit hook added with 'cargo dev setup git-hook'"),
-                            Arg::new("force-override")
-                                .long("force-override")
+                            Arg::new("force")
+                                .long("force")
                                 .short('f')
                                 .action(ArgAction::SetTrue)
-                                .help("Forces the override of an existing git pre-commit hook"),
+                                .help("Override an existing toolchain"),
+                            Arg::new("release")
+                                .long("release")
+                                .short('r')
+                                .action(ArgAction::SetTrue)
+                                .help("Point to --release clippy binaries"),
+                            Arg::new("name")
+                                .long("name")
+                                .default_value("clippy")
+                                .help("The name of the created toolchain"),
                         ]),
                     Command::new("vscode-tasks")
                         .about("Add several tasks to vscode for formatting, validation and testing")
diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs
index 5d9cde06cd8..2940d56350f 100644
--- a/clippy_dev/src/new_lint.rs
+++ b/clippy_dev/src/new_lint.rs
@@ -36,7 +36,6 @@ impl<T> Context for io::Result<T> {
 /// # Errors
 ///
 /// This function errors out if the files couldn't be created or written to.
-#[allow(clippy::missing_panics_doc)]
 pub fn create(
     pass: &String,
     lint_name: Option<&String>,
diff --git a/clippy_dev/src/setup/mod.rs b/clippy_dev/src/setup/mod.rs
index f691ae4fa45..b0d31814639 100644
--- a/clippy_dev/src/setup/mod.rs
+++ b/clippy_dev/src/setup/mod.rs
@@ -1,5 +1,6 @@
 pub mod git_hook;
 pub mod intellij;
+pub mod toolchain;
 pub mod vscode;
 
 use std::path::Path;
diff --git a/clippy_dev/src/setup/toolchain.rs b/clippy_dev/src/setup/toolchain.rs
new file mode 100644
index 00000000000..8d98c6c92d9
--- /dev/null
+++ b/clippy_dev/src/setup/toolchain.rs
@@ -0,0 +1,75 @@
+use std::env::consts::EXE_SUFFIX;
+use std::env::current_dir;
+use std::ffi::OsStr;
+use std::fs;
+use std::path::{Path, PathBuf};
+use walkdir::WalkDir;
+
+use super::verify_inside_clippy_dir;
+
+pub fn create(force: bool, release: bool, name: &str) {
+    if !verify_inside_clippy_dir() {
+        return;
+    }
+
+    let rustup_home = std::env::var("RUSTUP_HOME").unwrap();
+    let toolchain = std::env::var("RUSTUP_TOOLCHAIN").unwrap();
+
+    let src = PathBuf::from_iter([&rustup_home, "toolchains", &toolchain]);
+    let dest = PathBuf::from_iter([&rustup_home, "toolchains", name]);
+
+    if dest.exists() {
+        if force {
+            fs::remove_dir_all(&dest).unwrap();
+        } else {
+            println!("{} already exists, pass `--force` to override it", dest.display());
+            return;
+        }
+    }
+
+    for entry in WalkDir::new(&src) {
+        let entry = entry.unwrap();
+        let relative = entry.path().strip_prefix(&src).unwrap();
+
+        if relative.starts_with("bin")
+            && matches!(
+                relative.file_stem().and_then(OsStr::to_str),
+                Some("cargo-clippy" | "clippy-driver")
+            )
+        {
+            continue;
+        }
+
+        let target = dest.join(relative);
+        if entry.file_type().is_dir() {
+            fs::create_dir(&target).unwrap();
+        } else {
+            fs::hard_link(entry.path(), target).unwrap();
+        }
+    }
+
+    symlink_bin("cargo-clippy", &dest, release);
+    symlink_bin("clippy-driver", &dest, release);
+
+    println!("Created toolchain {name}, use it in other projects with e.g. `cargo +{name} clippy`");
+    println!("Note: This will need to be re-run whenever the Clippy `rust-toolchain` changes");
+}
+
+fn symlink_bin(bin: &str, dest: &Path, release: bool) {
+    #[cfg(windows)]
+    use std::os::windows::fs::symlink_file as symlink;
+
+    #[cfg(not(windows))]
+    use std::os::unix::fs::symlink;
+
+    let profile = if release { "release" } else { "debug" };
+    let file_name = format!("{bin}{EXE_SUFFIX}");
+
+    let mut src = current_dir().unwrap();
+    src.extend(["target", profile, &file_name]);
+
+    let mut dest = dest.to_path_buf();
+    dest.extend(["bin", &file_name]);
+
+    symlink(src, dest).unwrap();
+}

From 245fbeef49c2395471498d20e67f4edf4222c865 Mon Sep 17 00:00:00 2001
From: Josh Stone <cuviper@gmail.com>
Date: Tue, 16 Apr 2024 16:45:59 -0700
Subject: [PATCH 46/47] The `multiple_unsafe_ops_per_block` test needs `asm!`

---
 tests/ui/multiple_unsafe_ops_per_block.rs     |  1 +
 tests/ui/multiple_unsafe_ops_per_block.stderr | 58 +++++++++----------
 2 files changed, 30 insertions(+), 29 deletions(-)

diff --git a/tests/ui/multiple_unsafe_ops_per_block.rs b/tests/ui/multiple_unsafe_ops_per_block.rs
index 8afb4df20af..6b8a103d4a9 100644
--- a/tests/ui/multiple_unsafe_ops_per_block.rs
+++ b/tests/ui/multiple_unsafe_ops_per_block.rs
@@ -1,3 +1,4 @@
+//@needs-asm-support
 //@aux-build:proc_macros.rs
 #![allow(unused)]
 #![allow(deref_nullptr)]
diff --git a/tests/ui/multiple_unsafe_ops_per_block.stderr b/tests/ui/multiple_unsafe_ops_per_block.stderr
index cff85ae115e..e732bde0707 100644
--- a/tests/ui/multiple_unsafe_ops_per_block.stderr
+++ b/tests/ui/multiple_unsafe_ops_per_block.stderr
@@ -1,5 +1,5 @@
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:36:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:37:5
    |
 LL | /     unsafe {
 LL | |         STATIC += 1;
@@ -8,12 +8,12 @@ LL | |     }
    | |_____^
    |
 note: modification of a mutable static occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:37:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:38:9
    |
 LL |         STATIC += 1;
    |         ^^^^^^^^^^^
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:38:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:39:9
    |
 LL |         not_very_safe();
    |         ^^^^^^^^^^^^^^^
@@ -21,7 +21,7 @@ LL |         not_very_safe();
    = help: to override `-D warnings` add `#[allow(clippy::multiple_unsafe_ops_per_block)]`
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:45:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:46:5
    |
 LL | /     unsafe {
 LL | |         drop(u.u);
@@ -30,18 +30,18 @@ LL | |     }
    | |_____^
    |
 note: union field access occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:46:14
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:47:14
    |
 LL |         drop(u.u);
    |              ^^^
 note: raw pointer dereference occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:47:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:48:9
    |
 LL |         *raw_ptr();
    |         ^^^^^^^^^^
 
 error: this `unsafe` block contains 3 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:52:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:53:5
    |
 LL | /     unsafe {
 LL | |         asm!("nop");
@@ -51,23 +51,23 @@ LL | |     }
    | |_____^
    |
 note: inline assembly used here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:53:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:54:9
    |
 LL |         asm!("nop");
    |         ^^^^^^^^^^^
 note: unsafe method call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:54:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:55:9
    |
 LL |         sample.not_very_safe();
    |         ^^^^^^^^^^^^^^^^^^^^^^
 note: modification of a mutable static occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:55:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:56:9
    |
 LL |         STATIC = 0;
    |         ^^^^^^^^^^
 
 error: this `unsafe` block contains 6 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:61:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:62:5
    |
 LL | /     unsafe {
 LL | |         drop(u.u);
@@ -79,55 +79,55 @@ LL | |     }
    | |_____^
    |
 note: union field access occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:62:14
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:63:14
    |
 LL |         drop(u.u);
    |              ^^^
 note: access of a mutable static occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:63:14
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:64:14
    |
 LL |         drop(STATIC);
    |              ^^^^^^
 note: unsafe method call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:64:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:65:9
    |
 LL |         sample.not_very_safe();
    |         ^^^^^^^^^^^^^^^^^^^^^^
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:65:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:66:9
    |
 LL |         not_very_safe();
    |         ^^^^^^^^^^^^^^^
 note: raw pointer dereference occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:66:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:67:9
    |
 LL |         *raw_ptr();
    |         ^^^^^^^^^^
 note: inline assembly used here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:67:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:68:9
    |
 LL |         asm!("nop");
    |         ^^^^^^^^^^^
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:105:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:106:5
    |
 LL |     unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:105:14
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:106:14
    |
 LL |     unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: raw pointer dereference occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:105:39
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:106:39
    |
 LL |     unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
    |                                       ^^^^^^^^^^^^^^^^^^
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:123:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:124:5
    |
 LL | /     unsafe {
 LL | |         x();
@@ -136,18 +136,18 @@ LL | |     }
    | |_____^
    |
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:124:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:125:9
    |
 LL |         x();
    |         ^^^
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:125:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:126:9
    |
 LL |         x();
    |         ^^^
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:134:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:135:9
    |
 LL | /         unsafe {
 LL | |             T::X();
@@ -156,18 +156,18 @@ LL | |         }
    | |_________^
    |
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:135:13
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:136:13
    |
 LL |             T::X();
    |             ^^^^^^
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:136:13
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:137:13
    |
 LL |             T::X();
    |             ^^^^^^
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:144:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:145:5
    |
 LL | /     unsafe {
 LL | |         x.0();
@@ -176,12 +176,12 @@ LL | |     }
    | |_____^
    |
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:145:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:146:9
    |
 LL |         x.0();
    |         ^^^^^
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:146:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:147:9
    |
 LL |         x.0();
    |         ^^^^^

From fca4e16ffb8c07186ee23becd44cd5c9fb51896c Mon Sep 17 00:00:00 2001
From: Philipp Krones <hello@philkrones.com>
Date: Thu, 18 Apr 2024 17:30:05 +0200
Subject: [PATCH 47/47] Bump nightly version -> 2024-04-18

---
 rust-toolchain | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rust-toolchain b/rust-toolchain
index fc476c50ee6..521c0d12983 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2024-04-05"
+channel = "nightly-2024-04-18"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]