From 197b444407b86b1990f4051b1cb28181e45eb965 Mon Sep 17 00:00:00 2001
From: Yuri Astrakhan <YuriAstrakhan@gmail.com>
Date: Tue, 16 Jul 2024 17:45:22 -0400
Subject: [PATCH 001/114] Ignore underscore-prefixed args for
 needless_pass_by_value lint

When a user explicitly tags a param as unused (yet?), there is no need to raise another lint on it.
---
 clippy_lints/src/needless_pass_by_value.rs | 15 ++++++++-------
 tests/ui/needless_pass_by_value.rs         | 12 ++++++++----
 tests/ui/needless_pass_by_value.stderr     | 10 +++++-----
 3 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs
index f2e00cef7e9ff..4b86db33fdec6 100644
--- a/clippy_lints/src/needless_pass_by_value.rs
+++ b/clippy_lints/src/needless_pass_by_value.rs
@@ -129,7 +129,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
             })
             .collect::<Vec<_>>();
 
-        // Collect moved variables and spans which will need dereferencings from the
+        // Collect moved variables and spans which will need dereferencing from the
         // function body.
         let MovedVariablesCtxt { moved_vars } = {
             let mut ctx = MovedVariablesCtxt::default();
@@ -148,12 +148,13 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                 return;
             }
 
-            // Ignore `self`s.
-            if idx == 0 {
-                if let PatKind::Binding(.., ident, _) = arg.pat.kind {
-                    if ident.name == kw::SelfLower {
-                        continue;
-                    }
+            // Ignore `self`s and params whose variable name starts with an underscore
+            if let PatKind::Binding(.., ident, _) = arg.pat.kind {
+                if idx == 0 && ident.name == kw::SelfLower {
+                    continue;
+                }
+                if ident.name.as_str().starts_with('_') {
+                    continue;
                 }
             }
 
diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs
index 14cba5a7eb520..9408b8c948fed 100644
--- a/tests/ui/needless_pass_by_value.rs
+++ b/tests/ui/needless_pass_by_value.rs
@@ -84,7 +84,7 @@ trait Serialize {}
 impl<'a, T> Serialize for &'a T where T: Serialize {}
 impl Serialize for i32 {}
 
-fn test_blanket_ref<T: Foo, S: Serialize>(_foo: T, _serializable: S) {}
+fn test_blanket_ref<T: Foo, S: Serialize>(vals: T, serializable: S) {}
 //~^ ERROR: this argument is passed by value, but not consumed in the function body
 
 fn issue_2114(s: String, t: String, u: Vec<i32>, v: Vec<i32>) {
@@ -116,7 +116,7 @@ impl<T: Serialize, U> S<T, U> {
     ) {
     }
 
-    fn baz(&self, _u: U, _s: Self) {}
+    fn baz(&self, uu: U, ss: Self) {}
     //~^ ERROR: this argument is passed by value, but not consumed in the function body
     //~| ERROR: this argument is passed by value, but not consumed in the function body
 }
@@ -162,13 +162,13 @@ fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) {
 // The following 3 lines should not cause an ICE. See #2831
 trait Bar<'a, A> {}
 impl<'b, T> Bar<'b, T> for T {}
-fn some_fun<'b, S: Bar<'b, ()>>(_item: S) {}
+fn some_fun<'b, S: Bar<'b, ()>>(items: S) {}
 //~^ ERROR: this argument is passed by value, but not consumed in the function body
 
 // Also this should not cause an ICE. See #2831
 trait Club<'a, A> {}
 impl<T> Club<'static, T> for T {}
-fn more_fun(_item: impl Club<'static, i32>) {}
+fn more_fun(items: impl Club<'static, i32>) {}
 //~^ ERROR: this argument is passed by value, but not consumed in the function body
 
 fn is_sync<T>(_: T)
@@ -177,6 +177,10 @@ where
 {
 }
 
+struct Obj(String);
+
+fn prefix_test(_unused_with_prefix: Obj) {}
+
 fn main() {
     // This should not cause an ICE either
     // https://github.com/rust-lang/rust-clippy/issues/3144
diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr
index 827a200ba6819..dce28186ff85e 100644
--- a/tests/ui/needless_pass_by_value.stderr
+++ b/tests/ui/needless_pass_by_value.stderr
@@ -46,7 +46,7 @@ LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) {
 error: this argument is passed by value, but not consumed in the function body
   --> tests/ui/needless_pass_by_value.rs:87:49
    |
-LL | fn test_blanket_ref<T: Foo, S: Serialize>(_foo: T, _serializable: S) {}
+LL | fn test_blanket_ref<T: Foo, S: Serialize>(vals: T, serializable: S) {}
    |                                                 ^ help: consider taking a reference instead: `&T`
 
 error: this argument is passed by value, but not consumed in the function body
@@ -106,13 +106,13 @@ LL |         t: String,
 error: this argument is passed by value, but not consumed in the function body
   --> tests/ui/needless_pass_by_value.rs:119:23
    |
-LL |     fn baz(&self, _u: U, _s: Self) {}
+LL |     fn baz(&self, uu: U, ss: Self) {}
    |                       ^ help: consider taking a reference instead: `&U`
 
 error: this argument is passed by value, but not consumed in the function body
   --> tests/ui/needless_pass_by_value.rs:119:30
    |
-LL |     fn baz(&self, _u: U, _s: Self) {}
+LL |     fn baz(&self, uu: U, ss: Self) {}
    |                              ^^^^ help: consider taking a reference instead: `&Self`
 
 error: this argument is passed by value, but not consumed in the function body
@@ -166,13 +166,13 @@ LL | struct CopyWrapper(u32);
 error: this argument is passed by value, but not consumed in the function body
   --> tests/ui/needless_pass_by_value.rs:165:40
    |
-LL | fn some_fun<'b, S: Bar<'b, ()>>(_item: S) {}
+LL | fn some_fun<'b, S: Bar<'b, ()>>(items: S) {}
    |                                        ^ help: consider taking a reference instead: `&S`
 
 error: this argument is passed by value, but not consumed in the function body
   --> tests/ui/needless_pass_by_value.rs:171:20
    |
-LL | fn more_fun(_item: impl Club<'static, i32>) {}
+LL | fn more_fun(items: impl Club<'static, i32>) {}
    |                    ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>`
 
 error: aborting due to 22 previous errors

From af35dcd33012c131bf2d3675bb40591b740c7728 Mon Sep 17 00:00:00 2001
From: apoisternex <santinoferrazzuolo@proton.me>
Date: Sat, 3 Aug 2024 21:24:51 -0300
Subject: [PATCH 002/114] Fix [`needless_return`] false negative when returned
 expression borrows a value

Fixes #12907

changelog: Fix [`needless_return`] false negative when returned expression borrows a value
---
 clippy_lints/src/returns.rs     | 22 ++++++++++++++++++----
 tests/ui/needless_return.fixed  |  4 ++++
 tests/ui/needless_return.rs     |  4 ++++
 tests/ui/needless_return.stderr | 14 +++++++++++++-
 4 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs
index 13016cdadb072..034c44a971dff 100644
--- a/clippy_lints/src/returns.rs
+++ b/clippy_lints/src/returns.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
 use clippy_utils::source::{snippet_opt, snippet_with_context};
 use clippy_utils::sugg::has_enclosing_paren;
-use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::visitors::{for_each_expr, for_each_unconsumed_temporary, Descend};
 use clippy_utils::{
     binary_expr_needs_parentheses, 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,
@@ -384,10 +384,24 @@ fn check_final_expr<'tcx>(
                 }
             };
 
-            let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner));
-            if borrows {
-                return;
+            if let Some(inner) = inner {
+                if for_each_unconsumed_temporary(cx, inner, |temporary_ty| {
+                    if temporary_ty.has_significant_drop(cx.tcx, cx.param_env)
+                        && temporary_ty
+                            .walk()
+                            .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(re) if !re.is_static()))
+                    {
+                        ControlFlow::Break(())
+                    } else {
+                        ControlFlow::Continue(())
+                    }
+                })
+                .is_break()
+                {
+                    return;
+                }
             }
+
             if ret_span.from_expansion() {
                 return;
             }
diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed
index fc4129e1db84f..c5c570690b450 100644
--- a/tests/ui/needless_return.fixed
+++ b/tests/ui/needless_return.fixed
@@ -355,4 +355,8 @@ fn conjunctive_blocks() -> String {
     ({ "a".to_string() } + "b" + { "c" })
 }
 
+fn issue12907() -> String {
+    "".split("").next().unwrap().to_string()
+}
+
 fn main() {}
diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs
index 61c7a02008f08..738611391dfdf 100644
--- a/tests/ui/needless_return.rs
+++ b/tests/ui/needless_return.rs
@@ -365,4 +365,8 @@ fn conjunctive_blocks() -> String {
     return { "a".to_string() } + "b" + { "c" };
 }
 
+fn issue12907() -> String {
+    return "".split("").next().unwrap().to_string();
+}
+
 fn main() {}
diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr
index ea9c230eafd22..da0fa220d8c4a 100644
--- a/tests/ui/needless_return.stderr
+++ b/tests/ui/needless_return.stderr
@@ -665,5 +665,17 @@ LL -     return { "a".to_string() } + "b" + { "c" };
 LL +     ({ "a".to_string() } + "b" + { "c" })
    |
 
-error: aborting due to 53 previous errors
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:369:5
+   |
+LL |     return "".split("").next().unwrap().to_string();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -     return "".split("").next().unwrap().to_string();
+LL +     "".split("").next().unwrap().to_string()
+   |
+
+error: aborting due to 54 previous errors
 

From 66283bff5fde5f310f3dd373d22cd4f892b3d312 Mon Sep 17 00:00:00 2001
From: apoisternex <santinoferrazzuolo@proton.me>
Date: Sun, 4 Aug 2024 10:45:42 -0300
Subject: [PATCH 003/114] apply [`needless_return`] suggestion

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

diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs
index 2f7d54e73ed79..1890b3fdd4020 100644
--- a/clippy_lints/src/useless_conversion.rs
+++ b/clippy_lints/src/useless_conversion.rs
@@ -217,12 +217,12 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                             },
                             ExprKind::MethodCall(.., args, _) => {
                                 cx.typeck_results().type_dependent_def_id(parent.hir_id).map(|did| {
-                                    return (
+                                    (
                                         did,
                                         args,
                                         cx.typeck_results().node_args(parent.hir_id),
                                         MethodOrFunction::Method,
-                                    );
+                                    )
                                 })
                             },
                             _ => None,

From c2ed04be16d4e23e4511726c7fb1da87de93fd62 Mon Sep 17 00:00:00 2001
From: kyoto7250 <50972773+kyoto7250@users.noreply.github.com>
Date: Fri, 9 Aug 2024 00:22:30 +0900
Subject: [PATCH 004/114] check the def_id with using diagnostic_item in
 unnecessary_min_or_max lint

https://github.com/rust-lang/rust-clippy/issues/13191
---
 .../src/methods/unnecessary_min_or_max.rs     | 45 ++++++++++---------
 tests/ui/unnecessary_min_or_max.fixed         | 29 ++++++++++++
 tests/ui/unnecessary_min_or_max.rs            | 29 ++++++++++++
 3 files changed, 82 insertions(+), 21 deletions(-)

diff --git a/clippy_lints/src/methods/unnecessary_min_or_max.rs b/clippy_lints/src/methods/unnecessary_min_or_max.rs
index 86c0a6322b666..ff5fa7d33e3ee 100644
--- a/clippy_lints/src/methods/unnecessary_min_or_max.rs
+++ b/clippy_lints/src/methods/unnecessary_min_or_max.rs
@@ -1,16 +1,15 @@
 use std::cmp::Ordering;
 
 use super::UNNECESSARY_MIN_OR_MAX;
-use clippy_utils::diagnostics::span_lint_and_sugg;
-
 use clippy_utils::consts::{ConstEvalCtxt, Constant, ConstantSource, FullInt};
+use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::Span;
+use rustc_span::{sym, Span};
 
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
@@ -21,26 +20,30 @@ pub(super) fn check<'tcx>(
 ) {
     let typeck_results = cx.typeck_results();
     let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck_results);
-    if let Some((left, ConstantSource::Local | ConstantSource::CoreConstant)) = ecx.eval_with_source(recv)
-        && let Some((right, ConstantSource::Local | ConstantSource::CoreConstant)) = ecx.eval_with_source(arg)
+    if let Some(id) = typeck_results.type_dependent_def_id(expr.hir_id)
+        && (cx.tcx.is_diagnostic_item(sym::cmp_ord_min, id) || cx.tcx.is_diagnostic_item(sym::cmp_ord_max, id))
     {
-        let Some(ord) = Constant::partial_cmp(cx.tcx, typeck_results.expr_ty(recv), &left, &right) else {
-            return;
-        };
+        if let Some((left, ConstantSource::Local | ConstantSource::CoreConstant)) = ecx.eval_with_source(recv)
+            && let Some((right, ConstantSource::Local | ConstantSource::CoreConstant)) = ecx.eval_with_source(arg)
+        {
+            let Some(ord) = Constant::partial_cmp(cx.tcx, typeck_results.expr_ty(recv), &left, &right) else {
+                return;
+            };
 
-        lint(cx, expr, name, recv.span, arg.span, ord);
-    } else if let Some(extrema) = detect_extrema(cx, recv) {
-        let ord = match extrema {
-            Extrema::Minimum => Ordering::Less,
-            Extrema::Maximum => Ordering::Greater,
-        };
-        lint(cx, expr, name, recv.span, arg.span, ord);
-    } else if let Some(extrema) = detect_extrema(cx, arg) {
-        let ord = match extrema {
-            Extrema::Minimum => Ordering::Greater,
-            Extrema::Maximum => Ordering::Less,
-        };
-        lint(cx, expr, name, recv.span, arg.span, ord);
+            lint(cx, expr, name, recv.span, arg.span, ord);
+        } else if let Some(extrema) = detect_extrema(cx, recv) {
+            let ord = match extrema {
+                Extrema::Minimum => Ordering::Less,
+                Extrema::Maximum => Ordering::Greater,
+            };
+            lint(cx, expr, name, recv.span, arg.span, ord);
+        } else if let Some(extrema) = detect_extrema(cx, arg) {
+            let ord = match extrema {
+                Extrema::Minimum => Ordering::Greater,
+                Extrema::Maximum => Ordering::Less,
+            };
+            lint(cx, expr, name, recv.span, arg.span, ord);
+        }
     }
 }
 
diff --git a/tests/ui/unnecessary_min_or_max.fixed b/tests/ui/unnecessary_min_or_max.fixed
index 392f6dd1fee43..1f3e131516ce6 100644
--- a/tests/ui/unnecessary_min_or_max.fixed
+++ b/tests/ui/unnecessary_min_or_max.fixed
@@ -65,3 +65,32 @@ fn random_u32() -> u32 {
     // random number generator
     0
 }
+
+struct Issue13191 {
+    min: u16,
+    max: u16,
+}
+
+impl Issue13191 {
+    fn new() -> Self {
+        Self { min: 0, max: 0 }
+    }
+
+    fn min(mut self, value: u16) -> Self {
+        self.min = value;
+        self
+    }
+
+    fn max(mut self, value: u16) -> Self {
+        self.max = value;
+        self
+    }
+}
+
+fn issue_13191() {
+    // should not fixed
+    Issue13191::new().min(0);
+
+    // should not fixed
+    Issue13191::new().max(0);
+}
diff --git a/tests/ui/unnecessary_min_or_max.rs b/tests/ui/unnecessary_min_or_max.rs
index b03755e6d23d1..58356b9d49e77 100644
--- a/tests/ui/unnecessary_min_or_max.rs
+++ b/tests/ui/unnecessary_min_or_max.rs
@@ -65,3 +65,32 @@ fn random_u32() -> u32 {
     // random number generator
     0
 }
+
+struct Issue13191 {
+    min: u16,
+    max: u16,
+}
+
+impl Issue13191 {
+    fn new() -> Self {
+        Self { min: 0, max: 0 }
+    }
+
+    fn min(mut self, value: u16) -> Self {
+        self.min = value;
+        self
+    }
+
+    fn max(mut self, value: u16) -> Self {
+        self.max = value;
+        self
+    }
+}
+
+fn issue_13191() {
+    // should not fixed
+    Issue13191::new().min(0);
+
+    // should not fixed
+    Issue13191::new().max(0);
+}

From 2645ea3a680c6f92dc524a55bafa80fa37ba97d9 Mon Sep 17 00:00:00 2001
From: xFrednet <xFrednet@gmail.com>
Date: Fri, 9 Aug 2024 20:38:41 +0200
Subject: [PATCH 005/114] Remove `feature=cargo-clippy` argument

As announced <https://blog.rust-lang.org/2024/02/28/Clippy-deprecating-feature-cargo-clippy.html>
---
 src/driver.rs | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/driver.rs b/src/driver.rs
index 3fafe2427a256..2de676aea9eaa 100644
--- a/src/driver.rs
+++ b/src/driver.rs
@@ -270,8 +270,6 @@ pub fn main() {
                 },
                 _ => Some(s.to_string()),
             })
-            // FIXME: remove this line in 1.79 to only keep `--cfg clippy`.
-            .chain(vec!["--cfg".into(), r#"feature="cargo-clippy""#.into()])
             .chain(vec!["--cfg".into(), "clippy".into()])
             .collect::<Vec<String>>();
 

From a5e3a3f9b6bd85611fa098dab8948ecdcac98acc Mon Sep 17 00:00:00 2001
From: y21 <30553356+y21@users.noreply.github.com>
Date: Mon, 12 Aug 2024 22:54:20 +0200
Subject: [PATCH 006/114] move `manual_c_str_literals` to complexity

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

diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index d7126990edb1d..44ed901696185 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -4025,7 +4025,7 @@ declare_clippy_lint! {
     /// ```
     #[clippy::version = "1.78.0"]
     pub MANUAL_C_STR_LITERALS,
-    pedantic,
+    complexity,
     r#"creating a `CStr` through functions when `c""` literals can be used"#
 }
 

From 9732128e831b3870b48d95280317f55b9619feb1 Mon Sep 17 00:00:00 2001
From: Alexey Semenyuk <alexsemenyuk88@gmail.com>
Date: Sun, 18 Aug 2024 22:05:57 +0500
Subject: [PATCH 007/114] Diverging subexpression lint should not fire on
 todo!()

---
 clippy_lints/src/mixed_read_write_in_expression.rs | 6 ++++++
 tests/ui/diverging_sub_expression.rs               | 6 ++++++
 2 files changed, 12 insertions(+)

diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs
index 6964d8c8dbb33..091b6403cb434 100644
--- a/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -1,4 +1,5 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
+use clippy_utils::macros::root_macro_call_first_node;
 use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id};
 use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, LetStmt, Node, Stmt, StmtKind};
@@ -134,6 +135,11 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
     }
 
     fn report_diverging_sub_expr(&mut self, e: &Expr<'_>) {
+        if let Some(macro_call) = root_macro_call_first_node(self.cx, e) {
+            if self.cx.tcx.item_name(macro_call.def_id).as_str() == "todo" {
+                return;
+            }
+        }
         span_lint(self.cx, DIVERGING_SUB_EXPRESSION, e.span, "sub-expression diverges");
     }
 }
diff --git a/tests/ui/diverging_sub_expression.rs b/tests/ui/diverging_sub_expression.rs
index e0acf050949a1..1abba60fd34a8 100644
--- a/tests/ui/diverging_sub_expression.rs
+++ b/tests/ui/diverging_sub_expression.rs
@@ -67,3 +67,9 @@ fn foobar() {
         };
     }
 }
+
+#[allow(unused)]
+fn ignore_todo() {
+    let x: u32 = todo!();
+    println!("{x}");
+}

From b615c821809ff3092f021fc669eb63cb47de9912 Mon Sep 17 00:00:00 2001
From: WeiTheShinobi <weitheshinobi@gmail.com>
Date: Wed, 21 Aug 2024 16:12:48 +0800
Subject: [PATCH 008/114] Add new lint: `used_underscore_items`

---
 CHANGELOG.md                            |   1 +
 clippy_lints/src/declared_lints.rs      |   1 +
 clippy_lints/src/misc.rs                | 174 ++++++++++++++++++------
 tests/ui/used_underscore_binding.stderr |  24 ++--
 tests/ui/used_underscore_items.rs       |  51 +++++++
 tests/ui/used_underscore_items.stderr   | 112 +++++++++++++++
 6 files changed, 308 insertions(+), 55 deletions(-)
 create mode 100644 tests/ui/used_underscore_items.rs
 create mode 100644 tests/ui/used_underscore_items.stderr

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fddc2fd994e87..2ba323997cf5f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6012,6 +6012,7 @@ Released 2018-09-13
 [`use_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_debug
 [`use_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_self
 [`used_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding
+[`used_underscore_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_items
 [`useless_asref`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_asref
 [`useless_attribute`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_attribute
 [`useless_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index 8754a4dff87b1..8d8b9056404c4 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -485,6 +485,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::misc::SHORT_CIRCUIT_STATEMENT_INFO,
     crate::misc::TOPLEVEL_REF_ARG_INFO,
     crate::misc::USED_UNDERSCORE_BINDING_INFO,
+    crate::misc::USED_UNDERSCORE_ITEMS_INFO,
     crate::misc_early::BUILTIN_TYPE_SHADOW_INFO,
     crate::misc_early::DOUBLE_NEG_INFO,
     crate::misc_early::DUPLICATE_UNDERSCORE_ARGUMENT_INFO,
diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs
index a9aafe7ed56cb..3fc3f2b3b7fa7 100644
--- a/clippy_lints/src/misc.rs
+++ b/clippy_lints/src/misc.rs
@@ -80,6 +80,45 @@ declare_clippy_lint! {
     "using a binding which is prefixed with an underscore"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for the use of item with a single leading
+    /// underscore.
+    ///
+    /// ### Why is this bad?
+    /// A single leading underscore is usually used to indicate
+    /// that a item will not be used. Using such a item breaks this
+    /// expectation.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// fn _foo() {}
+    ///
+    /// struct _FooStruct {}
+    ///
+    /// fn main() {
+    ///     _foo();
+    ///     let _ = _FooStruct{};
+    /// }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// fn foo() {}
+    ///
+    /// struct FooStruct {}
+    ///
+    /// fn main() {
+    ///     foo();
+    ///     let _ = FooStruct{};
+    /// }
+    /// ```
+    #[clippy::version = "pre 1.29.0"]
+    pub USED_UNDERSCORE_ITEMS,
+    pedantic,
+    "using a item which is prefixed with an underscore"
+}
+
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for the use of short circuit boolean conditions as
@@ -104,6 +143,7 @@ declare_clippy_lint! {
 declare_lint_pass!(LintPass => [
     TOPLEVEL_REF_ARG,
     USED_UNDERSCORE_BINDING,
+    USED_UNDERSCORE_ITEMS,
     SHORT_CIRCUIT_STATEMENT,
 ]);
 
@@ -205,51 +245,99 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
         {
             return;
         }
-        let (definition_hir_id, ident) = match expr.kind {
-            ExprKind::Path(ref qpath) => {
-                if let QPath::Resolved(None, path) = qpath
-                    && let Res::Local(id) = path.res
-                    && is_used(cx, expr)
-                {
-                    (id, last_path_segment(qpath).ident)
-                } else {
-                    return;
-                }
-            },
-            ExprKind::Field(recv, ident) => {
-                if let Some(adt_def) = cx.typeck_results().expr_ty_adjusted(recv).ty_adt_def()
-                    && let Some(field) = adt_def.all_fields().find(|field| field.name == ident.name)
-                    && let Some(local_did) = field.did.as_local()
-                    && !cx.tcx.type_of(field.did).skip_binder().is_phantom_data()
-                {
-                    (cx.tcx.local_def_id_to_hir_id(local_did), ident)
-                } else {
-                    return;
-                }
+
+        used_underscore_binding(cx, expr);
+        used_underscore_items(cx, expr);
+    }
+}
+
+fn used_underscore_items<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+    let (def_id, ident) = match expr.kind {
+        ExprKind::Call(func, ..) => {
+            if let ExprKind::Path(QPath::Resolved(.., path)) = func.kind
+                && let Some(last_segment) = path.segments.last()
+                && let Res::Def(_, def_id) = last_segment.res
+            {
+                (def_id, last_segment.ident)
+            } else {
+                return;
+            }
+        },
+        ExprKind::MethodCall(path, ..) => {
+            if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
+                (def_id, path.ident)
+            } else {
+                return;
+            }
+        },
+        ExprKind::Struct(QPath::Resolved(_, path), ..) => {
+            if let Some(last_segment) = path.segments.last()
+                && let Res::Def(_, def_id) = last_segment.res
+            {
+                (def_id, last_segment.ident)
+            } else {
+                return;
+            }
+        },
+        _ => return,
+    };
+    let name = ident.name.as_str();
+    let definition_span = cx.tcx.def_span(def_id);
+    if name.starts_with('_') && !name.starts_with("__") && !definition_span.from_expansion() {
+        span_lint_and_then(
+            cx,
+            USED_UNDERSCORE_ITEMS,
+            expr.span,
+            "used underscore-prefixed item".to_string(),
+            |diag| {
+                diag.span_note(definition_span, "item is defined here".to_string());
             },
-            _ => return,
-        };
+        );
+    }
+}
 
-        let name = ident.name.as_str();
-        if name.starts_with('_')
-            && !name.starts_with("__")
-            && let definition_span = cx.tcx.hir().span(definition_hir_id)
-            && !definition_span.from_expansion()
-            && !fulfill_or_allowed(cx, USED_UNDERSCORE_BINDING, [expr.hir_id, definition_hir_id])
-        {
-            span_lint_and_then(
-                cx,
-                USED_UNDERSCORE_BINDING,
-                expr.span,
-                format!(
-                    "used binding `{name}` which is prefixed with an underscore. A leading \
-                     underscore signals that a binding will not be used"
-                ),
-                |diag| {
-                    diag.span_note(definition_span, format!("`{name}` is defined here"));
-                },
-            );
-        }
+fn used_underscore_binding<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+    let (definition_hir_id, ident) = match expr.kind {
+        ExprKind::Path(ref qpath) => {
+            if let QPath::Resolved(None, path) = qpath
+                && let Res::Local(id) = path.res
+                && is_used(cx, expr)
+            {
+                (id, last_path_segment(qpath).ident)
+            } else {
+                return;
+            }
+        },
+        ExprKind::Field(recv, ident) => {
+            if let Some(adt_def) = cx.typeck_results().expr_ty_adjusted(recv).ty_adt_def()
+                && let Some(field) = adt_def.all_fields().find(|field| field.name == ident.name)
+                && let Some(local_did) = field.did.as_local()
+                && !cx.tcx.type_of(field.did).skip_binder().is_phantom_data()
+            {
+                (cx.tcx.local_def_id_to_hir_id(local_did), ident)
+            } else {
+                return;
+            }
+        },
+        _ => return,
+    };
+
+    let name = ident.name.as_str();
+    if name.starts_with('_')
+        && !name.starts_with("__")
+        && let definition_span = cx.tcx.hir().span(definition_hir_id)
+        && !definition_span.from_expansion()
+        && !fulfill_or_allowed(cx, USED_UNDERSCORE_BINDING, [expr.hir_id, definition_hir_id])
+    {
+        span_lint_and_then(
+            cx,
+            USED_UNDERSCORE_BINDING,
+            expr.span,
+            "used underscore-prefixed binding".to_string(),
+            |diag| {
+                diag.span_note(definition_span, "binding is defined here".to_string());
+            },
+        );
     }
 }
 
diff --git a/tests/ui/used_underscore_binding.stderr b/tests/ui/used_underscore_binding.stderr
index 556e1792b3e68..f9e8013d3ad57 100644
--- a/tests/ui/used_underscore_binding.stderr
+++ b/tests/ui/used_underscore_binding.stderr
@@ -1,10 +1,10 @@
-error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
+error: used underscore-prefixed binding
   --> tests/ui/used_underscore_binding.rs:23:5
    |
 LL |     _foo + 1
    |     ^^^^
    |
-note: `_foo` is defined here
+note: binding is defined here
   --> tests/ui/used_underscore_binding.rs:22:22
    |
 LL | fn prefix_underscore(_foo: u32) -> u32 {
@@ -12,61 +12,61 @@ LL | fn prefix_underscore(_foo: u32) -> u32 {
    = note: `-D clippy::used-underscore-binding` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::used_underscore_binding)]`
 
-error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
+error: used underscore-prefixed binding
   --> tests/ui/used_underscore_binding.rs:28:20
    |
 LL |     println!("{}", _foo);
    |                    ^^^^
    |
-note: `_foo` is defined here
+note: binding is defined here
   --> tests/ui/used_underscore_binding.rs:27:24
    |
 LL | fn in_macro_or_desugar(_foo: u32) {
    |                        ^^^^
 
-error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
+error: used underscore-prefixed binding
   --> tests/ui/used_underscore_binding.rs:29:16
    |
 LL |     assert_eq!(_foo, _foo);
    |                ^^^^
    |
-note: `_foo` is defined here
+note: binding is defined here
   --> tests/ui/used_underscore_binding.rs:27:24
    |
 LL | fn in_macro_or_desugar(_foo: u32) {
    |                        ^^^^
 
-error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
+error: used underscore-prefixed binding
   --> tests/ui/used_underscore_binding.rs:29:22
    |
 LL |     assert_eq!(_foo, _foo);
    |                      ^^^^
    |
-note: `_foo` is defined here
+note: binding is defined here
   --> tests/ui/used_underscore_binding.rs:27:24
    |
 LL | fn in_macro_or_desugar(_foo: u32) {
    |                        ^^^^
 
-error: used binding `_underscore_field` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
+error: used underscore-prefixed binding
   --> tests/ui/used_underscore_binding.rs:42:5
    |
 LL |     s._underscore_field += 1;
    |     ^^^^^^^^^^^^^^^^^^^
    |
-note: `_underscore_field` is defined here
+note: binding is defined here
   --> tests/ui/used_underscore_binding.rs:36:5
    |
 LL |     _underscore_field: u32,
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
-error: used binding `_i` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
+error: used underscore-prefixed binding
   --> tests/ui/used_underscore_binding.rs:103:16
    |
 LL |         uses_i(_i);
    |                ^^
    |
-note: `_i` is defined here
+note: binding is defined here
   --> tests/ui/used_underscore_binding.rs:102:13
    |
 LL |         let _i = 5;
diff --git a/tests/ui/used_underscore_items.rs b/tests/ui/used_underscore_items.rs
new file mode 100644
index 0000000000000..6b2ca44e32c4e
--- /dev/null
+++ b/tests/ui/used_underscore_items.rs
@@ -0,0 +1,51 @@
+#![allow(unused)]
+#![warn(clippy::used_underscore_items)]
+
+// should not lint macro
+macro_rules! macro_wrap_func {
+    () => {
+        fn _marco_foo() {}
+    };
+}
+
+macro_wrap_func!();
+
+struct _FooStruct {}
+
+impl _FooStruct {
+    fn _method_call(self) {}
+}
+
+fn _foo1() {}
+
+fn _foo2() -> i32 {
+    0
+}
+
+mod a {
+    pub mod b {
+        pub mod c {
+            pub fn _foo3() {}
+
+            pub struct _FooStruct2 {}
+
+            impl _FooStruct2 {
+                pub fn _method_call(self) {}
+            }
+        }
+    }
+}
+
+fn main() {
+    _foo1();
+    let _ = _foo2();
+    a::b::c::_foo3();
+    let _ = &_FooStruct {};
+    let _ = _FooStruct {};
+
+    let foo_struct = _FooStruct {};
+    foo_struct._method_call();
+
+    let foo_struct2 = a::b::c::_FooStruct2 {};
+    foo_struct2._method_call();
+}
diff --git a/tests/ui/used_underscore_items.stderr b/tests/ui/used_underscore_items.stderr
new file mode 100644
index 0000000000000..127d8248a943d
--- /dev/null
+++ b/tests/ui/used_underscore_items.stderr
@@ -0,0 +1,112 @@
+error: used underscore-prefixed item
+  --> tests/ui/used_underscore_items.rs:40:5
+   |
+LL |     _foo1();
+   |     ^^^^^^^
+   |
+note: item is defined here
+  --> tests/ui/used_underscore_items.rs:19:1
+   |
+LL | fn _foo1() {}
+   | ^^^^^^^^^^
+   = note: `-D clippy::used-underscore-items` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::used_underscore_items)]`
+
+error: used underscore-prefixed item
+  --> tests/ui/used_underscore_items.rs:41:13
+   |
+LL |     let _ = _foo2();
+   |             ^^^^^^^
+   |
+note: item is defined here
+  --> tests/ui/used_underscore_items.rs:21:1
+   |
+LL | fn _foo2() -> i32 {
+   | ^^^^^^^^^^^^^^^^^
+
+error: used underscore-prefixed item
+  --> tests/ui/used_underscore_items.rs:42:5
+   |
+LL |     a::b::c::_foo3();
+   |     ^^^^^^^^^^^^^^^^
+   |
+note: item is defined here
+  --> tests/ui/used_underscore_items.rs:28:13
+   |
+LL |             pub fn _foo3() {}
+   |             ^^^^^^^^^^^^^^
+
+error: used underscore-prefixed item
+  --> tests/ui/used_underscore_items.rs:43:14
+   |
+LL |     let _ = &_FooStruct {};
+   |              ^^^^^^^^^^^^^
+   |
+note: item is defined here
+  --> tests/ui/used_underscore_items.rs:13:1
+   |
+LL | struct _FooStruct {}
+   | ^^^^^^^^^^^^^^^^^
+
+error: used underscore-prefixed item
+  --> tests/ui/used_underscore_items.rs:44:13
+   |
+LL |     let _ = _FooStruct {};
+   |             ^^^^^^^^^^^^^
+   |
+note: item is defined here
+  --> tests/ui/used_underscore_items.rs:13:1
+   |
+LL | struct _FooStruct {}
+   | ^^^^^^^^^^^^^^^^^
+
+error: used underscore-prefixed item
+  --> tests/ui/used_underscore_items.rs:46:22
+   |
+LL |     let foo_struct = _FooStruct {};
+   |                      ^^^^^^^^^^^^^
+   |
+note: item is defined here
+  --> tests/ui/used_underscore_items.rs:13:1
+   |
+LL | struct _FooStruct {}
+   | ^^^^^^^^^^^^^^^^^
+
+error: used underscore-prefixed item
+  --> tests/ui/used_underscore_items.rs:47:5
+   |
+LL |     foo_struct._method_call();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: item is defined here
+  --> tests/ui/used_underscore_items.rs:16:5
+   |
+LL |     fn _method_call(self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: used underscore-prefixed item
+  --> tests/ui/used_underscore_items.rs:49:23
+   |
+LL |     let foo_struct2 = a::b::c::_FooStruct2 {};
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: item is defined here
+  --> tests/ui/used_underscore_items.rs:30:13
+   |
+LL |             pub struct _FooStruct2 {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+error: used underscore-prefixed item
+  --> tests/ui/used_underscore_items.rs:50:5
+   |
+LL |     foo_struct2._method_call();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: item is defined here
+  --> tests/ui/used_underscore_items.rs:33:17
+   |
+LL |                 pub fn _method_call(self) {}
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
+

From 89ad7334e014639621113ad8c38727e493d5e01d Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sat, 3 Aug 2024 11:17:43 +0200
Subject: [PATCH 009/114] stabilize const_fn_floating_point_arithmetic

---
 tests/ui/floating_point_abs.fixed      |  1 -
 tests/ui/floating_point_abs.rs         |  1 -
 tests/ui/floating_point_abs.stderr     | 16 ++++++++--------
 tests/ui/floating_point_mul_add.fixed  |  1 -
 tests/ui/floating_point_mul_add.rs     |  1 -
 tests/ui/floating_point_mul_add.stderr | 26 +++++++++++++-------------
 tests/ui/floating_point_rad.fixed      |  1 -
 tests/ui/floating_point_rad.rs         |  1 -
 tests/ui/floating_point_rad.stderr     | 16 ++++++++--------
 9 files changed, 29 insertions(+), 35 deletions(-)

diff --git a/tests/ui/floating_point_abs.fixed b/tests/ui/floating_point_abs.fixed
index 5312a8b29c67a..33183c7697243 100644
--- a/tests/ui/floating_point_abs.fixed
+++ b/tests/ui/floating_point_abs.fixed
@@ -1,4 +1,3 @@
-#![feature(const_fn_floating_point_arithmetic)]
 #![warn(clippy::suboptimal_flops)]
 
 /// Allow suboptimal ops in constant context
diff --git a/tests/ui/floating_point_abs.rs b/tests/ui/floating_point_abs.rs
index 8619177130c9f..a08d5bbcef5ce 100644
--- a/tests/ui/floating_point_abs.rs
+++ b/tests/ui/floating_point_abs.rs
@@ -1,4 +1,3 @@
-#![feature(const_fn_floating_point_arithmetic)]
 #![warn(clippy::suboptimal_flops)]
 
 /// Allow suboptimal ops in constant context
diff --git a/tests/ui/floating_point_abs.stderr b/tests/ui/floating_point_abs.stderr
index f5a778c5b7650..0c1f68f3b7fd2 100644
--- a/tests/ui/floating_point_abs.stderr
+++ b/tests/ui/floating_point_abs.stderr
@@ -1,5 +1,5 @@
 error: manual implementation of `abs` method
-  --> tests/ui/floating_point_abs.rs:15:5
+  --> tests/ui/floating_point_abs.rs:14:5
    |
 LL |     if num >= 0.0 { num } else { -num }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.abs()`
@@ -8,43 +8,43 @@ LL |     if num >= 0.0 { num } else { -num }
    = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]`
 
 error: manual implementation of `abs` method
-  --> tests/ui/floating_point_abs.rs:19:5
+  --> tests/ui/floating_point_abs.rs:18:5
    |
 LL |     if 0.0 < num { num } else { -num }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.abs()`
 
 error: manual implementation of `abs` method
-  --> tests/ui/floating_point_abs.rs:23:5
+  --> tests/ui/floating_point_abs.rs:22:5
    |
 LL |     if a.a > 0.0 { a.a } else { -a.a }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.a.abs()`
 
 error: manual implementation of `abs` method
-  --> tests/ui/floating_point_abs.rs:27:5
+  --> tests/ui/floating_point_abs.rs:26:5
    |
 LL |     if 0.0 >= num { -num } else { num }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.abs()`
 
 error: manual implementation of `abs` method
-  --> tests/ui/floating_point_abs.rs:31:5
+  --> tests/ui/floating_point_abs.rs:30:5
    |
 LL |     if a.a < 0.0 { -a.a } else { a.a }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.a.abs()`
 
 error: manual implementation of negation of `abs` method
-  --> tests/ui/floating_point_abs.rs:35:5
+  --> tests/ui/floating_point_abs.rs:34:5
    |
 LL |     if num < 0.0 { num } else { -num }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-num.abs()`
 
 error: manual implementation of negation of `abs` method
-  --> tests/ui/floating_point_abs.rs:39:5
+  --> tests/ui/floating_point_abs.rs:38:5
    |
 LL |     if 0.0 >= num { num } else { -num }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-num.abs()`
 
 error: manual implementation of negation of `abs` method
-  --> tests/ui/floating_point_abs.rs:44:12
+  --> tests/ui/floating_point_abs.rs:43:12
    |
 LL |         a: if a.a >= 0.0 { -a.a } else { a.a },
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-a.a.abs()`
diff --git a/tests/ui/floating_point_mul_add.fixed b/tests/ui/floating_point_mul_add.fixed
index 3ce2edf2c71f3..164aac2601a55 100644
--- a/tests/ui/floating_point_mul_add.fixed
+++ b/tests/ui/floating_point_mul_add.fixed
@@ -1,4 +1,3 @@
-#![feature(const_fn_floating_point_arithmetic)]
 #![warn(clippy::suboptimal_flops)]
 
 /// Allow suboptimal_ops in constant context
diff --git a/tests/ui/floating_point_mul_add.rs b/tests/ui/floating_point_mul_add.rs
index b5e4a8db4db2a..ae024b7f224be 100644
--- a/tests/ui/floating_point_mul_add.rs
+++ b/tests/ui/floating_point_mul_add.rs
@@ -1,4 +1,3 @@
-#![feature(const_fn_floating_point_arithmetic)]
 #![warn(clippy::suboptimal_flops)]
 
 /// Allow suboptimal_ops in constant context
diff --git a/tests/ui/floating_point_mul_add.stderr b/tests/ui/floating_point_mul_add.stderr
index 3e1a071de7377..9c75909f71584 100644
--- a/tests/ui/floating_point_mul_add.stderr
+++ b/tests/ui/floating_point_mul_add.stderr
@@ -1,5 +1,5 @@
 error: multiply and add expressions can be calculated more efficiently and accurately
-  --> tests/ui/floating_point_mul_add.rs:20:13
+  --> tests/ui/floating_point_mul_add.rs:19:13
    |
 LL |     let _ = a * b + c;
    |             ^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
@@ -8,73 +8,73 @@ LL |     let _ = a * b + c;
    = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]`
 
 error: multiply and add expressions can be calculated more efficiently and accurately
-  --> tests/ui/floating_point_mul_add.rs:21:13
+  --> tests/ui/floating_point_mul_add.rs:20:13
    |
 LL |     let _ = a * b - c;
    |             ^^^^^^^^^ help: consider using: `a.mul_add(b, -c)`
 
 error: multiply and add expressions can be calculated more efficiently and accurately
-  --> tests/ui/floating_point_mul_add.rs:22:13
+  --> tests/ui/floating_point_mul_add.rs:21:13
    |
 LL |     let _ = c + a * b;
    |             ^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
 
 error: multiply and add expressions can be calculated more efficiently and accurately
-  --> tests/ui/floating_point_mul_add.rs:23:13
+  --> tests/ui/floating_point_mul_add.rs:22:13
    |
 LL |     let _ = c - a * b;
    |             ^^^^^^^^^ help: consider using: `a.mul_add(-b, c)`
 
 error: multiply and add expressions can be calculated more efficiently and accurately
-  --> tests/ui/floating_point_mul_add.rs:24:13
+  --> tests/ui/floating_point_mul_add.rs:23:13
    |
 LL |     let _ = a + 2.0 * 4.0;
    |             ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4.0, a)`
 
 error: multiply and add expressions can be calculated more efficiently and accurately
-  --> tests/ui/floating_point_mul_add.rs:25:13
+  --> tests/ui/floating_point_mul_add.rs:24:13
    |
 LL |     let _ = a + 2. * 4.;
    |             ^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4., a)`
 
 error: multiply and add expressions can be calculated more efficiently and accurately
-  --> tests/ui/floating_point_mul_add.rs:27:13
+  --> tests/ui/floating_point_mul_add.rs:26:13
    |
 LL |     let _ = (a * b) + c;
    |             ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
 
 error: multiply and add expressions can be calculated more efficiently and accurately
-  --> tests/ui/floating_point_mul_add.rs:28:13
+  --> tests/ui/floating_point_mul_add.rs:27:13
    |
 LL |     let _ = c + (a * b);
    |             ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
 
 error: multiply and add expressions can be calculated more efficiently and accurately
-  --> tests/ui/floating_point_mul_add.rs:29:13
+  --> tests/ui/floating_point_mul_add.rs:28:13
    |
 LL |     let _ = a * b * c + d;
    |             ^^^^^^^^^^^^^ help: consider using: `(a * b).mul_add(c, d)`
 
 error: multiply and add expressions can be calculated more efficiently and accurately
-  --> tests/ui/floating_point_mul_add.rs:31:13
+  --> tests/ui/floating_point_mul_add.rs:30:13
    |
 LL |     let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c))`
 
 error: multiply and add expressions can be calculated more efficiently and accurately
-  --> tests/ui/floating_point_mul_add.rs:32:13
+  --> tests/ui/floating_point_mul_add.rs:31:13
    |
 LL |     let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1234.567_f64.mul_add(45.67834_f64, 0.0004_f64)`
 
 error: multiply and add expressions can be calculated more efficiently and accurately
-  --> tests/ui/floating_point_mul_add.rs:34:13
+  --> tests/ui/floating_point_mul_add.rs:33:13
    |
 LL |     let _ = (a * a + b).sqrt();
    |             ^^^^^^^^^^^ help: consider using: `a.mul_add(a, b)`
 
 error: multiply and add expressions can be calculated more efficiently and accurately
-  --> tests/ui/floating_point_mul_add.rs:37:13
+  --> tests/ui/floating_point_mul_add.rs:36:13
    |
 LL |     let _ = a - (b * u as f64);
    |             ^^^^^^^^^^^^^^^^^^ help: consider using: `b.mul_add(-(u as f64), a)`
diff --git a/tests/ui/floating_point_rad.fixed b/tests/ui/floating_point_rad.fixed
index a710bd9bd6074..2f93d233cb408 100644
--- a/tests/ui/floating_point_rad.fixed
+++ b/tests/ui/floating_point_rad.fixed
@@ -1,4 +1,3 @@
-#![feature(const_fn_floating_point_arithmetic)]
 #![warn(clippy::suboptimal_flops)]
 
 /// Allow suboptimal_flops in constant context
diff --git a/tests/ui/floating_point_rad.rs b/tests/ui/floating_point_rad.rs
index 14656f021df45..9690effc4e105 100644
--- a/tests/ui/floating_point_rad.rs
+++ b/tests/ui/floating_point_rad.rs
@@ -1,4 +1,3 @@
-#![feature(const_fn_floating_point_arithmetic)]
 #![warn(clippy::suboptimal_flops)]
 
 /// Allow suboptimal_flops in constant context
diff --git a/tests/ui/floating_point_rad.stderr b/tests/ui/floating_point_rad.stderr
index 64674342c2b99..b834f5374e0b3 100644
--- a/tests/ui/floating_point_rad.stderr
+++ b/tests/ui/floating_point_rad.stderr
@@ -1,5 +1,5 @@
 error: conversion to radians can be done more accurately
-  --> tests/ui/floating_point_rad.rs:11:13
+  --> tests/ui/floating_point_rad.rs:10:13
    |
 LL |     let _ = degrees as f64 * std::f64::consts::PI / 180.0;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(degrees as f64).to_radians()`
@@ -8,43 +8,43 @@ LL |     let _ = degrees as f64 * std::f64::consts::PI / 180.0;
    = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]`
 
 error: conversion to degrees can be done more accurately
-  --> tests/ui/floating_point_rad.rs:12:13
+  --> tests/ui/floating_point_rad.rs:11:13
    |
 LL |     let _ = degrees as f64 * 180.0 / std::f64::consts::PI;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(degrees as f64).to_degrees()`
 
 error: conversion to degrees can be done more accurately
-  --> tests/ui/floating_point_rad.rs:17:13
+  --> tests/ui/floating_point_rad.rs:16:13
    |
 LL |     let _ = x * 180f32 / std::f32::consts::PI;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()`
 
 error: conversion to degrees can be done more accurately
-  --> tests/ui/floating_point_rad.rs:18:13
+  --> tests/ui/floating_point_rad.rs:17:13
    |
 LL |     let _ = 90. * 180f64 / std::f64::consts::PI;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.0_f64.to_degrees()`
 
 error: conversion to degrees can be done more accurately
-  --> tests/ui/floating_point_rad.rs:19:13
+  --> tests/ui/floating_point_rad.rs:18:13
    |
 LL |     let _ = 90.5 * 180f64 / std::f64::consts::PI;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.5_f64.to_degrees()`
 
 error: conversion to radians can be done more accurately
-  --> tests/ui/floating_point_rad.rs:20:13
+  --> tests/ui/floating_point_rad.rs:19:13
    |
 LL |     let _ = x * std::f32::consts::PI / 180f32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_radians()`
 
 error: conversion to radians can be done more accurately
-  --> tests/ui/floating_point_rad.rs:21:13
+  --> tests/ui/floating_point_rad.rs:20:13
    |
 LL |     let _ = 90. * std::f32::consts::PI / 180f32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.0_f64.to_radians()`
 
 error: conversion to radians can be done more accurately
-  --> tests/ui/floating_point_rad.rs:22:13
+  --> tests/ui/floating_point_rad.rs:21:13
    |
 LL |     let _ = 90.5 * std::f32::consts::PI / 180f32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.5_f64.to_radians()`

From b179c3e7f72cb03fe9546a008e054f356854fdca Mon Sep 17 00:00:00 2001
From: kyoto7250 <50972773+kyoto7250@users.noreply.github.com>
Date: Sat, 24 Aug 2024 23:29:11 +0900
Subject: [PATCH 010/114] check std::panic::panic_any in panic lint

---
 clippy_lints/src/panic_unimplemented.rs | 78 +++++++++++++++----------
 clippy_utils/src/paths.rs               |  1 +
 tests/ui-toml/panic/panic.rs            |  5 ++
 tests/ui-toml/panic/panic.stderr        | 10 +++-
 4 files changed, 62 insertions(+), 32 deletions(-)

diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs
index 4eefd0065f65c..fa5b02a5a41ba 100644
--- a/clippy_lints/src/panic_unimplemented.rs
+++ b/clippy_lints/src/panic_unimplemented.rs
@@ -1,8 +1,9 @@
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::is_in_test;
 use clippy_utils::macros::{is_panic, root_macro_call_first_node};
-use rustc_hir::Expr;
+use clippy_utils::{is_in_test, match_def_path, paths};
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
 
@@ -95,10 +96,49 @@ impl_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANIC])
 
 impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        let Some(macro_call) = root_macro_call_first_node(cx, expr) else {
-            return;
-        };
-        if is_panic(cx, macro_call.def_id) {
+        if let Some(macro_call) = root_macro_call_first_node(cx, expr) {
+            if is_panic(cx, macro_call.def_id) {
+                if cx.tcx.hir().is_inside_const_context(expr.hir_id)
+                    || self.allow_panic_in_tests && is_in_test(cx.tcx, expr.hir_id)
+                {
+                    return;
+                }
+
+                span_lint(
+                    cx,
+                    PANIC,
+                    macro_call.span,
+                    "`panic` should not be present in production code",
+                );
+                return;
+            }
+            match cx.tcx.item_name(macro_call.def_id).as_str() {
+                "todo" => {
+                    span_lint(
+                        cx,
+                        TODO,
+                        macro_call.span,
+                        "`todo` should not be present in production code",
+                    );
+                },
+                "unimplemented" => {
+                    span_lint(
+                        cx,
+                        UNIMPLEMENTED,
+                        macro_call.span,
+                        "`unimplemented` should not be present in production code",
+                    );
+                },
+                "unreachable" => {
+                    span_lint(cx, UNREACHABLE, macro_call.span, "usage of the `unreachable!` macro");
+                },
+                _ => {},
+            }
+        } else if let ExprKind::Call(func, [_]) = expr.kind
+            && let ExprKind::Path(QPath::Resolved(None, expr_path)) = func.kind
+            && let Res::Def(DefKind::Fn, def_id) = expr_path.res
+            && match_def_path(cx, def_id, &paths::PANIC_ANY)
+        {
             if cx.tcx.hir().is_inside_const_context(expr.hir_id)
                 || self.allow_panic_in_tests && is_in_test(cx.tcx, expr.hir_id)
             {
@@ -108,32 +148,10 @@ impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented {
             span_lint(
                 cx,
                 PANIC,
-                macro_call.span,
-                "`panic` should not be present in production code",
+                expr.span,
+                "`panic_any` should not be present in production code",
             );
             return;
         }
-        match cx.tcx.item_name(macro_call.def_id).as_str() {
-            "todo" => {
-                span_lint(
-                    cx,
-                    TODO,
-                    macro_call.span,
-                    "`todo` should not be present in production code",
-                );
-            },
-            "unimplemented" => {
-                span_lint(
-                    cx,
-                    UNIMPLEMENTED,
-                    macro_call.span,
-                    "`unimplemented` should not be present in production code",
-                );
-            },
-            "unreachable" => {
-                span_lint(cx, UNREACHABLE, macro_call.span, "usage of the `unreachable!` macro");
-            },
-            _ => {},
-        }
     }
 }
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 684c645c19964..a767798a9c36e 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -56,6 +56,7 @@ pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to
 pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
 pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockReadGuard"];
 pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockWriteGuard"];
+pub const PANIC_ANY: [&str; 3] = ["std", "panic", "panic_any"];
 pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"];
 pub const PATH_MAIN_SEPARATOR: [&str; 3] = ["std", "path", "MAIN_SEPARATOR"];
 pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
diff --git a/tests/ui-toml/panic/panic.rs b/tests/ui-toml/panic/panic.rs
index 618a37ddfc555..b6264c950e450 100644
--- a/tests/ui-toml/panic/panic.rs
+++ b/tests/ui-toml/panic/panic.rs
@@ -1,5 +1,6 @@
 //@compile-flags: --test
 #![warn(clippy::panic)]
+use std::panic::panic_any;
 
 fn main() {
     enum Enam {
@@ -12,6 +13,10 @@ fn main() {
     }
 }
 
+fn issue_13292() {
+    panic_any("should lint")
+}
+
 #[test]
 fn lonely_test() {
     enum Enam {
diff --git a/tests/ui-toml/panic/panic.stderr b/tests/ui-toml/panic/panic.stderr
index bf7503e086c9d..a034207d919fe 100644
--- a/tests/ui-toml/panic/panic.stderr
+++ b/tests/ui-toml/panic/panic.stderr
@@ -1,5 +1,5 @@
 error: `panic` should not be present in production code
-  --> tests/ui-toml/panic/panic.rs:11:14
+  --> tests/ui-toml/panic/panic.rs:12:14
    |
 LL |         _ => panic!(""),
    |              ^^^^^^^^^^
@@ -7,5 +7,11 @@ LL |         _ => panic!(""),
    = note: `-D clippy::panic` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::panic)]`
 
-error: aborting due to 1 previous error
+error: `panic_any` should not be present in production code
+  --> tests/ui-toml/panic/panic.rs:17:5
+   |
+LL |     panic_any("should lint")
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 

From 3c4367a80f391b46f47c264ac8ea919c6ceda792 Mon Sep 17 00:00:00 2001
From: Pavel Grigorenko <GrigorenkoPV@ya.ru>
Date: Fri, 23 Aug 2024 01:12:57 +0300
Subject: [PATCH 011/114] Fix `elided_named_lifetimes` in code

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

diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs
index 448946bd66d51..c6ca17175e213 100644
--- a/clippy_lints/src/unused_io_amount.rs
+++ b/clippy_lints/src/unused_io_amount.rs
@@ -235,7 +235,7 @@ 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> {
+fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
     if let ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind {
         if let ExprKind::Call(func, [ref arg_0, ..]) = expr.kind {
             if matches!(

From 3474df6a8e211457012132bbbf1add59436f1731 Mon Sep 17 00:00:00 2001
From: Alex Macleod <alex@macleod.io>
Date: Sat, 24 Aug 2024 17:43:34 +0000
Subject: [PATCH 012/114] Rewrite empty_line_after_doc_comments and
 empty_line_after_outer_attr

---
 clippy_lints/src/attrs/empty_line_after.rs    |  52 ---
 clippy_lints/src/attrs/mod.rs                 |  95 -----
 clippy_lints/src/declared_lints.rs            |   4 +-
 clippy_lints/src/doc/empty_line_after.rs      | 329 ++++++++++++++++++
 clippy_lints/src/doc/lazy_continuation.rs     |  24 --
 clippy_lints/src/doc/mod.rs                   |  85 ++++-
 .../src/doc/suspicious_doc_comments.rs        |   6 +-
 clippy_lints/src/methods/iter_kv_map.rs       |   1 -
 clippy_utils/src/attrs.rs                     |   8 +-
 clippy_utils/src/hir_utils.rs                 |   4 +-
 clippy_utils/src/lib.rs                       |  15 +-
 clippy_utils/src/source.rs                    |  60 +---
 .../disallowed_names.rs                       |   2 +-
 .../disallowed_names.rs                       |   2 +-
 tests/ui/allow_attributes_without_reason.rs   |   1 -
 .../ui/allow_attributes_without_reason.stderr |   4 +-
 tests/ui/cast_alignment.rs                    |   8 +-
 tests/ui/cmp_owned/without_suggestion.rs      |   4 +-
 tests/ui/collapsible_else_if.fixed            |   5 +-
 tests/ui/collapsible_else_if.rs               |   5 +-
 tests/ui/collapsible_else_if.stderr           |  16 +-
 tests/ui/crashes/associated-constant-ice.rs   |   2 +-
 tests/ui/crashes/cc_seme.rs                   |   4 +-
 tests/ui/crashes/ice-11230.rs                 |   2 +-
 tests/ui/crashes/ice-1588.rs                  |   2 +-
 tests/ui/crashes/ice-1969.rs                  |   2 +-
 tests/ui/crashes/ice-2499.rs                  |   6 +-
 tests/ui/crashes/ice-2594.rs                  |   1 -
 tests/ui/crashes/ice-2727.rs                  |   2 +-
 tests/ui/crashes/ice-2760.rs                  |   8 +-
 tests/ui/crashes/ice-2862.rs                  |   2 +-
 tests/ui/crashes/ice-2865.rs                  |   2 +-
 tests/ui/crashes/ice-3151.rs                  |   2 +-
 tests/ui/crashes/ice-3462.rs                  |   2 +-
 tests/ui/crashes/ice-3747.rs                  |   2 +-
 tests/ui/crashes/ice-700.rs                   |   2 +-
 tests/ui/crashes/ice_exact_size.rs            |   2 +-
 tests/ui/crashes/if_same_then_else.rs         |   2 +-
 tests/ui/crashes/inherent_impl.rs             |   2 +-
 tests/ui/crashes/issue-825.rs                 |   2 +-
 tests/ui/crashes/match_same_arms_const.rs     |   2 +-
 tests/ui/crashes/returns.rs                   |   2 +-
 tests/ui/doc/doc_lazy_blank_line.fixed        |  47 ---
 tests/ui/doc/doc_lazy_blank_line.rs           |  43 ---
 tests/ui/doc/doc_lazy_blank_line.stderr       |  56 ---
 tests/ui/doc/doc_lazy_list.fixed              |   9 +-
 tests/ui/doc/doc_lazy_list.stderr             |  27 +-
 tests/ui/duplicate_underscore_argument.rs     |   1 -
 tests/ui/duplicate_underscore_argument.stderr |   2 +-
 .../ui/empty_line_after/doc_comments.1.fixed  | 135 +++++++
 .../ui/empty_line_after/doc_comments.2.fixed  | 144 ++++++++
 tests/ui/empty_line_after/doc_comments.rs     | 147 ++++++++
 tests/ui/empty_line_after/doc_comments.stderr | 176 ++++++++++
 .../empty_line_after/outer_attribute.1.fixed  | 103 ++++++
 .../empty_line_after/outer_attribute.2.fixed  | 106 ++++++
 tests/ui/empty_line_after/outer_attribute.rs  | 112 ++++++
 .../empty_line_after/outer_attribute.stderr   | 103 ++++++
 tests/ui/empty_line_after_doc_comments.rs     | 132 -------
 tests/ui/empty_line_after_doc_comments.stderr |  37 --
 tests/ui/empty_line_after_outer_attribute.rs  | 120 -------
 .../empty_line_after_outer_attribute.stderr   |  54 ---
 tests/ui/exit1.rs                             |   2 +-
 tests/ui/exit2.rs                             |   2 +-
 tests/ui/exit3.rs                             |   2 +-
 tests/ui/expect_fun_call.fixed                |   2 -
 tests/ui/expect_fun_call.rs                   |   2 -
 tests/ui/expect_fun_call.stderr               |  30 +-
 tests/ui/match_overlapping_arm.rs             |   2 -
 tests/ui/match_overlapping_arm.stderr         |  32 +-
 tests/ui/string_slice.rs                      |   6 +-
 tests/ui/tabs_in_doc_comments.fixed           |   1 -
 tests/ui/tabs_in_doc_comments.rs              |   1 -
 tests/ui/tabs_in_doc_comments.stderr          |  16 +-
 73 files changed, 1563 insertions(+), 872 deletions(-)
 delete mode 100644 clippy_lints/src/attrs/empty_line_after.rs
 create mode 100644 clippy_lints/src/doc/empty_line_after.rs
 delete mode 100644 tests/ui/doc/doc_lazy_blank_line.fixed
 delete mode 100644 tests/ui/doc/doc_lazy_blank_line.rs
 delete mode 100644 tests/ui/doc/doc_lazy_blank_line.stderr
 create mode 100644 tests/ui/empty_line_after/doc_comments.1.fixed
 create mode 100644 tests/ui/empty_line_after/doc_comments.2.fixed
 create mode 100644 tests/ui/empty_line_after/doc_comments.rs
 create mode 100644 tests/ui/empty_line_after/doc_comments.stderr
 create mode 100644 tests/ui/empty_line_after/outer_attribute.1.fixed
 create mode 100644 tests/ui/empty_line_after/outer_attribute.2.fixed
 create mode 100644 tests/ui/empty_line_after/outer_attribute.rs
 create mode 100644 tests/ui/empty_line_after/outer_attribute.stderr
 delete mode 100644 tests/ui/empty_line_after_doc_comments.rs
 delete mode 100644 tests/ui/empty_line_after_doc_comments.stderr
 delete mode 100644 tests/ui/empty_line_after_outer_attribute.rs
 delete mode 100644 tests/ui/empty_line_after_outer_attribute.stderr

diff --git a/clippy_lints/src/attrs/empty_line_after.rs b/clippy_lints/src/attrs/empty_line_after.rs
deleted file mode 100644
index 7ff644b4c445f..0000000000000
--- a/clippy_lints/src/attrs/empty_line_after.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-use super::{EMPTY_LINE_AFTER_DOC_COMMENTS, EMPTY_LINE_AFTER_OUTER_ATTR};
-use clippy_utils::diagnostics::span_lint;
-use clippy_utils::source::{is_present_in_source, without_block_comments, SpanRangeExt};
-use rustc_ast::{AttrKind, AttrStyle};
-use rustc_lint::EarlyContext;
-use rustc_span::Span;
-
-/// Check for empty lines after outer attributes.
-///
-/// Attributes and documentation comments are both considered outer attributes
-/// by the AST. However, the average user likely considers them to be different.
-/// Checking for empty lines after each of these attributes is split into two different
-/// lints but can share the same logic.
-pub(super) fn check(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
-    let mut iter = item.attrs.iter().peekable();
-    while let Some(attr) = iter.next() {
-        if (matches!(attr.kind, AttrKind::Normal(..)) || matches!(attr.kind, AttrKind::DocComment(..)))
-            && attr.style == AttrStyle::Outer
-            && is_present_in_source(cx, attr.span)
-        {
-            let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt(), item.span.parent());
-            let end_of_attr_to_next_attr_or_item = Span::new(
-                attr.span.hi(),
-                iter.peek().map_or(item.span.lo(), |next_attr| next_attr.span.lo()),
-                item.span.ctxt(),
-                item.span.parent(),
-            );
-
-            if let Some(snippet) = end_of_attr_to_next_attr_or_item.get_source_text(cx) {
-                let lines = snippet.split('\n').collect::<Vec<_>>();
-                let lines = without_block_comments(lines);
-
-                if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 {
-                    let (lint_msg, lint_type) = match attr.kind {
-                        AttrKind::DocComment(..) => (
-                            "found an empty line after a doc comment. \
-                            Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?",
-                            EMPTY_LINE_AFTER_DOC_COMMENTS,
-                        ),
-                        AttrKind::Normal(..) => (
-                            "found an empty line after an outer attribute. \
-                            Perhaps you forgot to add a `!` to make it an inner attribute?",
-                            EMPTY_LINE_AFTER_OUTER_ATTR,
-                        ),
-                    };
-
-                    span_lint(cx, lint_type, begin_of_attr_to_item, lint_msg);
-                }
-            }
-        }
-    }
-}
diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs
index 3b14e9aee7fc0..c8fea25c9f285 100644
--- a/clippy_lints/src/attrs/mod.rs
+++ b/clippy_lints/src/attrs/mod.rs
@@ -4,7 +4,6 @@ mod blanket_clippy_restriction_lints;
 mod deprecated_cfg_attr;
 mod deprecated_semver;
 mod duplicated_attributes;
-mod empty_line_after;
 mod inline_always;
 mod mixed_attributes_style;
 mod non_minimal_cfg;
@@ -126,94 +125,6 @@ declare_clippy_lint! {
     "use of `#[deprecated(since = \"x\")]` where x is not semver"
 }
 
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for empty lines after outer attributes
-    ///
-    /// ### Why is this bad?
-    /// Most likely the attribute was meant to be an inner attribute using a '!'.
-    /// If it was meant to be an outer attribute, then the following item
-    /// should not be separated by empty lines.
-    ///
-    /// ### Known problems
-    /// Can cause false positives.
-    ///
-    /// From the clippy side it's difficult to detect empty lines between an attributes and the
-    /// following item because empty lines and comments are not part of the AST. The parsing
-    /// currently works for basic cases but is not perfect.
-    ///
-    /// ### Example
-    /// ```no_run
-    /// #[allow(dead_code)]
-    ///
-    /// fn not_quite_good_code() { }
-    /// ```
-    ///
-    /// Use instead:
-    /// ```no_run
-    /// // Good (as inner attribute)
-    /// #![allow(dead_code)]
-    ///
-    /// fn this_is_fine() { }
-    ///
-    /// // or
-    ///
-    /// // Good (as outer attribute)
-    /// #[allow(dead_code)]
-    /// fn this_is_fine_too() { }
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub EMPTY_LINE_AFTER_OUTER_ATTR,
-    nursery,
-    "empty line after outer attribute"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for empty lines after documentation comments.
-    ///
-    /// ### Why is this bad?
-    /// The documentation comment was most likely meant to be an inner attribute or regular comment.
-    /// If it was intended to be a documentation comment, then the empty line should be removed to
-    /// be more idiomatic.
-    ///
-    /// ### Known problems
-    /// Only detects empty lines immediately following the documentation. If the doc comment is followed
-    /// by an attribute and then an empty line, this lint will not trigger. Use `empty_line_after_outer_attr`
-    /// in combination with this lint to detect both cases.
-    ///
-    /// Does not detect empty lines after doc attributes (e.g. `#[doc = ""]`).
-    ///
-    /// ### Example
-    /// ```no_run
-    /// /// Some doc comment with a blank line after it.
-    ///
-    /// fn not_quite_good_code() { }
-    /// ```
-    ///
-    /// Use instead:
-    /// ```no_run
-    /// /// Good (no blank line)
-    /// fn this_is_fine() { }
-    /// ```
-    ///
-    /// ```no_run
-    /// // Good (convert to a regular comment)
-    ///
-    /// fn this_is_fine_too() { }
-    /// ```
-    ///
-    /// ```no_run
-    /// //! Good (convert to a comment on an inner attribute)
-    ///
-    /// fn this_is_fine_as_well() { }
-    /// ```
-    #[clippy::version = "1.70.0"]
-    pub EMPTY_LINE_AFTER_DOC_COMMENTS,
-    nursery,
-    "empty line after documentation comments"
-}
-
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category.
@@ -601,18 +512,12 @@ impl EarlyAttributes {
 
 impl_lint_pass!(EarlyAttributes => [
     DEPRECATED_CFG_ATTR,
-    EMPTY_LINE_AFTER_OUTER_ATTR,
-    EMPTY_LINE_AFTER_DOC_COMMENTS,
     NON_MINIMAL_CFG,
     DEPRECATED_CLIPPY_CFG_ATTR,
     UNNECESSARY_CLIPPY_CFG,
 ]);
 
 impl EarlyLintPass for EarlyAttributes {
-    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
-        empty_line_after::check(cx, item);
-    }
-
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
         deprecated_cfg_attr::check(cx, attr, &self.msrv);
         deprecated_cfg_attr::check_clippy(cx, attr);
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index 60e517131737a..2c77ebc39e4de 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -49,8 +49,6 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::attrs::DEPRECATED_CLIPPY_CFG_ATTR_INFO,
     crate::attrs::DEPRECATED_SEMVER_INFO,
     crate::attrs::DUPLICATED_ATTRIBUTES_INFO,
-    crate::attrs::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO,
-    crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO,
     crate::attrs::INLINE_ALWAYS_INFO,
     crate::attrs::MIXED_ATTRIBUTES_STYLE_INFO,
     crate::attrs::NON_MINIMAL_CFG_INFO,
@@ -138,6 +136,8 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::doc::DOC_LINK_WITH_QUOTES_INFO,
     crate::doc::DOC_MARKDOWN_INFO,
     crate::doc::EMPTY_DOCS_INFO,
+    crate::doc::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO,
+    crate::doc::EMPTY_LINE_AFTER_OUTER_ATTR_INFO,
     crate::doc::MISSING_ERRORS_DOC_INFO,
     crate::doc::MISSING_PANICS_DOC_INFO,
     crate::doc::MISSING_SAFETY_DOC_INFO,
diff --git a/clippy_lints/src/doc/empty_line_after.rs b/clippy_lints/src/doc/empty_line_after.rs
new file mode 100644
index 0000000000000..289debe0a6a94
--- /dev/null
+++ b/clippy_lints/src/doc/empty_line_after.rs
@@ -0,0 +1,329 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::{snippet_indent, SpanRangeExt};
+use clippy_utils::tokenize_with_text;
+use itertools::Itertools;
+use rustc_ast::token::CommentKind;
+use rustc_ast::{AttrKind, AttrStyle, Attribute};
+use rustc_errors::{Applicability, Diag, SuggestionStyle};
+use rustc_hir::{ItemKind, Node};
+use rustc_lexer::TokenKind;
+use rustc_lint::LateContext;
+use rustc_span::{ExpnKind, InnerSpan, Span, SpanData};
+
+use super::{EMPTY_LINE_AFTER_DOC_COMMENTS, EMPTY_LINE_AFTER_OUTER_ATTR};
+
+#[derive(Debug, PartialEq, Clone, Copy)]
+enum StopKind {
+    Attr,
+    Doc(CommentKind),
+}
+
+impl StopKind {
+    fn is_doc(self) -> bool {
+        matches!(self, StopKind::Doc(_))
+    }
+}
+
+#[derive(Debug)]
+struct Stop {
+    span: Span,
+    kind: StopKind,
+    first: usize,
+    last: usize,
+}
+
+impl Stop {
+    fn convert_to_inner(&self) -> (Span, String) {
+        let inner = match self.kind {
+            // #|[...]
+            StopKind::Attr => InnerSpan::new(1, 1),
+            // /// or /**
+            //   ^      ^
+            StopKind::Doc(_) => InnerSpan::new(2, 3),
+        };
+        (self.span.from_inner(inner), "!".into())
+    }
+
+    fn comment_out(&self, cx: &LateContext<'_>, suggestions: &mut Vec<(Span, String)>) {
+        match self.kind {
+            StopKind::Attr => {
+                if cx.tcx.sess.source_map().is_multiline(self.span) {
+                    suggestions.extend([
+                        (self.span.shrink_to_lo(), "/* ".into()),
+                        (self.span.shrink_to_hi(), " */".into()),
+                    ]);
+                } else {
+                    suggestions.push((self.span.shrink_to_lo(), "// ".into()));
+                }
+            },
+            StopKind::Doc(CommentKind::Line) => suggestions.push((self.span.shrink_to_lo(), "// ".into())),
+            StopKind::Doc(CommentKind::Block) => {
+                // /** outer */  /*! inner */
+                //  ^             ^
+                let asterisk = self.span.from_inner(InnerSpan::new(1, 2));
+                suggestions.push((asterisk, String::new()));
+            },
+        }
+    }
+
+    fn from_attr(cx: &LateContext<'_>, attr: &Attribute) -> Option<Self> {
+        let SpanData { lo, hi, .. } = attr.span.data();
+        let file = cx.tcx.sess.source_map().lookup_source_file(lo);
+
+        Some(Self {
+            span: attr.span,
+            kind: match attr.kind {
+                AttrKind::Normal(_) => StopKind::Attr,
+                AttrKind::DocComment(comment_kind, _) => StopKind::Doc(comment_kind),
+            },
+            first: file.lookup_line(file.relative_position(lo))?,
+            last: file.lookup_line(file.relative_position(hi))?,
+        })
+    }
+}
+
+/// Represents a set of attrs/doc comments separated by 1 or more empty lines
+///
+/// ```ignore
+/// /// chunk 1 docs
+/// // not an empty line so also part of chunk 1
+/// #[chunk_1_attrs] // <-- prev_stop
+///
+/// /* gap */
+///
+/// /// chunk 2 docs // <-- next_stop
+/// #[chunk_2_attrs]
+/// ```
+struct Gap<'a> {
+    /// The span of individual empty lines including the newline at the end of the line
+    empty_lines: Vec<Span>,
+    has_comment: bool,
+    next_stop: &'a Stop,
+    prev_stop: &'a Stop,
+    /// The chunk that includes [`prev_stop`](Self::prev_stop)
+    prev_chunk: &'a [Stop],
+}
+
+impl<'a> Gap<'a> {
+    fn new(cx: &LateContext<'_>, prev_chunk: &'a [Stop], next_chunk: &'a [Stop]) -> Option<Self> {
+        let prev_stop = prev_chunk.last()?;
+        let next_stop = next_chunk.first()?;
+        let gap_span = prev_stop.span.between(next_stop.span);
+        let gap_snippet = gap_span.get_source_text(cx)?;
+
+        let mut has_comment = false;
+        let mut empty_lines = Vec::new();
+
+        for (token, source, inner_span) in tokenize_with_text(&gap_snippet) {
+            match token {
+                TokenKind::BlockComment {
+                    doc_style: None,
+                    terminated: true,
+                }
+                | TokenKind::LineComment { doc_style: None } => has_comment = true,
+                TokenKind::Whitespace => {
+                    let newlines = source.bytes().positions(|b| b == b'\n');
+                    empty_lines.extend(
+                        newlines
+                            .tuple_windows()
+                            .map(|(a, b)| InnerSpan::new(inner_span.start + a + 1, inner_span.start + b))
+                            .map(|inner_span| gap_span.from_inner(inner_span)),
+                    );
+                },
+                // Ignore cfg_attr'd out attributes as they may contain empty lines, could also be from macro
+                // shenanigans
+                _ => return None,
+            }
+        }
+
+        (!empty_lines.is_empty()).then_some(Self {
+            empty_lines,
+            has_comment,
+            next_stop,
+            prev_stop,
+            prev_chunk,
+        })
+    }
+}
+
+/// If the node the attributes/docs apply to is the first in the module/crate suggest converting
+/// them to inner attributes/docs
+fn suggest_inner(cx: &LateContext<'_>, diag: &mut Diag<'_, ()>, kind: StopKind, gaps: &[Gap<'_>]) {
+    let Some(owner) = cx.last_node_with_lint_attrs.as_owner() else {
+        return;
+    };
+    let parent_desc = match cx.tcx.parent_hir_node(owner.into()) {
+        Node::Item(item)
+            if let ItemKind::Mod(parent_mod) = item.kind
+                && let [first, ..] = parent_mod.item_ids
+                && first.owner_id == owner =>
+        {
+            "parent module"
+        },
+        Node::Crate(crate_mod)
+            if let Some(first) = crate_mod
+                .item_ids
+                .iter()
+                .map(|&id| cx.tcx.hir().item(id))
+                // skip prelude imports
+                .find(|item| !matches!(item.span.ctxt().outer_expn_data().kind, ExpnKind::AstPass(_)))
+                && first.owner_id == owner =>
+        {
+            "crate"
+        },
+        _ => return,
+    };
+
+    diag.multipart_suggestion_verbose(
+        match kind {
+            StopKind::Attr => format!("if the attribute should apply to the {parent_desc} use an inner attribute"),
+            StopKind::Doc(_) => format!("if the comment should document the {parent_desc} use an inner doc comment"),
+        },
+        gaps.iter()
+            .flat_map(|gap| gap.prev_chunk)
+            .map(Stop::convert_to_inner)
+            .collect(),
+        Applicability::MaybeIncorrect,
+    );
+}
+
+fn check_gaps(cx: &LateContext<'_>, gaps: &[Gap<'_>]) -> bool {
+    let Some(first_gap) = gaps.first() else {
+        return false;
+    };
+    let empty_lines = || gaps.iter().flat_map(|gap| gap.empty_lines.iter().copied());
+    let mut has_comment = false;
+    let mut has_attr = false;
+    for gap in gaps {
+        has_comment |= gap.has_comment;
+        if !has_attr {
+            has_attr = gap.prev_chunk.iter().any(|stop| stop.kind == StopKind::Attr);
+        }
+    }
+    let kind = first_gap.prev_stop.kind;
+    let (lint, kind_desc) = match kind {
+        StopKind::Attr => (EMPTY_LINE_AFTER_OUTER_ATTR, "outer attribute"),
+        StopKind::Doc(_) => (EMPTY_LINE_AFTER_DOC_COMMENTS, "doc comment"),
+    };
+    let (lines, are, them) = if empty_lines().nth(1).is_some() {
+        ("lines", "are", "them")
+    } else {
+        ("line", "is", "it")
+    };
+    span_lint_and_then(
+        cx,
+        lint,
+        first_gap.prev_stop.span.to(empty_lines().last().unwrap()),
+        format!("empty {lines} after {kind_desc}"),
+        |diag| {
+            if let Some(owner) = cx.last_node_with_lint_attrs.as_owner() {
+                let def_id = owner.to_def_id();
+                let def_descr = cx.tcx.def_descr(def_id);
+                diag.span_label(
+                    cx.tcx.def_span(def_id),
+                    match kind {
+                        StopKind::Attr => format!("the attribute applies to this {def_descr}"),
+                        StopKind::Doc(_) => format!("the comment documents this {def_descr}"),
+                    },
+                );
+            }
+
+            diag.multipart_suggestion_with_style(
+                format!("if the empty {lines} {are} unintentional remove {them}"),
+                empty_lines().map(|empty_line| (empty_line, String::new())).collect(),
+                Applicability::MaybeIncorrect,
+                SuggestionStyle::HideCodeAlways,
+            );
+
+            if has_comment && kind.is_doc() {
+                // Likely doc comments that applied to some now commented out code
+                //
+                // /// Old docs for Foo
+                // // struct Foo;
+
+                let mut suggestions = Vec::new();
+                for stop in gaps.iter().flat_map(|gap| gap.prev_chunk) {
+                    stop.comment_out(cx, &mut suggestions);
+                }
+                let name = match cx.tcx.hir().opt_name(cx.last_node_with_lint_attrs) {
+                    Some(name) => format!("`{name}`"),
+                    None => "this".into(),
+                };
+                diag.multipart_suggestion_verbose(
+                    format!("if the doc comment should not document {name} comment it out"),
+                    suggestions,
+                    Applicability::MaybeIncorrect,
+                );
+            } else {
+                suggest_inner(cx, diag, kind, gaps);
+            }
+
+            if kind == StopKind::Doc(CommentKind::Line)
+                && gaps
+                    .iter()
+                    .all(|gap| !gap.has_comment && gap.next_stop.kind == StopKind::Doc(CommentKind::Line))
+            {
+                // Commentless empty gaps between line doc comments, possibly intended to be part of the markdown
+
+                let indent = snippet_indent(cx, first_gap.prev_stop.span).unwrap_or_default();
+                diag.multipart_suggestion_verbose(
+                    format!("if the documentation should include the empty {lines} include {them} in the comment"),
+                    empty_lines()
+                        .map(|empty_line| (empty_line, format!("{indent}///")))
+                        .collect(),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        },
+    );
+    kind.is_doc()
+}
+
+/// Returns `true` if [`EMPTY_LINE_AFTER_DOC_COMMENTS`] triggered, used to skip other doc comment
+/// lints where they would be confusing
+///
+/// [`EMPTY_LINE_AFTER_OUTER_ATTR`] is also here to share an implementation but does not return
+/// `true` if it triggers
+pub(super) fn check(cx: &LateContext<'_>, attrs: &[Attribute]) -> bool {
+    let mut outer = attrs
+        .iter()
+        .filter(|attr| attr.style == AttrStyle::Outer && !attr.span.from_expansion())
+        .map(|attr| Stop::from_attr(cx, attr))
+        .collect::<Option<Vec<_>>>()
+        .unwrap_or_default();
+
+    if outer.is_empty() {
+        return false;
+    }
+
+    // Push a fake attribute Stop for the item itself so we check for gaps between the last outer
+    // attr/doc comment and the item they apply to
+    let span = cx.tcx.hir().span(cx.last_node_with_lint_attrs);
+    if !span.from_expansion()
+        && let Ok(line) = cx.tcx.sess.source_map().lookup_line(span.lo())
+    {
+        outer.push(Stop {
+            span,
+            kind: StopKind::Attr,
+            first: line.line,
+            // last doesn't need to be accurate here, we don't compare it with anything
+            last: line.line,
+        });
+    }
+
+    let mut gaps = Vec::new();
+    let mut last = 0;
+    for pos in outer
+        .array_windows()
+        .positions(|[a, b]| b.first.saturating_sub(a.last) > 1)
+    {
+        // we want to be after the first stop in the window
+        let pos = pos + 1;
+        if let Some(gap) = Gap::new(cx, &outer[last..pos], &outer[pos..]) {
+            last = pos;
+            gaps.push(gap);
+        }
+    }
+
+    check_gaps(cx, &gaps)
+}
diff --git a/clippy_lints/src/doc/lazy_continuation.rs b/clippy_lints/src/doc/lazy_continuation.rs
index 771bcac244187..f9e4a43c0e7a8 100644
--- a/clippy_lints/src/doc/lazy_continuation.rs
+++ b/clippy_lints/src/doc/lazy_continuation.rs
@@ -22,7 +22,6 @@ pub(super) fn check(
     range: Range<usize>,
     mut span: Span,
     containers: &[super::Container],
-    line_break_span: Span,
 ) {
     if doc[range.clone()].contains('\t') {
         // We don't do tab stops correctly.
@@ -52,29 +51,6 @@ pub(super) fn check(
             "doc list item without indentation"
         };
         span_lint_and_then(cx, DOC_LAZY_CONTINUATION, span, msg, |diag| {
-            let snippet = clippy_utils::source::snippet(cx, line_break_span, "");
-            if snippet.chars().filter(|&c| c == '\n').count() > 1
-                && let Some(doc_comment_start) = snippet.rfind('\n')
-                && let doc_comment = snippet[doc_comment_start..].trim()
-                && (doc_comment == "///" || doc_comment == "//!")
-            {
-                // suggest filling in a blank line
-                diag.span_suggestion_verbose(
-                    line_break_span.shrink_to_lo(),
-                    "if this should be its own paragraph, add a blank doc comment line",
-                    format!("\n{doc_comment}"),
-                    Applicability::MaybeIncorrect,
-                );
-                if ccount > 0 || blockquote_level > 0 {
-                    diag.help("if this not intended to be a quote at all, escape it with `\\>`");
-                } else {
-                    let indent = list_indentation - lcount;
-                    diag.help(format!(
-                        "if this is intended to be part of the list, indent {indent} spaces"
-                    ));
-                }
-                return;
-            }
             if ccount == 0 && blockquote_level == 0 {
                 // simpler suggestion style for indentation
                 let indent = list_indentation - lcount;
diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs
index 790579b21c902..6db63b59e020e 100644
--- a/clippy_lints/src/doc/mod.rs
+++ b/clippy_lints/src/doc/mod.rs
@@ -32,6 +32,7 @@ use rustc_span::{sym, Span};
 use std::ops::Range;
 use url::Url;
 
+mod empty_line_after;
 mod link_with_quotes;
 mod markdown;
 mod missing_headers;
@@ -455,7 +456,82 @@ declare_clippy_lint! {
     "ensure that the first line of a documentation paragraph isn't too long"
 }
 
-#[derive(Clone)]
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for empty lines after outer attributes
+    ///
+    /// ### Why is this bad?
+    /// The attribute may have meant to be an inner attribute (`#![attr]`). If
+    /// it was meant to be an outer attribute (`#[attr]`) then the empty line
+    /// should be removed
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #[allow(dead_code)]
+    ///
+    /// fn not_quite_good_code() {}
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// // Good (as inner attribute)
+    /// #![allow(dead_code)]
+    ///
+    /// fn this_is_fine() {}
+    ///
+    /// // or
+    ///
+    /// // Good (as outer attribute)
+    /// #[allow(dead_code)]
+    /// fn this_is_fine_too() {}
+    /// ```
+    #[clippy::version = "pre 1.29.0"]
+    pub EMPTY_LINE_AFTER_OUTER_ATTR,
+    suspicious,
+    "empty line after outer attribute"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for empty lines after doc comments.
+    ///
+    /// ### Why is this bad?
+    /// The doc comment may have meant to be an inner doc comment, regular
+    /// comment or applied to some old code that is now commented out. If it was
+    /// intended to be a doc comment, then the empty line should be removed.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// /// Some doc comment with a blank line after it.
+    ///
+    /// fn f() {}
+    ///
+    /// /// Docs for `old_code`
+    /// // fn old_code() {}
+    ///
+    /// fn new_code() {}
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// //! Convert it to an inner doc comment
+    ///
+    /// // Or a regular comment
+    ///
+    /// /// Or remove the empty line
+    /// fn f() {}
+    ///
+    /// // /// Docs for `old_code`
+    /// // fn old_code() {}
+    ///
+    /// fn new_code() {}
+    /// ```
+    #[clippy::version = "1.70.0"]
+    pub EMPTY_LINE_AFTER_DOC_COMMENTS,
+    suspicious,
+    "empty line after doc comments"
+}
+
 pub struct Documentation {
     valid_idents: FxHashSet<String>,
     check_private_items: bool,
@@ -482,6 +558,8 @@ impl_lint_pass!(Documentation => [
     SUSPICIOUS_DOC_COMMENTS,
     EMPTY_DOCS,
     DOC_LAZY_CONTINUATION,
+    EMPTY_LINE_AFTER_OUTER_ATTR,
+    EMPTY_LINE_AFTER_DOC_COMMENTS,
     TOO_LONG_FIRST_DOC_PARAGRAPH,
 ]);
 
@@ -612,12 +690,10 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[
         Some(("fake".into(), "fake".into()))
     }
 
-    if is_doc_hidden(attrs) {
+    if suspicious_doc_comments::check(cx, attrs) || empty_line_after::check(cx, attrs) || is_doc_hidden(attrs) {
         return None;
     }
 
-    suspicious_doc_comments::check(cx, attrs);
-
     let (fragments, _) = attrs_to_doc_fragments(
         attrs.iter().filter_map(|attr| {
             if in_external_macro(cx.sess(), attr.span) {
@@ -816,7 +892,6 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                         range.end..next_range.start,
                         Span::new(span.hi(), next_span.lo(), span.ctxt(), span.parent()),
                         &containers[..],
-                        span,
                     );
                 }
             },
diff --git a/clippy_lints/src/doc/suspicious_doc_comments.rs b/clippy_lints/src/doc/suspicious_doc_comments.rs
index d7ad30efec3c6..f6f942b10cadb 100644
--- a/clippy_lints/src/doc/suspicious_doc_comments.rs
+++ b/clippy_lints/src/doc/suspicious_doc_comments.rs
@@ -7,7 +7,7 @@ use rustc_span::Span;
 
 use super::SUSPICIOUS_DOC_COMMENTS;
 
-pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
+pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) -> bool {
     let replacements: Vec<_> = collect_doc_replacements(attrs);
 
     if let Some((&(lo_span, _), &(hi_span, _))) = replacements.first().zip(replacements.last()) {
@@ -24,6 +24,10 @@ pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
                 );
             },
         );
+
+        true
+    } else {
+        false
     }
 }
 
diff --git a/clippy_lints/src/methods/iter_kv_map.rs b/clippy_lints/src/methods/iter_kv_map.rs
index 33de3b87abc82..390dd24b5058d 100644
--- a/clippy_lints/src/methods/iter_kv_map.rs
+++ b/clippy_lints/src/methods/iter_kv_map.rs
@@ -14,7 +14,6 @@ use rustc_span::sym;
 /// - `hashmap.into_iter().map(|(_, v)| v)`
 ///
 /// on `HashMaps` and `BTreeMaps` in std
-
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     map_type: &'tcx str,     // iter / into_iter
diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs
index 42c8b218d14e8..935a1686c0af5 100644
--- a/clippy_utils/src/attrs.rs
+++ b/clippy_utils/src/attrs.rs
@@ -183,15 +183,15 @@ pub fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool {
         let mut iter = tokenize_with_text(src);
 
         // Search for the token sequence [`#`, `[`, `cfg`]
-        while iter.any(|(t, _)| matches!(t, TokenKind::Pound)) {
-            let mut iter = iter.by_ref().skip_while(|(t, _)| {
+        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")))
+            if matches!(iter.next(), Some((TokenKind::OpenBracket, ..)))
+                && matches!(iter.next(), Some((TokenKind::Ident, "cfg", _)))
             {
                 return true;
             }
diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs
index f61ef9ac1b05e..c1e21ec4e3917 100644
--- a/clippy_utils/src/hir_utils.rs
+++ b/clippy_utils/src/hir_utils.rs
@@ -1194,8 +1194,8 @@ fn eq_span_tokens(
             && let Some(rsrc) = right.get_source_range(cx)
             && let Some(rsrc) = rsrc.as_str()
         {
-            let pred = |t: &(_, _)| pred(t.0);
-            let map = |(_, x)| x;
+            let pred = |&(token, ..): &(TokenKind, _, _)| pred(token);
+            let map = |(_, source, _)| source;
 
             let ltok = tokenize_with_text(lsrc).filter(pred).map(map);
             let rtok = tokenize_with_text(rsrc).filter(pred).map(map);
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index aec83e54747a9..668728405747d 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -121,7 +121,7 @@ use rustc_middle::ty::{
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, Ident, Symbol};
-use rustc_span::{sym, Span};
+use rustc_span::{sym, InnerSpan, Span};
 use rustc_target::abi::Integer;
 use visitors::Visitable;
 
@@ -2949,13 +2949,14 @@ pub fn expr_use_ctxt<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> ExprU
 }
 
 /// Tokenizes the input while keeping the text associated with each token.
-pub fn tokenize_with_text(s: &str) -> impl Iterator<Item = (TokenKind, &str)> {
+pub fn tokenize_with_text(s: &str) -> impl Iterator<Item = (TokenKind, &str, InnerSpan)> {
     let mut pos = 0;
     tokenize(s).map(move |t| {
         let end = pos + t.len;
         let range = pos as usize..end as usize;
+        let inner = InnerSpan::new(range.start, range.end);
         pos = end;
-        (t.kind, s.get(range).unwrap_or_default())
+        (t.kind, s.get(range).unwrap_or_default(), inner)
     })
 }
 
@@ -2979,8 +2980,8 @@ pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool {
 pub fn span_extract_comment(sm: &SourceMap, span: Span) -> String {
     let snippet = sm.span_to_snippet(span).unwrap_or_default();
     let res = tokenize_with_text(&snippet)
-        .filter(|(t, _)| matches!(t, TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }))
-        .map(|(_, s)| s)
+        .filter(|(t, ..)| matches!(t, TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }))
+        .map(|(_, s, _)| s)
         .join("\n");
     res
 }
@@ -3000,7 +3001,7 @@ pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
 /// pat: Some(a)
 /// else_body: return None
 /// ```
-
+///
 /// And for this example:
 /// ```ignore
 /// let Some(FooBar { a, b }) = ex else { return None };
@@ -3010,7 +3011,7 @@ pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
 /// pat: Some(FooBar { a, b })
 /// else_body: return None
 /// ```
-
+///
 /// We output `Some(a)` in the first instance, and `Some(FooBar { a, b })` in the second, because
 /// the question mark operator is applicable here. Callers have to check whether we are in a
 /// constant or not.
diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs
index 482e1e0147b18..f97fb4a6471dc 100644
--- a/clippy_utils/src/source.rs
+++ b/clippy_utils/src/source.rs
@@ -666,39 +666,6 @@ pub fn walk_span_to_context(span: Span, outer: SyntaxContext) -> Option<Span> {
     (outer_span.ctxt() == outer).then_some(outer_span)
 }
 
-/// Removes block comments from the given `Vec` of lines.
-///
-/// # Examples
-///
-/// ```rust,ignore
-/// without_block_comments(vec!["/*", "foo", "*/"]);
-/// // => vec![]
-///
-/// without_block_comments(vec!["bar", "/*", "foo", "*/"]);
-/// // => vec!["bar"]
-/// ```
-pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> {
-    let mut without = vec![];
-
-    let mut nest_level = 0;
-
-    for line in lines {
-        if line.contains("/*") {
-            nest_level += 1;
-            continue;
-        } else if line.contains("*/") {
-            nest_level -= 1;
-            continue;
-        }
-
-        if nest_level == 0 {
-            without.push(line);
-        }
-    }
-
-    without
-}
-
 /// Trims the whitespace from the start and the end of the span.
 pub fn trim_span(sm: &SourceMap, span: Span) -> Span {
     let data = span.data();
@@ -776,7 +743,7 @@ pub fn str_literal_to_char_literal(
 
 #[cfg(test)]
 mod test {
-    use super::{reindent_multiline, without_block_comments};
+    use super::reindent_multiline;
 
     #[test]
     fn test_reindent_multiline_single_line() {
@@ -844,29 +811,4 @@ mod test {
         z
     }".into(), true, Some(8)));
     }
-
-    #[test]
-    fn test_without_block_comments_lines_without_block_comments() {
-        let result = without_block_comments(vec!["/*", "", "*/"]);
-        println!("result: {result:?}");
-        assert!(result.is_empty());
-
-        let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]);
-        assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]);
-
-        let result = without_block_comments(vec!["/* rust", "", "*/"]);
-        assert!(result.is_empty());
-
-        let result = without_block_comments(vec!["/* one-line comment */"]);
-        assert!(result.is_empty());
-
-        let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]);
-        assert!(result.is_empty());
-
-        let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]);
-        assert!(result.is_empty());
-
-        let result = without_block_comments(vec!["foo", "bar", "baz"]);
-        assert_eq!(result, vec!["foo", "bar", "baz"]);
-    }
 }
diff --git a/tests/ui-toml/disallowed_names_append/disallowed_names.rs b/tests/ui-toml/disallowed_names_append/disallowed_names.rs
index a2e2b46c42693..61ae8de8e3357 100644
--- a/tests/ui-toml/disallowed_names_append/disallowed_names.rs
+++ b/tests/ui-toml/disallowed_names_append/disallowed_names.rs
@@ -1,4 +1,4 @@
-#[warn(clippy::disallowed_names)]
+#![warn(clippy::disallowed_names)]
 
 fn main() {
     // `foo` is part of the default configuration
diff --git a/tests/ui-toml/disallowed_names_replace/disallowed_names.rs b/tests/ui-toml/disallowed_names_replace/disallowed_names.rs
index a2e2b46c42693..61ae8de8e3357 100644
--- a/tests/ui-toml/disallowed_names_replace/disallowed_names.rs
+++ b/tests/ui-toml/disallowed_names_replace/disallowed_names.rs
@@ -1,4 +1,4 @@
-#[warn(clippy::disallowed_names)]
+#![warn(clippy::disallowed_names)]
 
 fn main() {
     // `foo` is part of the default configuration
diff --git a/tests/ui/allow_attributes_without_reason.rs b/tests/ui/allow_attributes_without_reason.rs
index 86f6b2c5742a9..334e7ddd9d233 100644
--- a/tests/ui/allow_attributes_without_reason.rs
+++ b/tests/ui/allow_attributes_without_reason.rs
@@ -15,7 +15,6 @@ use proc_macros::{external, with_span};
 #[warn(deref_nullptr)]
 #[deny(deref_nullptr)]
 #[forbid(deref_nullptr)]
-
 fn main() {
     external! {
         #[allow(dead_code)]
diff --git a/tests/ui/allow_attributes_without_reason.stderr b/tests/ui/allow_attributes_without_reason.stderr
index 9bc3ca0f2afd3..86d7845df0416 100644
--- a/tests/ui/allow_attributes_without_reason.stderr
+++ b/tests/ui/allow_attributes_without_reason.stderr
@@ -36,7 +36,7 @@ LL | #[expect(dead_code)]
    = help: try adding a reason at the end with `, reason = ".."`
 
 error: `allow` attribute without specifying a reason
-  --> tests/ui/allow_attributes_without_reason.rs:47:5
+  --> tests/ui/allow_attributes_without_reason.rs:46:5
    |
 LL |     #[allow(unused)]
    |     ^^^^^^^^^^^^^^^^
@@ -44,7 +44,7 @@ LL |     #[allow(unused)]
    = help: try adding a reason at the end with `, reason = ".."`
 
 error: `allow` attribute without specifying a reason
-  --> tests/ui/allow_attributes_without_reason.rs:47:5
+  --> tests/ui/allow_attributes_without_reason.rs:46:5
    |
 LL |     #[allow(unused)]
    |     ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/cast_alignment.rs b/tests/ui/cast_alignment.rs
index 98ef5e36f9488..72f5d4268cc1b 100644
--- a/tests/ui/cast_alignment.rs
+++ b/tests/ui/cast_alignment.rs
@@ -2,16 +2,16 @@
 
 #![feature(rustc_private)]
 #![feature(core_intrinsics)]
-extern crate libc;
-
-#[warn(clippy::cast_ptr_alignment)]
-#[allow(
+#![warn(clippy::cast_ptr_alignment)]
+#![allow(
     clippy::no_effect,
     clippy::unnecessary_operation,
     clippy::cast_lossless,
     clippy::borrow_as_ptr
 )]
 
+extern crate libc;
+
 fn main() {
     /* These should be warned against */
 
diff --git a/tests/ui/cmp_owned/without_suggestion.rs b/tests/ui/cmp_owned/without_suggestion.rs
index ec45d635c1727..913aab7274716 100644
--- a/tests/ui/cmp_owned/without_suggestion.rs
+++ b/tests/ui/cmp_owned/without_suggestion.rs
@@ -1,5 +1,5 @@
-#[allow(clippy::unnecessary_operation)]
-#[allow(clippy::implicit_clone)]
+#![allow(clippy::unnecessary_operation)]
+#![allow(clippy::implicit_clone)]
 
 fn main() {
     let x = &Baz;
diff --git a/tests/ui/collapsible_else_if.fixed b/tests/ui/collapsible_else_if.fixed
index 3b410b2f17b80..c2d76146c641d 100644
--- a/tests/ui/collapsible_else_if.fixed
+++ b/tests/ui/collapsible_else_if.fixed
@@ -1,9 +1,7 @@
 #![allow(clippy::assertions_on_constants, clippy::equatable_if_let, clippy::needless_if)]
+#![warn(clippy::collapsible_if, clippy::collapsible_else_if)]
 
 #[rustfmt::skip]
-#[warn(clippy::collapsible_if)]
-#[warn(clippy::collapsible_else_if)]
-
 fn main() {
     let x = "hello";
     let y = "world";
@@ -76,7 +74,6 @@ fn main() {
 }
 
 #[rustfmt::skip]
-#[allow(dead_code)]
 fn issue_7318() {
     if true { println!("I've been resolved!")
     }else if false {}
diff --git a/tests/ui/collapsible_else_if.rs b/tests/ui/collapsible_else_if.rs
index 772ef6f9fc606..3579e46cd4479 100644
--- a/tests/ui/collapsible_else_if.rs
+++ b/tests/ui/collapsible_else_if.rs
@@ -1,9 +1,7 @@
 #![allow(clippy::assertions_on_constants, clippy::equatable_if_let, clippy::needless_if)]
+#![warn(clippy::collapsible_if, clippy::collapsible_else_if)]
 
 #[rustfmt::skip]
-#[warn(clippy::collapsible_if)]
-#[warn(clippy::collapsible_else_if)]
-
 fn main() {
     let x = "hello";
     let y = "world";
@@ -90,7 +88,6 @@ fn main() {
 }
 
 #[rustfmt::skip]
-#[allow(dead_code)]
 fn issue_7318() {
     if true { println!("I've been resolved!")
     }else{
diff --git a/tests/ui/collapsible_else_if.stderr b/tests/ui/collapsible_else_if.stderr
index dc19d90b4d132..395c2dcf68dc0 100644
--- a/tests/ui/collapsible_else_if.stderr
+++ b/tests/ui/collapsible_else_if.stderr
@@ -1,5 +1,5 @@
 error: this `else { if .. }` block can be collapsed
-  --> tests/ui/collapsible_else_if.rs:13:12
+  --> tests/ui/collapsible_else_if.rs:11:12
    |
 LL |       } else {
    |  ____________^
@@ -19,7 +19,7 @@ LL +     }
    |
 
 error: this `else { if .. }` block can be collapsed
-  --> tests/ui/collapsible_else_if.rs:21:12
+  --> tests/ui/collapsible_else_if.rs:19:12
    |
 LL |       } else {
    |  ____________^
@@ -37,7 +37,7 @@ LL +     }
    |
 
 error: this `else { if .. }` block can be collapsed
-  --> tests/ui/collapsible_else_if.rs:29:12
+  --> tests/ui/collapsible_else_if.rs:27:12
    |
 LL |       } else {
    |  ____________^
@@ -60,7 +60,7 @@ LL +     }
    |
 
 error: this `else { if .. }` block can be collapsed
-  --> tests/ui/collapsible_else_if.rs:40:12
+  --> tests/ui/collapsible_else_if.rs:38:12
    |
 LL |       } else {
    |  ____________^
@@ -83,7 +83,7 @@ LL +     }
    |
 
 error: this `else { if .. }` block can be collapsed
-  --> tests/ui/collapsible_else_if.rs:51:12
+  --> tests/ui/collapsible_else_if.rs:49:12
    |
 LL |       } else {
    |  ____________^
@@ -106,7 +106,7 @@ LL +     }
    |
 
 error: this `else { if .. }` block can be collapsed
-  --> tests/ui/collapsible_else_if.rs:62:12
+  --> tests/ui/collapsible_else_if.rs:60:12
    |
 LL |       } else {
    |  ____________^
@@ -129,7 +129,7 @@ LL +     }
    |
 
 error: this `else { if .. }` block can be collapsed
-  --> tests/ui/collapsible_else_if.rs:73:12
+  --> tests/ui/collapsible_else_if.rs:71:12
    |
 LL |       } else {
    |  ____________^
@@ -152,7 +152,7 @@ LL +     }
    |
 
 error: this `else { if .. }` block can be collapsed
-  --> tests/ui/collapsible_else_if.rs:96:10
+  --> tests/ui/collapsible_else_if.rs:93:10
    |
 LL |       }else{
    |  __________^
diff --git a/tests/ui/crashes/associated-constant-ice.rs b/tests/ui/crashes/associated-constant-ice.rs
index 948deba3ea6e3..fec16671eeb32 100644
--- a/tests/ui/crashes/associated-constant-ice.rs
+++ b/tests/ui/crashes/associated-constant-ice.rs
@@ -1,4 +1,4 @@
-/// Test for https://github.com/rust-lang/rust-clippy/issues/1698
+// Test for https://github.com/rust-lang/rust-clippy/issues/1698
 
 pub trait Trait {
     const CONSTANT: u8;
diff --git a/tests/ui/crashes/cc_seme.rs b/tests/ui/crashes/cc_seme.rs
index 98588be9cf829..98897d6d7aaf9 100644
--- a/tests/ui/crashes/cc_seme.rs
+++ b/tests/ui/crashes/cc_seme.rs
@@ -1,6 +1,4 @@
-#[allow(dead_code)]
-
-/// Test for https://github.com/rust-lang/rust-clippy/issues/478
+// Test for https://github.com/rust-lang/rust-clippy/issues/478
 
 enum Baz {
     One,
diff --git a/tests/ui/crashes/ice-11230.rs b/tests/ui/crashes/ice-11230.rs
index 5761882273e00..94044e9435ed4 100644
--- a/tests/ui/crashes/ice-11230.rs
+++ b/tests/ui/crashes/ice-11230.rs
@@ -1,4 +1,4 @@
-/// Test for https://github.com/rust-lang/rust-clippy/issues/11230
+// Test for https://github.com/rust-lang/rust-clippy/issues/11230
 
 fn main() {
     const A: &[for<'a> fn(&'a ())] = &[];
diff --git a/tests/ui/crashes/ice-1588.rs b/tests/ui/crashes/ice-1588.rs
index b0a3d11bce463..9ec093721c17e 100644
--- a/tests/ui/crashes/ice-1588.rs
+++ b/tests/ui/crashes/ice-1588.rs
@@ -1,6 +1,6 @@
 #![allow(clippy::all)]
 
-/// Test for https://github.com/rust-lang/rust-clippy/issues/1588
+// Test for https://github.com/rust-lang/rust-clippy/issues/1588
 
 fn main() {
     match 1 {
diff --git a/tests/ui/crashes/ice-1969.rs b/tests/ui/crashes/ice-1969.rs
index 96a8fe6c24d56..eb901c7672948 100644
--- a/tests/ui/crashes/ice-1969.rs
+++ b/tests/ui/crashes/ice-1969.rs
@@ -1,6 +1,6 @@
 #![allow(clippy::all)]
 
-/// Test for https://github.com/rust-lang/rust-clippy/issues/1969
+// Test for https://github.com/rust-lang/rust-clippy/issues/1969
 
 fn main() {}
 
diff --git a/tests/ui/crashes/ice-2499.rs b/tests/ui/crashes/ice-2499.rs
index 45b3b1869dde6..732f331ad145e 100644
--- a/tests/ui/crashes/ice-2499.rs
+++ b/tests/ui/crashes/ice-2499.rs
@@ -1,8 +1,8 @@
 #![allow(dead_code, clippy::char_lit_as_u8, clippy::needless_bool)]
 
-/// Should not trigger an ICE in `SpanlessHash` / `consts::constant`
-///
-/// Issue: https://github.com/rust-lang/rust-clippy/issues/2499
+// Should not trigger an ICE in `SpanlessHash` / `consts::constant`
+//
+// Issue: https://github.com/rust-lang/rust-clippy/issues/2499
 
 fn f(s: &[u8]) -> bool {
     let t = s[0] as char;
diff --git a/tests/ui/crashes/ice-2594.rs b/tests/ui/crashes/ice-2594.rs
index 3f3986b6fc692..dddf860bd1785 100644
--- a/tests/ui/crashes/ice-2594.rs
+++ b/tests/ui/crashes/ice-2594.rs
@@ -3,7 +3,6 @@
 /// Should not trigger an ICE in `SpanlessHash` / `consts::constant`
 ///
 /// Issue: https://github.com/rust-lang/rust-clippy/issues/2594
-
 fn spanless_hash_ice() {
     let txt = "something";
     let empty_header: [u8; 1] = [1; 1];
diff --git a/tests/ui/crashes/ice-2727.rs b/tests/ui/crashes/ice-2727.rs
index 56024abc8f58d..59fb9b04b86d0 100644
--- a/tests/ui/crashes/ice-2727.rs
+++ b/tests/ui/crashes/ice-2727.rs
@@ -1,4 +1,4 @@
-/// Test for https://github.com/rust-lang/rust-clippy/issues/2727
+// Test for https://github.com/rust-lang/rust-clippy/issues/2727
 
 pub fn f(new: fn()) {
     new();
diff --git a/tests/ui/crashes/ice-2760.rs b/tests/ui/crashes/ice-2760.rs
index 61ef24804986e..5f7d91abf9959 100644
--- a/tests/ui/crashes/ice-2760.rs
+++ b/tests/ui/crashes/ice-2760.rs
@@ -5,10 +5,10 @@
     dead_code
 )]
 
-/// This should not compile-fail with:
-///
-///      error[E0277]: the trait bound `T: Foo` is not satisfied
-// See rust-lang/rust-clippy#2760.
+// This should not compile-fail with:
+//
+//      error[E0277]: the trait bound `T: Foo` is not satisfied
+// See https://github.com/rust-lang/rust-clippy/issues/2760
 
 trait Foo {
     type Bar;
diff --git a/tests/ui/crashes/ice-2862.rs b/tests/ui/crashes/ice-2862.rs
index 8326e3663b054..2573b571f55cd 100644
--- a/tests/ui/crashes/ice-2862.rs
+++ b/tests/ui/crashes/ice-2862.rs
@@ -1,4 +1,4 @@
-/// Test for https://github.com/rust-lang/rust-clippy/issues/2862
+// Test for https://github.com/rust-lang/rust-clippy/issues/2862
 
 pub trait FooMap {
     fn map<B, F: Fn() -> B>(&self, f: F) -> B;
diff --git a/tests/ui/crashes/ice-2865.rs b/tests/ui/crashes/ice-2865.rs
index c629813960162..28363707acca7 100644
--- a/tests/ui/crashes/ice-2865.rs
+++ b/tests/ui/crashes/ice-2865.rs
@@ -1,6 +1,6 @@
 #![allow(dead_code, clippy::extra_unused_lifetimes)]
 
-/// Test for https://github.com/rust-lang/rust-clippy/issues/2865
+// Test for https://github.com/rust-lang/rust-clippy/issues/2865
 
 struct Ice {
     size: String,
diff --git a/tests/ui/crashes/ice-3151.rs b/tests/ui/crashes/ice-3151.rs
index 268ba86fc7aa8..f88a26cb48592 100644
--- a/tests/ui/crashes/ice-3151.rs
+++ b/tests/ui/crashes/ice-3151.rs
@@ -1,4 +1,4 @@
-/// Test for https://github.com/rust-lang/rust-clippy/issues/3151
+// Test for https://github.com/rust-lang/rust-clippy/issues/3151
 
 #[derive(Clone)]
 pub struct HashMap<V, S> {
diff --git a/tests/ui/crashes/ice-3462.rs b/tests/ui/crashes/ice-3462.rs
index 21cd9d337cdd0..ccd617e305dae 100644
--- a/tests/ui/crashes/ice-3462.rs
+++ b/tests/ui/crashes/ice-3462.rs
@@ -2,7 +2,7 @@
 #![allow(clippy::disallowed_names, clippy::equatable_if_let, clippy::needless_if)]
 #![allow(unused)]
 
-/// Test for https://github.com/rust-lang/rust-clippy/issues/3462
+// Test for https://github.com/rust-lang/rust-clippy/issues/3462
 
 enum Foo {
     Bar,
diff --git a/tests/ui/crashes/ice-3747.rs b/tests/ui/crashes/ice-3747.rs
index cdf018cbc88d8..44b1d7ed1b2e8 100644
--- a/tests/ui/crashes/ice-3747.rs
+++ b/tests/ui/crashes/ice-3747.rs
@@ -1,4 +1,4 @@
-/// Test for https://github.com/rust-lang/rust-clippy/issues/3747
+// Test for https://github.com/rust-lang/rust-clippy/issues/3747
 
 macro_rules! a {
     ( $pub:tt $($attr:tt)* ) => {
diff --git a/tests/ui/crashes/ice-700.rs b/tests/ui/crashes/ice-700.rs
index 0cbceedbd6bdb..5e004b94330ea 100644
--- a/tests/ui/crashes/ice-700.rs
+++ b/tests/ui/crashes/ice-700.rs
@@ -1,6 +1,6 @@
 #![deny(clippy::all)]
 
-/// Test for https://github.com/rust-lang/rust-clippy/issues/700
+// Test for https://github.com/rust-lang/rust-clippy/issues/700
 
 fn core() {}
 
diff --git a/tests/ui/crashes/ice_exact_size.rs b/tests/ui/crashes/ice_exact_size.rs
index 30e4b11ec0bd4..c0671eaff1450 100644
--- a/tests/ui/crashes/ice_exact_size.rs
+++ b/tests/ui/crashes/ice_exact_size.rs
@@ -1,6 +1,6 @@
 #![deny(clippy::all)]
 
-/// Test for https://github.com/rust-lang/rust-clippy/issues/1336
+// Test for https://github.com/rust-lang/rust-clippy/issues/1336
 
 #[allow(dead_code)]
 struct Foo;
diff --git a/tests/ui/crashes/if_same_then_else.rs b/tests/ui/crashes/if_same_then_else.rs
index 2f913292995ea..a900fe5e6bc66 100644
--- a/tests/ui/crashes/if_same_then_else.rs
+++ b/tests/ui/crashes/if_same_then_else.rs
@@ -1,7 +1,7 @@
 #![allow(clippy::comparison_chain)]
 #![deny(clippy::if_same_then_else)]
 
-/// Test for https://github.com/rust-lang/rust-clippy/issues/2426
+// Test for https://github.com/rust-lang/rust-clippy/issues/2426
 
 fn main() {}
 
diff --git a/tests/ui/crashes/inherent_impl.rs b/tests/ui/crashes/inherent_impl.rs
index aeb27b5ba8c2f..800a5a383f626 100644
--- a/tests/ui/crashes/inherent_impl.rs
+++ b/tests/ui/crashes/inherent_impl.rs
@@ -1,6 +1,6 @@
 #![deny(clippy::multiple_inherent_impl)]
 
-/// Test for https://github.com/rust-lang/rust-clippy/issues/4578
+// Test for https://github.com/rust-lang/rust-clippy/issues/4578
 
 macro_rules! impl_foo {
     ($struct:ident) => {
diff --git a/tests/ui/crashes/issue-825.rs b/tests/ui/crashes/issue-825.rs
index 05696e3d7d56f..e8b455a0ec67b 100644
--- a/tests/ui/crashes/issue-825.rs
+++ b/tests/ui/crashes/issue-825.rs
@@ -1,6 +1,6 @@
 #![allow(warnings)]
 
-/// Test for https://github.com/rust-lang/rust-clippy/issues/825
+// Test for https://github.com/rust-lang/rust-clippy/issues/825
 
 // this should compile in a reasonable amount of time
 fn rust_type_id(name: &str) {
diff --git a/tests/ui/crashes/match_same_arms_const.rs b/tests/ui/crashes/match_same_arms_const.rs
index 94c939665e616..626179c001557 100644
--- a/tests/ui/crashes/match_same_arms_const.rs
+++ b/tests/ui/crashes/match_same_arms_const.rs
@@ -1,6 +1,6 @@
 #![deny(clippy::match_same_arms)]
 
-/// Test for https://github.com/rust-lang/rust-clippy/issues/2427
+// Test for https://github.com/rust-lang/rust-clippy/issues/2427
 
 const PRICE_OF_SWEETS: u32 = 5;
 const PRICE_OF_KINDNESS: u32 = 0;
diff --git a/tests/ui/crashes/returns.rs b/tests/ui/crashes/returns.rs
index 8021ed4607dde..91cdb5306c895 100644
--- a/tests/ui/crashes/returns.rs
+++ b/tests/ui/crashes/returns.rs
@@ -1,4 +1,4 @@
-/// Test for https://github.com/rust-lang/rust-clippy/issues/1346
+// Test for https://github.com/rust-lang/rust-clippy/issues/1346
 
 #[deny(warnings)]
 fn cfg_return() -> i32 {
diff --git a/tests/ui/doc/doc_lazy_blank_line.fixed b/tests/ui/doc/doc_lazy_blank_line.fixed
deleted file mode 100644
index 1aaa26afe7f26..0000000000000
--- a/tests/ui/doc/doc_lazy_blank_line.fixed
+++ /dev/null
@@ -1,47 +0,0 @@
-// https://github.com/rust-lang/rust-clippy/issues/12917
-#![warn(clippy::doc_lazy_continuation)]
-
-/// This is a constant.
-///
-/// The meaning of which should not be explained.
-pub const A: i32 = 42;
-
-/// This is another constant, no longer used.
-///
-/// This block of documentation has a long
-/// explanation and derivation to explain
-/// why it is what it is, and how it's used.
-///
-/// It is left here for historical reasons, and
-/// for reference.
-///
-/// Reasons it's great:
-///  - First reason
-///  - Second reason
-///
-//pub const B: i32 = 1337;
-
-/// This is yet another constant.
-///
-/// This has a similar fate as `B`.
-///
-/// Reasons it's useful:
-///  1. First reason
-///  2. Second reason
-///
-//pub const C: i32 = 8008;
-
-/// This is still in use.
-pub const D: i32 = 20;
-
-/// > blockquote code path
-///
-
-/// bottom text
-pub const E: i32 = 20;
-
-/// > blockquote code path
-///
-#[repr(C)]
-/// bottom text
-pub struct Foo(i32);
diff --git a/tests/ui/doc/doc_lazy_blank_line.rs b/tests/ui/doc/doc_lazy_blank_line.rs
deleted file mode 100644
index e1ab8fc838926..0000000000000
--- a/tests/ui/doc/doc_lazy_blank_line.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-// https://github.com/rust-lang/rust-clippy/issues/12917
-#![warn(clippy::doc_lazy_continuation)]
-
-/// This is a constant.
-///
-/// The meaning of which should not be explained.
-pub const A: i32 = 42;
-
-/// This is another constant, no longer used.
-///
-/// This block of documentation has a long
-/// explanation and derivation to explain
-/// why it is what it is, and how it's used.
-///
-/// It is left here for historical reasons, and
-/// for reference.
-///
-/// Reasons it's great:
-///  - First reason
-///  - Second reason
-//pub const B: i32 = 1337;
-
-/// This is yet another constant.
-///
-/// This has a similar fate as `B`.
-///
-/// Reasons it's useful:
-///  1. First reason
-///  2. Second reason
-//pub const C: i32 = 8008;
-
-/// This is still in use.
-pub const D: i32 = 20;
-
-/// > blockquote code path
-
-/// bottom text
-pub const E: i32 = 20;
-
-/// > blockquote code path
-#[repr(C)]
-/// bottom text
-pub struct Foo(i32);
diff --git a/tests/ui/doc/doc_lazy_blank_line.stderr b/tests/ui/doc/doc_lazy_blank_line.stderr
deleted file mode 100644
index 854906a747418..0000000000000
--- a/tests/ui/doc/doc_lazy_blank_line.stderr
+++ /dev/null
@@ -1,56 +0,0 @@
-error: doc list item without indentation
-  --> tests/ui/doc/doc_lazy_blank_line.rs:23:5
-   |
-LL | /// This is yet another constant.
-   |     ^
-   |
-   = help: if this is intended to be part of the list, indent 3 spaces
-   = note: `-D clippy::doc-lazy-continuation` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::doc_lazy_continuation)]`
-help: if this should be its own paragraph, add a blank doc comment line
-   |
-LL ~ ///  - Second reason
-LL + ///
-   |
-
-error: doc list item without indentation
-  --> tests/ui/doc/doc_lazy_blank_line.rs:32:5
-   |
-LL | /// This is still in use.
-   |     ^
-   |
-   = help: if this is intended to be part of the list, indent 4 spaces
-help: if this should be its own paragraph, add a blank doc comment line
-   |
-LL ~ ///  2. Second reason
-LL + ///
-   |
-
-error: doc quote line without `>` marker
-  --> tests/ui/doc/doc_lazy_blank_line.rs:37:5
-   |
-LL | /// bottom text
-   |     ^
-   |
-   = help: if this not intended to be a quote at all, escape it with `\>`
-help: if this should be its own paragraph, add a blank doc comment line
-   |
-LL ~ /// > blockquote code path
-LL + ///
-   |
-
-error: doc quote line without `>` marker
-  --> tests/ui/doc/doc_lazy_blank_line.rs:42:5
-   |
-LL | /// bottom text
-   |     ^
-   |
-   = help: if this not intended to be a quote at all, escape it with `\>`
-help: if this should be its own paragraph, add a blank doc comment line
-   |
-LL ~ /// > blockquote code path
-LL + ///
-   |
-
-error: aborting due to 4 previous errors
-
diff --git a/tests/ui/doc/doc_lazy_list.fixed b/tests/ui/doc/doc_lazy_list.fixed
index ea59ae4c01c96..da537518a2b53 100644
--- a/tests/ui/doc/doc_lazy_list.fixed
+++ b/tests/ui/doc/doc_lazy_list.fixed
@@ -7,9 +7,8 @@ fn one() {}
 
 /// 1. first line
 ///    lazy list continuations don't make warnings with this lint
-///
 //~^ ERROR: doc list item without indentation
-/// because they don't have the
+///    because they don't have the
 //~^ ERROR: doc list item without indentation
 fn two() {}
 
@@ -20,9 +19,8 @@ fn three() {}
 
 ///   - first line
 ///     lazy list continuations don't make warnings with this lint
-///
 //~^ ERROR: doc list item without indentation
-/// because they don't have the
+///     because they don't have the
 //~^ ERROR: doc list item without indentation
 fn four() {}
 
@@ -33,9 +31,8 @@ fn five() {}
 
 ///   - - first line
 ///       this will warn on the lazy continuation
-///
 //~^ ERROR: doc list item without indentation
-///     and so should this
+///       and so should this
 //~^ ERROR: doc list item without indentation
 fn six() {}
 
diff --git a/tests/ui/doc/doc_lazy_list.stderr b/tests/ui/doc/doc_lazy_list.stderr
index 52aa74df8948c..b38f43b7555f1 100644
--- a/tests/ui/doc/doc_lazy_list.stderr
+++ b/tests/ui/doc/doc_lazy_list.stderr
@@ -30,12 +30,11 @@ error: doc list item without indentation
 LL | /// because they don't have the
    |     ^
    |
-   = help: if this is intended to be part of the list, indent 3 spaces
-help: if this should be its own paragraph, add a blank doc comment line
-   |
-LL ~ /// lazy list continuations don't make warnings with this lint
-LL + ///
+   = help: if this is supposed to be its own paragraph, add a blank line
+help: indent this line
    |
+LL | ///    because they don't have the
+   |     +++
 
 error: doc list item without indentation
   --> tests/ui/doc/doc_lazy_list.rs:16:5
@@ -67,12 +66,11 @@ error: doc list item without indentation
 LL | /// because they don't have the
    |     ^
    |
-   = help: if this is intended to be part of the list, indent 4 spaces
-help: if this should be its own paragraph, add a blank doc comment line
-   |
-LL ~ /// lazy list continuations don't make warnings with this lint
-LL + ///
+   = help: if this is supposed to be its own paragraph, add a blank line
+help: indent this line
    |
+LL | ///     because they don't have the
+   |     ++++
 
 error: doc list item without indentation
   --> tests/ui/doc/doc_lazy_list.rs:28:5
@@ -104,12 +102,11 @@ error: doc list item without indentation
 LL | ///     and so should this
    |     ^^^^
    |
-   = help: if this is intended to be part of the list, indent 2 spaces
-help: if this should be its own paragraph, add a blank doc comment line
-   |
-LL ~ /// this will warn on the lazy continuation
-LL + ///
+   = help: if this is supposed to be its own paragraph, add a blank line
+help: indent this line
    |
+LL | ///       and so should this
+   |         ++
 
 error: doc list item without indentation
   --> tests/ui/doc/doc_lazy_list.rs:56:5
diff --git a/tests/ui/duplicate_underscore_argument.rs b/tests/ui/duplicate_underscore_argument.rs
index 118f6e4a34c0a..a725538436cb1 100644
--- a/tests/ui/duplicate_underscore_argument.rs
+++ b/tests/ui/duplicate_underscore_argument.rs
@@ -1,5 +1,4 @@
 #![warn(clippy::duplicate_underscore_argument)]
-#[allow(dead_code, unused)]
 
 fn join_the_dark_side(darth: i32, _darth: i32) {}
 //~^ ERROR: `darth` already exists, having another argument having almost the same name ma
diff --git a/tests/ui/duplicate_underscore_argument.stderr b/tests/ui/duplicate_underscore_argument.stderr
index 40a24b823d115..74979b157882a 100644
--- a/tests/ui/duplicate_underscore_argument.stderr
+++ b/tests/ui/duplicate_underscore_argument.stderr
@@ -1,5 +1,5 @@
 error: `darth` already exists, having another argument having almost the same name makes code comprehension and documentation more difficult
-  --> tests/ui/duplicate_underscore_argument.rs:4:23
+  --> tests/ui/duplicate_underscore_argument.rs:3:23
    |
 LL | fn join_the_dark_side(darth: i32, _darth: i32) {}
    |                       ^^^^^
diff --git a/tests/ui/empty_line_after/doc_comments.1.fixed b/tests/ui/empty_line_after/doc_comments.1.fixed
new file mode 100644
index 0000000000000..fd6a94b6a80c8
--- /dev/null
+++ b/tests/ui/empty_line_after/doc_comments.1.fixed
@@ -0,0 +1,135 @@
+#![warn(clippy::empty_line_after_outer_attr, clippy::empty_line_after_doc_comments)]
+
+//~vvv empty_line_after_doc_comments
+/// Meant to be an
+/// inner doc comment
+/// for the crate
+fn first_in_crate() {}
+
+mod m {
+    //~vvv empty_line_after_doc_comments
+    /// Meant to be an
+    /// inner doc comment
+    /// for the module
+    fn first_in_module() {}
+}
+
+mod some_mod {
+    //! This doc comment should *NOT* produce a warning
+
+    mod some_inner_mod {
+        fn some_noop() {}
+    }
+
+    //~v empty_line_after_doc_comments
+    /// # Indented
+    /// Blank line
+    fn indented() {}
+}
+
+//~v empty_line_after_doc_comments
+/// This should produce a warning
+fn with_doc_and_newline() {}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+/// some comment
+fn with_no_newline_and_comment() {}
+
+//~v empty_line_after_doc_comments
+/// This doc comment should produce a warning
+/** This is also a doc comment and is part of the warning
+ */
+#[allow(non_camel_case_types)]
+#[allow(missing_docs)]
+#[allow(dead_code)]
+fn three_attributes() {}
+
+mod misattributed {
+    //~v empty_line_after_doc_comments
+    /// docs for `old_code`
+    // fn old_code() {}
+    fn new_code() {}
+
+    //~vv empty_line_after_doc_comments
+    /// Docs
+    /// for OldA
+    // struct OldA;
+    /// Docs
+    /// for OldB
+    // struct OldB;
+    /// Docs
+    /// for Multiple
+    #[allow(dead_code)]
+    struct Multiple;
+}
+
+mod block_comments {
+    //~v empty_line_after_doc_comments
+    /**
+     * Meant to be inner doc comment
+     */
+    fn first_in_module() {}
+
+    //~v empty_line_after_doc_comments
+    /**
+     * Docs for `old_code`
+     */
+    /* fn old_code() {} */
+    /**
+     * Docs for `new_code`
+     */
+    fn new_code() {}
+
+    //~v empty_line_after_doc_comments
+    /// Docs for `old_code2`
+    /* fn old_code2() {} */
+    /// Docs for `new_code2`
+    fn new_code2() {}
+}
+
+// This should *NOT* produce a warning
+#[doc = "
+Returns the escaped value of the textual representation of
+
+"]
+pub fn function() -> bool {
+    true
+}
+
+// This should *NOT* produce a warning
+#[derive(Clone, Copy)]
+pub enum FooFighter {
+    Bar1,
+
+    Bar2,
+
+    Bar3,
+
+    Bar4,
+}
+
+/// Should not lint
+// some line comment
+/// gaps without an empty line
+struct LineComment;
+
+/// This should *NOT* produce a warning because the empty line is inside a block comment
+/*
+
+*/
+pub struct EmptyInBlockComment;
+
+/// This should *NOT* produce a warning
+/* test */
+pub struct BlockComment;
+
+/// Ignore the empty line inside a cfg_attr'd out attribute
+#[cfg_attr(any(), multiline(
+    foo = 1
+
+    bar = 2
+))]
+fn empty_line_in_cfg_attr() {}
+
+fn main() {}
diff --git a/tests/ui/empty_line_after/doc_comments.2.fixed b/tests/ui/empty_line_after/doc_comments.2.fixed
new file mode 100644
index 0000000000000..7a57dcd92332b
--- /dev/null
+++ b/tests/ui/empty_line_after/doc_comments.2.fixed
@@ -0,0 +1,144 @@
+#![warn(clippy::empty_line_after_outer_attr, clippy::empty_line_after_doc_comments)]
+
+//~vvv empty_line_after_doc_comments
+//! Meant to be an
+//! inner doc comment
+//! for the crate
+
+fn first_in_crate() {}
+
+mod m {
+    //~vvv empty_line_after_doc_comments
+    //! Meant to be an
+    //! inner doc comment
+    //! for the module
+
+    fn first_in_module() {}
+}
+
+mod some_mod {
+    //! This doc comment should *NOT* produce a warning
+
+    mod some_inner_mod {
+        fn some_noop() {}
+    }
+
+    //~v empty_line_after_doc_comments
+    /// # Indented
+    ///
+    /// Blank line
+    fn indented() {}
+}
+
+//~v empty_line_after_doc_comments
+/// This should produce a warning
+fn with_doc_and_newline() {}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+/// some comment
+fn with_no_newline_and_comment() {}
+
+//~v empty_line_after_doc_comments
+/// This doc comment should produce a warning
+/** This is also a doc comment and is part of the warning
+ */
+#[allow(non_camel_case_types)]
+#[allow(missing_docs)]
+#[allow(dead_code)]
+fn three_attributes() {}
+
+mod misattributed {
+    //~v empty_line_after_doc_comments
+    // /// docs for `old_code`
+    // fn old_code() {}
+
+    fn new_code() {}
+
+    //~vv empty_line_after_doc_comments
+    // /// Docs
+    // /// for OldA
+    // struct OldA;
+
+    // /// Docs
+    // /// for OldB
+    // struct OldB;
+
+    /// Docs
+    /// for Multiple
+    #[allow(dead_code)]
+    struct Multiple;
+}
+
+mod block_comments {
+    //~v empty_line_after_doc_comments
+    /*!
+     * Meant to be inner doc comment
+     */
+
+    fn first_in_module() {}
+
+    //~v empty_line_after_doc_comments
+    /*
+     * Docs for `old_code`
+     */
+    /* fn old_code() {} */
+
+    /**
+     * Docs for `new_code`
+     */
+    fn new_code() {}
+
+    //~v empty_line_after_doc_comments
+    // /// Docs for `old_code2`
+    /* fn old_code2() {} */
+
+    /// Docs for `new_code2`
+    fn new_code2() {}
+}
+
+// This should *NOT* produce a warning
+#[doc = "
+Returns the escaped value of the textual representation of
+
+"]
+pub fn function() -> bool {
+    true
+}
+
+// This should *NOT* produce a warning
+#[derive(Clone, Copy)]
+pub enum FooFighter {
+    Bar1,
+
+    Bar2,
+
+    Bar3,
+
+    Bar4,
+}
+
+/// Should not lint
+// some line comment
+/// gaps without an empty line
+struct LineComment;
+
+/// This should *NOT* produce a warning because the empty line is inside a block comment
+/*
+
+*/
+pub struct EmptyInBlockComment;
+
+/// This should *NOT* produce a warning
+/* test */
+pub struct BlockComment;
+
+/// Ignore the empty line inside a cfg_attr'd out attribute
+#[cfg_attr(any(), multiline(
+    foo = 1
+
+    bar = 2
+))]
+fn empty_line_in_cfg_attr() {}
+
+fn main() {}
diff --git a/tests/ui/empty_line_after/doc_comments.rs b/tests/ui/empty_line_after/doc_comments.rs
new file mode 100644
index 0000000000000..1da761a5c3d52
--- /dev/null
+++ b/tests/ui/empty_line_after/doc_comments.rs
@@ -0,0 +1,147 @@
+#![warn(clippy::empty_line_after_outer_attr, clippy::empty_line_after_doc_comments)]
+
+//~vvv empty_line_after_doc_comments
+/// Meant to be an
+/// inner doc comment
+/// for the crate
+
+fn first_in_crate() {}
+
+mod m {
+    //~vvv empty_line_after_doc_comments
+    /// Meant to be an
+    /// inner doc comment
+    /// for the module
+
+    fn first_in_module() {}
+}
+
+mod some_mod {
+    //! This doc comment should *NOT* produce a warning
+
+    mod some_inner_mod {
+        fn some_noop() {}
+    }
+
+    //~v empty_line_after_doc_comments
+    /// # Indented
+
+    /// Blank line
+    fn indented() {}
+}
+
+//~v empty_line_after_doc_comments
+/// This should produce a warning
+
+fn with_doc_and_newline() {}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+/// some comment
+fn with_no_newline_and_comment() {}
+
+//~v empty_line_after_doc_comments
+/// This doc comment should produce a warning
+
+/** This is also a doc comment and is part of the warning
+ */
+
+#[allow(non_camel_case_types)]
+#[allow(missing_docs)]
+#[allow(dead_code)]
+fn three_attributes() {}
+
+mod misattributed {
+    //~v empty_line_after_doc_comments
+    /// docs for `old_code`
+    // fn old_code() {}
+
+    fn new_code() {}
+
+    //~vv empty_line_after_doc_comments
+    /// Docs
+    /// for OldA
+    // struct OldA;
+
+    /// Docs
+    /// for OldB
+    // struct OldB;
+
+    /// Docs
+    /// for Multiple
+    #[allow(dead_code)]
+    struct Multiple;
+}
+
+mod block_comments {
+    //~v empty_line_after_doc_comments
+    /**
+     * Meant to be inner doc comment
+     */
+
+    fn first_in_module() {}
+
+    //~v empty_line_after_doc_comments
+    /**
+     * Docs for `old_code`
+     */
+    /* fn old_code() {} */
+
+    /**
+     * Docs for `new_code`
+     */
+    fn new_code() {}
+
+    //~v empty_line_after_doc_comments
+    /// Docs for `old_code2`
+    /* fn old_code2() {} */
+
+    /// Docs for `new_code2`
+    fn new_code2() {}
+}
+
+// This should *NOT* produce a warning
+#[doc = "
+Returns the escaped value of the textual representation of
+
+"]
+pub fn function() -> bool {
+    true
+}
+
+// This should *NOT* produce a warning
+#[derive(Clone, Copy)]
+pub enum FooFighter {
+    Bar1,
+
+    Bar2,
+
+    Bar3,
+
+    Bar4,
+}
+
+/// Should not lint
+// some line comment
+/// gaps without an empty line
+struct LineComment;
+
+/// This should *NOT* produce a warning because the empty line is inside a block comment
+/*
+
+*/
+pub struct EmptyInBlockComment;
+
+/// This should *NOT* produce a warning
+/* test */
+pub struct BlockComment;
+
+/// Ignore the empty line inside a cfg_attr'd out attribute
+#[cfg_attr(any(), multiline(
+    foo = 1
+
+    bar = 2
+))]
+fn empty_line_in_cfg_attr() {}
+
+fn main() {}
diff --git a/tests/ui/empty_line_after/doc_comments.stderr b/tests/ui/empty_line_after/doc_comments.stderr
new file mode 100644
index 0000000000000..c238b4c9a17f2
--- /dev/null
+++ b/tests/ui/empty_line_after/doc_comments.stderr
@@ -0,0 +1,176 @@
+error: empty line after doc comment
+  --> tests/ui/empty_line_after/doc_comments.rs:6:1
+   |
+LL | / /// for the crate
+LL | |
+   | |_
+LL |   fn first_in_crate() {}
+   |   ------------------- the comment documents this function
+   |
+   = note: `-D clippy::empty-line-after-doc-comments` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::empty_line_after_doc_comments)]`
+   = help: if the empty line is unintentional remove it
+help: if the comment should document the crate use an inner doc comment
+   |
+LL ~ //! Meant to be an
+LL ~ //! inner doc comment
+LL ~ //! for the crate
+   |
+
+error: empty line after doc comment
+  --> tests/ui/empty_line_after/doc_comments.rs:14:5
+   |
+LL | /     /// for the module
+LL | |
+   | |_
+LL |       fn first_in_module() {}
+   |       -------------------- the comment documents this function
+   |
+   = help: if the empty line is unintentional remove it
+help: if the comment should document the parent module use an inner doc comment
+   |
+LL ~     //! Meant to be an
+LL ~     //! inner doc comment
+LL ~     //! for the module
+   |
+
+error: empty line after doc comment
+  --> tests/ui/empty_line_after/doc_comments.rs:27:5
+   |
+LL | /     /// # Indented
+LL | |
+   | |_
+LL |       /// Blank line
+LL |       fn indented() {}
+   |       ------------- the comment documents this function
+   |
+   = help: if the empty line is unintentional remove it
+help: if the documentation should include the empty line include it in the comment
+   |
+LL |     ///
+   |
+
+error: empty line after doc comment
+  --> tests/ui/empty_line_after/doc_comments.rs:34:1
+   |
+LL | / /// This should produce a warning
+LL | |
+   | |_
+LL |   fn with_doc_and_newline() {}
+   |   ------------------------- the comment documents this function
+   |
+   = help: if the empty line is unintentional remove it
+
+error: empty lines after doc comment
+  --> tests/ui/empty_line_after/doc_comments.rs:44:1
+   |
+LL | / /// This doc comment should produce a warning
+LL | |
+LL | | /** This is also a doc comment and is part of the warning
+LL | |  */
+LL | |
+   | |_
+...
+LL |   fn three_attributes() {}
+   |   --------------------- the comment documents this function
+   |
+   = help: if the empty lines are unintentional remove them
+
+error: empty line after doc comment
+  --> tests/ui/empty_line_after/doc_comments.rs:56:5
+   |
+LL | /     /// docs for `old_code`
+LL | |     // fn old_code() {}
+LL | |
+   | |_
+LL |       fn new_code() {}
+   |       ------------- the comment documents this function
+   |
+   = help: if the empty line is unintentional remove it
+help: if the doc comment should not document `new_code` comment it out
+   |
+LL |     // /// docs for `old_code`
+   |     ++
+
+error: empty lines after doc comment
+  --> tests/ui/empty_line_after/doc_comments.rs:63:5
+   |
+LL | /     /// for OldA
+LL | |     // struct OldA;
+LL | |
+LL | |     /// Docs
+LL | |     /// for OldB
+LL | |     // struct OldB;
+LL | |
+   | |_
+...
+LL |       struct Multiple;
+   |       --------------- the comment documents this struct
+   |
+   = help: if the empty lines are unintentional remove them
+help: if the doc comment should not document `Multiple` comment it out
+   |
+LL ~     // /// Docs
+LL ~     // /// for OldA
+LL |     // struct OldA;
+LL |
+LL ~     // /// Docs
+LL ~     // /// for OldB
+   |
+
+error: empty line after doc comment
+  --> tests/ui/empty_line_after/doc_comments.rs:78:5
+   |
+LL | /     /**
+LL | |      * Meant to be inner doc comment
+LL | |      */
+LL | |
+   | |_
+LL |       fn first_in_module() {}
+   |       -------------------- the comment documents this function
+   |
+   = help: if the empty line is unintentional remove it
+help: if the comment should document the parent module use an inner doc comment
+   |
+LL |     /*!
+   |       ~
+
+error: empty line after doc comment
+  --> tests/ui/empty_line_after/doc_comments.rs:85:5
+   |
+LL | /     /**
+LL | |      * Docs for `old_code`
+LL | |      */
+LL | |     /* fn old_code() {} */
+LL | |
+   | |_
+...
+LL |       fn new_code() {}
+   |       ------------- the comment documents this function
+   |
+   = help: if the empty line is unintentional remove it
+help: if the doc comment should not document `new_code` comment it out
+   |
+LL -     /**
+LL +     /*
+   |
+
+error: empty line after doc comment
+  --> tests/ui/empty_line_after/doc_comments.rs:96:5
+   |
+LL | /     /// Docs for `old_code2`
+LL | |     /* fn old_code2() {} */
+LL | |
+   | |_
+LL |       /// Docs for `new_code2`
+LL |       fn new_code2() {}
+   |       -------------- the comment documents this function
+   |
+   = help: if the empty line is unintentional remove it
+help: if the doc comment should not document `new_code2` comment it out
+   |
+LL |     // /// Docs for `old_code2`
+   |     ++
+
+error: aborting due to 10 previous errors
+
diff --git a/tests/ui/empty_line_after/outer_attribute.1.fixed b/tests/ui/empty_line_after/outer_attribute.1.fixed
new file mode 100644
index 0000000000000..cd7ea24b6be35
--- /dev/null
+++ b/tests/ui/empty_line_after/outer_attribute.1.fixed
@@ -0,0 +1,103 @@
+//@aux-build:../auxiliary/proc_macro_attr.rs
+#![warn(clippy::empty_line_after_outer_attr, clippy::empty_line_after_doc_comments)]
+
+//~v empty_line_after_outer_attr
+#[crate_type = "lib"]
+fn first_in_crate() {}
+
+#[macro_use]
+extern crate proc_macro_attr;
+
+//~v empty_line_after_outer_attr
+#[inline]
+/// some comment
+fn with_one_newline_and_comment() {}
+
+#[inline]
+/// some comment
+fn with_no_newline_and_comment() {}
+
+//~v empty_line_after_outer_attr
+#[inline]
+fn with_one_newline() {}
+
+#[rustfmt::skip]
+mod two_lines {
+    //~v empty_line_after_outer_attr
+    #[crate_type = "lib"]
+    fn with_two_newlines() {}
+}
+
+//~v empty_line_after_outer_attr
+#[doc = "doc attributes should be considered attributes"]
+enum Baz {
+    One,
+    Two,
+}
+
+//~v empty_line_after_outer_attr
+#[repr(C)]
+struct Foo {
+    one: isize,
+    two: isize,
+}
+
+//~v empty_line_after_outer_attr
+#[allow(dead_code)]
+mod foo {}
+
+//~v empty_line_after_outer_attr
+#[inline]
+// Still lint cases where the empty line does not immediately follow the attribute
+fn comment_before_empty_line() {}
+
+#[doc = "
+Returns the escaped value of the textual representation of
+
+"]
+pub fn function() -> bool {
+    true
+}
+
+#[derive(Clone, Copy)]
+pub enum FooFighter {
+    Bar1,
+
+    Bar2,
+
+    Bar3,
+
+    Bar4,
+}
+
+#[crate_type = "lib"]
+/*
+
+*/
+pub struct EmptyLineInBlockComment;
+
+#[crate_type = "lib"]
+/* test */
+pub struct BlockComment;
+
+// See https://github.com/rust-lang/rust-clippy/issues/5567
+#[rustfmt::skip]
+#[fake_async_trait]
+pub trait Bazz {
+    fn foo() -> Vec<u8> {
+        let _i = "";
+
+
+
+        vec![]
+    }
+}
+
+#[derive(Clone, Copy)]
+#[dummy(string = "first line
+
+second line
+")]
+pub struct Args;
+
+fn main() {}
diff --git a/tests/ui/empty_line_after/outer_attribute.2.fixed b/tests/ui/empty_line_after/outer_attribute.2.fixed
new file mode 100644
index 0000000000000..1b044d2fcde41
--- /dev/null
+++ b/tests/ui/empty_line_after/outer_attribute.2.fixed
@@ -0,0 +1,106 @@
+//@aux-build:../auxiliary/proc_macro_attr.rs
+#![warn(clippy::empty_line_after_outer_attr, clippy::empty_line_after_doc_comments)]
+
+//~v empty_line_after_outer_attr
+#![crate_type = "lib"]
+
+fn first_in_crate() {}
+
+#[macro_use]
+extern crate proc_macro_attr;
+
+//~v empty_line_after_outer_attr
+#[inline]
+/// some comment
+fn with_one_newline_and_comment() {}
+
+#[inline]
+/// some comment
+fn with_no_newline_and_comment() {}
+
+//~v empty_line_after_outer_attr
+#[inline]
+fn with_one_newline() {}
+
+#[rustfmt::skip]
+mod two_lines {
+    //~v empty_line_after_outer_attr
+    #![crate_type = "lib"]
+
+
+    fn with_two_newlines() {}
+}
+
+//~v empty_line_after_outer_attr
+#[doc = "doc attributes should be considered attributes"]
+enum Baz {
+    One,
+    Two,
+}
+
+//~v empty_line_after_outer_attr
+#[repr(C)]
+struct Foo {
+    one: isize,
+    two: isize,
+}
+
+//~v empty_line_after_outer_attr
+#[allow(dead_code)]
+mod foo {}
+
+//~v empty_line_after_outer_attr
+#[inline]
+// Still lint cases where the empty line does not immediately follow the attribute
+fn comment_before_empty_line() {}
+
+#[doc = "
+Returns the escaped value of the textual representation of
+
+"]
+pub fn function() -> bool {
+    true
+}
+
+#[derive(Clone, Copy)]
+pub enum FooFighter {
+    Bar1,
+
+    Bar2,
+
+    Bar3,
+
+    Bar4,
+}
+
+#[crate_type = "lib"]
+/*
+
+*/
+pub struct EmptyLineInBlockComment;
+
+#[crate_type = "lib"]
+/* test */
+pub struct BlockComment;
+
+// See https://github.com/rust-lang/rust-clippy/issues/5567
+#[rustfmt::skip]
+#[fake_async_trait]
+pub trait Bazz {
+    fn foo() -> Vec<u8> {
+        let _i = "";
+
+
+
+        vec![]
+    }
+}
+
+#[derive(Clone, Copy)]
+#[dummy(string = "first line
+
+second line
+")]
+pub struct Args;
+
+fn main() {}
diff --git a/tests/ui/empty_line_after/outer_attribute.rs b/tests/ui/empty_line_after/outer_attribute.rs
new file mode 100644
index 0000000000000..81e1a7ab8ed54
--- /dev/null
+++ b/tests/ui/empty_line_after/outer_attribute.rs
@@ -0,0 +1,112 @@
+//@aux-build:../auxiliary/proc_macro_attr.rs
+#![warn(clippy::empty_line_after_outer_attr, clippy::empty_line_after_doc_comments)]
+
+//~v empty_line_after_outer_attr
+#[crate_type = "lib"]
+
+fn first_in_crate() {}
+
+#[macro_use]
+extern crate proc_macro_attr;
+
+//~v empty_line_after_outer_attr
+#[inline]
+
+/// some comment
+fn with_one_newline_and_comment() {}
+
+#[inline]
+/// some comment
+fn with_no_newline_and_comment() {}
+
+//~v empty_line_after_outer_attr
+#[inline]
+
+fn with_one_newline() {}
+
+#[rustfmt::skip]
+mod two_lines {
+    //~v empty_line_after_outer_attr
+    #[crate_type = "lib"]
+
+
+    fn with_two_newlines() {}
+}
+
+//~v empty_line_after_outer_attr
+#[doc = "doc attributes should be considered attributes"]
+
+enum Baz {
+    One,
+    Two,
+}
+
+//~v empty_line_after_outer_attr
+#[repr(C)]
+
+struct Foo {
+    one: isize,
+    two: isize,
+}
+
+//~v empty_line_after_outer_attr
+#[allow(dead_code)]
+
+mod foo {}
+
+//~v empty_line_after_outer_attr
+#[inline]
+// Still lint cases where the empty line does not immediately follow the attribute
+
+fn comment_before_empty_line() {}
+
+#[doc = "
+Returns the escaped value of the textual representation of
+
+"]
+pub fn function() -> bool {
+    true
+}
+
+#[derive(Clone, Copy)]
+pub enum FooFighter {
+    Bar1,
+
+    Bar2,
+
+    Bar3,
+
+    Bar4,
+}
+
+#[crate_type = "lib"]
+/*
+
+*/
+pub struct EmptyLineInBlockComment;
+
+#[crate_type = "lib"]
+/* test */
+pub struct BlockComment;
+
+// See https://github.com/rust-lang/rust-clippy/issues/5567
+#[rustfmt::skip]
+#[fake_async_trait]
+pub trait Bazz {
+    fn foo() -> Vec<u8> {
+        let _i = "";
+
+
+
+        vec![]
+    }
+}
+
+#[derive(Clone, Copy)]
+#[dummy(string = "first line
+
+second line
+")]
+pub struct Args;
+
+fn main() {}
diff --git a/tests/ui/empty_line_after/outer_attribute.stderr b/tests/ui/empty_line_after/outer_attribute.stderr
new file mode 100644
index 0000000000000..b73ebb4f6623f
--- /dev/null
+++ b/tests/ui/empty_line_after/outer_attribute.stderr
@@ -0,0 +1,103 @@
+error: empty line after outer attribute
+  --> tests/ui/empty_line_after/outer_attribute.rs:5:1
+   |
+LL | / #[crate_type = "lib"]
+LL | |
+   | |_
+LL |   fn first_in_crate() {}
+   |   ------------------- the attribute applies to this function
+   |
+   = note: `-D clippy::empty-line-after-outer-attr` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::empty_line_after_outer_attr)]`
+   = help: if the empty line is unintentional remove it
+help: if the attribute should apply to the crate use an inner attribute
+   |
+LL | #![crate_type = "lib"]
+   |  +
+
+error: empty line after outer attribute
+  --> tests/ui/empty_line_after/outer_attribute.rs:13:1
+   |
+LL | / #[inline]
+LL | |
+   | |_
+LL |   /// some comment
+LL |   fn with_one_newline_and_comment() {}
+   |   --------------------------------- the attribute applies to this function
+   |
+   = help: if the empty line is unintentional remove it
+
+error: empty line after outer attribute
+  --> tests/ui/empty_line_after/outer_attribute.rs:23:1
+   |
+LL | / #[inline]
+LL | |
+   | |_
+LL |   fn with_one_newline() {}
+   |   --------------------- the attribute applies to this function
+   |
+   = help: if the empty line is unintentional remove it
+
+error: empty lines after outer attribute
+  --> tests/ui/empty_line_after/outer_attribute.rs:30:5
+   |
+LL | /     #[crate_type = "lib"]
+LL | |
+LL | |
+   | |_
+LL |       fn with_two_newlines() {}
+   |       ---------------------- the attribute applies to this function
+   |
+   = help: if the empty lines are unintentional remove them
+help: if the attribute should apply to the parent module use an inner attribute
+   |
+LL |     #![crate_type = "lib"]
+   |      +
+
+error: empty line after outer attribute
+  --> tests/ui/empty_line_after/outer_attribute.rs:37:1
+   |
+LL | / #[doc = "doc attributes should be considered attributes"]
+LL | |
+   | |_
+LL |   enum Baz {
+   |   -------- the attribute applies to this enum
+   |
+   = help: if the empty line is unintentional remove it
+
+error: empty line after outer attribute
+  --> tests/ui/empty_line_after/outer_attribute.rs:45:1
+   |
+LL | / #[repr(C)]
+LL | |
+   | |_
+LL |   struct Foo {
+   |   ---------- the attribute applies to this struct
+   |
+   = help: if the empty line is unintentional remove it
+
+error: empty line after outer attribute
+  --> tests/ui/empty_line_after/outer_attribute.rs:53:1
+   |
+LL | / #[allow(dead_code)]
+LL | |
+   | |_
+LL |   mod foo {}
+   |   ------- the attribute applies to this module
+   |
+   = help: if the empty line is unintentional remove it
+
+error: empty line after outer attribute
+  --> tests/ui/empty_line_after/outer_attribute.rs:58:1
+   |
+LL | / #[inline]
+LL | | // Still lint cases where the empty line does not immediately follow the attribute
+LL | |
+   | |_
+LL |   fn comment_before_empty_line() {}
+   |   ------------------------------ the attribute applies to this function
+   |
+   = help: if the empty line is unintentional remove it
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/empty_line_after_doc_comments.rs b/tests/ui/empty_line_after_doc_comments.rs
deleted file mode 100644
index dd78491749c77..0000000000000
--- a/tests/ui/empty_line_after_doc_comments.rs
+++ /dev/null
@@ -1,132 +0,0 @@
-//@aux-build:proc_macro_attr.rs
-#![warn(clippy::empty_line_after_doc_comments)]
-#![allow(clippy::assertions_on_constants, clippy::duplicated_attributes)]
-#![feature(custom_inner_attributes)]
-#![rustfmt::skip]
-
-#[macro_use]
-extern crate proc_macro_attr;
-
-mod some_mod {
-    //! This doc comment should *NOT* produce a warning
-
-    mod some_inner_mod {
-        fn some_noop() {}
-    }
-}
-
-/// This should produce a warning
-
-fn with_doc_and_newline() { assert!(true)}
-
-// This should *NOT* produce a warning
-#[crate_type = "lib"]
-
-/// some comment
-fn with_one_newline_and_comment() { assert!(true) }
-
-// This should *NOT* produce a warning
-#[crate_type = "lib"]
-/// some comment
-fn with_no_newline_and_comment() { assert!(true) }
-
-
-// This should *NOT* produce a warning
-#[crate_type = "lib"]
-
-fn with_one_newline() { assert!(true) }
-
-// This should *NOT* produce a warning
-#[crate_type = "lib"]
-
-
-fn with_two_newlines() { assert!(true) }
-
-
-// This should *NOT* produce a warning
-#[crate_type = "lib"]
-
-enum Baz {
-    One,
-    Two
-}
-
-// This should *NOT* produce a warning
-#[crate_type = "lib"]
-
-struct Foo {
-    one: isize,
-    two: isize
-}
-
-// This should *NOT* produce a warning
-#[crate_type = "lib"]
-
-mod foo {
-}
-
-/// This doc comment should produce a warning
-
-/** This is also a doc comment and should produce a warning
- */
-
-// This should *NOT* produce a warning
-#[allow(non_camel_case_types)]
-#[allow(missing_docs)]
-#[allow(missing_docs)]
-fn three_attributes() { assert!(true) }
-
-// This should *NOT* produce a warning
-#[doc = "
-Returns the escaped value of the textual representation of
-
-"]
-pub fn function() -> bool {
-    true
-}
-
-// This should *NOT* produce a warning
-#[derive(Clone, Copy)]
-pub enum FooFighter {
-    Bar1,
-
-    Bar2,
-
-    Bar3,
-
-    Bar4
-}
-
-// This should *NOT* produce a warning because the empty line is inside a block comment
-#[crate_type = "lib"]
-/*
-
-*/
-pub struct S;
-
-// This should *NOT* produce a warning
-#[crate_type = "lib"]
-/* test */
-pub struct T;
-
-// This should *NOT* produce a warning
-// See https://github.com/rust-lang/rust-clippy/issues/5567
-#[fake_async_trait]
-pub trait Bazz {
-    fn foo() -> Vec<u8> {
-        let _i = "";
-
-
-
-        vec![]
-    }
-}
-
-#[derive(Clone, Copy)]
-#[dummy(string = "first line
-
-second line
-")]
-pub struct Args;
-
-fn main() {}
diff --git a/tests/ui/empty_line_after_doc_comments.stderr b/tests/ui/empty_line_after_doc_comments.stderr
deleted file mode 100644
index 889ccf6ba19dd..0000000000000
--- a/tests/ui/empty_line_after_doc_comments.stderr
+++ /dev/null
@@ -1,37 +0,0 @@
-error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
-  --> tests/ui/empty_line_after_doc_comments.rs:18:1
-   |
-LL | / /// This should produce a warning
-LL | |
-LL | | fn with_doc_and_newline() { assert!(true)}
-   | |_
-   |
-   = note: `-D clippy::empty-line-after-doc-comments` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::empty_line_after_doc_comments)]`
-
-error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
-  --> tests/ui/empty_line_after_doc_comments.rs:68:1
-   |
-LL | / /// This doc comment should produce a warning
-LL | |
-LL | | /** This is also a doc comment and should produce a warning
-LL | |  */
-...  |
-LL | | #[allow(missing_docs)]
-LL | | fn three_attributes() { assert!(true) }
-   | |_
-
-error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
-  --> tests/ui/empty_line_after_doc_comments.rs:70:1
-   |
-LL | / /** This is also a doc comment and should produce a warning
-LL | |  */
-LL | |
-LL | | // This should *NOT* produce a warning
-...  |
-LL | | #[allow(missing_docs)]
-LL | | fn three_attributes() { assert!(true) }
-   | |_
-
-error: aborting due to 3 previous errors
-
diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs
deleted file mode 100644
index f147cf2cd5d1e..0000000000000
--- a/tests/ui/empty_line_after_outer_attribute.rs
+++ /dev/null
@@ -1,120 +0,0 @@
-//@aux-build:proc_macro_attr.rs
-#![warn(clippy::empty_line_after_outer_attr)]
-#![allow(clippy::assertions_on_constants, clippy::duplicated_attributes)]
-#![feature(custom_inner_attributes)]
-#![rustfmt::skip]
-
-#[macro_use]
-extern crate proc_macro_attr;
-
-// This should produce a warning
-#[crate_type = "lib"]
-
-/// some comment
-fn with_one_newline_and_comment() { assert!(true) }
-
-// This should not produce a warning
-#[crate_type = "lib"]
-/// some comment
-fn with_no_newline_and_comment() { assert!(true) }
-
-
-// This should produce a warning
-#[crate_type = "lib"]
-
-fn with_one_newline() { assert!(true) }
-
-// This should produce a warning, too
-#[crate_type = "lib"]
-
-
-fn with_two_newlines() { assert!(true) }
-
-
-// This should produce a warning
-#[crate_type = "lib"]
-
-enum Baz {
-    One,
-    Two
-}
-
-// This should produce a warning
-#[crate_type = "lib"]
-
-struct Foo {
-    one: isize,
-    two: isize
-}
-
-// This should produce a warning
-#[crate_type = "lib"]
-
-mod foo {
-}
-
-/// This doc comment should not produce a warning
-
-/** This is also a doc comment and should not produce a warning
- */
-
-// This should not produce a warning
-#[allow(non_camel_case_types)]
-#[allow(missing_docs)]
-#[allow(missing_docs)]
-fn three_attributes() { assert!(true) }
-
-// This should not produce a warning
-#[doc = "
-Returns the escaped value of the textual representation of
-
-"]
-pub fn function() -> bool {
-    true
-}
-
-// This should not produce a warning
-#[derive(Clone, Copy)]
-pub enum FooFighter {
-    Bar1,
-
-    Bar2,
-
-    Bar3,
-
-    Bar4
-}
-
-// This should not produce a warning because the empty line is inside a block comment
-#[crate_type = "lib"]
-/*
-
-*/
-pub struct S;
-
-// This should not produce a warning
-#[crate_type = "lib"]
-/* test */
-pub struct T;
-
-// This should not produce a warning
-// See https://github.com/rust-lang/rust-clippy/issues/5567
-#[fake_async_trait]
-pub trait Bazz {
-    fn foo() -> Vec<u8> {
-        let _i = "";
-
-
-
-        vec![]
-    }
-}
-
-#[derive(Clone, Copy)]
-#[dummy(string = "first line
-
-second line
-")]
-pub struct Args;
-
-fn main() {}
diff --git a/tests/ui/empty_line_after_outer_attribute.stderr b/tests/ui/empty_line_after_outer_attribute.stderr
deleted file mode 100644
index b43e6e30da220..0000000000000
--- a/tests/ui/empty_line_after_outer_attribute.stderr
+++ /dev/null
@@ -1,54 +0,0 @@
-error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
-  --> tests/ui/empty_line_after_outer_attribute.rs:11:1
-   |
-LL | / #[crate_type = "lib"]
-LL | |
-LL | | /// some comment
-LL | | fn with_one_newline_and_comment() { assert!(true) }
-   | |_
-   |
-   = note: `-D clippy::empty-line-after-outer-attr` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::empty_line_after_outer_attr)]`
-
-error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
-  --> tests/ui/empty_line_after_outer_attribute.rs:23:1
-   |
-LL | / #[crate_type = "lib"]
-LL | |
-LL | | fn with_one_newline() { assert!(true) }
-   | |_
-
-error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
-  --> tests/ui/empty_line_after_outer_attribute.rs:28:1
-   |
-LL | / #[crate_type = "lib"]
-...  |
-LL | | fn with_two_newlines() { assert!(true) }
-   | |_
-
-error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
-  --> tests/ui/empty_line_after_outer_attribute.rs:35:1
-   |
-LL | / #[crate_type = "lib"]
-LL | |
-LL | | enum Baz {
-   | |_
-
-error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
-  --> tests/ui/empty_line_after_outer_attribute.rs:43:1
-   |
-LL | / #[crate_type = "lib"]
-LL | |
-LL | | struct Foo {
-   | |_
-
-error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
-  --> tests/ui/empty_line_after_outer_attribute.rs:51:1
-   |
-LL | / #[crate_type = "lib"]
-LL | |
-LL | | mod foo {
-   | |_
-
-error: aborting due to 6 previous errors
-
diff --git a/tests/ui/exit1.rs b/tests/ui/exit1.rs
index a89f6dd4ca0eb..36b3c42fd9958 100644
--- a/tests/ui/exit1.rs
+++ b/tests/ui/exit1.rs
@@ -1,4 +1,4 @@
-#[warn(clippy::exit)]
+#![warn(clippy::exit)]
 
 fn not_main() {
     if true {
diff --git a/tests/ui/exit2.rs b/tests/ui/exit2.rs
index d5ff93fb9ccb8..9bbb7b073a4b0 100644
--- a/tests/ui/exit2.rs
+++ b/tests/ui/exit2.rs
@@ -1,4 +1,4 @@
-#[warn(clippy::exit)]
+#![warn(clippy::exit)]
 
 fn also_not_main() {
     std::process::exit(3);
diff --git a/tests/ui/exit3.rs b/tests/ui/exit3.rs
index 9dc0e1015a4f7..cab908aafd33d 100644
--- a/tests/ui/exit3.rs
+++ b/tests/ui/exit3.rs
@@ -1,4 +1,4 @@
-#[warn(clippy::exit)]
+#![warn(clippy::exit)]
 
 fn main() {
     if true {
diff --git a/tests/ui/expect_fun_call.fixed b/tests/ui/expect_fun_call.fixed
index 6ac3c43ad2982..8f800c71941a1 100644
--- a/tests/ui/expect_fun_call.fixed
+++ b/tests/ui/expect_fun_call.fixed
@@ -5,8 +5,6 @@
     clippy::unnecessary_literal_unwrap
 )]
 
-/// Checks implementation of the `EXPECT_FUN_CALL` lint
-
 macro_rules! one {
     () => {
         1
diff --git a/tests/ui/expect_fun_call.rs b/tests/ui/expect_fun_call.rs
index 22ea2db504fa4..b5cfafb2993e5 100644
--- a/tests/ui/expect_fun_call.rs
+++ b/tests/ui/expect_fun_call.rs
@@ -5,8 +5,6 @@
     clippy::unnecessary_literal_unwrap
 )]
 
-/// Checks implementation of the `EXPECT_FUN_CALL` lint
-
 macro_rules! one {
     () => {
         1
diff --git a/tests/ui/expect_fun_call.stderr b/tests/ui/expect_fun_call.stderr
index b41904d04fa4c..bae853ac5c19a 100644
--- a/tests/ui/expect_fun_call.stderr
+++ b/tests/ui/expect_fun_call.stderr
@@ -1,5 +1,5 @@
 error: use of `expect` followed by a function call
-  --> tests/ui/expect_fun_call.rs:37:26
+  --> tests/ui/expect_fun_call.rs:35:26
    |
 LL |     with_none_and_format.expect(&format!("Error {}: fake error", error_code));
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))`
@@ -8,85 +8,85 @@ LL |     with_none_and_format.expect(&format!("Error {}: fake error", error_code
    = help: to override `-D warnings` add `#[allow(clippy::expect_fun_call)]`
 
 error: use of `expect` followed by a function call
-  --> tests/ui/expect_fun_call.rs:40:26
+  --> tests/ui/expect_fun_call.rs:38:26
    |
 LL |     with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str());
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))`
 
 error: use of `expect` followed by a function call
-  --> tests/ui/expect_fun_call.rs:43:37
+  --> tests/ui/expect_fun_call.rs:41:37
    |
 LL |     with_none_and_format_with_macro.expect(format!("Error {}: fake error", one!()).as_str());
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("Error {}: fake error", one!()))`
 
 error: use of `expect` followed by a function call
-  --> tests/ui/expect_fun_call.rs:53:25
+  --> tests/ui/expect_fun_call.rs:51:25
    |
 LL |     with_err_and_format.expect(&format!("Error {}: fake error", error_code));
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))`
 
 error: use of `expect` followed by a function call
-  --> tests/ui/expect_fun_call.rs:56:25
+  --> tests/ui/expect_fun_call.rs:54:25
    |
 LL |     with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str());
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))`
 
 error: use of `expect` followed by a function call
-  --> tests/ui/expect_fun_call.rs:68:17
+  --> tests/ui/expect_fun_call.rs:66:17
    |
 LL |     Some("foo").expect(format!("{} {}", 1, 2).as_ref());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{} {}", 1, 2))`
 
 error: use of `expect` followed by a function call
-  --> tests/ui/expect_fun_call.rs:89:21
+  --> tests/ui/expect_fun_call.rs:87:21
    |
 LL |         Some("foo").expect(&get_string());
    |                     ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_string()) })`
 
 error: use of `expect` followed by a function call
-  --> tests/ui/expect_fun_call.rs:90:21
+  --> tests/ui/expect_fun_call.rs:88:21
    |
 LL |         Some("foo").expect(get_string().as_ref());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_string()) })`
 
 error: use of `expect` followed by a function call
-  --> tests/ui/expect_fun_call.rs:91:21
+  --> tests/ui/expect_fun_call.rs:89:21
    |
 LL |         Some("foo").expect(get_string().as_str());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_string()) })`
 
 error: use of `expect` followed by a function call
-  --> tests/ui/expect_fun_call.rs:93:21
+  --> tests/ui/expect_fun_call.rs:91:21
    |
 LL |         Some("foo").expect(get_static_str());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_static_str()) })`
 
 error: use of `expect` followed by a function call
-  --> tests/ui/expect_fun_call.rs:94:21
+  --> tests/ui/expect_fun_call.rs:92:21
    |
 LL |         Some("foo").expect(get_non_static_str(&0));
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_non_static_str(&0).to_string()) })`
 
 error: use of `expect` followed by a function call
-  --> tests/ui/expect_fun_call.rs:98:16
+  --> tests/ui/expect_fun_call.rs:96:16
    |
 LL |     Some(true).expect(&format!("key {}, {}", 1, 2));
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("key {}, {}", 1, 2))`
 
 error: use of `expect` followed by a function call
-  --> tests/ui/expect_fun_call.rs:104:17
+  --> tests/ui/expect_fun_call.rs:102:17
    |
 LL |         opt_ref.expect(&format!("{:?}", opt_ref));
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{:?}", opt_ref))`
 
 error: use of `expect` followed by a function call
-  --> tests/ui/expect_fun_call.rs:108:20
+  --> tests/ui/expect_fun_call.rs:106:20
    |
 LL |     format_capture.expect(&format!("{error_code}"));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{error_code}"))`
 
 error: use of `expect` followed by a function call
-  --> tests/ui/expect_fun_call.rs:111:30
+  --> tests/ui/expect_fun_call.rs:109:30
    |
 LL |     format_capture_and_value.expect(&format!("{error_code}, {}", 1));
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{error_code}, {}", 1))`
diff --git a/tests/ui/match_overlapping_arm.rs b/tests/ui/match_overlapping_arm.rs
index 4457ae73da2f0..a056fdeaa5d0c 100644
--- a/tests/ui/match_overlapping_arm.rs
+++ b/tests/ui/match_overlapping_arm.rs
@@ -2,8 +2,6 @@
 #![allow(clippy::redundant_pattern_matching)]
 #![allow(clippy::if_same_then_else, clippy::equatable_if_let, clippy::needless_if)]
 
-/// Tests for match_overlapping_arm
-
 fn overlapping() {
     const FOO: u64 = 2;
 
diff --git a/tests/ui/match_overlapping_arm.stderr b/tests/ui/match_overlapping_arm.stderr
index 65092ffbb5558..a60a09a079907 100644
--- a/tests/ui/match_overlapping_arm.stderr
+++ b/tests/ui/match_overlapping_arm.stderr
@@ -1,11 +1,11 @@
 error: some ranges overlap
-  --> tests/ui/match_overlapping_arm.rs:11:9
+  --> tests/ui/match_overlapping_arm.rs:9:9
    |
 LL |         0..=10 => println!("0..=10"),
    |         ^^^^^^
    |
 note: overlaps with this
-  --> tests/ui/match_overlapping_arm.rs:13:9
+  --> tests/ui/match_overlapping_arm.rs:11:9
    |
 LL |         0..=11 => println!("0..=11"),
    |         ^^^^^^
@@ -13,85 +13,85 @@ LL |         0..=11 => println!("0..=11"),
    = help: to override `-D warnings` add `#[allow(clippy::match_overlapping_arm)]`
 
 error: some ranges overlap
-  --> tests/ui/match_overlapping_arm.rs:18:9
+  --> tests/ui/match_overlapping_arm.rs:16:9
    |
 LL |         0..=5 => println!("0..=5"),
    |         ^^^^^
    |
 note: overlaps with this
-  --> tests/ui/match_overlapping_arm.rs:21:9
+  --> tests/ui/match_overlapping_arm.rs:19:9
    |
 LL |         FOO..=11 => println!("FOO..=11"),
    |         ^^^^^^^^
 
 error: some ranges overlap
-  --> tests/ui/match_overlapping_arm.rs:56:9
+  --> tests/ui/match_overlapping_arm.rs:54:9
    |
 LL |         0..11 => println!("0..11"),
    |         ^^^^^
    |
 note: overlaps with this
-  --> tests/ui/match_overlapping_arm.rs:58:9
+  --> tests/ui/match_overlapping_arm.rs:56:9
    |
 LL |         0..=11 => println!("0..=11"),
    |         ^^^^^^
 
 error: some ranges overlap
-  --> tests/ui/match_overlapping_arm.rs:82:9
+  --> tests/ui/match_overlapping_arm.rs:80:9
    |
 LL |         0..=10 => println!("0..=10"),
    |         ^^^^^^
    |
 note: overlaps with this
-  --> tests/ui/match_overlapping_arm.rs:81:9
+  --> tests/ui/match_overlapping_arm.rs:79:9
    |
 LL |         5..14 => println!("5..14"),
    |         ^^^^^
 
 error: some ranges overlap
-  --> tests/ui/match_overlapping_arm.rs:88:9
+  --> tests/ui/match_overlapping_arm.rs:86:9
    |
 LL |         0..7 => println!("0..7"),
    |         ^^^^
    |
 note: overlaps with this
-  --> tests/ui/match_overlapping_arm.rs:90:9
+  --> tests/ui/match_overlapping_arm.rs:88:9
    |
 LL |         0..=10 => println!("0..=10"),
    |         ^^^^^^
 
 error: some ranges overlap
-  --> tests/ui/match_overlapping_arm.rs:101:9
+  --> tests/ui/match_overlapping_arm.rs:99:9
    |
 LL |         ..=23 => println!("..=23"),
    |         ^^^^^
    |
 note: overlaps with this
-  --> tests/ui/match_overlapping_arm.rs:103:9
+  --> tests/ui/match_overlapping_arm.rs:101:9
    |
 LL |         ..26 => println!("..26"),
    |         ^^^^
 
 error: some ranges overlap
-  --> tests/ui/match_overlapping_arm.rs:111:9
+  --> tests/ui/match_overlapping_arm.rs:109:9
    |
 LL |         21..=30 => (),
    |         ^^^^^^^
    |
 note: overlaps with this
-  --> tests/ui/match_overlapping_arm.rs:113:9
+  --> tests/ui/match_overlapping_arm.rs:111:9
    |
 LL |         21..=40 => (),
    |         ^^^^^^^
 
 error: some ranges overlap
-  --> tests/ui/match_overlapping_arm.rs:126:9
+  --> tests/ui/match_overlapping_arm.rs:124:9
    |
 LL |         0..=0x0000_0000_0000_00ff => (),
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: overlaps with this
-  --> tests/ui/match_overlapping_arm.rs:128:9
+  --> tests/ui/match_overlapping_arm.rs:126:9
    |
 LL |         0..=0x0000_0000_0000_ffff => (),
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/string_slice.rs b/tests/ui/string_slice.rs
index 1d1911aaa1d91..dc519493a4dd3 100644
--- a/tests/ui/string_slice.rs
+++ b/tests/ui/string_slice.rs
@@ -1,7 +1,7 @@
-use std::borrow::Cow;
+#![warn(clippy::string_slice)]
+#![allow(clippy::no_effect)]
 
-#[warn(clippy::string_slice)]
-#[allow(clippy::no_effect)]
+use std::borrow::Cow;
 
 fn main() {
     &"Ölkanne"[1..];
diff --git a/tests/ui/tabs_in_doc_comments.fixed b/tests/ui/tabs_in_doc_comments.fixed
index 26cc5c27e88cc..3536c1746df36 100644
--- a/tests/ui/tabs_in_doc_comments.fixed
+++ b/tests/ui/tabs_in_doc_comments.fixed
@@ -1,5 +1,4 @@
 #![warn(clippy::tabs_in_doc_comments)]
-#[allow(dead_code)]
 
 ///
 /// Struct to hold two strings:
diff --git a/tests/ui/tabs_in_doc_comments.rs b/tests/ui/tabs_in_doc_comments.rs
index 14b06966ecc1a..033a685066e1a 100644
--- a/tests/ui/tabs_in_doc_comments.rs
+++ b/tests/ui/tabs_in_doc_comments.rs
@@ -1,5 +1,4 @@
 #![warn(clippy::tabs_in_doc_comments)]
-#[allow(dead_code)]
 
 ///
 /// Struct to hold two strings:
diff --git a/tests/ui/tabs_in_doc_comments.stderr b/tests/ui/tabs_in_doc_comments.stderr
index aef6c39145263..f8d30b728e58c 100644
--- a/tests/ui/tabs_in_doc_comments.stderr
+++ b/tests/ui/tabs_in_doc_comments.stderr
@@ -1,5 +1,5 @@
 error: using tabs in doc comments is not recommended
-  --> tests/ui/tabs_in_doc_comments.rs:6:5
+  --> tests/ui/tabs_in_doc_comments.rs:5:5
    |
 LL | ///     - first        one
    |     ^^^^ help: consider using four spaces per tab
@@ -8,43 +8,43 @@ LL | ///     - first        one
    = help: to override `-D warnings` add `#[allow(clippy::tabs_in_doc_comments)]`
 
 error: using tabs in doc comments is not recommended
-  --> tests/ui/tabs_in_doc_comments.rs:6:13
+  --> tests/ui/tabs_in_doc_comments.rs:5:13
    |
 LL | ///     - first        one
    |                ^^^^^^^^ help: consider using four spaces per tab
 
 error: using tabs in doc comments is not recommended
-  --> tests/ui/tabs_in_doc_comments.rs:7:5
+  --> tests/ui/tabs_in_doc_comments.rs:6:5
    |
 LL | ///     - second    one
    |     ^^^^ help: consider using four spaces per tab
 
 error: using tabs in doc comments is not recommended
-  --> tests/ui/tabs_in_doc_comments.rs:7:14
+  --> tests/ui/tabs_in_doc_comments.rs:6:14
    |
 LL | ///     - second    one
    |                 ^^^^ help: consider using four spaces per tab
 
 error: using tabs in doc comments is not recommended
-  --> tests/ui/tabs_in_doc_comments.rs:10:9
+  --> tests/ui/tabs_in_doc_comments.rs:9:9
    |
 LL |     ///     - First String:
    |         ^^^^ help: consider using four spaces per tab
 
 error: using tabs in doc comments is not recommended
-  --> tests/ui/tabs_in_doc_comments.rs:11:9
+  --> tests/ui/tabs_in_doc_comments.rs:10:9
    |
 LL |     ///         - needs to be inside here
    |         ^^^^^^^^ help: consider using four spaces per tab
 
 error: using tabs in doc comments is not recommended
-  --> tests/ui/tabs_in_doc_comments.rs:14:9
+  --> tests/ui/tabs_in_doc_comments.rs:13:9
    |
 LL |     ///     - Second String:
    |         ^^^^ help: consider using four spaces per tab
 
 error: using tabs in doc comments is not recommended
-  --> tests/ui/tabs_in_doc_comments.rs:15:9
+  --> tests/ui/tabs_in_doc_comments.rs:14:9
    |
 LL |     ///         - needs to be inside here
    |         ^^^^^^^^ help: consider using four spaces per tab

From 173d5a6af0f2352b3efa0b3a2faad87207706936 Mon Sep 17 00:00:00 2001
From: Jason Newcomb <jsnewcomb@pm.me>
Date: Sat, 24 Aug 2024 17:34:45 -0400
Subject: [PATCH 013/114] Merge commit
 '0f8eabd6231366bfc1bb1464601297c2d48f8f68' into clippyup

---
 .cargo/config.toml                            |    6 +-
 .github/deploy.sh                             |    1 +
 .github/workflows/clippy_bors.yml             |    5 -
 CHANGELOG.md                                  |    1 +
 Cargo.toml                                    |    4 +-
 book/src/development/adding_lints.md          |    2 +-
 book/src/lint_configuration.md                |    8 +-
 clippy_config/Cargo.toml                      |    1 -
 clippy_config/src/conf.rs                     |   23 +-
 clippy_config/src/lib.rs                      |    2 +-
 clippy_config/src/msrvs.rs                    |   17 +-
 clippy_dev/src/main.rs                        |    1 +
 clippy_dev/src/update_lints.rs                |    2 +-
 clippy_lints/Cargo.toml                       |    1 -
 clippy_lints/src/absolute_paths.rs            |   95 +-
 clippy_lints/src/approx_const.rs              |    3 +-
 clippy_lints/src/assigning_clones.rs          |    3 +-
 clippy_lints/src/attrs/empty_line_after.rs    |    4 +-
 clippy_lints/src/attrs/mod.rs                 |    6 +-
 clippy_lints/src/attrs/non_minimal_cfg.rs     |   11 +-
 .../src/attrs/unnecessary_clippy_cfg.rs       |   11 +-
 clippy_lints/src/attrs/useless_attribute.rs   |   10 +-
 clippy_lints/src/booleans.rs                  |   33 +-
 clippy_lints/src/borrow_deref_ref.rs          |    7 +-
 clippy_lints/src/cargo/common_metadata.rs     |    2 -
 clippy_lints/src/cargo/mod.rs                 |    6 +-
 .../src/cargo/multiple_crate_versions.rs      |    2 -
 clippy_lints/src/casts/as_ptr_cast_mut.rs     |    4 +-
 clippy_lints/src/casts/cast_lossless.rs       |    4 +-
 .../src/casts/cast_possible_truncation.rs     |    6 +-
 .../src/casts/fn_to_numeric_cast_any.rs       |    5 +-
 clippy_lints/src/casts/unnecessary_cast.rs    |    8 +-
 clippy_lints/src/casts/zero_ptr.rs            |    4 +-
 clippy_lints/src/cfg_not_test.rs              |    2 +-
 clippy_lints/src/checked_conversions.rs       |    2 -
 clippy_lints/src/cognitive_complexity.rs      |    2 -
 clippy_lints/src/collapsible_if.rs            |   14 -
 clippy_lints/src/collection_is_never_read.rs  |   37 +-
 clippy_lints/src/create_dir.rs                |    5 +-
 clippy_lints/src/declared_lints.rs            |    5 +-
 clippy_lints/src/doc/lazy_continuation.rs     |   11 +-
 clippy_lints/src/doc/markdown.rs              |   19 +-
 clippy_lints/src/doc/mod.rs                   |  122 +-
 .../src/doc/too_long_first_doc_paragraph.rs   |   91 ++
 clippy_lints/src/else_if_without_else.rs      |    2 -
 clippy_lints/src/empty_enum.rs                |    2 -
 clippy_lints/src/enum_clike.rs                |    3 -
 clippy_lints/src/eta_reduction.rs             |    4 +-
 clippy_lints/src/float_literal.rs             |    8 +-
 clippy_lints/src/format.rs                    |    6 +-
 clippy_lints/src/format_args.rs               |   33 +-
 clippy_lints/src/format_impl.rs               |    2 +-
 clippy_lints/src/from_over_into.rs            |   12 +-
 clippy_lints/src/from_str_radix_10.rs         |    4 +-
 .../src/functions/impl_trait_in_params.rs     |   11 +-
 clippy_lints/src/functions/must_use.rs        |   16 +-
 clippy_lints/src/functions/too_many_lines.rs  |   91 +-
 clippy_lints/src/if_not_else.rs               |    3 -
 clippy_lints/src/implicit_return.rs           |   13 +-
 clippy_lints/src/incompatible_msrv.rs         |   15 +-
 .../src/inconsistent_struct_constructor.rs    |   23 +-
 clippy_lints/src/indexing_slicing.rs          |    2 -
 clippy_lints/src/infinite_iter.rs             |   33 +-
 clippy_lints/src/inherent_impl.rs             |    2 -
 clippy_lints/src/inline_fn_without_body.rs    |    2 -
 clippy_lints/src/int_plus_one.rs              |    8 +-
 clippy_lints/src/item_name_repetitions.rs     |    2 -
 clippy_lints/src/items_after_statements.rs    |    2 -
 clippy_lints/src/items_after_test_module.rs   |    9 +-
 clippy_lints/src/large_enum_variant.rs        |    2 -
 clippy_lints/src/large_stack_frames.rs        |    4 +-
 clippy_lints/src/legacy_numeric_constants.rs  |    5 +-
 clippy_lints/src/len_zero.rs                  |    4 +-
 clippy_lints/src/lib.rs                       |   48 +-
 clippy_lints/src/literal_representation.rs    |    9 +-
 clippy_lints/src/loops/explicit_iter_loop.rs  |   12 +-
 clippy_lints/src/macro_metavars_in_unsafe.rs  |   21 +-
 clippy_lints/src/manual_async_fn.rs           |    8 +-
 clippy_lints/src/manual_float_methods.rs      |    4 +-
 clippy_lints/src/manual_hash_one.rs           |    6 +-
 clippy_lints/src/manual_non_exhaustive.rs     |    6 +-
 clippy_lints/src/manual_range_patterns.rs     |    6 +-
 clippy_lints/src/manual_retain.rs             |   33 +-
 clippy_lints/src/matches/collapsible_match.rs |    2 +-
 clippy_lints/src/matches/manual_unwrap_or.rs  |    8 +-
 clippy_lints/src/matches/single_match.rs      |    2 +-
 ...se_sensitive_file_extension_comparisons.rs |   12 +-
 .../src/methods/filter_map_bool_then.rs       |    8 +-
 .../methods/from_iter_instead_of_collect.rs   |    4 +-
 clippy_lints/src/methods/get_unwrap.rs        |    3 +-
 .../src/methods/is_digit_ascii_radix.rs       |    2 -
 .../src/methods/join_absolute_paths.rs        |    4 +-
 clippy_lints/src/methods/manual_ok_or.rs      |    8 +-
 clippy_lints/src/methods/manual_try_fold.rs   |   10 +-
 clippy_lints/src/methods/mod.rs               |    6 +-
 .../methods/needless_character_iteration.rs   |    6 +-
 clippy_lints/src/methods/needless_collect.rs  |    9 +-
 .../src/methods/needless_option_as_deref.rs   |    4 +-
 .../src/methods/string_lit_chars_any.rs       |    4 +-
 .../src/methods/unnecessary_get_then_check.rs |   10 +-
 .../src/methods/unnecessary_iter_cloned.rs    |    8 +-
 .../src/methods/unnecessary_lazy_eval.rs      |    4 +-
 .../src/methods/unnecessary_to_owned.rs       |   18 +-
 .../src/methods/unused_enumerate_index.rs     |   12 +-
 clippy_lints/src/min_ident_chars.rs           |    4 +-
 .../src/misc_early/unneeded_field_pattern.rs  |   27 +-
 .../src/missing_enforced_import_rename.rs     |    4 +-
 clippy_lints/src/mut_key.rs                   |   14 +-
 clippy_lints/src/mutex_atomic.rs              |    4 -
 clippy_lints/src/needless_bool.rs             |    4 -
 clippy_lints/src/needless_continue.rs         |   35 -
 clippy_lints/src/needless_if.rs               |    4 +-
 clippy_lints/src/needless_late_init.rs        |   11 +-
 clippy_lints/src/needless_pass_by_value.rs    |   10 +-
 clippy_lints/src/no_effect.rs                 |   47 +-
 clippy_lints/src/non_copy_const.rs            |    6 +-
 clippy_lints/src/nonstandard_macro_braces.rs  |    6 +-
 .../src/operators/arithmetic_side_effects.rs  |    2 +-
 .../src/operators/assign_op_pattern.rs        |    6 +-
 .../src/operators/misrefactored_assign_op.rs  |    6 +-
 clippy_lints/src/operators/mod.rs             |    2 +-
 .../src/operators/needless_bitwise_bool.rs    |    6 +-
 clippy_lints/src/operators/ptr_eq.rs          |    6 +-
 clippy_lints/src/pathbuf_init_then_push.rs    |    8 +-
 clippy_lints/src/ptr.rs                       |   16 +-
 clippy_lints/src/ptr_offset_with_cast.rs      |    6 +-
 clippy_lints/src/redundant_clone.rs           |    4 +-
 clippy_lints/src/reference.rs                 |   10 +-
 clippy_lints/src/regex.rs                     |    4 +-
 clippy_lints/src/returns.rs                   |   27 +-
 clippy_lints/src/single_range_in_vec_init.rs  |    8 +-
 clippy_lints/src/size_of_in_element_count.rs  |    3 -
 clippy_lints/src/std_instead_of_core.rs       |    5 +-
 clippy_lints/src/strings.rs                   |    2 +-
 clippy_lints/src/trait_bounds.rs              |   10 +-
 clippy_lints/src/unit_types/unit_arg.rs       |   20 +-
 clippy_lints/src/unused_io_amount.rs          |    9 +-
 clippy_lints/src/unused_unit.rs               |   22 +-
 clippy_lints/src/unwrap.rs                    |    6 +-
 clippy_lints/src/use_self.rs                  |    2 +-
 clippy_lints/src/utils/author.rs              |    3 -
 .../src/utils/format_args_collector.rs        |   49 +-
 clippy_lints/src/utils/internal_lints.rs      |    1 -
 .../internal_lints/lint_without_lint_pass.rs  |   10 +-
 .../internal_lints/metadata_collector.rs      | 1078 -----------------
 clippy_lints/src/vec.rs                       |    8 +-
 clippy_lints/src/visibility.rs                |   14 +-
 clippy_lints/src/wildcard_imports.rs          |    6 +-
 clippy_lints/src/write.rs                     |    8 +-
 clippy_utils/Cargo.toml                       |    1 -
 clippy_utils/src/attrs.rs                     |   38 +-
 clippy_utils/src/check_proc_macro.rs          |   12 +-
 clippy_utils/src/consts.rs                    |    2 +-
 clippy_utils/src/hir_utils.rs                 |   22 +-
 clippy_utils/src/lib.rs                       |   21 +-
 clippy_utils/src/macros.rs                    |   18 +-
 clippy_utils/src/qualify_min_const_fn.rs      |    7 +-
 clippy_utils/src/source.rs                    |  101 +-
 clippy_utils/src/ty.rs                        |   25 +-
 declare_clippy_lint/src/lib.rs                |   25 +-
 lintcheck/src/json.rs                         |   39 +-
 lintcheck/src/output.rs                       |   14 +-
 rust-toolchain                                |    2 +-
 tests/compile-test.rs                         |  385 ++++--
 tests/config-metadata.rs                      |   78 ++
 .../absolute_paths.allow_crates.stderr        |   45 +-
 .../absolute_paths.allow_long.stderr          |   14 +
 .../absolute_paths.default.stderr             |   80 ++
 .../absolute_paths.disallow_crates.stderr     |   71 --
 .../absolute_paths.no_short.stderr            |   98 ++
 .../ui-toml/absolute_paths/absolute_paths.rs  |  178 +--
 .../absolute_paths_2015.default.stderr        |   14 +
 .../absolute_paths/absolute_paths_2015.rs     |   16 +
 .../absolute_paths/allow_crates/clippy.toml   |    3 +-
 .../absolute_paths/allow_long/clippy.toml     |    1 +
 .../absolute_paths/auxiliary/helper.rs        |   11 -
 .../absolute_paths/default/clippy.toml        |    0
 .../disallow_crates/clippy.toml               |    1 -
 .../absolute_paths/no_short/clippy.toml       |    1 +
 .../macro_metavars_in_unsafe/default/test.rs  |   15 +-
 .../default/test.stderr                       |   16 +-
 tests/ui/assigning_clones.fixed               |   20 +
 tests/ui/assigning_clones.rs                  |   20 +
 .../complex_conditionals_nested.stderr        |    2 +-
 .../checked_unwrap/simple_conditionals.stderr |   26 +-
 tests/ui/collapsible_match.stderr             |    2 +-
 tests/ui/crashes/ice-3717.fixed               |   11 +
 tests/ui/crashes/ice-3717.rs                  |    2 -
 tests/ui/crashes/ice-3717.stderr              |    2 +-
 .../declare_interior_mutable_const/others.rs  |   17 +
 .../others.stderr                             |   10 +-
 tests/ui/doc/doc_markdown-issue_13097.fixed   |   13 +
 tests/ui/doc/doc_markdown-issue_13097.rs      |   13 +
 tests/ui/doc/doc_markdown-issue_13097.stderr  |   18 +
 tests/ui/double_must_use.rs                   |    8 +-
 tests/ui/double_must_use.stderr               |   16 +-
 tests/ui/explicit_iter_loop.fixed             |   12 +
 tests/ui/explicit_iter_loop.rs                |   12 +
 .../ui/inconsistent_struct_constructor.fixed  |   21 +
 tests/ui/inconsistent_struct_constructor.rs   |   21 +
 .../ui/inconsistent_struct_constructor.stderr |    4 +-
 tests/ui/min_rust_version_invalid_attr.rs     |    2 +-
 tests/ui/min_rust_version_invalid_attr.stderr |    4 +-
 tests/ui/string_slice.rs                      |    5 +
 tests/ui/string_slice.stderr                  |   14 +-
 .../ui/too_long_first_doc_paragraph-fix.fixed |    9 +
 tests/ui/too_long_first_doc_paragraph-fix.rs  |    8 +
 .../too_long_first_doc_paragraph-fix.stderr   |   20 +
 tests/ui/too_long_first_doc_paragraph.rs      |   53 +
 tests/ui/too_long_first_doc_paragraph.stderr  |   22 +
 tests/ui/unnecessary_lazy_eval.stderr         |  566 ++++++---
 .../ui/unnecessary_lazy_eval_unfixable.stderr |   35 +-
 triagebot.toml                                |    1 +
 util/gh-pages/index.html                      |  393 +-----
 util/gh-pages/script.js                       |  100 +-
 util/gh-pages/style.css                       |  398 ++++++
 216 files changed, 3044 insertions(+), 2961 deletions(-)
 create mode 100644 clippy_lints/src/doc/too_long_first_doc_paragraph.rs
 delete mode 100644 clippy_lints/src/utils/internal_lints/metadata_collector.rs
 create mode 100644 tests/config-metadata.rs
 create mode 100644 tests/ui-toml/absolute_paths/absolute_paths.allow_long.stderr
 create mode 100644 tests/ui-toml/absolute_paths/absolute_paths.default.stderr
 delete mode 100644 tests/ui-toml/absolute_paths/absolute_paths.disallow_crates.stderr
 create mode 100644 tests/ui-toml/absolute_paths/absolute_paths.no_short.stderr
 create mode 100644 tests/ui-toml/absolute_paths/absolute_paths_2015.default.stderr
 create mode 100644 tests/ui-toml/absolute_paths/absolute_paths_2015.rs
 create mode 100644 tests/ui-toml/absolute_paths/allow_long/clippy.toml
 delete mode 100644 tests/ui-toml/absolute_paths/auxiliary/helper.rs
 create mode 100644 tests/ui-toml/absolute_paths/default/clippy.toml
 delete mode 100644 tests/ui-toml/absolute_paths/disallow_crates/clippy.toml
 create mode 100644 tests/ui-toml/absolute_paths/no_short/clippy.toml
 create mode 100644 tests/ui/crashes/ice-3717.fixed
 create mode 100644 tests/ui/doc/doc_markdown-issue_13097.fixed
 create mode 100644 tests/ui/doc/doc_markdown-issue_13097.rs
 create mode 100644 tests/ui/doc/doc_markdown-issue_13097.stderr
 create mode 100644 tests/ui/too_long_first_doc_paragraph-fix.fixed
 create mode 100644 tests/ui/too_long_first_doc_paragraph-fix.rs
 create mode 100644 tests/ui/too_long_first_doc_paragraph-fix.stderr
 create mode 100644 tests/ui/too_long_first_doc_paragraph.rs
 create mode 100644 tests/ui/too_long_first_doc_paragraph.stderr
 create mode 100644 util/gh-pages/style.css

diff --git a/.cargo/config.toml b/.cargo/config.toml
index ce07290d1e1e5..d9c635df5dc79 100644
--- a/.cargo/config.toml
+++ b/.cargo/config.toml
@@ -1,10 +1,10 @@
 [alias]
+bless = "test --config env.RUSTC_BLESS='1'"
 uitest = "test --test compile-test"
-uibless = "test --test compile-test -- -- --bless"
-bless = "test -- -- --bless"
+uibless = "bless --test compile-test"
 dev = "run --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --"
 lintcheck = "run --package lintcheck --bin lintcheck --manifest-path lintcheck/Cargo.toml  -- "
-collect-metadata = "test --test dogfood --features internal -- collect_metadata"
+collect-metadata = "test --test compile-test --config env.COLLECT_METADATA='1'"
 
 [build]
 # -Zbinary-dep-depinfo allows us to track which rlib files to use for compiling UI tests
diff --git a/.github/deploy.sh b/.github/deploy.sh
index 5a59f94ec918b..d937661c0f828 100644
--- a/.github/deploy.sh
+++ b/.github/deploy.sh
@@ -10,6 +10,7 @@ mkdir out/master/
 cp util/gh-pages/index.html out/master
 cp util/gh-pages/script.js out/master
 cp util/gh-pages/lints.json out/master
+cp util/gh-pages/style.css out/master
 
 if [[ -n $TAG_NAME ]]; then
   echo "Save the doc for the current tag ($TAG_NAME) and point stable/ to it"
diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml
index 10e18e84c89fd..2aa13313fa518 100644
--- a/.github/workflows/clippy_bors.yml
+++ b/.github/workflows/clippy_bors.yml
@@ -136,11 +136,6 @@ jobs:
     - name: Test metadata collection
       run: cargo collect-metadata
 
-    - name: Test lint_configuration.md is up-to-date
-      run: |
-        echo "run \`cargo collect-metadata\` if this fails"
-        git update-index --refresh
-
   integration_build:
     needs: changelog
     runs-on: ubuntu-latest
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fddc2fd994e87..9bc4ad9698dbd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5914,6 +5914,7 @@ Released 2018-09-13
 [`to_string_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_format_args
 [`to_string_trait_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_trait_impl
 [`todo`]: https://rust-lang.github.io/rust-clippy/master/index.html#todo
+[`too_long_first_doc_paragraph`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_long_first_doc_paragraph
 [`too_many_arguments`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments
 [`too_many_lines`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines
 [`toplevel_ref_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#toplevel_ref_arg
diff --git a/Cargo.toml b/Cargo.toml
index 78409c7a09e29..b48b881097f47 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -30,8 +30,11 @@ color-print = "0.3.4"
 anstream = "0.6.0"
 
 [dev-dependencies]
+cargo_metadata = "0.18.1"
 ui_test = "0.25"
 regex = "1.5.5"
+serde = { version = "1.0.145", features = ["derive"] }
+serde_json = "1.0.122"
 toml = "0.7.3"
 walkdir = "2.3"
 filetime = "0.2.9"
@@ -41,7 +44,6 @@ itertools = "0.12"
 clippy_utils = { path = "clippy_utils" }
 if_chain = "1.0"
 quote = "1.0.25"
-serde = { version = "1.0.145", features = ["derive"] }
 syn = { version = "2.0", features = ["full"] }
 futures = "0.3"
 parking_lot = "0.12"
diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md
index a71d94daca74c..963e02e5c1616 100644
--- a/book/src/development/adding_lints.md
+++ b/book/src/development/adding_lints.md
@@ -739,7 +739,7 @@ for some users. Adding a configuration is done in the following steps:
 
 5. Update [Lint Configuration](../lint_configuration.md)
 
-   Run `cargo collect-metadata` to generate documentation changes for the book.
+   Run `cargo bless --test config-metadata` to generate documentation changes for the book.
 
 [`clippy_config::conf`]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_config/src/conf.rs
 [`clippy_lints` lib file]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/lib.rs
diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md
index e3d550b146629..78348797588a6 100644
--- a/book/src/lint_configuration.md
+++ b/book/src/lint_configuration.md
@@ -1,5 +1,5 @@
 <!--
-This file is generated by `cargo collect-metadata`.
+This file is generated by `cargo bless --test config-metadata`.
 Please use that command to update the file and do not edit it by hand.
 -->
 
@@ -199,7 +199,7 @@ Allowed names below the minimum allowed characters. The value `".."` can be used
 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:** `["j", "z", "i", "y", "n", "x", "w"]`
+**Default Value:** `["i", "j", "x", "y", "z", "w", "n"]`
 
 ---
 **Affected lints:**
@@ -455,7 +455,7 @@ default configuration of Clippy. By default, any configuration will replace the
 * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`.
 * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list.
 
-**Default Value:** `["TiB", "CoreGraphics", "CoffeeScript", "TeX", "Direct2D", "PiB", "DirectX", "NetBSD", "OAuth", "NaN", "OpenType", "WebGL2", "WebTransport", "JavaScript", "OpenSSL", "OpenSSH", "EiB", "PureScript", "OpenAL", "MiB", "WebAssembly", "MinGW", "CoreFoundation", "WebGPU", "ClojureScript", "CamelCase", "OpenDNS", "NaNs", "OpenMP", "GitLab", "KiB", "sRGB", "CoreText", "macOS", "TypeScript", "GiB", "OpenExr", "YCbCr", "OpenTelemetry", "OpenBSD", "FreeBSD", "GPLv2", "PostScript", "WebP", "LaTeX", "TensorFlow", "AccessKit", "TrueType", "OpenStreetMap", "OpenGL", "DevOps", "OCaml", "WebRTC", "WebGL", "BibLaTeX", "GitHub", "GraphQL", "iOS", "Direct3D", "BibTeX", "DirectWrite", "GPLv3", "IPv6", "WebSocket", "IPv4", "ECMAScript"]`
+**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "AccessKit", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]`
 
 ---
 **Affected lints:**
@@ -949,5 +949,3 @@ Whether to also emit warnings for unsafe blocks with metavariable expansions in
 ---
 **Affected lints:**
 * [`macro_metavars_in_unsafe`](https://rust-lang.github.io/rust-clippy/master/index.html#macro_metavars_in_unsafe)
-
-
diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml
index d5b28e2532371..5c4e0761dbca7 100644
--- a/clippy_config/Cargo.toml
+++ b/clippy_config/Cargo.toml
@@ -7,7 +7,6 @@ edition = "2021"
 
 [dependencies]
 itertools = "0.12"
-rustc-semver = "1.1"
 serde = { version = "1.0", features = ["derive"] }
 toml = "0.7.3"
 
diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs
index 4c2a8255d6b65..a6f1b958bfb17 100644
--- a/clippy_config/src/conf.rs
+++ b/clippy_config/src/conf.rs
@@ -1,7 +1,6 @@
 use crate::msrvs::Msrv;
 use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename};
 use crate::ClippyConfiguration;
-use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_session::Session;
 use rustc_span::edit_distance::edit_distance;
@@ -218,7 +217,7 @@ macro_rules! define_Conf {
 define_Conf! {
     /// Which crates to allow absolute paths from
     #[lints(absolute_paths)]
-    absolute_paths_allowed_crates: FxHashSet<String> = FxHashSet::default(),
+    absolute_paths_allowed_crates: Vec<String> = Vec::new(),
     /// The maximum number of segments a path can have before being linted, anything above this will
     /// be linted.
     #[lints(absolute_paths)]
@@ -280,12 +279,12 @@ define_Conf! {
     allowed_dotfiles: Vec<String> = Vec::default(),
     /// A list of crate names to allow duplicates of
     #[lints(multiple_crate_versions)]
-    allowed_duplicate_crates: FxHashSet<String> = FxHashSet::default(),
+    allowed_duplicate_crates: Vec<String> = Vec::new(),
     /// Allowed names below the minimum allowed characters. The value `".."` can be used 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.
     #[lints(min_ident_chars)]
-    allowed_idents_below_min_chars: FxHashSet<String> =
+    allowed_idents_below_min_chars: Vec<String> =
         DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string).collect(),
     /// 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`),
@@ -323,7 +322,7 @@ define_Conf! {
     /// 2. Paths with any segment that containing the word 'prelude'
     /// are already allowed by default.
     #[lints(wildcard_imports)]
-    allowed_wildcard_imports: FxHashSet<String> = FxHashSet::default(),
+    allowed_wildcard_imports: Vec<String> = Vec::new(),
     /// Suppress checking of the passed type names in all types of operations.
     ///
     /// If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead.
@@ -355,7 +354,7 @@ define_Conf! {
     /// arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]]
     /// ```
     #[lints(arithmetic_side_effects)]
-    arithmetic_side_effects_allowed_binary: Vec<[String; 2]> = <_>::default(),
+    arithmetic_side_effects_allowed_binary: Vec<(String, String)> = <_>::default(),
     /// Suppress checking of the passed type names in unary operations like "negation" (`-`).
     ///
     /// #### Example
@@ -431,7 +430,7 @@ define_Conf! {
     /// * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`.
     /// * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list.
     #[lints(doc_markdown)]
-    doc_valid_idents: FxHashSet<String> = DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect(),
+    doc_valid_idents: Vec<String> = DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect(),
     /// Whether to apply the raw pointer heuristic to determine if a type is `Send`.
     #[lints(non_send_fields_in_send_ty)]
     enable_raw_pointer_heuristic_for_send: bool = true,
@@ -706,12 +705,12 @@ fn deserialize(file: &SourceFile) -> TryConf {
                 DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS,
             );
             // TODO: THIS SHOULD BE TESTED, this comment will be gone soon
-            if conf.conf.allowed_idents_below_min_chars.contains("..") {
+            if conf.conf.allowed_idents_below_min_chars.iter().any(|e| e == "..") {
                 conf.conf
                     .allowed_idents_below_min_chars
                     .extend(DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string));
             }
-            if conf.conf.doc_valid_idents.contains("..") {
+            if conf.conf.doc_valid_idents.iter().any(|e| e == "..") {
                 conf.conf
                     .doc_valid_idents
                     .extend(DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string));
@@ -890,14 +889,14 @@ fn calculate_dimensions(fields: &[&str]) -> (usize, Vec<usize>) {
 
 #[cfg(test)]
 mod tests {
-    use rustc_data_structures::fx::{FxHashMap, FxHashSet};
     use serde::de::IgnoredAny;
+    use std::collections::{HashMap, HashSet};
     use std::fs;
     use walkdir::WalkDir;
 
     #[test]
     fn configs_are_tested() {
-        let mut names: FxHashSet<String> = crate::get_configuration_metadata()
+        let mut names: HashSet<String> = crate::get_configuration_metadata()
             .into_iter()
             .map(|meta| meta.name.replace('_', "-"))
             .collect();
@@ -910,7 +909,7 @@ mod tests {
         for entry in toml_files {
             let file = fs::read_to_string(entry.path()).unwrap();
             #[allow(clippy::zero_sized_map_values)]
-            if let Ok(map) = toml::from_str::<FxHashMap<String, IgnoredAny>>(&file) {
+            if let Ok(map) = toml::from_str::<HashMap<String, IgnoredAny>>(&file) {
                 for name in map.keys() {
                     names.remove(name.as_str());
                 }
diff --git a/clippy_config/src/lib.rs b/clippy_config/src/lib.rs
index d2246f12029b3..ac838cc81d2f0 100644
--- a/clippy_config/src/lib.rs
+++ b/clippy_config/src/lib.rs
@@ -14,7 +14,7 @@
 )]
 
 extern crate rustc_ast;
-extern crate rustc_data_structures;
+extern crate rustc_attr;
 #[allow(unused_extern_crates)]
 extern crate rustc_driver;
 extern crate rustc_errors;
diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs
index fc56ac5179686..0e8215aa8e3cd 100644
--- a/clippy_config/src/msrvs.rs
+++ b/clippy_config/src/msrvs.rs
@@ -1,6 +1,6 @@
 use rustc_ast::Attribute;
-use rustc_semver::RustcVersion;
-use rustc_session::Session;
+use rustc_attr::parse_version;
+use rustc_session::{RustcVersion, Session};
 use rustc_span::{sym, Symbol};
 use serde::Deserialize;
 use std::fmt;
@@ -10,7 +10,7 @@ macro_rules! msrv_aliases {
         $($name:ident),* $(,)?
     })*) => {
         $($(
-        pub const $name: RustcVersion = RustcVersion::new($major, $minor, $patch);
+        pub const $name: RustcVersion = RustcVersion { major: $major, minor :$minor, patch: $patch };
         )*)*
     };
 }
@@ -18,6 +18,7 @@ macro_rules! msrv_aliases {
 // names may refer to stabilized feature flags or library items
 msrv_aliases! {
     1,81,0  { LINT_REASONS_STABILIZATION }
+    1,80,0 { BOX_INTO_ITER}
     1,77,0 { C_STR_LITERALS }
     1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT }
     1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE }
@@ -81,9 +82,9 @@ impl<'de> Deserialize<'de> for Msrv {
         D: serde::Deserializer<'de>,
     {
         let v = String::deserialize(deserializer)?;
-        RustcVersion::parse(&v)
+        parse_version(Symbol::intern(&v))
             .map(|v| Msrv { stack: vec![v] })
-            .map_err(|_| serde::de::Error::custom("not a valid Rust version"))
+            .ok_or_else(|| serde::de::Error::custom("not a valid Rust version"))
     }
 }
 
@@ -95,7 +96,7 @@ impl Msrv {
     pub fn read_cargo(&mut self, sess: &Session) {
         let cargo_msrv = std::env::var("CARGO_PKG_RUST_VERSION")
             .ok()
-            .and_then(|v| RustcVersion::parse(&v).ok());
+            .and_then(|v| parse_version(Symbol::intern(&v)));
 
         match (self.current(), cargo_msrv) {
             (None, Some(cargo_msrv)) => self.stack = vec![cargo_msrv],
@@ -115,7 +116,7 @@ impl Msrv {
     }
 
     pub fn meets(&self, required: RustcVersion) -> bool {
-        self.current().map_or(true, |version| version.meets(required))
+        self.current().map_or(true, |msrv| msrv >= required)
     }
 
     fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option<RustcVersion> {
@@ -131,7 +132,7 @@ impl Msrv {
             }
 
             if let Some(msrv) = msrv_attr.value_str() {
-                if let Ok(version) = RustcVersion::parse(msrv.as_str()) {
+                if let Some(version) = parse_version(msrv) {
                     return Some(version);
                 }
 
diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs
index 755b04b0b232f..fc15913354cd6 100644
--- a/clippy_dev/src/main.rs
+++ b/clippy_dev/src/main.rs
@@ -1,3 +1,4 @@
+#![feature(rustc_private)]
 // warn on lints, that are included in `rust-lang/rust`s bootstrap
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs
index 15578d69c3a9d..8dbda1c634c28 100644
--- a/clippy_dev/src/update_lints.rs
+++ b/clippy_dev/src/update_lints.rs
@@ -604,7 +604,7 @@ fn gen_declared_lints<'a>(
     details.sort_unstable();
 
     let mut output = GENERATED_FILE_COMMENT.to_string();
-    output.push_str("pub(crate) static LINTS: &[&crate::LintInfo] = &[\n");
+    output.push_str("pub static LINTS: &[&crate::LintInfo] = &[\n");
 
     for (is_public, module_name, lint_name) in details {
         if !is_public {
diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml
index 99ed93468a01a..fbd4566da58c7 100644
--- a/clippy_lints/Cargo.toml
+++ b/clippy_lints/Cargo.toml
@@ -25,7 +25,6 @@ regex = { version = "1.5", optional = true }
 unicode-normalization = "0.1"
 unicode-script = { version = "0.5", default-features = false }
 semver = "1.0"
-rustc-semver = "1.1"
 url = "2.2"
 
 [dev-dependencies]
diff --git a/clippy_lints/src/absolute_paths.rs b/clippy_lints/src/absolute_paths.rs
index c0a9d888e0b0b..c72b3f1318c86 100644
--- a/clippy_lints/src/absolute_paths.rs
+++ b/clippy_lints/src/absolute_paths.rs
@@ -1,6 +1,6 @@
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::is_from_proc_macro;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
@@ -8,6 +8,7 @@ use rustc_hir::{HirId, ItemKind, Node, Path};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
 use rustc_span::symbol::kw;
+use rustc_span::Symbol;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -24,6 +25,13 @@ declare_clippy_lint! {
     /// Note: One exception to this is code from macro expansion - this does not lint such cases, as
     /// using absolute paths is the proper way of referencing items in one.
     ///
+    /// ### Known issues
+    ///
+    /// There are currently a few cases which are not caught by this lint:
+    /// * Macro calls. e.g. `path::to::macro!()`
+    /// * Derive macros. e.g. `#[derive(path::to::macro)]`
+    /// * Attribute macros. e.g. `#[path::to::macro]`
+    ///
     /// ### Example
     /// ```no_run
     /// let x = std::f64::consts::PI;
@@ -48,63 +56,66 @@ impl_lint_pass!(AbsolutePaths => [ABSOLUTE_PATHS]);
 
 pub struct AbsolutePaths {
     pub absolute_paths_max_segments: u64,
-    pub absolute_paths_allowed_crates: &'static FxHashSet<String>,
+    pub absolute_paths_allowed_crates: FxHashSet<Symbol>,
 }
 
 impl AbsolutePaths {
     pub fn new(conf: &'static Conf) -> Self {
         Self {
             absolute_paths_max_segments: conf.absolute_paths_max_segments,
-            absolute_paths_allowed_crates: &conf.absolute_paths_allowed_crates,
+            absolute_paths_allowed_crates: conf
+                .absolute_paths_allowed_crates
+                .iter()
+                .map(|x| Symbol::intern(x))
+                .collect(),
         }
     }
 }
 
-impl LateLintPass<'_> for AbsolutePaths {
+impl<'tcx> LateLintPass<'tcx> for AbsolutePaths {
     // We should only lint `QPath::Resolved`s, but since `Path` is only used in `Resolved` and `UsePath`
     // we don't need to use a visitor or anything as we can just check if the `Node` for `hir_id` isn't
     // a `Use`
-    #[expect(clippy::cast_possible_truncation)]
-    fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) {
-        let Self {
-            absolute_paths_max_segments,
-            absolute_paths_allowed_crates,
-        } = self;
-
-        if !path.span.from_expansion()
-            && let node = cx.tcx.hir_node(hir_id)
-            && !matches!(node, Node::Item(item) if matches!(item.kind, ItemKind::Use(_, _)))
-            && let [first, rest @ ..] = path.segments
-            // Handle `::std`
-            && let (segment, len) = if first.ident.name == kw::PathRoot {
-                // Indexing is fine as `PathRoot` must be followed by another segment. `len() - 1`
-                // is fine here for the same reason
-                (&rest[0], path.segments.len() - 1)
-            } else {
-                (first, path.segments.len())
-            }
-            && len > *absolute_paths_max_segments as usize
-            && let Some(segment_snippet) = snippet_opt(cx, segment.ident.span)
-            && segment_snippet == segment.ident.as_str()
-        {
-            let is_abs_external =
-                matches!(segment.res, Res::Def(DefKind::Mod, DefId { index, .. }) if index == CRATE_DEF_INDEX);
-            let is_abs_crate = segment.ident.name == kw::Crate;
-
-            if is_abs_external && absolute_paths_allowed_crates.contains(segment.ident.name.as_str())
-                || is_abs_crate && absolute_paths_allowed_crates.contains("crate")
+    fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, hir_id: HirId) {
+        let segments = match path.segments {
+            [] | [_] => return,
+            // Don't count enum variants and trait items as part of the length.
+            [rest @ .., _]
+                if let [.., s] = rest
+                    && matches!(s.res, Res::Def(DefKind::Enum | DefKind::Trait | DefKind::TraitAlias, _)) =>
+            {
+                rest
+            },
+            path => path,
+        };
+        if let [s1, s2, ..] = segments
+            && let has_root = s1.ident.name == kw::PathRoot
+            && let first = if has_root { s2 } else { s1 }
+            && let len = segments.len() - usize::from(has_root)
+            && len as u64 > self.absolute_paths_max_segments
+            && let crate_name = if let Res::Def(DefKind::Mod, DefId { index, .. }) = first.res
+                && index == CRATE_DEF_INDEX
             {
+                // `other_crate::foo` or `::other_crate::foo`
+                first.ident.name
+            } else if first.ident.name == kw::Crate || has_root {
+                // `::foo` or `crate::foo`
+                kw::Crate
+            } else {
                 return;
             }
-
-            if is_abs_external || is_abs_crate {
-                span_lint(
-                    cx,
-                    ABSOLUTE_PATHS,
-                    path.span,
-                    "consider bringing this path into scope with the `use` keyword",
-                );
-            }
+            && !path.span.from_expansion()
+            && let node = cx.tcx.hir_node(hir_id)
+            && !matches!(node, Node::Item(item) if matches!(item.kind, ItemKind::Use(..)))
+            && !self.absolute_paths_allowed_crates.contains(&crate_name)
+            && !is_from_proc_macro(cx, path)
+        {
+            span_lint(
+                cx,
+                ABSOLUTE_PATHS,
+                path.span,
+                "consider bringing this path into scope with the `use` keyword",
+            );
         }
     }
 }
diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs
index 3b4cc1134802d..56f5e903dc3e2 100644
--- a/clippy_lints/src/approx_const.rs
+++ b/clippy_lints/src/approx_const.rs
@@ -4,8 +4,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_semver::RustcVersion;
-use rustc_session::impl_lint_pass;
+use rustc_session::{impl_lint_pass, RustcVersion};
 use rustc_span::symbol;
 use std::f64::consts as f64;
 
diff --git a/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs
index 6e336efbb90a2..55645d04eef36 100644
--- a/clippy_lints/src/assigning_clones.rs
+++ b/clippy_lints/src/assigning_clones.rs
@@ -3,7 +3,7 @@ use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::mir::{enclosing_mir, PossibleBorrowerMap};
 use clippy_utils::sugg::Sugg;
-use clippy_utils::{is_diag_trait_item, last_path_segment, local_is_initialized, path_to_local};
+use clippy_utils::{is_diag_trait_item, is_in_test, last_path_segment, local_is_initialized, path_to_local};
 use rustc_errors::Applicability;
 use rustc_hir::{self as hir, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -118,6 +118,7 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones {
                 }
             )
             && !clone_source_borrows_from_dest(cx, lhs, rhs.span)
+            && !is_in_test(cx.tcx, e.hir_id)
         {
             span_lint_and_then(
                 cx,
diff --git a/clippy_lints/src/attrs/empty_line_after.rs b/clippy_lints/src/attrs/empty_line_after.rs
index ca43e76ac5780..7ff644b4c445f 100644
--- a/clippy_lints/src/attrs/empty_line_after.rs
+++ b/clippy_lints/src/attrs/empty_line_after.rs
@@ -1,6 +1,6 @@
 use super::{EMPTY_LINE_AFTER_DOC_COMMENTS, EMPTY_LINE_AFTER_OUTER_ATTR};
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::source::{is_present_in_source, snippet_opt, without_block_comments};
+use clippy_utils::source::{is_present_in_source, without_block_comments, SpanRangeExt};
 use rustc_ast::{AttrKind, AttrStyle};
 use rustc_lint::EarlyContext;
 use rustc_span::Span;
@@ -26,7 +26,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
                 item.span.parent(),
             );
 
-            if let Some(snippet) = snippet_opt(cx, end_of_attr_to_next_attr_or_item) {
+            if let Some(snippet) = end_of_attr_to_next_attr_or_item.get_source_text(cx) {
                 let lines = snippet.split('\n').collect::<Vec<_>>();
                 let lines = without_block_comments(lines);
 
diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs
index 8f430ae601a85..3b14e9aee7fc0 100644
--- a/clippy_lints/src/attrs/mod.rs
+++ b/clippy_lints/src/attrs/mod.rs
@@ -1,5 +1,3 @@
-//! checks for attributes
-
 mod allow_attributes;
 mod allow_attributes_without_reason;
 mod blanket_clippy_restriction_lints;
@@ -310,8 +308,8 @@ declare_clippy_lint! {
     /// ```rust,ignore
     /// #[allow(unused_mut)]
     /// fn foo() -> usize {
-    ///    let mut a = Vec::new();
-    ///    a.len()
+    ///     let mut a = Vec::new();
+    ///     a.len()
     /// }
     /// ```
     /// Use instead:
diff --git a/clippy_lints/src/attrs/non_minimal_cfg.rs b/clippy_lints/src/attrs/non_minimal_cfg.rs
index 3fde70615853d..877025cce4c2b 100644
--- a/clippy_lints/src/attrs/non_minimal_cfg.rs
+++ b/clippy_lints/src/attrs/non_minimal_cfg.rs
@@ -1,6 +1,6 @@
 use super::{Attribute, NON_MINIMAL_CFG};
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use rustc_ast::{MetaItemKind, NestedMetaItem};
 use rustc_errors::Applicability;
 use rustc_lint::EarlyContext;
@@ -29,8 +29,13 @@ fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
                         meta.span,
                         "unneeded sub `cfg` when there is only one condition",
                         |diag| {
-                            if let Some(snippet) = snippet_opt(cx, list[0].span()) {
-                                diag.span_suggestion(meta.span, "try", snippet, Applicability::MaybeIncorrect);
+                            if let Some(snippet) = list[0].span().get_source_text(cx) {
+                                diag.span_suggestion(
+                                    meta.span,
+                                    "try",
+                                    snippet.to_owned(),
+                                    Applicability::MaybeIncorrect,
+                                );
                             }
                         },
                     );
diff --git a/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs b/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs
index 486e7c6ec4f4a..478ba7a187be5 100644
--- a/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs
+++ b/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs
@@ -1,6 +1,7 @@
 use super::{Attribute, UNNECESSARY_CLIPPY_CFG};
 use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
+use itertools::Itertools;
 use rustc_ast::AttrStyle;
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, Level};
@@ -31,7 +32,7 @@ pub(super) fn check(
             return;
         }
         if nb_items == clippy_lints.len() {
-            if let Some(snippet) = snippet_opt(cx, behind_cfg_attr.span) {
+            if let Some(snippet) = behind_cfg_attr.span.get_source_text(cx) {
                 span_lint_and_sugg(
                     cx,
                     UNNECESSARY_CLIPPY_CFG,
@@ -47,11 +48,7 @@ pub(super) fn check(
                 );
             }
         } else {
-            let snippet = clippy_lints
-                .iter()
-                .filter_map(|sp| snippet_opt(cx, *sp))
-                .collect::<Vec<_>>()
-                .join(",");
+            let snippet = clippy_lints.iter().filter_map(|sp| sp.get_source_text(cx)).join(",");
             span_lint_and_note(
                 cx,
                 UNNECESSARY_CLIPPY_CFG,
diff --git a/clippy_lints/src/attrs/useless_attribute.rs b/clippy_lints/src/attrs/useless_attribute.rs
index f0868231d01a3..67ba605a59fa5 100644
--- a/clippy_lints/src/attrs/useless_attribute.rs
+++ b/clippy_lints/src/attrs/useless_attribute.rs
@@ -1,7 +1,7 @@
 use super::utils::{extract_clippy_lint, is_lint_level, is_word};
 use super::{Attribute, USELESS_ATTRIBUTE};
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::{first_line_of_span, snippet_opt};
+use clippy_utils::source::{first_line_of_span, SpanRangeExt};
 use rustc_ast::NestedMetaItem;
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
@@ -69,14 +69,14 @@ pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute])
                 }
                 let line_span = first_line_of_span(cx, attr.span);
 
-                if let Some(mut sugg) = snippet_opt(cx, line_span) {
-                    if sugg.contains("#[") {
+                if let Some(src) = line_span.get_source_text(cx) {
+                    if src.contains("#[") {
+                        #[expect(clippy::collapsible_span_lint_calls)]
                         span_lint_and_then(cx, USELESS_ATTRIBUTE, line_span, "useless lint attribute", |diag| {
-                            sugg = sugg.replacen("#[", "#![", 1);
                             diag.span_suggestion(
                                 line_span,
                                 "if you just forgot a `!`, use",
-                                sugg,
+                                src.replacen("#[", "#![", 1),
                                 Applicability::MaybeIncorrect,
                             );
                         });
diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs
index a2f48c18170a6..e933fdf1d6e6e 100644
--- a/clippy_lints/src/booleans.rs
+++ b/clippy_lints/src/booleans.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
 use clippy_utils::eq_expr_value;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
@@ -134,28 +134,30 @@ fn check_inverted_bool_in_condition(
 
     let suggestion = match (left.kind, right.kind) {
         (ExprKind::Unary(UnOp::Not, left_sub), ExprKind::Unary(UnOp::Not, right_sub)) => {
-            let Some(left) = snippet_opt(cx, left_sub.span) else {
+            let Some(left) = left_sub.span.get_source_text(cx) else {
                 return;
             };
-            let Some(right) = snippet_opt(cx, right_sub.span) else {
+            let Some(right) = right_sub.span.get_source_text(cx) else {
                 return;
             };
             let Some(op) = bin_op_eq_str(op) else { return };
             format!("{left} {op} {right}")
         },
         (ExprKind::Unary(UnOp::Not, left_sub), _) => {
-            let Some(left) = snippet_opt(cx, left_sub.span) else {
+            let Some(left) = left_sub.span.get_source_text(cx) else {
                 return;
             };
-            let Some(right) = snippet_opt(cx, right.span) else {
+            let Some(right) = right.span.get_source_text(cx) else {
                 return;
             };
             let Some(op) = inverted_bin_op_eq_str(op) else { return };
             format!("{left} {op} {right}")
         },
         (_, ExprKind::Unary(UnOp::Not, right_sub)) => {
-            let Some(left) = snippet_opt(cx, left.span) else { return };
-            let Some(right) = snippet_opt(cx, right_sub.span) else {
+            let Some(left) = left.span.get_source_text(cx) else {
+                return;
+            };
+            let Some(right) = right_sub.span.get_source_text(cx) else {
                 return;
             };
             let Some(op) = inverted_bin_op_eq_str(op) else { return };
@@ -313,8 +315,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
                         self.output.push_str(&str);
                     } else {
                         self.output.push('!');
-                        let snip = snippet_opt(self.cx, terminal.span)?;
-                        self.output.push_str(&snip);
+                        self.output.push_str(&terminal.span.get_source_text(self.cx)?);
                     }
                 },
                 True | False | Not(_) => {
@@ -345,8 +346,12 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
                 }
             },
             &Term(n) => {
-                let snip = snippet_opt(self.cx, self.terminals[n as usize].span.source_callsite())?;
-                self.output.push_str(&snip);
+                self.output.push_str(
+                    &self.terminals[n as usize]
+                        .span
+                        .source_callsite()
+                        .get_source_text(self.cx)?,
+                );
             },
         }
         Some(())
@@ -370,8 +375,8 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
                 _ => None,
             }
             .and_then(|op| {
-                let lhs_snippet = snippet_opt(cx, lhs.span)?;
-                let rhs_snippet = snippet_opt(cx, rhs.span)?;
+                let lhs_snippet = lhs.span.get_source_text(cx)?;
+                let rhs_snippet = rhs.span.get_source_text(cx)?;
 
                 if !(lhs_snippet.starts_with('(') && lhs_snippet.ends_with(')')) {
                     if let (ExprKind::Cast(..), BinOpKind::Ge) = (&lhs.kind, binop.node) {
@@ -399,7 +404,7 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
                     let path: &str = path.ident.name.as_str();
                     a == path
                 })
-                .and_then(|(_, neg_method)| Some(format!("{}.{neg_method}()", snippet_opt(cx, receiver.span)?)))
+                .and_then(|(_, neg_method)| Some(format!("{}.{neg_method}()", receiver.span.get_source_text(cx)?)))
         },
         _ => None,
     }
diff --git a/clippy_lints/src/borrow_deref_ref.rs b/clippy_lints/src/borrow_deref_ref.rs
index bd123a725a736..cba8224b84c9e 100644
--- a/clippy_lints/src/borrow_deref_ref.rs
+++ b/clippy_lints/src/borrow_deref_ref.rs
@@ -1,6 +1,6 @@
 use crate::reference::DEREF_ADDROF;
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::{get_parent_expr, is_from_proc_macro, is_lint_allowed};
 use rustc_errors::Applicability;
@@ -73,6 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
                 }
             })
             && !is_from_proc_macro(cx, e)
+            && let Some(deref_text) = deref_target.span.get_source_text(cx)
         {
             span_lint_and_then(
                 cx,
@@ -83,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
                     diag.span_suggestion(
                         e.span,
                         "if you would like to reborrow, try removing `&*`",
-                        snippet_opt(cx, deref_target.span).unwrap(),
+                        deref_text.as_str(),
                         Applicability::MachineApplicable,
                     );
 
@@ -98,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
                     diag.span_suggestion(
                         e.span,
                         "if you would like to deref, try using `&**`",
-                        format!("&**{}", &snippet_opt(cx, deref_target.span).unwrap()),
+                        format!("&**{deref_text}"),
                         Applicability::MaybeIncorrect,
                     );
                 },
diff --git a/clippy_lints/src/cargo/common_metadata.rs b/clippy_lints/src/cargo/common_metadata.rs
index 3af2d8c025684..fed0aa8b2758b 100644
--- a/clippy_lints/src/cargo/common_metadata.rs
+++ b/clippy_lints/src/cargo/common_metadata.rs
@@ -1,5 +1,3 @@
-//! lint on missing cargo common metadata
-
 use cargo_metadata::Metadata;
 use clippy_utils::diagnostics::span_lint;
 use rustc_lint::LateContext;
diff --git a/clippy_lints/src/cargo/mod.rs b/clippy_lints/src/cargo/mod.rs
index 312ad4c299007..96a2b1614646e 100644
--- a/clippy_lints/src/cargo/mod.rs
+++ b/clippy_lints/src/cargo/mod.rs
@@ -205,7 +205,7 @@ declare_clippy_lint! {
 }
 
 pub struct Cargo {
-    allowed_duplicate_crates: &'static FxHashSet<String>,
+    allowed_duplicate_crates: FxHashSet<String>,
     ignore_publish: bool,
 }
 
@@ -221,7 +221,7 @@ impl_lint_pass!(Cargo => [
 impl Cargo {
     pub fn new(conf: &'static Conf) -> Self {
         Self {
-            allowed_duplicate_crates: &conf.allowed_duplicate_crates,
+            allowed_duplicate_crates: conf.allowed_duplicate_crates.iter().cloned().collect(),
             ignore_publish: conf.cargo_ignore_publish,
         }
     }
@@ -263,7 +263,7 @@ impl LateLintPass<'_> for Cargo {
         {
             match MetadataCommand::new().exec() {
                 Ok(metadata) => {
-                    multiple_crate_versions::check(cx, &metadata, self.allowed_duplicate_crates);
+                    multiple_crate_versions::check(cx, &metadata, &self.allowed_duplicate_crates);
                 },
                 Err(e) => {
                     for lint in WITH_DEPS_LINTS {
diff --git a/clippy_lints/src/cargo/multiple_crate_versions.rs b/clippy_lints/src/cargo/multiple_crate_versions.rs
index 2769463c8a53c..44cd1f7192fb1 100644
--- a/clippy_lints/src/cargo/multiple_crate_versions.rs
+++ b/clippy_lints/src/cargo/multiple_crate_versions.rs
@@ -1,5 +1,3 @@
-//! lint on multiple versions of a crate being used
-
 use cargo_metadata::{DependencyKind, Metadata, Node, Package, PackageId};
 use clippy_utils::diagnostics::span_lint;
 use itertools::Itertools;
diff --git a/clippy_lints/src/casts/as_ptr_cast_mut.rs b/clippy_lints/src/casts/as_ptr_cast_mut.rs
index f05fd3fcde500..15ecba20a0bc4 100644
--- a/clippy_lints/src/casts/as_ptr_cast_mut.rs
+++ b/clippy_lints/src/casts/as_ptr_cast_mut.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
@@ -19,7 +19,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
         && let as_ptr_sig = cx.tcx.fn_sig(as_ptr_did).instantiate_identity()
         && let Some(first_param_ty) = as_ptr_sig.skip_binder().inputs().iter().next()
         && let ty::Ref(_, _, Mutability::Not) = first_param_ty.kind()
-        && let Some(recv) = snippet_opt(cx, receiver.span)
+        && let Some(recv) = receiver.span.get_source_text(cx)
     {
         // `as_mut_ptr` might not exist
         let applicability = Applicability::MaybeIncorrect;
diff --git a/clippy_lints/src/casts/cast_lossless.rs b/clippy_lints/src/casts/cast_lossless.rs
index bd3acc06f4b2b..346aed7e9f117 100644
--- a/clippy_lints/src/casts/cast_lossless.rs
+++ b/clippy_lints/src/casts/cast_lossless.rs
@@ -1,7 +1,7 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_in_const_context;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_isize_or_usize;
 use rustc_errors::Applicability;
@@ -34,7 +34,7 @@ pub(super) fn check(
             diag.help("an `as` cast can become silently lossy if the types change in the future");
             let mut applicability = Applicability::MachineApplicable;
             let from_sugg = Sugg::hir_with_context(cx, cast_from_expr, expr.span.ctxt(), "<from>", &mut applicability);
-            let Some(ty) = snippet_opt(cx, hygiene::walk_chain(cast_to_hir.span, expr.span.ctxt())) else {
+            let Some(ty) = hygiene::walk_chain(cast_to_hir.span, expr.span.ctxt()).get_source_text(cx) else {
                 return;
             };
             match cast_to_hir.kind {
diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs
index 102fe25fc67b0..5708aae3f3eca 100644
--- a/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -4,7 +4,7 @@ use clippy_utils::expr_or_init;
 use clippy_utils::source::snippet;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
-use rustc_errors::{Applicability, Diag, SuggestionStyle};
+use rustc_errors::{Applicability, Diag};
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
@@ -190,12 +190,10 @@ fn offer_suggestion(
         format!("{cast_to_snip}::try_from({})", Sugg::hir(cx, cast_expr, ".."))
     };
 
-    diag.span_suggestion_with_style(
+    diag.span_suggestion_verbose(
         expr.span,
         "... or use `try_from` and handle the error accordingly",
         suggestion,
         Applicability::Unspecified,
-        // always show the suggestion in a separate line
-        SuggestionStyle::ShowAlways,
     );
 }
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 5dc6df1e907d0..b22e8f4ee8919 100644
--- a/clippy_lints/src/casts/fn_to_numeric_cast_any.rs
+++ b/clippy_lints/src/casts/fn_to_numeric_cast_any.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_applicability;
-use rustc_errors::{Applicability, SuggestionStyle};
+use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
@@ -24,12 +24,11 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
             expr.span,
             format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
             |diag| {
-                diag.span_suggestion_with_style(
+                diag.span_suggestion_verbose(
                     expr.span,
                     "did you mean to invoke the function?",
                     format!("{from_snippet}() as {cast_to}"),
                     applicability,
-                    SuggestionStyle::ShowAlways,
                 );
             },
         );
diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs
index fb0b0cba6a662..566adc83d6903 100644
--- a/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/clippy_lints/src/casts/unnecessary_cast.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::numeric_literal::NumericLiteral;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::{snippet_opt, SpanRangeExt};
 use clippy_utils::visitors::{for_each_expr_without_closures, Visitable};
 use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local};
 use rustc_ast::{LitFloatType, LitIntType, LitKind};
@@ -104,7 +104,7 @@ pub(super) fn check<'tcx>(
         let literal_str = &cast_str;
 
         if let LitKind::Int(n, _) = lit.node
-            && let Some(src) = snippet_opt(cx, cast_expr.span)
+            && let Some(src) = cast_expr.span.get_source_text(cx)
             && cast_to.is_floating_point()
             && let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node)
             && let from_nbits = 128 - n.get().leading_zeros()
@@ -131,7 +131,7 @@ pub(super) fn check<'tcx>(
             | LitKind::Float(_, LitFloatType::Suffixed(_))
                 if cast_from.kind() == cast_to.kind() =>
             {
-                if let Some(src) = snippet_opt(cx, cast_expr.span) {
+                if let Some(src) = cast_expr.span.get_source_text(cx) {
                     if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) {
                         lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
                         return true;
@@ -253,7 +253,7 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx
             let res = cx.qpath_res(&qpath, expr.hir_id);
             // Function call
             if let Res::Def(DefKind::Fn, def_id) = res {
-                let Some(snippet) = snippet_opt(cx, cx.tcx.def_span(def_id)) else {
+                let Some(snippet) = cx.tcx.def_span(def_id).get_source_text(cx) else {
                     return ControlFlow::Continue(());
                 };
                 // This is the worst part of this entire function. This is the only way I know of to
diff --git a/clippy_lints/src/casts/zero_ptr.rs b/clippy_lints/src/casts/zero_ptr.rs
index 3c1c7d2dc3a54..c5c4a28646d27 100644
--- a/clippy_lints/src/casts/zero_ptr.rs
+++ b/clippy_lints/src/casts/zero_ptr.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::{is_in_const_context, is_integer_literal, std_or_core};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, Mutability, Ty, TyKind};
@@ -20,7 +20,7 @@ pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_>
 
         let sugg = if let TyKind::Infer = mut_ty.ty.kind {
             format!("{std_or_core}::{sugg_fn}()")
-        } else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) {
+        } else if let Some(mut_ty_snip) = mut_ty.ty.span.get_source_text(cx) {
             format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()")
         } else {
             return;
diff --git a/clippy_lints/src/cfg_not_test.rs b/clippy_lints/src/cfg_not_test.rs
index b54f392bf2fad..d820c1e0720b8 100644
--- a/clippy_lints/src/cfg_not_test.rs
+++ b/clippy_lints/src/cfg_not_test.rs
@@ -5,7 +5,7 @@ use rustc_session::declare_lint_pass;
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for usage of `cfg` that excludes code from `test` builds. (i.e., `#{cfg(not(test))]`)
+    /// Checks for usage of `cfg` that excludes code from `test` builds. (i.e., `#[cfg(not(test))]`)
     ///
     /// ### Why is this bad?
     /// This may give the false impression that a codebase has 100% coverage, yet actually has untested code.
diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs
index 1711565fca891..dd7c34d1e4687 100644
--- a/clippy_lints/src/checked_conversions.rs
+++ b/clippy_lints/src/checked_conversions.rs
@@ -1,5 +1,3 @@
-//! lint on manually implemented checked conversions that could be transformed into `try_from`
-
 use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs
index 5fa0522e4e5f9..0099eefbc8dc1 100644
--- a/clippy_lints/src/cognitive_complexity.rs
+++ b/clippy_lints/src/cognitive_complexity.rs
@@ -1,5 +1,3 @@
-//! calculate cognitive complexity and warn about overly complex functions
-
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::source::{IntoSpan, SpanRangeExt};
diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs
index f311c052ad6ee..e73bfc6ebf7a1 100644
--- a/clippy_lints/src/collapsible_if.rs
+++ b/clippy_lints/src/collapsible_if.rs
@@ -1,17 +1,3 @@
-//! Checks for if expressions that contain only an if expression.
-//!
-//! For example, the lint would catch:
-//!
-//! ```rust,ignore
-//! if x {
-//!     if y {
-//!         println!("Hello world");
-//!     }
-//! }
-//! ```
-//!
-//! This lint is **warn** by default
-
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::{snippet, snippet_block, snippet_block_with_applicability};
 use clippy_utils::sugg::Sugg;
diff --git a/clippy_lints/src/collection_is_never_read.rs b/clippy_lints/src/collection_is_never_read.rs
index eebda3ff76fd9..c6847411c75ab 100644
--- a/clippy_lints/src/collection_is_never_read.rs
+++ b/clippy_lints/src/collection_is_never_read.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
+use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item};
 use clippy_utils::visitors::{for_each_expr, Visitable};
 use clippy_utils::{get_enclosing_block, path_to_local_id};
 use core::ops::ControlFlow;
@@ -7,7 +7,6 @@ use rustc_hir::{Body, ExprKind, HirId, LangItem, LetStmt, Node, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 use rustc_span::symbol::sym;
-use rustc_span::Symbol;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -44,24 +43,11 @@ declare_clippy_lint! {
 }
 declare_lint_pass!(CollectionIsNeverRead => [COLLECTION_IS_NEVER_READ]);
 
-// Add `String` here when it is added to diagnostic items
-static COLLECTIONS: [Symbol; 9] = [
-    sym::BTreeMap,
-    sym::BTreeSet,
-    sym::BinaryHeap,
-    sym::HashMap,
-    sym::HashSet,
-    sym::LinkedList,
-    sym::Option,
-    sym::Vec,
-    sym::VecDeque,
-];
-
 impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead {
     fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) {
         // Look for local variables whose type is a container. Search surrounding block for read access.
         if let PatKind::Binding(_, local_id, _, _) = local.pat.kind
-            && match_acceptable_type(cx, local, &COLLECTIONS)
+            && match_acceptable_type(cx, local)
             && let Some(enclosing_block) = get_enclosing_block(cx, local.hir_id)
             && has_no_read_access(cx, local_id, enclosing_block)
         {
@@ -70,11 +56,22 @@ impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead {
     }
 }
 
-fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>, collections: &[Symbol]) -> bool {
+fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>) -> 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
-        || is_type_lang_item(cx, ty, LangItem::String)
+    matches!(
+        get_type_diagnostic_name(cx, ty),
+        Some(
+            sym::BTreeMap
+                | sym::BTreeSet
+                | sym::BinaryHeap
+                | sym::HashMap
+                | sym::HashSet
+                | sym::LinkedList
+                | sym::Option
+                | sym::Vec
+                | sym::VecDeque
+        )
+    ) || is_type_lang_item(cx, ty, LangItem::String)
 }
 
 fn has_no_read_access<'tcx, T: Visitable<'tcx>>(cx: &LateContext<'tcx>, id: HirId, block: T) -> bool {
diff --git a/clippy_lints/src/create_dir.rs b/clippy_lints/src/create_dir.rs
index b49a977dbeaf1..24570d8f4401c 100644
--- a/clippy_lints/src/create_dir.rs
+++ b/clippy_lints/src/create_dir.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_applicability;
-use rustc_errors::{Applicability, SuggestionStyle};
+use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
@@ -46,7 +46,7 @@ impl LateLintPass<'_> for CreateDir {
                 "calling `std::fs::create_dir` where there may be a better way",
                 |diag| {
                     let mut app = Applicability::MaybeIncorrect;
-                    diag.span_suggestion_with_style(
+                    diag.span_suggestion_verbose(
                         expr.span,
                         "consider calling `std::fs::create_dir_all` instead",
                         format!(
@@ -54,7 +54,6 @@ impl LateLintPass<'_> for CreateDir {
                             snippet_with_applicability(cx, arg.span, "..", &mut app)
                         ),
                         app,
-                        SuggestionStyle::ShowAlways,
                     );
                 },
             );
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index 3fb083dd83310..60e517131737a 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -2,7 +2,7 @@
 // Use that command to update this file and do not edit by hand.
 // Manual edits will be overwritten.
 
-pub(crate) static LINTS: &[&crate::LintInfo] = &[
+pub static LINTS: &[&crate::LintInfo] = &[
     #[cfg(feature = "internal")]
     crate::utils::internal_lints::almost_standard_lint_formulation::ALMOST_STANDARD_LINT_FORMULATION_INFO,
     #[cfg(feature = "internal")]
@@ -22,8 +22,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     #[cfg(feature = "internal")]
     crate::utils::internal_lints::lint_without_lint_pass::MISSING_CLIPPY_VERSION_ATTRIBUTE_INFO,
     #[cfg(feature = "internal")]
-    crate::utils::internal_lints::metadata_collector::METADATA_COLLECTOR_INFO,
-    #[cfg(feature = "internal")]
     crate::utils::internal_lints::msrv_attr_impl::MISSING_MSRV_ATTR_IMPL_INFO,
     #[cfg(feature = "internal")]
     crate::utils::internal_lints::outer_expn_data_pass::OUTER_EXPN_EXPN_DATA_INFO,
@@ -146,6 +144,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::doc::NEEDLESS_DOCTEST_MAIN_INFO,
     crate::doc::SUSPICIOUS_DOC_COMMENTS_INFO,
     crate::doc::TEST_ATTR_IN_DOCTEST_INFO,
+    crate::doc::TOO_LONG_FIRST_DOC_PARAGRAPH_INFO,
     crate::doc::UNNECESSARY_SAFETY_DOC_INFO,
     crate::double_parens::DOUBLE_PARENS_INFO,
     crate::drop_forget_ref::DROP_NON_DROP_INFO,
diff --git a/clippy_lints/src/doc/lazy_continuation.rs b/clippy_lints/src/doc/lazy_continuation.rs
index bd1cc46e1850e..771bcac244187 100644
--- a/clippy_lints/src/doc/lazy_continuation.rs
+++ b/clippy_lints/src/doc/lazy_continuation.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use itertools::Itertools;
-use rustc_errors::{Applicability, SuggestionStyle};
+use rustc_errors::Applicability;
 use rustc_lint::LateContext;
 use rustc_span::{BytePos, Span};
 use std::ops::Range;
@@ -59,12 +59,11 @@ pub(super) fn check(
                 && (doc_comment == "///" || doc_comment == "//!")
             {
                 // suggest filling in a blank line
-                diag.span_suggestion_with_style(
+                diag.span_suggestion_verbose(
                     line_break_span.shrink_to_lo(),
                     "if this should be its own paragraph, add a blank doc comment line",
                     format!("\n{doc_comment}"),
                     Applicability::MaybeIncorrect,
-                    SuggestionStyle::ShowAlways,
                 );
                 if ccount > 0 || blockquote_level > 0 {
                     diag.help("if this not intended to be a quote at all, escape it with `\\>`");
@@ -79,12 +78,11 @@ pub(super) fn check(
             if ccount == 0 && blockquote_level == 0 {
                 // simpler suggestion style for indentation
                 let indent = list_indentation - lcount;
-                diag.span_suggestion_with_style(
+                diag.span_suggestion_verbose(
                     span.shrink_to_hi(),
                     "indent this line",
                     std::iter::repeat(" ").take(indent).join(""),
                     Applicability::MaybeIncorrect,
-                    SuggestionStyle::ShowAlways,
                 );
                 diag.help("if this is supposed to be its own paragraph, add a blank line");
                 return;
@@ -107,12 +105,11 @@ pub(super) fn check(
                     suggested.push_str(text);
                 }
             }
-            diag.span_suggestion_with_style(
+            diag.span_suggestion_verbose(
                 span,
                 "add markers to start of line",
                 suggested,
                 Applicability::MachineApplicable,
-                SuggestionStyle::ShowAlways,
             );
             diag.help("if this not intended to be a quote at all, escape it with `\\>`");
         });
diff --git a/clippy_lints/src/doc/markdown.rs b/clippy_lints/src/doc/markdown.rs
index 41c0bcd55adca..8cdaba88e5095 100644
--- a/clippy_lints/src/doc/markdown.rs
+++ b/clippy_lints/src/doc/markdown.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet_with_applicability;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{Applicability, SuggestionStyle};
+use rustc_errors::Applicability;
 use rustc_lint::LateContext;
 use rustc_span::{BytePos, Pos, Span};
 use url::Url;
@@ -92,6 +92,10 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, b
             && matches!(prefix.chars().last(), Some('S' | 'X'))
         {
             prefix
+        } else if let Some(prefix) = s.strip_suffix("ified")
+            && prefix.chars().all(|c| c.is_ascii_uppercase())
+        {
+            prefix
         } else {
             s.strip_suffix('s').unwrap_or(s)
         };
@@ -133,24 +137,15 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, b
     }
 
     if has_underscore(word) || word.contains("::") || is_camel_case(word) || word.ends_with("()") {
-        let mut applicability = Applicability::MachineApplicable;
-
         span_lint_and_then(
             cx,
             DOC_MARKDOWN,
             span,
             "item in documentation is missing backticks",
             |diag| {
+                let mut applicability = Applicability::MachineApplicable;
                 let snippet = snippet_with_applicability(cx, span, "..", &mut applicability);
-                diag.span_suggestion_with_style(
-                    span,
-                    "try",
-                    format!("`{snippet}`"),
-                    applicability,
-                    // always show the suggestion in a separate line, since the
-                    // inline presentation adds another pair of backticks
-                    SuggestionStyle::ShowAlways,
-                );
+                diag.span_suggestion_verbose(span, "try", format!("`{snippet}`"), applicability);
             },
         );
     }
diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs
index d7b3a7c74f3ce..790579b21c902 100644
--- a/clippy_lints/src/doc/mod.rs
+++ b/clippy_lints/src/doc/mod.rs
@@ -1,4 +1,6 @@
 mod lazy_continuation;
+mod too_long_first_doc_paragraph;
+
 use clippy_config::Conf;
 use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
@@ -309,7 +311,7 @@ declare_clippy_lint! {
     /// ### Known problems
     /// Inner doc comments can only appear before items, so there are certain cases where the suggestion
     /// made by this lint is not valid code. For example:
-    /// ```rs
+    /// ```rust
     /// fn foo() {}
     /// ///!
     /// fn bar() {}
@@ -422,15 +424,47 @@ declare_clippy_lint! {
     "require every line of a paragraph to be indented and marked"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks if the first line in the documentation of items listed in module page is too long.
+    ///
+    /// ### Why is this bad?
+    /// Documentation will show the first paragraph of the doscstring in the summary page of a
+    /// module, so having a nice, short summary in the first paragraph is part of writing good docs.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// /// A very short summary.
+    /// /// A much longer explanation that goes into a lot more detail about
+    /// /// how the thing works, possibly with doclinks and so one,
+    /// /// and probably spanning a many rows.
+    /// struct Foo {}
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// /// A very short summary.
+    /// ///
+    /// /// A much longer explanation that goes into a lot more detail about
+    /// /// how the thing works, possibly with doclinks and so one,
+    /// /// and probably spanning a many rows.
+    /// struct Foo {}
+    /// ```
+    #[clippy::version = "1.81.0"]
+    pub TOO_LONG_FIRST_DOC_PARAGRAPH,
+    style,
+    "ensure that the first line of a documentation paragraph isn't too long"
+}
+
+#[derive(Clone)]
 pub struct Documentation {
-    valid_idents: &'static FxHashSet<String>,
+    valid_idents: FxHashSet<String>,
     check_private_items: bool,
 }
 
 impl Documentation {
     pub fn new(conf: &'static Conf) -> Self {
         Self {
-            valid_idents: &conf.doc_valid_idents,
+            valid_idents: conf.doc_valid_idents.iter().cloned().collect(),
             check_private_items: conf.check_private_items,
         }
     }
@@ -448,48 +482,60 @@ impl_lint_pass!(Documentation => [
     SUSPICIOUS_DOC_COMMENTS,
     EMPTY_DOCS,
     DOC_LAZY_CONTINUATION,
+    TOO_LONG_FIRST_DOC_PARAGRAPH,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for Documentation {
     fn check_attributes(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
-        let Some(headers) = check_attrs(cx, self.valid_idents, attrs) else {
+        let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else {
             return;
         };
 
         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_info = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value);
-                        missing_headers::check(
+            Node::Item(item) => {
+                too_long_first_doc_paragraph::check(
+                    cx,
+                    item,
+                    attrs,
+                    headers.first_paragraph_len,
+                    self.check_private_items,
+                );
+                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_info = 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_info,
+                                self.check_private_items,
+                            );
+                        }
+                    },
+                    ItemKind::Trait(_, unsafety, ..) => match (headers.safety, unsafety) {
+                        (false, Safety::Unsafe) => span_lint(
                             cx,
-                            item.owner_id,
-                            sig,
-                            headers,
-                            Some(body_id),
-                            panic_info,
-                            self.check_private_items,
-                        );
-                    }
-                },
-                ItemKind::Trait(_, unsafety, ..) => match (headers.safety, unsafety) {
-                    (false, Safety::Unsafe) => span_lint(
-                        cx,
-                        MISSING_SAFETY_DOC,
-                        cx.tcx.def_span(item.owner_id),
-                        "docs for unsafe trait missing `# Safety` section",
-                    ),
-                    (true, Safety::Safe) => span_lint(
-                        cx,
-                        UNNECESSARY_SAFETY_DOC,
-                        cx.tcx.def_span(item.owner_id),
-                        "docs for safe trait have unnecessary `# Safety` section",
-                    ),
+                            MISSING_SAFETY_DOC,
+                            cx.tcx.def_span(item.owner_id),
+                            "docs for unsafe trait missing `# Safety` section",
+                        ),
+                        (true, Safety::Safe) => 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
@@ -547,6 +593,7 @@ struct DocHeaders {
     safety: bool,
     errors: bool,
     panics: bool,
+    first_paragraph_len: usize,
 }
 
 /// Does some pre-processing on raw, desugared `#[doc]` attributes such as parsing them and
@@ -653,6 +700,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
     let mut paragraph_range = 0..0;
     let mut code_level = 0;
     let mut blockquote_level = 0;
+    let mut is_first_paragraph = true;
 
     let mut containers = Vec::new();
 
@@ -720,6 +768,10 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                 }
                 ticks_unbalanced = false;
                 paragraph_range = range;
+                if is_first_paragraph {
+                    headers.first_paragraph_len = doc[paragraph_range.clone()].chars().count();
+                    is_first_paragraph = false;
+                }
             },
             End(TagEnd::Heading(_) | TagEnd::Paragraph | TagEnd::Item) => {
                 if let End(TagEnd::Heading(_)) = event {
diff --git a/clippy_lints/src/doc/too_long_first_doc_paragraph.rs b/clippy_lints/src/doc/too_long_first_doc_paragraph.rs
new file mode 100644
index 0000000000000..7bb3bb12f2ca9
--- /dev/null
+++ b/clippy_lints/src/doc/too_long_first_doc_paragraph.rs
@@ -0,0 +1,91 @@
+use rustc_ast::ast::Attribute;
+use rustc_errors::Applicability;
+use rustc_hir::{Item, ItemKind};
+use rustc_lint::LateContext;
+
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::is_from_proc_macro;
+use clippy_utils::source::snippet_opt;
+
+use super::TOO_LONG_FIRST_DOC_PARAGRAPH;
+
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    item: &Item<'_>,
+    attrs: &[Attribute],
+    mut first_paragraph_len: usize,
+    check_private_items: bool,
+) {
+    if !check_private_items && !cx.effective_visibilities.is_exported(item.owner_id.def_id) {
+        return;
+    }
+    if first_paragraph_len <= 200
+        || !matches!(
+            item.kind,
+            // This is the list of items which can be documented AND are displayed on the module
+            // page. So associated items or impl blocks are not part of this list.
+            ItemKind::Static(..)
+                | ItemKind::Const(..)
+                | ItemKind::Fn(..)
+                | ItemKind::Macro(..)
+                | ItemKind::Mod(..)
+                | ItemKind::TyAlias(..)
+                | ItemKind::Enum(..)
+                | ItemKind::Struct(..)
+                | ItemKind::Union(..)
+                | ItemKind::Trait(..)
+                | ItemKind::TraitAlias(..)
+        )
+    {
+        return;
+    }
+
+    let mut spans = Vec::new();
+    let mut should_suggest_empty_doc = false;
+
+    for attr in attrs {
+        if let Some(doc) = attr.doc_str() {
+            spans.push(attr.span);
+            let doc = doc.as_str();
+            let doc = doc.trim();
+            if spans.len() == 1 {
+                // We make this suggestion only if the first doc line ends with a punctuation
+                // because it might just need to add an empty line with `///`.
+                should_suggest_empty_doc = doc.ends_with('.') || doc.ends_with('!') || doc.ends_with('?');
+            }
+            let len = doc.chars().count();
+            if len >= first_paragraph_len {
+                break;
+            }
+            first_paragraph_len -= len;
+        }
+    }
+
+    let &[first_span, .., last_span] = spans.as_slice() else {
+        return;
+    };
+    if is_from_proc_macro(cx, item) {
+        return;
+    }
+
+    span_lint_and_then(
+        cx,
+        TOO_LONG_FIRST_DOC_PARAGRAPH,
+        first_span.with_hi(last_span.lo()),
+        "first doc comment paragraph is too long",
+        |diag| {
+            if should_suggest_empty_doc
+                && let Some(second_span) = spans.get(1)
+                && let new_span = first_span.with_hi(second_span.lo()).with_lo(first_span.hi())
+                && let Some(snippet) = snippet_opt(cx, new_span)
+            {
+                diag.span_suggestion(
+                    new_span,
+                    "add an empty line",
+                    format!("{snippet}///\n"),
+                    Applicability::MachineApplicable,
+                );
+            }
+        },
+    );
+}
diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs
index 02f9c2c36488d..5315f55ba3882 100644
--- a/clippy_lints/src/else_if_without_else.rs
+++ b/clippy_lints/src/else_if_without_else.rs
@@ -1,5 +1,3 @@
-//! Lint on if expressions with an else if, but without a final else branch.
-
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_ast::ast::{Expr, ExprKind};
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs
index 1869faab1d326..f4c55738cb83a 100644
--- a/clippy_lints/src/empty_enum.rs
+++ b/clippy_lints/src/empty_enum.rs
@@ -1,5 +1,3 @@
-//! lint when there is an enum with no variants
-
 use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs
index e54cd248ead29..4755cefe784c5 100644
--- a/clippy_lints/src/enum_clike.rs
+++ b/clippy_lints/src/enum_clike.rs
@@ -1,6 +1,3 @@
-//! lint on C-like enums that are `repr(isize/usize)` and have values that
-//! don't fit into an `i32`
-
 use clippy_utils::consts::{mir_to_const, Constant};
 use clippy_utils::diagnostics::span_lint;
 use rustc_hir::{Item, ItemKind};
diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs
index a7e831fdc42a8..cabc659225828 100644
--- a/clippy_lints/src/eta_reduction.rs
+++ b/clippy_lints/src/eta_reduction.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::higher::VecArgs;
 use clippy_utils::source::snippet_opt;
-use clippy_utils::ty::type_diagnostic_name;
+use clippy_utils::ty::get_type_diagnostic_name;
 use clippy_utils::usage::{local_used_after_expr, local_used_in};
 use clippy_utils::{get_path_from_caller_to_method_type, is_adjusted, path_to_local, path_to_local_id};
 use rustc_errors::Applicability;
@@ -139,7 +139,7 @@ fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tc
         {
             let callee_ty_raw = typeck.expr_ty(callee);
             let callee_ty = callee_ty_raw.peel_refs();
-            if matches!(type_diagnostic_name(cx, callee_ty), Some(sym::Arc | sym::Rc))
+            if matches!(get_type_diagnostic_name(cx, callee_ty), Some(sym::Arc | sym::Rc))
                 || !check_inputs(typeck, body.params, None, args)
             {
                 return;
diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs
index f095c1add91f8..012ad8e1a2298 100644
--- a/clippy_lints/src/float_literal.rs
+++ b/clippy_lints/src/float_literal.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::numeric_literal;
 use rustc_ast::ast::{self, LitFloatType, LitKind};
-use rustc_errors::{Applicability, SuggestionStyle};
+use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, FloatTy};
@@ -117,12 +117,11 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
                             if type_suffix.is_none() {
                                 float_str.push_str(".0");
                             }
-                            diag.span_suggestion_with_style(
+                            diag.span_suggestion_verbose(
                                 expr.span,
                                 "consider changing the type or replacing it with",
                                 numeric_literal::format(&float_str, type_suffix, true),
                                 Applicability::MachineApplicable,
-                                SuggestionStyle::ShowAlways,
                             );
                         },
                     );
@@ -134,12 +133,11 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
                     expr.span,
                     "float has excessive precision",
                     |diag| {
-                        diag.span_suggestion_with_style(
+                        diag.span_suggestion_verbose(
                             expr.span,
                             "consider changing the type or truncating it to",
                             numeric_literal::format(&float_str, type_suffix, true),
                             Applicability::MachineApplicable,
-                            SuggestionStyle::ShowAlways,
                         );
                     },
                 );
diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs
index 0b248f784b762..4dedff69b9abd 100644
--- a/clippy_lints/src/format.rs
+++ b/clippy_lints/src/format.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::macros::{find_format_arg_expr, root_macro_call_first_node, FormatArgsStorage};
-use clippy_utils::source::{snippet_opt, snippet_with_context};
+use clippy_utils::source::{snippet_with_context, SpanRangeExt};
 use clippy_utils::sugg::Sugg;
 use rustc_ast::{FormatArgsPiece, FormatOptions, FormatTrait};
 use rustc_errors::Applicability;
@@ -65,7 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat {
                 ([], []) => span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability),
                 ([], [_]) => {
                     // Simulate macro expansion, converting {{ and }} to { and }.
-                    let Some(snippet) = snippet_opt(cx, format_args.span) else {
+                    let Some(snippet) = format_args.span.get_source_text(cx) else {
                         return;
                     };
                     let s_expand = snippet.replace("{{", "{").replace("}}", "}");
@@ -73,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat {
                     span_useless_format(cx, call_site, sugg, applicability);
                 },
                 ([arg], [piece]) => {
-                    if let Ok(value) = find_format_arg_expr(expr, arg)
+                    if let Some(value) = find_format_arg_expr(expr, arg)
                         && let FormatArgsPiece::Placeholder(placeholder) = piece
                         && placeholder.format_trait == FormatTrait::Display
                         && placeholder.format_options == FormatOptions::default()
diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs
index a31d5cb6ec77f..020c0c5440d93 100644
--- a/clippy_lints/src/format_args.rs
+++ b/clippy_lints/src/format_args.rs
@@ -7,7 +7,7 @@ use clippy_utils::macros::{
     find_format_arg_expr, format_arg_removal_span, format_placeholder_format_span, is_assert_macro, is_format_macro,
     is_panic, matching_root_macro_call, root_macro_call_first_node, FormatArgsStorage, FormatParamUsage, MacroCall,
 };
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::{implements_trait, is_type_lang_item};
 use itertools::Itertools;
 use rustc_ast::{
@@ -224,13 +224,11 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> {
             if let FormatArgsPiece::Placeholder(placeholder) = piece
                 && let Ok(index) = placeholder.argument.index
                 && let Some(arg) = self.format_args.arguments.all_args().get(index)
+                && let Some(arg_expr) = find_format_arg_expr(self.expr, arg)
             {
-                let arg_expr = find_format_arg_expr(self.expr, arg);
-
                 self.check_unused_format_specifier(placeholder, arg_expr);
 
-                if let Ok(arg_expr) = arg_expr
-                    && placeholder.format_trait == FormatTrait::Display
+                if placeholder.format_trait == FormatTrait::Display
                     && placeholder.format_options == FormatOptions::default()
                     && !self.is_aliased(index)
                 {
@@ -242,28 +240,13 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> {
         }
     }
 
-    fn check_unused_format_specifier(
-        &self,
-        placeholder: &FormatPlaceholder,
-        arg_expr: Result<&Expr<'_>, &rustc_ast::Expr>,
-    ) {
-        let ty_or_ast_expr = arg_expr.map(|expr| self.cx.typeck_results().expr_ty(expr).peel_refs());
-
-        let is_format_args = match ty_or_ast_expr {
-            Ok(ty) => is_type_lang_item(self.cx, ty, LangItem::FormatArguments),
-            Err(expr) => matches!(expr.peel_parens_and_refs().kind, rustc_ast::ExprKind::FormatArgs(_)),
-        };
-
+    fn check_unused_format_specifier(&self, placeholder: &FormatPlaceholder, arg: &Expr<'_>) {
         let options = &placeholder.format_options;
 
-        let arg_span = match arg_expr {
-            Ok(expr) => expr.span,
-            Err(expr) => expr.span,
-        };
-
         if let Some(placeholder_span) = placeholder.span
-            && is_format_args
             && *options != FormatOptions::default()
+            && let ty = self.cx.typeck_results().expr_ty(arg).peel_refs()
+            && is_type_lang_item(self.cx, ty, LangItem::FormatArguments)
         {
             span_lint_and_then(
                 self.cx,
@@ -274,7 +257,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> {
                     let mut suggest_format = |spec| {
                         let message = format!("for the {spec} to apply consider using `format!()`");
 
-                        if let Some(mac_call) = matching_root_macro_call(self.cx, arg_span, sym::format_args_macro) {
+                        if let Some(mac_call) = matching_root_macro_call(self.cx, arg.span, sym::format_args_macro) {
                             diag.span_suggestion(
                                 self.cx.sess().source_map().span_until_char(mac_call.span, '!'),
                                 message,
@@ -424,7 +407,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> {
                 count_needed_derefs(receiver_ty, cx.typeck_results().expr_adjustments(receiver).iter())
             && implements_trait(cx, target, display_trait_id, &[])
             && let Some(sized_trait_id) = cx.tcx.lang_items().sized_trait()
-            && let Some(receiver_snippet) = snippet_opt(cx, receiver.span.source_callsite())
+            && let Some(receiver_snippet) = receiver.span.source_callsite().get_source_text(cx)
         {
             let needs_ref = !implements_trait(cx, receiver_ty, sized_trait_id, &[]);
             if n_needed_derefs == 0 && !needs_ref {
diff --git a/clippy_lints/src/format_impl.rs b/clippy_lints/src/format_impl.rs
index e6f27cb82d17a..7cd12ac7db852 100644
--- a/clippy_lints/src/format_impl.rs
+++ b/clippy_lints/src/format_impl.rs
@@ -196,7 +196,7 @@ impl<'a, 'tcx> FormatImplExpr<'a, 'tcx> {
                     && trait_name == self.format_trait_impl.name
                     && let Ok(index) = placeholder.argument.index
                     && let Some(arg) = format_args.arguments.all_args().get(index)
-                    && let Ok(arg_expr) = find_format_arg_expr(self.expr, arg)
+                    && let Some(arg_expr) = find_format_arg_expr(self.expr, arg)
                 {
                     self.check_format_arg_self(arg_expr);
                 }
diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs
index 1c1d8b57bc41b..b84bf7c821ce8 100644
--- a/clippy_lints/src/from_over_into.rs
+++ b/clippy_lints/src/from_over_into.rs
@@ -3,7 +3,7 @@ use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::span_is_local;
 use clippy_utils::path_def_id;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_path, Visitor};
 use rustc_hir::{
@@ -178,8 +178,8 @@ fn convert_to_from(
         return None;
     };
 
-    let from = snippet_opt(cx, self_ty.span)?;
-    let into = snippet_opt(cx, target_ty.span)?;
+    let from = self_ty.span.get_source_text(cx)?;
+    let into = target_ty.span.get_source_text(cx)?;
 
     let mut suggestions = vec![
         // impl Into<T> for U  ->  impl From<T> for U
@@ -187,10 +187,10 @@ fn convert_to_from(
         (into_trait_seg.ident.span, String::from("From")),
         // impl Into<T> for U  ->  impl Into<U> for U
         //           ~                       ~
-        (target_ty.span, from.clone()),
+        (target_ty.span, from.to_owned()),
         // impl Into<T> for U  ->  impl Into<T> for T
         //                  ~                       ~
-        (self_ty.span, into),
+        (self_ty.span, into.to_owned()),
         // fn into(self) -> T  ->  fn from(self) -> T
         //    ~~~~                    ~~~~
         (impl_item.ident.span, String::from("from")),
@@ -223,7 +223,7 @@ fn convert_to_from(
     }
 
     for span in finder.upper {
-        suggestions.push((span, from.clone()));
+        suggestions.push((span, from.to_owned()));
     }
     for span in finder.lower {
         suggestions.push((span, String::from("val")));
diff --git a/clippy_lints/src/from_str_radix_10.rs b/clippy_lints/src/from_str_radix_10.rs
index 6ab7bbc2dfc0c..e5fa67d696427 100644
--- a/clippy_lints/src/from_str_radix_10.rs
+++ b/clippy_lints/src/from_str_radix_10.rs
@@ -22,8 +22,8 @@ declare_clippy_lint! {
     ///
     /// ### Known problems
     ///
-    /// This lint may suggest using (&<expression>).parse() instead of <expression>.parse() directly
-    /// in some cases, which is correct but adds unnecessary complexity to the code.
+    /// This lint may suggest using `(&<expression>).parse()` instead of `<expression>.parse()`
+    /// directly in some cases, which is correct but adds unnecessary complexity to the code.
     ///
     /// ### Example
     /// ```ignore
diff --git a/clippy_lints/src/functions/impl_trait_in_params.rs b/clippy_lints/src/functions/impl_trait_in_params.rs
index cf85c74e688d2..05e341e06fde4 100644
--- a/clippy_lints/src/functions/impl_trait_in_params.rs
+++ b/clippy_lints/src/functions/impl_trait_in_params.rs
@@ -1,6 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_in_test;
 
+use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, GenericParam, Generics, HirId, ImplItem, ImplItemKind, TraitItem, TraitItemKind};
@@ -18,20 +19,18 @@ fn report(cx: &LateContext<'_>, param: &GenericParam<'_>, generics: &Generics<'_
         |diag| {
             if let Some(gen_span) = generics.span_for_param_suggestion() {
                 // If there's already a generic param with the same bound, do not lint **this** suggestion.
-                diag.span_suggestion_with_style(
+                diag.span_suggestion_verbose(
                     gen_span,
                     "add a type parameter",
                     format!(", {{ /* Generic name */ }}: {}", &param.name.ident().as_str()[5..]),
-                    rustc_errors::Applicability::HasPlaceholders,
-                    rustc_errors::SuggestionStyle::ShowAlways,
+                    Applicability::HasPlaceholders,
                 );
             } else {
-                diag.span_suggestion_with_style(
+                diag.span_suggestion_verbose(
                     generics.span,
                     "add a type parameter",
                     format!("<{{ /* Generic name */ }}: {}>", &param.name.ident().as_str()[5..]),
-                    rustc_errors::Applicability::HasPlaceholders,
-                    rustc_errors::SuggestionStyle::ShowAlways,
+                    Applicability::HasPlaceholders,
                 );
             }
         },
diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs
index b179d7b52492c..9382812104706 100644
--- a/clippy_lints/src/functions/must_use.rs
+++ b/clippy_lints/src/functions/must_use.rs
@@ -8,11 +8,11 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, Ty};
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{sym, Span};
 
 use clippy_utils::attrs::is_proc_macro;
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::is_must_use_ty;
 use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{return_ty, trait_ref_of_method};
@@ -129,9 +129,9 @@ fn check_needless_must_use(
             cx,
             DOUBLE_MUST_USE,
             fn_header_span,
-            "this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]`",
+            "this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`",
             None,
-            "either add some descriptive text or remove the attribute",
+            "either add some descriptive message or remove the attribute",
         );
     }
 }
@@ -155,7 +155,7 @@ fn check_must_use_candidate<'tcx>(
         return;
     }
     span_lint_and_then(cx, MUST_USE_CANDIDATE, fn_span, msg, |diag| {
-        if let Some(snippet) = snippet_opt(cx, fn_span) {
+        if let Some(snippet) = fn_span.get_source_text(cx) {
             diag.span_suggestion(
                 fn_span,
                 "add the attribute",
@@ -193,17 +193,13 @@ fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut DefIdSet)
     }
 }
 
-static KNOWN_WRAPPER_TYS: &[Symbol] = &[sym::Rc, sym::Arc];
-
 fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, tys: &mut DefIdSet) -> bool {
     match *ty.kind() {
         // primitive types are never mutable
         ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false,
         ty::Adt(adt, args) => {
             tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.param_env)
-                || KNOWN_WRAPPER_TYS
-                    .iter()
-                    .any(|&sym| cx.tcx.is_diagnostic_item(sym, adt.did()))
+                || matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::Rc | sym::Arc))
                     && args.types().any(|ty| is_mutable_ty(cx, ty, tys))
         },
         ty::Tuple(args) => args.iter().any(|ty| is_mutable_ty(cx, ty, tys)),
diff --git a/clippy_lints/src/functions/too_many_lines.rs b/clippy_lints/src/functions/too_many_lines.rs
index 586ca58d60dd6..0f5ce340c44dd 100644
--- a/clippy_lints/src/functions/too_many_lines.rs
+++ b/clippy_lints/src/functions/too_many_lines.rs
@@ -1,12 +1,11 @@
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::source::SpanRangeExt;
 use rustc_hir as hir;
 use rustc_hir::intravisit::FnKind;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_span::Span;
 
-use clippy_utils::diagnostics::span_lint;
-use clippy_utils::source::snippet_opt;
-
 use super::TOO_MANY_LINES;
 
 pub(super) fn check_fn(
@@ -22,57 +21,57 @@ pub(super) fn check_fn(
         return;
     }
 
-    let Some(code_snippet) = snippet_opt(cx, body.value.span) else {
-        return;
-    };
     let mut line_count: u64 = 0;
-    let mut in_comment = false;
-    let mut code_in_line;
+    let too_many = body.value.span.check_source_text(cx, |src| {
+        let mut in_comment = false;
+        let mut code_in_line;
 
-    let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..))
-        && code_snippet.as_bytes().first().copied() == Some(b'{')
-        && code_snippet.as_bytes().last().copied() == Some(b'}')
-    {
-        // Removing the braces from the enclosing block
-        &code_snippet[1..code_snippet.len() - 1]
-    } else {
-        &code_snippet
-    }
-    .trim() // Remove leading and trailing blank lines
-    .lines();
+        let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..))
+            && src.as_bytes().first().copied() == Some(b'{')
+            && src.as_bytes().last().copied() == Some(b'}')
+        {
+            // Removing the braces from the enclosing block
+            &src[1..src.len() - 1]
+        } else {
+            src
+        }
+        .trim() // Remove leading and trailing blank lines
+        .lines();
 
-    for mut line in function_lines {
-        code_in_line = false;
-        loop {
-            line = line.trim_start();
-            if line.is_empty() {
-                break;
-            }
-            if in_comment {
-                if let Some(i) = line.find("*/") {
-                    line = &line[i + 2..];
-                    in_comment = false;
-                    continue;
+        for mut line in function_lines {
+            code_in_line = false;
+            loop {
+                line = line.trim_start();
+                if line.is_empty() {
+                    break;
                 }
-            } else {
-                let multi_idx = line.find("/*").unwrap_or(line.len());
-                let single_idx = line.find("//").unwrap_or(line.len());
-                code_in_line |= multi_idx > 0 && single_idx > 0;
-                // Implies multi_idx is below line.len()
-                if multi_idx < single_idx {
-                    line = &line[multi_idx + 2..];
-                    in_comment = true;
-                    continue;
+                if in_comment {
+                    if let Some(i) = line.find("*/") {
+                        line = &line[i + 2..];
+                        in_comment = false;
+                        continue;
+                    }
+                } else {
+                    let multi_idx = line.find("/*").unwrap_or(line.len());
+                    let single_idx = line.find("//").unwrap_or(line.len());
+                    code_in_line |= multi_idx > 0 && single_idx > 0;
+                    // Implies multi_idx is below line.len()
+                    if multi_idx < single_idx {
+                        line = &line[multi_idx + 2..];
+                        in_comment = true;
+                        continue;
+                    }
                 }
+                break;
+            }
+            if code_in_line {
+                line_count += 1;
             }
-            break;
-        }
-        if code_in_line {
-            line_count += 1;
         }
-    }
+        line_count > too_many_lines_threshold
+    });
 
-    if line_count > too_many_lines_threshold {
+    if too_many {
         span_lint(
             cx,
             TOO_MANY_LINES,
diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs
index 0ebd8d0c237b6..120c5396a1cd5 100644
--- a/clippy_lints/src/if_not_else.rs
+++ b/clippy_lints/src/if_not_else.rs
@@ -1,6 +1,3 @@
-//! lint on if branches that could be swapped so no `!` operation is necessary
-//! on the condition
-
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::is_else_clause;
diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs
index b926e1e62ba0c..ba06567b9572c 100644
--- a/clippy_lints/src/implicit_return.rs
+++ b/clippy_lints/src/implicit_return.rs
@@ -3,7 +3,7 @@ use clippy_utils::source::{snippet_with_applicability, snippet_with_context, wal
 use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{get_async_fn_body, is_async_fn, is_from_proc_macro};
 use core::ops::ControlFlow;
-use rustc_errors::{Applicability, SuggestionStyle};
+use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, HirId};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -54,13 +54,7 @@ fn lint_return(cx: &LateContext<'_>, emission_place: HirId, span: Span) {
         |diag| {
             let mut app = Applicability::MachineApplicable;
             let snip = snippet_with_applicability(cx, span, "..", &mut app);
-            diag.span_suggestion_with_style(
-                span,
-                "add `return` as shown",
-                format!("return {snip}"),
-                app,
-                SuggestionStyle::ShowAlways,
-            );
+            diag.span_suggestion_verbose(span, "add `return` as shown", format!("return {snip}"), app);
         },
     );
 }
@@ -75,12 +69,11 @@ fn lint_break(cx: &LateContext<'_>, emission_place: HirId, break_span: Span, exp
         |diag| {
             let mut app = Applicability::MachineApplicable;
             let snip = snippet_with_context(cx, expr_span, break_span.ctxt(), "..", &mut app).0;
-            diag.span_suggestion_with_style(
+            diag.span_suggestion_verbose(
                 break_span,
                 "change `break` to `return` as shown",
                 format!("return {snip}"),
                 app,
-                SuggestionStyle::ShowAlways,
             );
         },
     );
diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs
index 0ef5b803a89d6..2ad045e12686c 100644
--- a/clippy_lints/src/incompatible_msrv.rs
+++ b/clippy_lints/src/incompatible_msrv.rs
@@ -7,8 +7,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::{Expr, ExprKind, HirId};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::TyCtxt;
-use rustc_semver::RustcVersion;
-use rustc_session::impl_lint_pass;
+use rustc_session::{impl_lint_pass, RustcVersion};
 use rustc_span::def_id::DefId;
 use rustc_span::{ExpnKind, Span};
 
@@ -65,18 +64,18 @@ impl IncompatibleMsrv {
                 StabilityLevel::Stable {
                     since: StableSince::Version(version),
                     ..
-                } => Some(RustcVersion::new(
-                    version.major.into(),
-                    version.minor.into(),
-                    version.patch.into(),
-                )),
+                } => Some(version),
                 _ => None,
             }) {
             version
         } else if let Some(parent_def_id) = tcx.opt_parent(def_id) {
             self.get_def_id_version(tcx, parent_def_id)
         } else {
-            RustcVersion::new(1, 0, 0)
+            RustcVersion {
+                major: 1,
+                minor: 0,
+                patch: 0,
+            }
         };
         self.is_above_msrv.insert(def_id, version);
         version
diff --git a/clippy_lints/src/inconsistent_struct_constructor.rs b/clippy_lints/src/inconsistent_struct_constructor.rs
index 5b0aadf35c62d..d386bfca6baa1 100644
--- a/clippy_lints/src/inconsistent_struct_constructor.rs
+++ b/clippy_lints/src/inconsistent_struct_constructor.rs
@@ -1,4 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::fulfill_or_allowed;
 use clippy_utils::source::snippet;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::Applicability;
@@ -71,6 +72,8 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
             && let ty = cx.typeck_results().expr_ty(expr)
             && let Some(adt_def) = ty.ty_adt_def()
             && adt_def.is_struct()
+            && let Some(local_def_id) = adt_def.did().as_local()
+            && let ty_hir_id = cx.tcx.local_def_id_to_hir_id(local_def_id)
             && let Some(variant) = adt_def.variants().iter().next()
         {
             let mut def_order_map = FxHashMap::default();
@@ -103,15 +106,17 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
                 snippet(cx, qpath.span(), ".."),
             );
 
-            span_lint_and_sugg(
-                cx,
-                INCONSISTENT_STRUCT_CONSTRUCTOR,
-                expr.span,
-                "struct constructor field order is inconsistent with struct definition field order",
-                "try",
-                sugg,
-                Applicability::MachineApplicable,
-            );
+            if !fulfill_or_allowed(cx, INCONSISTENT_STRUCT_CONSTRUCTOR, Some(ty_hir_id)) {
+                span_lint_and_sugg(
+                    cx,
+                    INCONSISTENT_STRUCT_CONSTRUCTOR,
+                    expr.span,
+                    "struct constructor field order is inconsistent with struct definition field order",
+                    "try",
+                    sugg,
+                    Applicability::MachineApplicable,
+                );
+            }
         }
     }
 }
diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs
index 3ac50b8f1fba5..22e9674714fe5 100644
--- a/clippy_lints/src/indexing_slicing.rs
+++ b/clippy_lints/src/indexing_slicing.rs
@@ -1,5 +1,3 @@
-//! lint on indexing and slicing operations
-
 use clippy_config::Conf;
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs
index 676d50c4951b1..71c317552ee1a 100644
--- a/clippy_lints/src/infinite_iter.rs
+++ b/clippy_lints/src/infinite_iter.rs
@@ -1,10 +1,10 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::higher;
-use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
+use clippy_utils::ty::{get_type_diagnostic_name, implements_trait};
 use rustc_hir::{BorrowKind, Closure, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -210,18 +210,6 @@ const COMPLETING_METHODS: [(&str, usize); 12] = [
     ("product", 0),
 ];
 
-/// the paths of types that are known to be infinitely allocating
-const INFINITE_COLLECTORS: &[Symbol] = &[
-    sym::BinaryHeap,
-    sym::BTreeMap,
-    sym::BTreeSet,
-    sym::HashMap,
-    sym::HashSet,
-    sym::LinkedList,
-    sym::Vec,
-    sym::VecDeque,
-];
-
 fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
     match expr.kind {
         ExprKind::MethodCall(method, receiver, args, _) => {
@@ -248,10 +236,19 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
                 }
             } else if method.ident.name == sym!(collect) {
                 let ty = cx.typeck_results().expr_ty(expr);
-                if INFINITE_COLLECTORS
-                    .iter()
-                    .any(|diag_item| is_type_diagnostic_item(cx, ty, *diag_item))
-                {
+                if matches!(
+                    get_type_diagnostic_name(cx, ty),
+                    Some(
+                        sym::BinaryHeap
+                            | sym::BTreeMap
+                            | sym::BTreeSet
+                            | sym::HashMap
+                            | sym::HashSet
+                            | sym::LinkedList
+                            | sym::Vec
+                            | sym::VecDeque,
+                    )
+                ) {
                     return is_infinite(cx, receiver);
                 }
             }
diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs
index 9eed7aa924339..d39f910f9936d 100644
--- a/clippy_lints/src/inherent_impl.rs
+++ b/clippy_lints/src/inherent_impl.rs
@@ -1,5 +1,3 @@
-//! lint on inherent implementations
-
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_lint_allowed;
 use rustc_data_structures::fx::FxHashMap;
diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs
index 5657c58bb0a47..1b900f6be8e85 100644
--- a/clippy_lints/src/inline_fn_without_body.rs
+++ b/clippy_lints/src/inline_fn_without_body.rs
@@ -1,5 +1,3 @@
-//! checks for `#[inline]` on trait methods without bodies
-
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::sugg::DiagExt;
 use rustc_errors::Applicability;
diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs
index b8e0eef7c7e9e..fc575bff7e63f 100644
--- a/clippy_lints/src/int_plus_one.rs
+++ b/clippy_lints/src/int_plus_one.rs
@@ -1,7 +1,5 @@
-//! lint on blocks unnecessarily using >= with a + 1 or - 1
-
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind};
 use rustc_ast::token;
 use rustc_errors::Applicability;
@@ -132,8 +130,8 @@ impl IntPlusOne {
             BinOpKind::Le => "<",
             _ => return None,
         };
-        if let Some(snippet) = snippet_opt(cx, node.span) {
-            if let Some(other_side_snippet) = snippet_opt(cx, other_side.span) {
+        if let Some(snippet) = node.span.get_source_text(cx) {
+            if let Some(other_side_snippet) = other_side.span.get_source_text(cx) {
                 let rec = match side {
                     Side::Lhs => Some(format!("{snippet} {binop_string} {other_side_snippet}")),
                     Side::Rhs => Some(format!("{other_side_snippet} {binop_string} {snippet}")),
diff --git a/clippy_lints/src/item_name_repetitions.rs b/clippy_lints/src/item_name_repetitions.rs
index 4d44bae02b87d..74bf82f58bdcf 100644
--- a/clippy_lints/src/item_name_repetitions.rs
+++ b/clippy_lints/src/item_name_repetitions.rs
@@ -1,5 +1,3 @@
-//! lint on enum variants that are prefixed or suffixed by the same characters
-
 use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_hir};
 use clippy_utils::is_bool;
diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs
index a88d8e24fda8d..4f066113aea33 100644
--- a/clippy_lints/src/items_after_statements.rs
+++ b/clippy_lints/src/items_after_statements.rs
@@ -1,5 +1,3 @@
-//! lint when items are used after statements
-
 use clippy_utils::diagnostics::span_lint_hir;
 use rustc_hir::{Block, ItemKind, StmtKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
diff --git a/clippy_lints/src/items_after_test_module.rs b/clippy_lints/src/items_after_test_module.rs
index 3614fb8cc963b..8caa484bb9934 100644
--- a/clippy_lints/src/items_after_test_module.rs
+++ b/clippy_lints/src/items_after_test_module.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_hir_and_then;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::{fulfill_or_allowed, is_cfg_test, is_from_proc_macro};
 use rustc_errors::{Applicability, SuggestionStyle};
 use rustc_hir::{HirId, Item, ItemKind, Mod};
@@ -93,11 +93,14 @@ impl LateLintPass<'_> for ItemsAfterTestModule {
                     if let Some(prev) = mod_pos.checked_sub(1)
                         && let prev = cx.tcx.hir().item(module.item_ids[prev])
                         && let items_span = last.span.with_lo(test_mod.span.hi())
-                        && let Some(items) = snippet_opt(cx, items_span)
+                        && let Some(items) = items_span.get_source_text(cx)
                     {
                         diag.multipart_suggestion_with_style(
                             "move the items to before the test module was defined",
-                            vec![(prev.span.shrink_to_hi(), items), (items_span, String::new())],
+                            vec![
+                                (prev.span.shrink_to_hi(), items.to_owned()),
+                                (items_span, String::new()),
+                            ],
                             Applicability::MachineApplicable,
                             SuggestionStyle::HideCodeAlways,
                         );
diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs
index 225d79aa71d68..2f027c1170728 100644
--- a/clippy_lints/src/large_enum_variant.rs
+++ b/clippy_lints/src/large_enum_variant.rs
@@ -1,5 +1,3 @@
-//! lint when there is a large size difference between variants on an enum
-
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_applicability;
diff --git a/clippy_lints/src/large_stack_frames.rs b/clippy_lints/src/large_stack_frames.rs
index 4abf7edc9b4e5..d2bdf194adad9 100644
--- a/clippy_lints/src/large_stack_frames.rs
+++ b/clippy_lints/src/large_stack_frames.rs
@@ -3,7 +3,7 @@ use std::{fmt, ops};
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::fn_has_unsatisfiable_preds;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, FnDecl};
@@ -186,7 +186,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames {
                         // 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)
+                        if let Some(name) = local_span.get_source_text(cx)
                             && is_ident(&name)
                         {
                             // If the local is an ordinary named variable,
diff --git a/clippy_lints/src/legacy_numeric_constants.rs b/clippy_lints/src/legacy_numeric_constants.rs
index 752e1326e3e05..ccab1e27d3b0c 100644
--- a/clippy_lints/src/legacy_numeric_constants.rs
+++ b/clippy_lints/src/legacy_numeric_constants.rs
@@ -3,7 +3,7 @@ use clippy_config::Conf;
 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_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::{ExprKind, Item, ItemKind, QPath, UseKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -143,12 +143,11 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
             && !is_from_proc_macro(cx, expr)
         {
             span_lint_hir_and_then(cx, LEGACY_NUMERIC_CONSTANTS, expr.hir_id, span, msg, |diag| {
-                diag.span_suggestion_with_style(
+                diag.span_suggestion_verbose(
                     span,
                     "use the associated constant instead",
                     sugg,
                     Applicability::MaybeIncorrect,
-                    SuggestionStyle::ShowAlways,
                 );
             });
         }
diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs
index 4c737371bd238..0bc7fc2dd9d1e 100644
--- a/clippy_lints/src/len_zero.rs
+++ b/clippy_lints/src/len_zero.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::source::{snippet_opt, snippet_with_context};
+use clippy_utils::source::{snippet_with_context, SpanRangeExt};
 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;
@@ -216,7 +216,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
 }
 
 fn span_without_enclosing_paren(cx: &LateContext<'_>, span: Span) -> Span {
-    let Some(snippet) = snippet_opt(cx, span) else {
+    let Some(snippet) = span.get_source_text(cx) else {
         return span;
     };
     if has_enclosing_paren(snippet) {
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index ce13a9afef5b0..2ac06b360bea4 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -66,8 +66,8 @@ extern crate declare_clippy_lint;
 #[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))]
 mod utils;
 
-mod declared_lints;
-mod deprecated_lints;
+pub mod declared_lints;
+pub mod deprecated_lints;
 
 // begin lints modules, do not remove this comment, it’s used in `update_lints`
 mod absolute_paths;
@@ -440,7 +440,7 @@ impl RegistrationGroups {
     }
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 pub(crate) enum LintCategory {
     Cargo,
     Complexity,
@@ -479,11 +479,39 @@ impl LintCategory {
     }
 }
 
-pub(crate) struct LintInfo {
+pub struct LintInfo {
     /// Double reference to maintain pointer equality
-    lint: &'static &'static Lint,
+    pub lint: &'static &'static Lint,
     category: LintCategory,
-    explanation: &'static str,
+    pub explanation: &'static str,
+    /// e.g. `clippy_lints/src/absolute_paths.rs#43`
+    pub location: &'static str,
+    pub version: Option<&'static str>,
+}
+
+impl LintInfo {
+    /// Returns the lint name in lowercase without the `clippy::` prefix
+    #[allow(clippy::missing_panics_doc)]
+    pub fn name_lower(&self) -> String {
+        self.lint.name.strip_prefix("clippy::").unwrap().to_ascii_lowercase()
+    }
+
+    /// Returns the name of the lint's category in lowercase (`style`, `pedantic`)
+    pub fn category_str(&self) -> &'static str {
+        match self.category {
+            Cargo => "cargo",
+            Complexity => "complexity",
+            Correctness => "correctness",
+            Nursery => "nursery",
+            Pedantic => "pedantic",
+            Perf => "perf",
+            Restriction => "restriction",
+            Style => "style",
+            Suspicious => "suspicious",
+            #[cfg(feature = "internal")]
+            Internal => "internal",
+        }
+    }
 }
 
 pub fn explain(name: &str) -> i32 {
@@ -538,14 +566,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
         store.register_removed(name, reason);
     }
 
-    #[cfg(feature = "internal")]
-    {
-        if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) {
-            store.register_late_pass(|_| Box::new(utils::internal_lints::metadata_collector::MetadataCollector::new()));
-            return;
-        }
-    }
-
     let format_args_storage = FormatArgsStorage::default();
     let format_args = format_args_storage.clone();
     store.register_early_pass(move || {
diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs
index 259e4d6c08fb7..81f2a03fb55fb 100644
--- a/clippy_lints/src/literal_representation.rs
+++ b/clippy_lints/src/literal_representation.rs
@@ -1,10 +1,7 @@
-//! Lints concerned with the grouping of digits with underscores in integral or
-//! floating-point literal expressions.
-
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::numeric_literal::{NumericLiteral, Radix};
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use rustc_ast::ast::{Expr, ExprKind, LitKind};
 use rustc_ast::token;
 use rustc_errors::Applicability;
@@ -228,7 +225,7 @@ impl LiteralDigitGrouping {
     }
 
     fn check_lit(&self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
-        if let Some(src) = snippet_opt(cx, span)
+        if let Some(src) = span.get_source_text(cx)
             && let Ok(lit_kind) = LitKind::from_token_lit(lit)
             && let Some(mut num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind)
         {
@@ -442,7 +439,7 @@ impl DecimalLiteralRepresentation {
         // Lint integral literals.
         if let Ok(lit_kind) = LitKind::from_token_lit(lit)
             && let LitKind::Int(val, _) = lit_kind
-            && let Some(src) = snippet_opt(cx, span)
+            && let Some(src) = span.get_source_text(cx)
             && let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind)
             && num_lit.radix == Radix::Decimal
             && val >= u128::from(self.threshold)
diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs
index eea5f2a94ea60..b134af500f540 100644
--- a/clippy_lints/src/loops/explicit_iter_loop.rs
+++ b/clippy_lints/src/loops/explicit_iter_loop.rs
@@ -3,7 +3,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::{
-    implements_trait, implements_trait_with_env, is_copy, make_normalized_projection,
+    implements_trait, implements_trait_with_env, is_copy, is_type_lang_item, make_normalized_projection,
     make_normalized_projection_with_regions, normalize_with_regions,
 };
 use rustc_errors::Applicability;
@@ -20,9 +20,10 @@ pub(super) fn check(
     msrv: &Msrv,
     enforce_iter_loop_reborrow: bool,
 ) {
-    let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr, enforce_iter_loop_reborrow) else {
+    let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr, enforce_iter_loop_reborrow, msrv) else {
         return;
     };
+
     if let ty::Array(_, count) = *ty.peel_refs().kind() {
         if !ty.is_ref() {
             if !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) {
@@ -109,6 +110,7 @@ fn is_ref_iterable<'tcx>(
     self_arg: &Expr<'_>,
     call_expr: &Expr<'_>,
     enforce_iter_loop_reborrow: bool,
+    msrv: &Msrv,
 ) -> Option<(AdjustKind, Ty<'tcx>)> {
     let typeck = cx.typeck_results();
     if let Some(trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
@@ -128,6 +130,12 @@ fn is_ref_iterable<'tcx>(
         let self_ty = typeck.expr_ty(self_arg);
         let self_is_copy = is_copy(cx, self_ty);
 
+        if !msrv.meets(msrvs::BOX_INTO_ITER)
+            && is_type_lang_item(cx, self_ty.peel_refs(), rustc_hir::LangItem::OwnedBox)
+        {
+            return None;
+        }
+
         if adjustments.is_empty() && self_is_copy {
             // Exact type match, already checked earlier
             return Some((AdjustKind::None, self_ty));
diff --git a/clippy_lints/src/macro_metavars_in_unsafe.rs b/clippy_lints/src/macro_metavars_in_unsafe.rs
index fed58f7ff1481..e215097142be9 100644
--- a/clippy_lints/src/macro_metavars_in_unsafe.rs
+++ b/clippy_lints/src/macro_metavars_in_unsafe.rs
@@ -122,8 +122,23 @@ struct BodyVisitor<'a, 'tcx> {
     /// within a relevant macro.
     macro_unsafe_blocks: Vec<HirId>,
     /// When this is >0, it means that the node currently being visited is "within" a
-    /// macro definition. This is not necessary for correctness, it merely helps reduce the number
-    /// of spans we need to insert into the map, since only spans from macros are relevant.
+    /// macro definition.
+    /// This is used to detect if an expression represents a metavariable.
+    ///
+    /// For example, the following pre-expansion code that we want to lint
+    /// ```ignore
+    /// macro_rules! m { ($e:expr) => { unsafe { $e; } } }
+    /// m!(1);
+    /// ```
+    /// would look like this post-expansion code:
+    /// ```ignore
+    /// unsafe { /* macro */
+    ///     1 /* root */; /* macro */
+    /// }
+    /// ```
+    /// Visiting the block and the statement will increment the `expn_depth` so that it is >0,
+    /// and visiting the expression with a root context while `expn_depth > 0` tells us
+    /// that it must be a metavariable.
     expn_depth: u32,
     cx: &'a LateContext<'tcx>,
     lint: &'a mut ExprMetavarsInUnsafe,
@@ -157,7 +172,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BodyVisitor<'a, 'tcx> {
             && (self.lint.warn_unsafe_macro_metavars_in_private_macros || is_public_macro(self.cx, macro_def_id))
         {
             self.macro_unsafe_blocks.push(block.hir_id);
+            self.expn_depth += 1;
             walk_block(self, block);
+            self.expn_depth -= 1;
             self.macro_unsafe_blocks.pop();
         } else if ctxt.is_root() && self.expn_depth > 0 {
             let unsafe_block = self.macro_unsafe_blocks.last().copied();
diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs
index 25c7e5d38b319..61723aec59049 100644
--- a/clippy_lints/src/manual_async_fn.rs
+++ b/clippy_lints/src/manual_async_fn.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt};
+use clippy_utils::source::{position_before_rarrow, snippet_block, SpanRangeExt};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
@@ -68,8 +68,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
                 header_span,
                 "this function can be simplified using the `async fn` syntax",
                 |diag| {
-                    if let Some(vis_snip) = snippet_opt(cx, *vis_span)
-                        && let Some(header_snip) = snippet_opt(cx, header_span)
+                    if let Some(vis_snip) = vis_span.get_source_text(cx)
+                        && let Some(header_snip) = header_span.get_source_text(cx)
                         && let Some(ret_pos) = position_before_rarrow(&header_snip)
                         && let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output)
                     {
@@ -190,6 +190,6 @@ fn suggested_ret(cx: &LateContext<'_>, output: &Ty<'_>) -> Option<(&'static str,
         Some((sugg, String::new()))
     } else {
         let sugg = "return the output of the future directly";
-        snippet_opt(cx, output.span).map(|snip| (sugg, format!(" -> {snip}")))
+        output.span.get_source_text(cx).map(|src| (sugg, format!(" -> {src}")))
     }
 }
diff --git a/clippy_lints/src/manual_float_methods.rs b/clippy_lints/src/manual_float_methods.rs
index 6bdc79129a9bc..9d3ddab60bb3a 100644
--- a/clippy_lints/src/manual_float_methods.rs
+++ b/clippy_lints/src/manual_float_methods.rs
@@ -1,6 +1,6 @@
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::{is_from_proc_macro, path_to_local};
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Constness, Expr, ExprKind};
@@ -103,7 +103,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
             // case somebody does that for some reason
             && (is_infinity(&const_1) && is_neg_infinity(&const_2)
                 || is_neg_infinity(&const_1) && is_infinity(&const_2))
-            && let Some(local_snippet) = snippet_opt(cx, first.span)
+            && let Some(local_snippet) = first.span.get_source_text(cx)
         {
             let variant = match (kind.node, lhs_kind.node, rhs_kind.node) {
                 (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Eq) => Variant::ManualIsInfinite,
diff --git a/clippy_lints/src/manual_hash_one.rs b/clippy_lints/src/manual_hash_one.rs
index 1c568b1b74f32..11716a539ab5c 100644
--- a/clippy_lints/src/manual_hash_one.rs
+++ b/clippy_lints/src/manual_hash_one.rs
@@ -1,7 +1,7 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_hir_and_then;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::visitors::{is_local_used, local_used_once};
 use clippy_utils::{is_trait_method, path_to_local_id};
 use rustc_errors::Applicability;
@@ -107,8 +107,8 @@ impl LateLintPass<'_> for ManualHashOne {
                 finish_expr.span,
                 "manual implementation of `BuildHasher::hash_one`",
                 |diag| {
-                    if let Some(build_hasher) = snippet_opt(cx, build_hasher.span)
-                        && let Some(hashed_value) = snippet_opt(cx, hashed_value.span)
+                    if let Some(build_hasher) = build_hasher.span.get_source_text(cx)
+                        && let Some(hashed_value) = hashed_value.span.get_source_text(cx)
                     {
                         diag.multipart_suggestion(
                             "try",
diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs
index 28cfe22835af6..6b1d90483ccd1 100644
--- a/clippy_lints/src/manual_non_exhaustive.rs
+++ b/clippy_lints/src/manual_non_exhaustive.rs
@@ -2,7 +2,7 @@ use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
 use clippy_utils::is_doc_hidden;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use rustc_ast::ast::{self, VisibilityKind};
 use rustc_ast::attr;
 use rustc_data_structures::fx::FxHashSet;
@@ -124,7 +124,7 @@ impl EarlyLintPass for ManualNonExhaustiveStruct {
                     |diag| {
                         if !item.attrs.iter().any(|attr| attr.has_name(sym::non_exhaustive))
                             && let header_span = cx.sess().source_map().span_until_char(item.span, delimiter)
-                            && let Some(snippet) = snippet_opt(cx, header_span)
+                            && let Some(snippet) = header_span.get_source_text(cx)
                         {
                             diag.span_suggestion(
                                 header_span,
@@ -194,7 +194,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum {
                 "this seems like a manual implementation of the non-exhaustive pattern",
                 |diag| {
                     let header_span = cx.sess().source_map().span_until_char(enum_span, '{');
-                    if let Some(snippet) = snippet_opt(cx, header_span) {
+                    if let Some(snippet) = header_span.get_source_text(cx) {
                         diag.span_suggestion(
                             header_span,
                             "add the attribute",
diff --git a/clippy_lints/src/manual_range_patterns.rs b/clippy_lints/src/manual_range_patterns.rs
index 07d4abbf5cd11..9afb2b5bc84cd 100644
--- a/clippy_lints/src/manual_range_patterns.rs
+++ b/clippy_lints/src/manual_range_patterns.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use rustc_ast::LitKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
@@ -143,8 +143,8 @@ impl LateLintPass<'_> for ManualRangePatterns {
                 pat.span,
                 "this OR pattern can be rewritten using a range",
                 |diag| {
-                    if let Some(min) = snippet_opt(cx, min.span)
-                        && let Some(max) = snippet_opt(cx, max.span)
+                    if let Some(min) = min.span.get_source_text(cx)
+                        && let Some(max) = max.span.get_source_text(cx)
                     {
                         diag.span_suggestion(
                             pat.span,
diff --git a/clippy_lints/src/manual_retain.rs b/clippy_lints/src/manual_retain.rs
index 09f6362b4ddc8..d4e53f8f74bd6 100644
--- a/clippy_lints/src/manual_retain.rs
+++ b/clippy_lints/src/manual_retain.rs
@@ -2,14 +2,13 @@ use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
-use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
+use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item};
 use clippy_utils::{match_def_path, paths, SpanlessEq};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::ExprKind::Assign;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_semver::RustcVersion;
 use rustc_session::impl_lint_pass;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
@@ -21,16 +20,6 @@ const ACCEPTABLE_METHODS: [&[&str]; 5] = [
     &paths::SLICE_INTO,
     &paths::VEC_DEQUE_ITER,
 ];
-const ACCEPTABLE_TYPES: [(rustc_span::Symbol, Option<RustcVersion>); 7] = [
-    (sym::BinaryHeap, Some(msrvs::BINARY_HEAP_RETAIN)),
-    (sym::BTreeSet, Some(msrvs::BTREE_SET_RETAIN)),
-    (sym::BTreeMap, Some(msrvs::BTREE_MAP_RETAIN)),
-    (sym::HashSet, Some(msrvs::HASH_SET_RETAIN)),
-    (sym::HashMap, Some(msrvs::HASH_MAP_RETAIN)),
-    (sym::Vec, None),
-    (sym::VecDeque, None),
-];
-const MAP_TYPES: [rustc_span::Symbol; 2] = [sym::BTreeMap, sym::HashMap];
 
 declare_clippy_lint! {
     /// ### What it does
@@ -265,16 +254,22 @@ fn match_acceptable_def_path(cx: &LateContext<'_>, collect_def_id: DefId) -> boo
 }
 
 fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: &Msrv) -> bool {
-    let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs();
-    ACCEPTABLE_TYPES.iter().any(|(ty, acceptable_msrv)| {
-        is_type_diagnostic_item(cx, expr_ty, *ty)
-            && acceptable_msrv.map_or(true, |acceptable_msrv| msrv.meets(acceptable_msrv))
-    })
+    let ty = cx.typeck_results().expr_ty(expr).peel_refs();
+    let required = match get_type_diagnostic_name(cx, ty) {
+        Some(sym::BinaryHeap) => msrvs::BINARY_HEAP_RETAIN,
+        Some(sym::BTreeSet) => msrvs::BTREE_SET_RETAIN,
+        Some(sym::BTreeMap) => msrvs::BTREE_MAP_RETAIN,
+        Some(sym::HashSet) => msrvs::HASH_SET_RETAIN,
+        Some(sym::HashMap) => msrvs::HASH_MAP_RETAIN,
+        Some(sym::Vec | sym::VecDeque) => return true,
+        _ => return false,
+    };
+    msrv.meets(required)
 }
 
 fn match_map_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
-    let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs();
-    MAP_TYPES.iter().any(|ty| is_type_diagnostic_item(cx, expr_ty, *ty))
+    let ty = cx.typeck_results().expr_ty(expr).peel_refs();
+    matches!(get_type_diagnostic_name(cx, ty), Some(sym::BTreeMap | sym::HashMap))
 }
 
 fn make_span_lint_and_sugg(cx: &LateContext<'_>, span: Span, sugg: String) {
diff --git a/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs
index 90cfdecc19936..b666e77c09ecb 100644
--- a/clippy_lints/src/matches/collapsible_match.rs
+++ b/clippy_lints/src/matches/collapsible_match.rs
@@ -96,7 +96,7 @@ fn check_arm<'tcx>(
         // collapsing patterns need an explicit field name in struct pattern matching
         // ex: Struct {x: Some(1)}
         let replace_msg = if is_innermost_parent_pat_struct {
-            format!(", prefixed by {}:", snippet(cx, binding_span, "their field name"))
+            format!(", prefixed by `{}`:", snippet(cx, binding_span, "their field name"))
         } else {
             String::new()
         };
diff --git a/clippy_lints/src/matches/manual_unwrap_or.rs b/clippy_lints/src/matches/manual_unwrap_or.rs
index 2d4c8daf5cb66..d5d83df93471c 100644
--- a/clippy_lints/src/matches/manual_unwrap_or.rs
+++ b/clippy_lints/src/matches/manual_unwrap_or.rs
@@ -1,6 +1,6 @@
 use clippy_utils::consts::ConstEvalCtxt;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
+use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt};
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::usage::contains_return_break_continue_macro;
 use clippy_utils::{is_res_lang_ctor, path_to_local_id, peel_blocks, sugg};
@@ -67,11 +67,11 @@ fn check_and_lint<'tcx>(
         && path_to_local_id(peel_blocks(then_expr), binding_hir_id)
         && cx.typeck_results().expr_adjustments(then_expr).is_empty()
         && let Some(ty_name) = find_type_name(cx, ty)
-        && let Some(or_body_snippet) = snippet_opt(cx, else_expr.span)
+        && let Some(or_body_snippet) = else_expr.span.get_source_text(cx)
         && let Some(indent) = indent_of(cx, expr.span)
         && ConstEvalCtxt::new(cx).eval_simple(else_expr).is_some()
     {
-        lint(cx, expr, let_expr, ty_name, or_body_snippet, indent);
+        lint(cx, expr, let_expr, ty_name, &or_body_snippet, indent);
     }
 }
 
@@ -110,7 +110,7 @@ fn lint<'tcx>(
     expr: &Expr<'tcx>,
     scrutinee: &'tcx Expr<'_>,
     ty_name: &str,
-    or_body_snippet: String,
+    or_body_snippet: &str,
     indent: usize,
 ) {
     let reindented_or_body = reindent_multiline(or_body_snippet.into(), true, Some(indent));
diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs
index 24dea03601c5f..b6930f7b9d10f 100644
--- a/clippy_lints/src/matches/single_match.rs
+++ b/clippy_lints/src/matches/single_match.rs
@@ -22,7 +22,7 @@ use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE};
 /// span, e.g. a string literal `"//"`, but we know that this isn't the case for empty
 /// match arms.
 fn empty_arm_has_comment(cx: &LateContext<'_>, span: Span) -> bool {
-    if let Some(ff) = span.get_source_text(cx)
+    if let Some(ff) = span.get_source_range(cx)
         && let Some(text) = ff.as_str()
     {
         text.as_bytes().windows(2).any(|w| w == b"//" || w == b"/*")
diff --git a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
index a5df863d800bb..740cce0a6c235 100644
--- a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
+++ b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
+use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt};
 use clippy_utils::ty::is_type_lang_item;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
@@ -49,10 +49,12 @@ pub(super) fn check<'tcx>(
             "case-sensitive file extension comparison",
             |diag| {
                 diag.help("consider using a case-insensitive comparison instead");
-                if let Some(mut recv_source) = snippet_opt(cx, recv.span) {
-                    if !cx.typeck_results().expr_ty(recv).is_ref() {
-                        recv_source = format!("&{recv_source}");
-                    }
+                if let Some(recv_source) = recv.span.get_source_text(cx) {
+                    let recv_source = if cx.typeck_results().expr_ty(recv).is_ref() {
+                        recv_source.to_owned()
+                    } else {
+                        format!("&{recv_source}")
+                    };
 
                     let suggestion_source = reindent_multiline(
                         format!(
diff --git a/clippy_lints/src/methods/filter_map_bool_then.rs b/clippy_lints/src/methods/filter_map_bool_then.rs
index 2e43d19a69911..4fbf661727daa 100644
--- a/clippy_lints/src/methods/filter_map_bool_then.rs
+++ b/clippy_lints/src/methods/filter_map_bool_then.rs
@@ -1,7 +1,7 @@
 use super::FILTER_MAP_BOOL_THEN;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::paths::BOOL_THEN;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::is_copy;
 use clippy_utils::{is_from_proc_macro, is_trait_method, match_def_path, peel_blocks};
 use rustc_errors::Applicability;
@@ -42,9 +42,9 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &
             .iter()
             .filter(|adj| matches!(adj.kind, Adjust::Deref(_)))
             .count()
-        && let Some(param_snippet) = snippet_opt(cx, param.span)
-        && let Some(filter) = snippet_opt(cx, recv.span)
-        && let Some(map) = snippet_opt(cx, then_body.span)
+        && let Some(param_snippet) = param.span.get_source_text(cx)
+        && let Some(filter) = recv.span.get_source_text(cx)
+        && let Some(map) = then_body.span.get_source_text(cx)
     {
         span_lint_and_sugg(
             cx,
diff --git a/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/clippy_lints/src/methods/from_iter_instead_of_collect.rs
index 917a8e33eb9fb..f4840785584ef 100644
--- a/clippy_lints/src/methods/from_iter_instead_of_collect.rs
+++ b/clippy_lints/src/methods/from_iter_instead_of_collect.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::{is_path_diagnostic_item, sugg};
 use rustc_errors::Applicability;
@@ -39,7 +39,7 @@ fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'_>) ->
     }
 
     let call_site = expr.span.source_callsite();
-    if let Some(snippet) = snippet_opt(cx, call_site)
+    if let Some(snippet) = call_site.get_source_text(cx)
         && let snippet_split = snippet.split("::").collect::<Vec<_>>()
         && let Some((_, elements)) = snippet_split.split_last()
     {
diff --git a/clippy_lints/src/methods/get_unwrap.rs b/clippy_lints/src/methods/get_unwrap.rs
index c6285c87a2636..9daad1a8a949e 100644
--- a/clippy_lints/src/methods/get_unwrap.rs
+++ b/clippy_lints/src/methods/get_unwrap.rs
@@ -74,7 +74,7 @@ pub(super) fn check<'tcx>(
                 "&"
             };
 
-            diag.span_suggestion_with_style(
+            diag.span_suggestion_verbose(
                 span,
                 "using `[]` is clearer and more concise",
                 format!(
@@ -82,7 +82,6 @@ pub(super) fn check<'tcx>(
                     snippet_with_applicability(cx, recv.span, "..", &mut applicability)
                 ),
                 applicability,
-                rustc_errors::SuggestionStyle::ShowAlways,
             );
         },
     );
diff --git a/clippy_lints/src/methods/is_digit_ascii_radix.rs b/clippy_lints/src/methods/is_digit_ascii_radix.rs
index 22d896433f07a..40b48ccca5d5d 100644
--- a/clippy_lints/src/methods/is_digit_ascii_radix.rs
+++ b/clippy_lints/src/methods/is_digit_ascii_radix.rs
@@ -1,5 +1,3 @@
-//! Lint for `c.is_digit(10)`
-
 use super::IS_DIGIT_ASCII_RADIX;
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, FullInt};
diff --git a/clippy_lints/src/methods/join_absolute_paths.rs b/clippy_lints/src/methods/join_absolute_paths.rs
index aa1ec60d434a5..2dad7fcf3c129 100644
--- a/clippy_lints/src/methods/join_absolute_paths.rs
+++ b/clippy_lints/src/methods/join_absolute_paths.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::expr_or_init;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
@@ -25,7 +25,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, join_a
             join_arg.span,
             "argument to `Path::join` starts with a path separator",
             |diag| {
-                let arg_str = snippet_opt(cx, spanned.span).unwrap_or_else(|| "..".to_string());
+                let arg_str = snippet(cx, spanned.span, "..");
 
                 let no_separator = if sym_str.starts_with('/') {
                     arg_str.replacen('/', "", 1)
diff --git a/clippy_lints/src/methods/manual_ok_or.rs b/clippy_lints/src/methods/manual_ok_or.rs
index b1af0083e65a9..b1a8e1e5e4709 100644
--- a/clippy_lints/src/methods/manual_ok_or.rs
+++ b/clippy_lints/src/methods/manual_ok_or.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
+use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt};
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id};
 use rustc_errors::Applicability;
@@ -23,11 +23,11 @@ pub(super) fn check<'tcx>(
         && let ExprKind::Call(err_path, [err_arg]) = or_expr.kind
         && is_res_lang_ctor(cx, path_res(cx, err_path), ResultErr)
         && is_ok_wrapping(cx, map_expr)
-        && let Some(recv_snippet) = snippet_opt(cx, recv.span)
-        && let Some(err_arg_snippet) = snippet_opt(cx, err_arg.span)
+        && let Some(recv_snippet) = recv.span.get_source_text(cx)
+        && let Some(err_arg_snippet) = err_arg.span.get_source_text(cx)
         && let Some(indent) = indent_of(cx, expr.span)
     {
-        let reindented_err_arg_snippet = reindent_multiline(err_arg_snippet.into(), true, Some(indent + 4));
+        let reindented_err_arg_snippet = reindent_multiline(err_arg_snippet.as_str().into(), true, Some(indent + 4));
         span_lint_and_sugg(
             cx,
             MANUAL_OK_OR,
diff --git a/clippy_lints/src/methods/manual_try_fold.rs b/clippy_lints/src/methods/manual_try_fold.rs
index f93edded729fc..11fba35c16ea3 100644
--- a/clippy_lints/src/methods/manual_try_fold.rs
+++ b/clippy_lints/src/methods/manual_try_fold.rs
@@ -1,6 +1,6 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::{is_from_proc_macro, is_trait_method};
 use rustc_errors::Applicability;
@@ -31,13 +31,15 @@ pub(super) fn check<'tcx>(
         && let Res::Def(DefKind::Ctor(_, _), _) = cx.qpath_res(&qpath, path.hir_id)
         && let ExprKind::Closure(closure) = acc.kind
         && !is_from_proc_macro(cx, expr)
-        && let Some(args_snip) = closure.fn_arg_span.and_then(|fn_arg_span| snippet_opt(cx, fn_arg_span))
+        && let Some(args_snip) = closure
+            .fn_arg_span
+            .and_then(|fn_arg_span| fn_arg_span.get_source_text(cx))
     {
         let init_snip = rest
             .is_empty()
             .then_some(first.span)
-            .and_then(|span| snippet_opt(cx, span))
-            .unwrap_or("...".to_owned());
+            .and_then(|span| span.get_source_text(cx))
+            .map_or_else(|| "...".to_owned(), |src| src.to_owned());
 
         span_lint_and_sugg(
             cx,
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 1d7b10fe8f045..d7126990edb1d 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -2702,10 +2702,10 @@ declare_clippy_lint! {
     ///             }
     ///         })
     /// }
-    ///  ```
+    /// ```
     ///
-    ///  After:
-    ///  ```rust
+    /// After:
+    /// ```rust
     /// use std::{fmt, num::ParseIntError};
     ///
     /// #[derive(Debug)]
diff --git a/clippy_lints/src/methods/needless_character_iteration.rs b/clippy_lints/src/methods/needless_character_iteration.rs
index e3d7820771547..332da722a37dc 100644
--- a/clippy_lints/src/methods/needless_character_iteration.rs
+++ b/clippy_lints/src/methods/needless_character_iteration.rs
@@ -7,7 +7,7 @@ use rustc_span::Span;
 use super::utils::get_last_chain_binding_hir_id;
 use super::NEEDLESS_CHARACTER_ITERATION;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::{match_def_path, path_to_local_id, peel_blocks};
 
 fn peels_expr_ref<'a, 'tcx>(mut expr: &'a Expr<'tcx>) -> &'a Expr<'tcx> {
@@ -35,7 +35,7 @@ fn handle_expr(
                 && path_to_local_id(receiver, first_param)
                 && let char_arg_ty = cx.typeck_results().expr_ty_adjusted(receiver).peel_refs()
                 && *char_arg_ty.kind() == ty::Char
-                && let Some(snippet) = snippet_opt(cx, before_chars)
+                && let Some(snippet) = before_chars.get_source_text(cx)
             {
                 span_lint_and_sugg(
                     cx,
@@ -79,7 +79,7 @@ fn handle_expr(
                 && let Some(fn_def_id) = cx.qpath_res(&path, fn_path.hir_id).opt_def_id()
                 && match_def_path(cx, fn_def_id, &["core", "char", "methods", "<impl char>", "is_ascii"])
                 && path_to_local_id(peels_expr_ref(arg), first_param)
-                && let Some(snippet) = snippet_opt(cx, before_chars)
+                && let Some(snippet) = before_chars.get_source_text(cx)
             {
                 span_lint_and_sugg(
                     cx,
diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs
index 46b457daf7074..f61923e5bf569 100644
--- a/clippy_lints/src/methods/needless_collect.rs
+++ b/clippy_lints/src/methods/needless_collect.rs
@@ -2,7 +2,7 @@ use super::NEEDLESS_COLLECT;
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
-use clippy_utils::ty::{is_type_diagnostic_item, make_normalized_projection, make_projection};
+use clippy_utils::ty::{get_type_diagnostic_name, make_normalized_projection, make_projection};
 use clippy_utils::{
     can_move_expr_to_closure, fn_def_id, get_enclosing_block, higher, is_trait_method, path_to_local, path_to_local_id,
     CaptureKind,
@@ -88,9 +88,10 @@ pub(super) fn check<'tcx>(
         Node::LetStmt(l) => {
             if let PatKind::Binding(BindingMode::NONE | BindingMode::MUT, id, _, None) = l.pat.kind
                 && let ty = cx.typeck_results().expr_ty(collect_expr)
-                && [sym::Vec, sym::VecDeque, sym::BinaryHeap, sym::LinkedList]
-                    .into_iter()
-                    .any(|item| is_type_diagnostic_item(cx, ty, item))
+                && matches!(
+                    get_type_diagnostic_name(cx, ty),
+                    Some(sym::Vec | sym::VecDeque | sym::BinaryHeap | sym::LinkedList)
+                )
                 && let iter_ty = cx.typeck_results().expr_ty(iter_expr)
                 && let Some(block) = get_enclosing_block(cx, l.hir_id)
                 && let Some(iter_calls) = detect_iter_and_into_iters(block, id, cx, get_captured_ids(cx, iter_ty))
diff --git a/clippy_lints/src/methods/needless_option_as_deref.rs b/clippy_lints/src/methods/needless_option_as_deref.rs
index eaae8613d44d9..9f714fdd47bb3 100644
--- a/clippy_lints/src/methods/needless_option_as_deref.rs
+++ b/clippy_lints/src/methods/needless_option_as_deref.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::path_res;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::usage::local_used_after_expr;
 use rustc_errors::Applicability;
@@ -32,7 +32,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, name
             expr.span,
             "derefed type is same as origin",
             "try",
-            snippet_opt(cx, recv.span).unwrap(),
+            recv.span.get_source_text(cx).unwrap().to_owned(),
             Applicability::MachineApplicable,
         );
     }
diff --git a/clippy_lints/src/methods/string_lit_chars_any.rs b/clippy_lints/src/methods/string_lit_chars_any.rs
index 5f6f027a3b59e..cc0d432b799d6 100644
--- a/clippy_lints/src/methods/string_lit_chars_any.rs
+++ b/clippy_lints/src/methods/string_lit_chars_any.rs
@@ -1,6 +1,6 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::{is_from_proc_macro, is_trait_method, path_to_local};
 use itertools::Itertools;
 use rustc_ast::LitKind;
@@ -34,7 +34,7 @@ pub(super) fn check<'tcx>(
             _ => return,
         }
         && !is_from_proc_macro(cx, expr)
-        && let Some(scrutinee_snip) = snippet_opt(cx, scrutinee.span)
+        && let Some(scrutinee_snip) = scrutinee.span.get_source_text(cx)
     {
         // Normalize the char using `map` so `join` doesn't use `Display`, if we don't then
         // something like `r"\"` will become `'\'`, which is of course invalid
diff --git a/clippy_lints/src/methods/unnecessary_get_then_check.rs b/clippy_lints/src/methods/unnecessary_get_then_check.rs
index f6184222d8e96..64eb84117954c 100644
--- a/clippy_lints/src/methods/unnecessary_get_then_check.rs
+++ b/clippy_lints/src/methods/unnecessary_get_then_check.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::is_type_diagnostic_item;
 
 use rustc_errors::Applicability;
@@ -38,11 +38,11 @@ pub(super) fn check(
         return;
     };
     let both_calls_span = get_call_span.with_hi(call_span.hi());
-    if let Some(snippet) = snippet_opt(cx, both_calls_span)
-        && let Some(arg_snippet) = snippet_opt(cx, arg.span)
+    if let Some(snippet) = both_calls_span.get_source_text(cx)
+        && let Some(arg_snippet) = arg.span.get_source_text(cx)
     {
         let generics_snippet = if let Some(generics) = path.args
-            && let Some(generics_snippet) = snippet_opt(cx, generics.span_ext)
+            && let Some(generics_snippet) = generics.span_ext.get_source_text(cx)
         {
             format!("::{generics_snippet}")
         } else {
@@ -63,7 +63,7 @@ pub(super) fn check(
                 suggestion,
                 Applicability::MaybeIncorrect,
             );
-        } else if let Some(caller_snippet) = snippet_opt(cx, get_caller.span) {
+        } else if let Some(caller_snippet) = get_caller.span.get_source_text(cx) {
             let full_span = get_caller.span.with_hi(call_span.hi());
 
             span_lint_and_then(
diff --git a/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/clippy_lints/src/methods/unnecessary_iter_cloned.rs
index 70885e46e955e..4d18bc7ac7777 100644
--- a/clippy_lints/src/methods/unnecessary_iter_cloned.rs
+++ b/clippy_lints/src/methods/unnecessary_iter_cloned.rs
@@ -1,7 +1,7 @@
 use super::utils::clone_or_copy_needed;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::ForLoop;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::{get_iterator_item_ty, implements_trait};
 use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{can_mut_borrow_both, fn_def_id, get_parent_expr, path_to_local};
@@ -40,7 +40,7 @@ pub fn check_for_loop_iter(
         && let Some(ForLoop { pat, body, .. }) = ForLoop::hir(grandparent)
         && let (clone_or_copy_needed, references_to_binding) = clone_or_copy_needed(cx, pat, body)
         && !clone_or_copy_needed
-        && let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
+        && let Some(receiver_snippet) = receiver.span.get_source_text(cx)
     {
         // Issue 12098
         // https://github.com/rust-lang/rust-clippy/issues/12098
@@ -100,7 +100,7 @@ pub fn check_for_loop_iter(
             && implements_trait(cx, collection_ty, into_iterator_trait_id, &[])
             && let Some(into_iter_item_ty) = cx.get_associated_type(collection_ty, into_iterator_trait_id, "Item")
             && iter_item_ty == into_iter_item_ty
-            && let Some(collection_snippet) = snippet_opt(cx, collection.span)
+            && let Some(collection_snippet) = collection.span.get_source_text(cx)
         {
             collection_snippet
         } else {
@@ -122,7 +122,7 @@ pub fn check_for_loop_iter(
                 } else {
                     Applicability::MachineApplicable
                 };
-                diag.span_suggestion(expr.span, "use", snippet, applicability);
+                diag.span_suggestion(expr.span, "use", snippet.to_owned(), applicability);
                 if !references_to_binding.is_empty() {
                     diag.multipart_suggestion(
                         "remove any references to the binding",
diff --git a/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/clippy_lints/src/methods/unnecessary_lazy_eval.rs
index 4429f0326058a..b84594c0da19f 100644
--- a/clippy_lints/src/methods/unnecessary_lazy_eval.rs
+++ b/clippy_lints/src/methods/unnecessary_lazy_eval.rs
@@ -64,9 +64,9 @@ pub(super) fn check<'tcx>(
                 // but prefer to avoid changing the signature of the function itself.
                 if let hir::ExprKind::MethodCall(.., span) = expr.kind {
                     span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| {
-                        diag.span_suggestion(
+                        diag.span_suggestion_verbose(
                             span,
-                            format!("use `{simplify_using}(..)` instead"),
+                            format!("use `{simplify_using}` instead"),
                             format!("{simplify_using}({})", snippet(cx, body_expr.span, "..")),
                             applicability,
                         );
diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs
index fed2b128dcf30..69c5bc57e2996 100644
--- a/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -2,7 +2,7 @@ use super::implicit_clone::is_clone_like;
 use super::unnecessary_iter_cloned::{self, is_into_iter};
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::source::{snippet, snippet_opt};
+use clippy_utils::source::{snippet, SpanRangeExt};
 use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item};
 use clippy_utils::visitors::find_all_ret_expressions;
 use clippy_utils::{
@@ -133,7 +133,7 @@ fn check_addr_of_expr(
         && (*referent_ty != receiver_ty
             || (matches!(referent_ty.kind(), ty::Array(..)) && is_copy(cx, *referent_ty))
             || is_cow_into_owned(cx, method_name, method_def_id))
-        && let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
+        && let Some(receiver_snippet) = receiver.span.get_source_text(cx)
     {
         if receiver_ty == target_ty && n_target_refs >= n_receiver_refs {
             span_lint_and_sugg(
@@ -167,7 +167,7 @@ fn check_addr_of_expr(
                     parent.span,
                     format!("unnecessary use of `{method_name}`"),
                     "use",
-                    receiver_snippet,
+                    receiver_snippet.to_owned(),
                     Applicability::MachineApplicable,
                 );
             } else {
@@ -217,7 +217,7 @@ fn check_into_iter_call_arg(
         && let parent_ty = cx.typeck_results().expr_ty(parent)
         && implements_trait(cx, parent_ty, iterator_trait_id, &[])
         && let Some(item_ty) = get_iterator_item_ty(cx, parent_ty)
-        && let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
+        && let Some(receiver_snippet) = receiver.span.get_source_text(cx)
     {
         if unnecessary_iter_cloned::check_for_loop_iter(cx, parent, method_name, receiver, true) {
             return true;
@@ -309,8 +309,8 @@ fn check_split_call_arg(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symb
     if let Some(parent) = get_parent_expr(cx, expr)
         && let Some((fn_name, argument_expr)) = get_fn_name_and_arg(cx, parent)
         && fn_name.as_str() == "split"
-        && let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
-        && let Some(arg_snippet) = snippet_opt(cx, argument_expr.span)
+        && let Some(receiver_snippet) = receiver.span.get_source_text(cx)
+        && let Some(arg_snippet) = argument_expr.span.get_source_text(cx)
     {
         // We may end-up here because of an expression like `x.to_string().split(…)` where the type of `x`
         // implements `AsRef<str>` but does not implement `Deref<Target = str>`. In this case, we have to
@@ -405,7 +405,7 @@ fn check_other_call_arg<'tcx>(
             None
         }
         && can_change_type(cx, maybe_arg, receiver_ty)
-        && let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
+        && let Some(receiver_snippet) = receiver.span.get_source_text(cx)
     {
         span_lint_and_sugg(
             cx,
@@ -695,7 +695,7 @@ fn check_if_applicable_to_argument<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'tcx
         && let arg_ty = arg_ty.peel_refs()
         // For now we limit this lint to `String` and `Vec`.
         && (is_str_and_string(cx, arg_ty, original_arg_ty) || is_slice_and_vec(cx, arg_ty, original_arg_ty))
-        && let Some(snippet) = snippet_opt(cx, caller.span)
+        && let Some(snippet) = caller.span.get_source_text(cx)
     {
         span_lint_and_sugg(
             cx,
@@ -706,7 +706,7 @@ fn check_if_applicable_to_argument<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'tcx
             if original_arg_ty.is_array() {
                 format!("{snippet}.as_slice()")
             } else {
-                snippet
+                snippet.to_owned()
             },
             Applicability::MaybeIncorrect,
         );
diff --git a/clippy_lints/src/methods/unused_enumerate_index.rs b/clippy_lints/src/methods/unused_enumerate_index.rs
index 3004d9c4233a7..ee5177d1ffaa1 100644
--- a/clippy_lints/src/methods/unused_enumerate_index.rs
+++ b/clippy_lints/src/methods/unused_enumerate_index.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_hir_and_then;
-use clippy_utils::source::{snippet, snippet_opt};
+use clippy_utils::source::{snippet, SpanRangeExt};
 use clippy_utils::{expr_or_init, is_trait_method, pat_is_wild};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, FnDecl, PatKind, TyKind};
@@ -81,8 +81,14 @@ pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>,
         let new_closure_param = match find_elem_explicit_type_span(closure.fn_decl) {
             // We have an explicit type. Get its snippet, that of the binding name, and do `binding: ty`.
             // Fallback to `..` if we fail getting either snippet.
-            Some(ty_span) => snippet_opt(cx, elem.span)
-                .and_then(|binding_name| snippet_opt(cx, ty_span).map(|ty_name| format!("{binding_name}: {ty_name}")))
+            Some(ty_span) => elem
+                .span
+                .get_source_text(cx)
+                .and_then(|binding_name| {
+                    ty_span
+                        .get_source_text(cx)
+                        .map(|ty_name| format!("{binding_name}: {ty_name}"))
+                })
                 .unwrap_or_else(|| "..".to_string()),
             // Otherwise, we have no explicit type. We can replace with the binding name of the element.
             None => snippet(cx, elem.span, "..").into_owned(),
diff --git a/clippy_lints/src/min_ident_chars.rs b/clippy_lints/src/min_ident_chars.rs
index 53fa444e93c40..c83e5198c2748 100644
--- a/clippy_lints/src/min_ident_chars.rs
+++ b/clippy_lints/src/min_ident_chars.rs
@@ -41,14 +41,14 @@ declare_clippy_lint! {
 impl_lint_pass!(MinIdentChars => [MIN_IDENT_CHARS]);
 
 pub struct MinIdentChars {
-    allowed_idents_below_min_chars: &'static FxHashSet<String>,
+    allowed_idents_below_min_chars: FxHashSet<String>,
     min_ident_chars_threshold: u64,
 }
 
 impl MinIdentChars {
     pub fn new(conf: &'static Conf) -> Self {
         Self {
-            allowed_idents_below_min_chars: &conf.allowed_idents_below_min_chars,
+            allowed_idents_below_min_chars: conf.allowed_idents_below_min_chars.iter().cloned().collect(),
             min_ident_chars_threshold: conf.min_ident_chars_threshold,
         }
     }
diff --git a/clippy_lints/src/misc_early/unneeded_field_pattern.rs b/clippy_lints/src/misc_early/unneeded_field_pattern.rs
index 6db03adf44ac9..33ab94e00a5c6 100644
--- a/clippy_lints/src/misc_early/unneeded_field_pattern.rs
+++ b/clippy_lints/src/misc_early/unneeded_field_pattern.rs
@@ -1,5 +1,6 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
+use itertools::Itertools;
 use rustc_ast::ast::{Pat, PatKind};
 use rustc_lint::EarlyContext;
 
@@ -45,19 +46,6 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
                             "you matched a field with a wildcard pattern, consider using `..` instead",
                         );
                     } else {
-                        let mut normal = vec![];
-
-                        for field in pfields {
-                            match field.pat.kind {
-                                PatKind::Wild => {},
-                                _ => {
-                                    if let Some(n) = snippet_opt(cx, field.span) {
-                                        normal.push(n);
-                                    }
-                                },
-                            }
-                        }
-
                         #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
                         span_lint_and_then(
                             cx,
@@ -65,7 +53,16 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
                             field.span,
                             "you matched a field with a wildcard pattern, consider using `..` instead",
                             |diag| {
-                                diag.help(format!("try with `{type_name} {{ {}, .. }}`", normal[..].join(", ")));
+                                diag.help(format!(
+                                    "try with `{type_name} {{ {}, .. }}`",
+                                    pfields
+                                        .iter()
+                                        .filter_map(|f| match f.pat.kind {
+                                            PatKind::Wild => None,
+                                            _ => f.span.get_source_text(cx),
+                                        })
+                                        .format(", "),
+                                ));
                             },
                         );
                     }
diff --git a/clippy_lints/src/missing_enforced_import_rename.rs b/clippy_lints/src/missing_enforced_import_rename.rs
index cdf6645b3df77..59f29d242abf3 100644
--- a/clippy_lints/src/missing_enforced_import_rename.rs
+++ b/clippy_lints/src/missing_enforced_import_rename.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
 use clippy_utils::def_path_def_ids;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::DefIdMap;
@@ -73,7 +73,7 @@ impl LateLintPass<'_> for ImportRename {
                     && let Some(name) = self.renames.get(&id)
                     // Remove semicolon since it is not present for nested imports
                     && let span_without_semi = cx.sess().source_map().span_until_char(item.span, ';')
-                    && let Some(snip) = snippet_opt(cx, span_without_semi)
+                    && let Some(snip) = span_without_semi.get_source_text(cx)
                     && let Some(import) = match snip.split_once(" as ") {
                         None => Some(snip.as_str()),
                         Some((import, rename)) => {
diff --git a/clippy_lints/src/mut_key.rs b/clippy_lints/src/mut_key.rs
index 83af9979b9e36..f52b3a6a5a160 100644
--- a/clippy_lints/src/mut_key.rs
+++ b/clippy_lints/src/mut_key.rs
@@ -125,14 +125,12 @@ impl<'tcx> MutableKeyType<'tcx> {
     // generics (because the compiler cannot ensure immutability for unknown types).
     fn check_ty_(&mut self, cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) {
         let ty = ty.peel_refs();
-        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()));
-            if !is_keyed_type {
-                return;
-            }
-
+        if let ty::Adt(def, args) = ty.kind()
+            && matches!(
+                cx.tcx.get_diagnostic_name(def.did()),
+                Some(sym::HashMap | sym::BTreeMap | sym::HashSet | sym::BTreeSet)
+            )
+        {
             let subst_ty = args.type_at(0);
             if self.interior_mut.is_interior_mut_ty(cx, subst_ty) {
                 span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type");
diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs
index 853e476a006c6..3884149645883 100644
--- a/clippy_lints/src/mutex_atomic.rs
+++ b/clippy_lints/src/mutex_atomic.rs
@@ -1,7 +1,3 @@
-//! Checks for usage of mutex where an atomic value could be used
-//!
-//! This lint is **allow** by default
-
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_hir::Expr;
diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs
index 9cb4fa41c73f1..df155a7a41257 100644
--- a/clippy_lints/src/needless_bool.rs
+++ b/clippy_lints/src/needless_bool.rs
@@ -1,7 +1,3 @@
-//! Checks for needless boolean results of if-else expressions
-//!
-//! This lint is **warn** by default
-
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs
index b97cb4579ca7b..ce97370d4d9fa 100644
--- a/clippy_lints/src/needless_continue.rs
+++ b/clippy_lints/src/needless_continue.rs
@@ -1,38 +1,3 @@
-//! Checks for continue statements in loops that are redundant.
-//!
-//! For example, the lint would catch
-//!
-//! ```rust
-//! let mut a = 1;
-//! let x = true;
-//!
-//! while a < 5 {
-//!     a = 6;
-//!     if x {
-//!         // ...
-//!     } else {
-//!         continue;
-//!     }
-//!     println!("Hello, world");
-//! }
-//! ```
-//!
-//! And suggest something like this:
-//!
-//! ```rust
-//! let mut a = 1;
-//! let x = true;
-//!
-//! while a < 5 {
-//!     a = 6;
-//!     if x {
-//!         // ...
-//!         println!("Hello, world");
-//!     }
-//! }
-//! ```
-//!
-//! This lint is **warn** by default.
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::source::{indent_of, snippet, snippet_block};
 use rustc_ast::ast;
diff --git a/clippy_lints/src/needless_if.rs b/clippy_lints/src/needless_if.rs
index 1d6233d432a75..8e14fbf2f8061 100644
--- a/clippy_lints/src/needless_if.rs
+++ b/clippy_lints/src/needless_if.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::higher::If;
 use clippy_utils::is_from_proc_macro;
-use clippy_utils::source::{snippet_opt, SpanRangeExt};
+use clippy_utils::source::SpanRangeExt;
 use rustc_errors::Applicability;
 use rustc_hir::{ExprKind, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -57,7 +57,7 @@ impl LateLintPass<'_> for NeedlessIf {
                 src.bytes()
                     .all(|ch| matches!(ch, b'{' | b'}') || ch.is_ascii_whitespace())
             })
-            && let Some(cond_snippet) = snippet_opt(cx, cond.span)
+            && let Some(cond_snippet) = cond.span.get_source_text(cx)
             && !is_from_proc_macro(cx, expr)
         {
             span_lint_and_sugg(
diff --git a/clippy_lints/src/needless_late_init.rs b/clippy_lints/src/needless_late_init.rs
index 4bfc30fa5cf80..46cdb82130f97 100644
--- a/clippy_lints/src/needless_late_init.rs
+++ b/clippy_lints/src/needless_late_init.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::path_to_local;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::{SourceText, SpanRangeExt};
 use clippy_utils::ty::needs_ordered_drop;
 use clippy_utils::visitors::{for_each_expr, for_each_expr_without_closures, is_local_used};
 use core::ops::ControlFlow;
@@ -236,7 +236,7 @@ fn first_usage<'tcx>(
         })
 }
 
-fn local_snippet_without_semicolon(cx: &LateContext<'_>, local: &LetStmt<'_>) -> Option<String> {
+fn local_snippet_without_semicolon(cx: &LateContext<'_>, local: &LetStmt<'_>) -> Option<SourceText> {
     let span = local.span.with_hi(match local.ty {
         // let <pat>: <ty>;
         // ~~~~~~~~~~~~~~~
@@ -246,7 +246,7 @@ fn local_snippet_without_semicolon(cx: &LateContext<'_>, local: &LetStmt<'_>) ->
         None => local.pat.span.hi(),
     });
 
-    snippet_opt(cx, span)
+    span.get_source_text(cx)
 }
 
 fn check<'tcx>(
@@ -275,7 +275,10 @@ fn check<'tcx>(
                 |diag| {
                     diag.multipart_suggestion(
                         format!("move the declaration `{binding_name}` here"),
-                        vec![(local_stmt.span, String::new()), (assign.lhs_span, let_snippet)],
+                        vec![
+                            (local_stmt.span, String::new()),
+                            (assign.lhs_span, let_snippet.to_owned()),
+                        ],
                         Applicability::MachineApplicable,
                     );
                 },
diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs
index a0bbf6b14b217..addb4b1aee807 100644
--- a/clippy_lints/src/needless_pass_by_value.rs
+++ b/clippy_lints/src/needless_pass_by_value.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_self;
 use clippy_utils::ptr::get_spans;
-use clippy_utils::source::{snippet, snippet_opt};
+use clippy_utils::source::{snippet, SpanRangeExt};
 use clippy_utils::ty::{
     implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item,
 };
@@ -242,8 +242,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                         for (span, suggestion) in clone_spans {
                             diag.span_suggestion(
                                 span,
-                                snippet_opt(cx, span)
-                                    .map_or("change the call to".into(), |x| format!("change `{x}` to")),
+                                span.get_source_text(cx)
+                                    .map_or("change the call to".to_owned(), |src| format!("change `{src}` to")),
                                 suggestion,
                                 Applicability::Unspecified,
                             );
@@ -267,8 +267,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                             for (span, suggestion) in clone_spans {
                                 diag.span_suggestion(
                                     span,
-                                    snippet_opt(cx, span)
-                                        .map_or("change the call to".into(), |x| format!("change `{x}` to")),
+                                    span.get_source_text(cx)
+                                        .map_or("change the call to".to_owned(), |src| format!("change `{src}` to")),
                                     suggestion,
                                     Applicability::Unspecified,
                                 );
diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs
index 8232e69db3917..b181791699a5b 100644
--- a/clippy_lints/src/no_effect.rs
+++ b/clippy_lints/src/no_effect.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::has_drop;
 use clippy_utils::{
     in_automatically_derived, is_inside_always_const_context, is_lint_allowed, path_to_local, peel_blocks,
@@ -268,34 +268,31 @@ fn check_unnecessary_operation(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
         && reduced.iter().all(|e| e.span.ctxt() == ctxt)
     {
         if let ExprKind::Index(..) = &expr.kind {
-            if is_inside_always_const_context(cx.tcx, expr.hir_id) {
-                return;
+            if !is_inside_always_const_context(cx.tcx, expr.hir_id)
+                && let [arr, func] = &*reduced
+                && let Some(arr) = arr.span.get_source_text(cx)
+                && let Some(func) = func.span.get_source_text(cx)
+            {
+                span_lint_hir_and_then(
+                    cx,
+                    UNNECESSARY_OPERATION,
+                    expr.hir_id,
+                    stmt.span,
+                    "unnecessary operation",
+                    |diag| {
+                        diag.span_suggestion(
+                            stmt.span,
+                            "statement can be written as",
+                            format!("assert!({arr}.len() > {func});"),
+                            Applicability::MaybeIncorrect,
+                        );
+                    },
+                );
             }
-            let snippet =
-                if let (Some(arr), Some(func)) = (snippet_opt(cx, reduced[0].span), snippet_opt(cx, reduced[1].span)) {
-                    format!("assert!({arr}.len() > {func});")
-                } else {
-                    return;
-                };
-            span_lint_hir_and_then(
-                cx,
-                UNNECESSARY_OPERATION,
-                expr.hir_id,
-                stmt.span,
-                "unnecessary operation",
-                |diag| {
-                    diag.span_suggestion(
-                        stmt.span,
-                        "statement can be written as",
-                        snippet,
-                        Applicability::MaybeIncorrect,
-                    );
-                },
-            );
         } else {
             let mut snippet = String::new();
             for e in reduced {
-                if let Some(snip) = snippet_opt(cx, e.span) {
+                if let Some(snip) = e.span.get_source_text(cx) {
                     snippet.push_str(&snip);
                     snippet.push(';');
                 } else {
diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs
index 6915cd4061551..25f547f1a43c0 100644
--- a/clippy_lints/src/non_copy_const.rs
+++ b/clippy_lints/src/non_copy_const.rs
@@ -1,7 +1,3 @@
-//! Checks for usage of const which the type is not `Freeze` (`Cell`-free).
-//!
-//! This lint is **warn** by default.
-
 use std::ptr;
 
 use clippy_config::Conf;
@@ -188,7 +184,7 @@ impl_lint_pass!(NonCopyConst<'_> => [DECLARE_INTERIOR_MUTABLE_CONST, BORROW_INTE
 impl<'tcx> NonCopyConst<'tcx> {
     pub fn new(tcx: TyCtxt<'tcx>, conf: &'static Conf) -> Self {
         Self {
-            interior_mut: InteriorMut::new(tcx, &conf.ignore_interior_mutability),
+            interior_mut: InteriorMut::without_pointers(tcx, &conf.ignore_interior_mutability),
         }
     }
 
diff --git a/clippy_lints/src/nonstandard_macro_braces.rs b/clippy_lints/src/nonstandard_macro_braces.rs
index 2aaf1e6ff46da..51ba29d7389b9 100644
--- a/clippy_lints/src/nonstandard_macro_braces.rs
+++ b/clippy_lints/src/nonstandard_macro_braces.rs
@@ -1,7 +1,7 @@
 use clippy_config::types::MacroMatcher;
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::{SourceText, SpanRangeExt};
 use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
@@ -34,7 +34,7 @@ declare_clippy_lint! {
 }
 
 /// The (callsite span, (open brace, close brace), source snippet)
-type MacroInfo = (Span, (char, char), String);
+type MacroInfo = (Span, (char, char), SourceText);
 
 pub struct MacroBraces {
     macro_braces: FxHashMap<String, (char, char)>,
@@ -94,7 +94,7 @@ fn is_offending_macro(cx: &EarlyContext<'_>, span: Span, mac_braces: &MacroBrace
     if let ExpnKind::Macro(MacroKind::Bang, mac_name) = span.ctxt().outer_expn_data().kind
         && let name = mac_name.as_str()
         && let Some(&braces) = mac_braces.macro_braces.get(name)
-        && let Some(snip) = snippet_opt(cx, span_call_site)
+        && let Some(snip) = span_call_site.get_source_text(cx)
         // we must check only invocation sites
         // https://github.com/rust-lang/rust-clippy/issues/7422
         && snip.starts_with(&format!("{name}!"))
diff --git a/clippy_lints/src/operators/arithmetic_side_effects.rs b/clippy_lints/src/operators/arithmetic_side_effects.rs
index bc71a4790b9d4..8b9f899d82d3f 100644
--- a/clippy_lints/src/operators/arithmetic_side_effects.rs
+++ b/clippy_lints/src/operators/arithmetic_side_effects.rs
@@ -35,7 +35,7 @@ impl ArithmeticSideEffects {
             ("f64", FxHashSet::from_iter(["f64"])),
             ("std::string::String", FxHashSet::from_iter(["str"])),
         ]);
-        for [lhs, rhs] in &conf.arithmetic_side_effects_allowed_binary {
+        for (lhs, rhs) in &conf.arithmetic_side_effects_allowed_binary {
             allowed_binary.entry(lhs).or_default().insert(rhs);
         }
         for s in &conf.arithmetic_side_effects_allowed {
diff --git a/clippy_lints/src/operators/assign_op_pattern.rs b/clippy_lints/src/operators/assign_op_pattern.rs
index 641d881d974b8..11c97b4ef0073 100644
--- a/clippy_lints/src/operators/assign_op_pattern.rs
+++ b/clippy_lints/src/operators/assign_op_pattern.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{binop_traits, eq_expr_value, trait_ref_of_method};
@@ -46,8 +46,8 @@ pub(super) fn check<'tcx>(
                     expr.span,
                     "manual implementation of an assign operation",
                     |diag| {
-                        if let (Some(snip_a), Some(snip_r)) =
-                            (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span))
+                        if let Some(snip_a) = assignee.span.get_source_text(cx)
+                            && let Some(snip_r) = rhs.span.get_source_text(cx)
                         {
                             diag.span_suggestion(
                                 expr.span,
diff --git a/clippy_lints/src/operators/misrefactored_assign_op.rs b/clippy_lints/src/operators/misrefactored_assign_op.rs
index 311cbd050a10c..8daedd1c90140 100644
--- a/clippy_lints/src/operators/misrefactored_assign_op.rs
+++ b/clippy_lints/src/operators/misrefactored_assign_op.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::{eq_expr_value, sugg};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -42,7 +42,9 @@ fn lint_misrefactored_assign_op(
         expr.span,
         "variable appears on both sides of an assignment operation",
         |diag| {
-            if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) {
+            if let Some(snip_a) = assignee.span.get_source_text(cx)
+                && let Some(snip_r) = rhs_other.span.get_source_text(cx)
+            {
                 let a = &sugg::Sugg::hir(cx, assignee, "..");
                 let r = &sugg::Sugg::hir(cx, rhs, "..");
                 let long = format!("{snip_a} = {}", sugg::make_binop(op, a, r));
diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs
index 9baecff801f21..9e8a821c3f4e8 100644
--- a/clippy_lints/src/operators/mod.rs
+++ b/clippy_lints/src/operators/mod.rs
@@ -80,7 +80,7 @@ declare_clippy_lint! {
     /// ```no_run
     /// // `n` can be any number, including `i32::MAX`.
     /// fn foo(n: i32) -> i32 {
-    ///   n + 1
+    ///     n + 1
     /// }
     /// ```
     ///
diff --git a/clippy_lints/src/operators/needless_bitwise_bool.rs b/clippy_lints/src/operators/needless_bitwise_bool.rs
index ab5fb1787004e..9d8e833ef6d75 100644
--- a/clippy_lints/src/operators/needless_bitwise_bool.rs
+++ b/clippy_lints/src/operators/needless_bitwise_bool.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
@@ -24,8 +24,8 @@ pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, op: BinOpKind, lhs: &Exp
             e.span,
             "use of bitwise operator instead of lazy operator between booleans",
             |diag| {
-                if let Some(lhs_snip) = snippet_opt(cx, lhs.span)
-                    && let Some(rhs_snip) = snippet_opt(cx, rhs.span)
+                if let Some(lhs_snip) = lhs.span.get_source_text(cx)
+                    && let Some(rhs_snip) = rhs.span.get_source_text(cx)
                 {
                     let sugg = format!("{lhs_snip} {op_str} {rhs_snip}");
                     diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable);
diff --git a/clippy_lints/src/operators/ptr_eq.rs b/clippy_lints/src/operators/ptr_eq.rs
index 607930561e0fc..861564d54569e 100644
--- a/clippy_lints/src/operators/ptr_eq.rs
+++ b/clippy_lints/src/operators/ptr_eq.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::std_or_core;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
@@ -22,8 +22,8 @@ pub(super) fn check<'tcx>(
 
         if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left)
             && let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right)
-            && let Some(left_snip) = snippet_opt(cx, left_var.span)
-            && let Some(right_snip) = snippet_opt(cx, right_var.span)
+            && let Some(left_snip) = left_var.span.get_source_text(cx)
+            && let Some(right_snip) = right_var.span.get_source_text(cx)
         {
             let Some(top_crate) = std_or_core(cx) else { return };
             span_lint_and_sugg(
diff --git a/clippy_lints/src/pathbuf_init_then_push.rs b/clippy_lints/src/pathbuf_init_then_push.rs
index 18bfb588a1187..d7fa48c1e38dd 100644
--- a/clippy_lints/src/pathbuf_init_then_push.rs
+++ b/clippy_lints/src/pathbuf_init_then_push.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::path_to_local_id;
-use clippy_utils::source::{snippet, snippet_opt};
+use clippy_utils::source::{snippet, SpanRangeExt};
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_ast::{LitKind, StrStyle};
 use rustc_errors::Applicability;
@@ -74,7 +74,7 @@ impl<'tcx> PathbufPushSearcher<'tcx> {
             && let Some(arg) = self.arg
             && let ExprKind::Lit(x) = arg.kind
             && let LitKind::Str(_, StrStyle::Cooked) = x.node
-            && let Some(s) = snippet_opt(cx, arg.span)
+            && let Some(s) = arg.span.get_source_text(cx)
         {
             Some(format!(" = PathBuf::from({s});"))
         } else {
@@ -84,8 +84,8 @@ impl<'tcx> PathbufPushSearcher<'tcx> {
 
     fn gen_pathbuf_join(&self, cx: &LateContext<'_>) -> Option<String> {
         let arg = self.arg?;
-        let arg_str = snippet_opt(cx, arg.span)?;
-        let init_val = snippet_opt(cx, self.init_val.span)?;
+        let arg_str = arg.span.get_source_text(cx)?;
+        let init_val = self.init_val.span.get_source_text(cx)?;
         Some(format!(" = {init_val}.join({arg_str});"))
     }
 
diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs
index 02c05e0aaf9ce..125f694996c1c 100644
--- a/clippy_lints/src/ptr.rs
+++ b/clippy_lints/src/ptr.rs
@@ -1,7 +1,5 @@
-//! Checks for usage of  `&Vec[_]` and `&String`.
-
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then};
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::expr_sig;
 use clippy_utils::visitors::contains_unsafe_block;
 use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local};
@@ -243,7 +241,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
                         .chain(result.replacements.iter().map(|r| {
                             (
                                 r.expr_span,
-                                format!("{}{}", snippet_opt(cx, r.self_span).unwrap(), r.replacement),
+                                format!("{}{}", r.self_span.get_source_text(cx).unwrap(), r.replacement),
                             )
                         }))
                         .collect(),
@@ -372,7 +370,7 @@ impl fmt::Display for DerefTyDisplay<'_, '_> {
             DerefTy::Path => f.write_str("Path"),
             DerefTy::Slice(hir_ty, ty) => {
                 f.write_char('[')?;
-                match hir_ty.and_then(|s| snippet_opt(self.0, s)) {
+                match hir_ty.and_then(|s| s.get_source_text(self.0)) {
                     Some(s) => f.write_str(&s)?,
                     None => ty.fmt(f)?,
                 }
@@ -413,6 +411,7 @@ impl<'tcx> DerefTy<'tcx> {
     }
 }
 
+#[expect(clippy::too_many_lines)]
 fn check_fn_args<'cx, 'tcx: 'cx>(
     cx: &'cx LateContext<'tcx>,
     fn_sig: ty::FnSig<'tcx>,
@@ -488,8 +487,6 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
                                 return None;
                             }
 
-                            let ty_name = snippet_opt(cx, ty.span()).unwrap_or_else(|| args.type_at(1).to_string());
-
                             span_lint_hir_and_then(
                                 cx,
                                 PTR_ARG,
@@ -500,7 +497,10 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
                                     diag.span_suggestion(
                                         hir_ty.span,
                                         "change this to",
-                                        format!("&{}{ty_name}", mutability.prefix_str()),
+                                        match ty.span().get_source_text(cx) {
+                                            Some(s) => format!("&{}{s}", mutability.prefix_str()),
+                                            None => format!("&{}{}", mutability.prefix_str(), args.type_at(1)),
+                                        },
                                         Applicability::Unspecified,
                                     );
                                 },
diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs
index 7c82895d60919..87a52cb2186c5 100644
--- a/clippy_lints/src/ptr_offset_with_cast.rs
+++ b/clippy_lints/src/ptr_offset_with_cast.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -120,8 +120,8 @@ fn build_suggestion(
     receiver_expr: &Expr<'_>,
     cast_lhs_expr: &Expr<'_>,
 ) -> Option<String> {
-    let receiver = snippet_opt(cx, receiver_expr.span)?;
-    let cast_lhs = snippet_opt(cx, cast_lhs_expr.span)?;
+    let receiver = receiver_expr.span.get_source_text(cx)?;
+    let cast_lhs = cast_lhs_expr.span.get_source_text(cx)?;
     Some(format!("{receiver}.{}({cast_lhs})", method.suggestion()))
 }
 
diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs
index a1231c082e68a..bfdc1cbeed7e1 100644
--- a/clippy_lints/src/redundant_clone.rs
+++ b/clippy_lints/src/redundant_clone.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
 use clippy_utils::mir::{visit_local_usage, LocalUsage, PossibleBorrowerMap};
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, is_type_lang_item, walk_ptrs_ty_depth};
 use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths};
 use rustc_errors::Applicability;
@@ -208,7 +208,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
                 .assert_crate_local()
                 .lint_root;
 
-            if let Some(snip) = snippet_opt(cx, span)
+            if let Some(snip) = span.get_source_text(cx)
                 && let Some(dot) = snip.rfind('.')
             {
                 let sugg_span = span.with_lo(span.lo() + BytePos(u32::try_from(dot).unwrap()));
diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs
index 8f32cf5f2a1db..2b4ef21fc48e1 100644
--- a/clippy_lints/src/reference.rs
+++ b/clippy_lints/src/reference.rs
@@ -1,10 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{snippet_opt, snippet_with_applicability};
+use clippy_utils::source::{snippet_with_applicability, SpanRangeExt};
 use rustc_ast::ast::{Expr, ExprKind, Mutability, UnOp};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::BytePos;
+use rustc_span::{BytePos, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -56,11 +56,11 @@ impl EarlyLintPass for DerefAddrOf {
         {
             let mut applicability = Applicability::MachineApplicable;
             let sugg = if e.span.from_expansion() {
-                if let Some(macro_source) = snippet_opt(cx, e.span) {
+                if let Some(macro_source) = e.span.get_source_text(cx) {
                     // Remove leading whitespace from the given span
                     // e.g: ` $visitor` turns into `$visitor`
-                    let trim_leading_whitespaces = |span| {
-                        snippet_opt(cx, span)
+                    let trim_leading_whitespaces = |span: Span| {
+                        span.get_source_text(cx)
                             .and_then(|snip| {
                                 #[expect(clippy::cast_possible_truncation)]
                                 snip.find(|c: char| !c.is_whitespace())
diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs
index 95014b230431c..f6ef02b7c2330 100644
--- a/clippy_lints/src/regex.rs
+++ b/clippy_lints/src/regex.rs
@@ -2,7 +2,7 @@ use std::fmt::Display;
 
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::{def_path_def_ids, path_def_id, paths};
 use rustc_ast::ast::{LitKind, StrStyle};
 use rustc_hir::def_id::DefIdMap;
@@ -122,7 +122,7 @@ fn lint_syntax_error(cx: &LateContext<'_>, error: &regex_syntax::Error, unescape
     };
 
     if let Some((primary, auxiliary, kind)) = parts
-        && let Some(literal_snippet) = snippet_opt(cx, base)
+        && let Some(literal_snippet) = base.get_source_text(cx)
         && let Some(inner) = literal_snippet.get(offset as usize..)
         // Only convert to native rustc spans if the parsed regex matches the
         // source snippet exactly, to ensure the span offsets are correct
diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs
index 13016cdadb072..5ce091b7a7a30 100644
--- a/clippy_lints/src/returns.rs
+++ b/clippy_lints/src/returns.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
-use clippy_utils::source::{snippet_opt, snippet_with_context};
+use clippy_utils::source::{snippet_with_context, SpanRangeExt};
 use clippy_utils::sugg::has_enclosing_paren;
 use clippy_utils::visitors::{for_each_expr, Descend};
 use clippy_utils::{
@@ -250,20 +250,25 @@ impl<'tcx> LateLintPass<'tcx> for Return {
                 |err| {
                     err.span_label(local.span, "unnecessary `let` binding");
 
-                    if let Some(mut snippet) = snippet_opt(cx, initexpr.span) {
-                        if binary_expr_needs_parentheses(initexpr) {
-                            if !has_enclosing_paren(&snippet) {
-                                snippet = format!("({snippet})");
+                    if let Some(src) = initexpr.span.get_source_text(cx) {
+                        let sugg = if binary_expr_needs_parentheses(initexpr) {
+                            if has_enclosing_paren(&src) {
+                                src.to_owned()
+                            } else {
+                                format!("({src})")
                             }
                         } else if !cx.typeck_results().expr_adjustments(retexpr).is_empty() {
-                            if !has_enclosing_paren(&snippet) {
-                                snippet = format!("({snippet})");
+                            if has_enclosing_paren(&src) {
+                                format!("{src} as _")
+                            } else {
+                                format!("({src}) as _")
                             }
-                            snippet.push_str(" as _");
-                        }
+                        } else {
+                            src.to_owned()
+                        };
                         err.multipart_suggestion(
                             "return the expression directly",
-                            vec![(local.span, String::new()), (retexpr.span, snippet)],
+                            vec![(local.span, String::new()), (retexpr.span, sugg)],
                             Applicability::MachineApplicable,
                         );
                     } else {
@@ -394,7 +399,7 @@ fn check_final_expr<'tcx>(
 
             // Returns may be used to turn an expression into a statement in rustc's AST.
             // This allows the addition of attributes, like `#[allow]` (See: clippy#9361)
-            // `#[expect(clippy::needless_return)]` needs to be handled separatly to
+            // `#[expect(clippy::needless_return)]` needs to be handled separately to
             // actually fulfill the expectation (clippy::#12998)
             match cx.tcx.hir().attrs(expr.hir_id) {
                 [] => {},
diff --git a/clippy_lints/src/single_range_in_vec_init.rs b/clippy_lints/src/single_range_in_vec_init.rs
index e05584296381c..44e585953bfb9 100644
--- a/clippy_lints/src/single_range_in_vec_init.rs
+++ b/clippy_lints/src/single_range_in_vec_init.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::get_trait_def_id;
 use clippy_utils::higher::VecArgs;
 use clippy_utils::macros::root_macro_call_first_node;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::implements_trait;
 use rustc_ast::{LitIntType, LitKind, UintTy};
 use rustc_errors::Applicability;
@@ -92,12 +92,12 @@ impl LateLintPass<'_> for SingleRangeInVecInit {
 
         if matches!(lang_item, LangItem::Range)
             && let ty = cx.typeck_results().expr_ty(start.expr)
-            && let Some(snippet) = snippet_opt(cx, span)
+            && let Some(snippet) = span.get_source_text(cx)
             // `is_from_proc_macro` will skip any `vec![]`. Let's not!
             && snippet.starts_with(suggested_type.starts_with())
             && snippet.ends_with(suggested_type.ends_with())
-            && let Some(start_snippet) = snippet_opt(cx, start.span)
-            && let Some(end_snippet) = snippet_opt(cx, end.span)
+            && let Some(start_snippet) = start.span.get_source_text(cx)
+            && let Some(end_snippet) = end.span.get_source_text(cx)
         {
             let should_emit_every_value = if let Some(step_def_id) = get_trait_def_id(cx.tcx, &["core", "iter", "Step"])
                 && implements_trait(cx, ty, step_def_id, &[])
diff --git a/clippy_lints/src/size_of_in_element_count.rs b/clippy_lints/src/size_of_in_element_count.rs
index 01f0e3cfadbd4..7750d8909d362 100644
--- a/clippy_lints/src/size_of_in_element_count.rs
+++ b/clippy_lints/src/size_of_in_element_count.rs
@@ -1,6 +1,3 @@
-//! Lint on use of `size_of` or `size_of_val` of T in an expression
-//! expecting a count of T
-
 use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs
index 974e21df817a8..44283a49e84b9 100644
--- a/clippy_lints/src/std_instead_of_core.rs
+++ b/clippy_lints/src/std_instead_of_core.rs
@@ -9,7 +9,6 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::{HirId, Path, PathSegment};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_semver::RustcVersion;
 use rustc_session::impl_lint_pass;
 use rustc_span::symbol::kw;
 use rustc_span::{sym, Span};
@@ -185,9 +184,7 @@ fn is_stable(cx: &LateContext<'_>, mut def_id: DefId, msrv: &Msrv) -> bool {
             } = stability.level
         {
             let stable = match since {
-                StableSince::Version(v) => {
-                    msrv.meets(RustcVersion::new(v.major.into(), v.minor.into(), v.patch.into()))
-                },
+                StableSince::Version(v) => msrv.meets(v),
                 StableSince::Current => msrv.current().is_none(),
                 StableSince::Err => false,
             };
diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs
index cfc387886dc01..6ca4ca000e9b4 100644
--- a/clippy_lints/src/strings.rs
+++ b/clippy_lints/src/strings.rs
@@ -190,7 +190,7 @@ impl<'tcx> LateLintPass<'tcx> for StringAdd {
                 }
             },
             ExprKind::Index(target, _idx, _) => {
-                let e_ty = cx.typeck_results().expr_ty(target).peel_refs();
+                let e_ty = cx.typeck_results().expr_ty_adjusted(target).peel_refs();
                 if e_ty.is_str() || is_type_lang_item(cx, e_ty, LangItem::String) {
                     span_lint(
                         cx,
diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs
index 59b74122f3084..2e87d36df3121 100644
--- a/clippy_lints/src/trait_bounds.rs
+++ b/clippy_lints/src/trait_bounds.rs
@@ -1,7 +1,7 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
-use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
+use clippy_utils::source::{snippet, snippet_with_applicability, SpanRangeExt};
 use clippy_utils::{is_from_proc_macro, SpanlessEq, SpanlessHash};
 use core::hash::{Hash, Hasher};
 use itertools::Itertools;
@@ -206,8 +206,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
 
                 let fixed_trait_snippet = unique_traits
                     .iter()
-                    .filter_map(|b| snippet_opt(cx, b.span))
-                    .collect::<Vec<_>>()
+                    .filter_map(|b| b.span.get_source_text(cx))
                     .join(" + ");
 
                 span_lint_and_sugg(
@@ -462,9 +461,8 @@ fn rollup_traits(
 
         let traits = comparable_bounds
             .iter()
-            .filter_map(|&(_, span)| snippet_opt(cx, span))
-            .collect::<Vec<_>>();
-        let traits = traits.join(" + ");
+            .filter_map(|&(_, span)| span.get_source_text(cx))
+            .join(" + ");
 
         span_lint_and_sugg(
             cx,
diff --git a/clippy_lints/src/unit_types/unit_arg.rs b/clippy_lints/src/unit_types/unit_arg.rs
index afc53e6f32d96..978d49f09c3a8 100644
--- a/clippy_lints/src/unit_types/unit_arg.rs
+++ b/clippy_lints/src/unit_types/unit_arg.rs
@@ -1,6 +1,6 @@
 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 clippy_utils::source::{indent_of, reindent_multiline, SourceText, SpanRangeExt};
 use rustc_errors::Applicability;
 use rustc_hir::{Block, Expr, ExprKind, MatchSource, Node, StmtKind};
 use rustc_lint::LateContext;
@@ -79,7 +79,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
                         && block.expr.is_none()
                         && let Some(last_stmt) = block.stmts.iter().last()
                         && let StmtKind::Semi(last_expr) = last_stmt.kind
-                        && let Some(snip) = snippet_opt(cx, last_expr.span)
+                        && let Some(snip) = last_expr.span.get_source_text(cx)
                     {
                         Some((last_stmt.span, snip))
                     } else {
@@ -90,24 +90,24 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
                     db.span_suggestion(
                         span,
                         "remove the semicolon from the last statement in the block",
-                        sugg,
+                        sugg.as_str(),
                         Applicability::MaybeIncorrect,
                     );
                     or = "or ";
                     applicability = Applicability::MaybeIncorrect;
                 });
 
-            let arg_snippets: Vec<String> = args_to_recover
+            let arg_snippets: Vec<_> = args_to_recover
                 .iter()
-                .filter_map(|arg| snippet_opt(cx, arg.span))
+                .filter_map(|arg| arg.span.get_source_text(cx))
                 .collect();
-            let arg_snippets_without_empty_blocks: Vec<String> = args_to_recover
+            let arg_snippets_without_empty_blocks: Vec<_> = args_to_recover
                 .iter()
                 .filter(|arg| !is_empty_block(arg))
-                .filter_map(|arg| snippet_opt(cx, arg.span))
+                .filter_map(|arg| arg.span.get_source_text(cx))
                 .collect();
 
-            if let Some(call_snippet) = snippet_opt(cx, expr.span) {
+            if let Some(call_snippet) = expr.span.get_source_text(cx) {
                 let sugg = fmt_stmts_and_call(
                     cx,
                     expr,
@@ -161,8 +161,8 @@ fn fmt_stmts_and_call(
     cx: &LateContext<'_>,
     call_expr: &Expr<'_>,
     call_snippet: &str,
-    args_snippets: &[impl AsRef<str>],
-    non_empty_block_args_snippets: &[impl AsRef<str>],
+    args_snippets: &[SourceText],
+    non_empty_block_args_snippets: &[SourceText],
 ) -> String {
     let call_expr_indent = indent_of(cx, call_expr.span).unwrap_or(0);
     let call_snippet_with_replacements = args_snippets
diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs
index 448946bd66d51..cfc4ea46bdb2b 100644
--- a/clippy_lints/src/unused_io_amount.rs
+++ b/clippy_lints/src/unused_io_amount.rs
@@ -34,11 +34,18 @@ declare_clippy_lint! {
     /// ```rust,ignore
     /// use std::io;
     /// fn foo<W: io::Write>(w: &mut W) -> io::Result<()> {
-    ///     // must be `w.write_all(b"foo")?;`
     ///     w.write(b"foo")?;
     ///     Ok(())
     /// }
     /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// use std::io;
+    /// fn foo<W: io::Write>(w: &mut W) -> io::Result<()> {
+    ///     w.write_all(b"foo")?;
+    ///     Ok(())
+    /// }
+    /// ```
     #[clippy::version = "pre 1.29.0"]
     pub UNUSED_IO_AMOUNT,
     correctness,
diff --git a/clippy_lints/src/unused_unit.rs b/clippy_lints/src/unused_unit.rs
index b70aa768b46b1..65f431d338bdb 100644
--- a/clippy_lints/src/unused_unit.rs
+++ b/clippy_lints/src/unused_unit.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{position_before_rarrow, snippet_opt};
+use clippy_utils::source::{position_before_rarrow, SpanRangeExt};
 use rustc_ast::visit::FnKind;
 use rustc_ast::{ast, ClosureBinder};
 use rustc_errors::Applicability;
@@ -128,15 +128,17 @@ fn is_unit_expr(expr: &ast::Expr) -> bool {
 
 fn lint_unneeded_unit_return(cx: &EarlyContext<'_>, ty: &ast::Ty, span: Span) {
     let (ret_span, appl) =
-        snippet_opt(cx, span.with_hi(ty.span.hi())).map_or((ty.span, Applicability::MaybeIncorrect), |fn_source| {
-            position_before_rarrow(&fn_source).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| {
-                (
-                    #[expect(clippy::cast_possible_truncation)]
-                    ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)),
-                    Applicability::MachineApplicable,
-                )
-            })
-        });
+        span.with_hi(ty.span.hi())
+            .get_source_text(cx)
+            .map_or((ty.span, Applicability::MaybeIncorrect), |src| {
+                position_before_rarrow(&src).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| {
+                    (
+                        #[expect(clippy::cast_possible_truncation)]
+                        ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)),
+                        Applicability::MachineApplicable,
+                    )
+                })
+            });
     span_lint_and_sugg(
         cx,
         UNUSED_UNIT,
diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs
index c0d9bcdd259c7..0b4ea0752b6ba 100644
--- a/clippy_lints/src/unwrap.rs
+++ b/clippy_lints/src/unwrap.rs
@@ -89,15 +89,15 @@ enum UnwrappableKind {
 impl UnwrappableKind {
     fn success_variant_pattern(self) -> &'static str {
         match self {
-            UnwrappableKind::Option => "Some(..)",
-            UnwrappableKind::Result => "Ok(..)",
+            UnwrappableKind::Option => "Some(<item>)",
+            UnwrappableKind::Result => "Ok(<item>)",
         }
     }
 
     fn error_variant_pattern(self) -> &'static str {
         match self {
             UnwrappableKind::Option => "None",
-            UnwrappableKind::Result => "Err(..)",
+            UnwrappableKind::Result => "Err(<item>)",
         }
     }
 }
diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs
index 93785b45c27d4..5da48f4f7fbd7 100644
--- a/clippy_lints/src/use_self.rs
+++ b/clippy_lints/src/use_self.rs
@@ -229,7 +229,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
             && let impl_ty = cx.tcx.type_of(impl_id).instantiate_identity()
             && same_type_and_consts(ty, impl_ty)
             // Ensure the type we encounter and the one from the impl have the same lifetime parameters. It may be that
-            // the lifetime parameters of `ty` are ellided (`impl<'a> Foo<'a> { fn new() -> Self { Foo{..} } }`, in
+            // the lifetime parameters of `ty` are elided (`impl<'a> Foo<'a> { fn new() -> Self { Foo{..} } }`, in
             // which case we must still trigger the lint.
             && (has_no_lifetime(ty) || same_lifetimes(ty, impl_ty))
         {
diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs
index 316c1f32d3a2a..0cce45290cfe7 100644
--- a/clippy_lints/src/utils/author.rs
+++ b/clippy_lints/src/utils/author.rs
@@ -1,6 +1,3 @@
-//! A group of attributes that can be attached to Rust code in order
-//! to generate a clippy lint detecting said code automatically.
-
 use clippy_utils::{get_attr, higher};
 use rustc_ast::ast::{LitFloatType, LitKind};
 use rustc_ast::LitIntType;
diff --git a/clippy_lints/src/utils/format_args_collector.rs b/clippy_lints/src/utils/format_args_collector.rs
index 5acfd35fd6ae6..f50ce6c99deac 100644
--- a/clippy_lints/src/utils/format_args_collector.rs
+++ b/clippy_lints/src/utils/format_args_collector.rs
@@ -1,5 +1,5 @@
 use clippy_utils::macros::FormatArgsStorage;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use itertools::Itertools;
 use rustc_ast::{Crate, Expr, ExprKind, FormatArgs};
 use rustc_data_structures::fx::FxHashMap;
@@ -75,38 +75,21 @@ fn has_span_from_proc_macro(cx: &EarlyContext<'_>, args: &FormatArgs) -> bool {
 
     // `format!("{} {} {c}", "one", "two", c = "three")`
     //                     ^^     ^^     ^^^^^^
-    let between_spans = once(args.span)
+    !once(args.span)
         .chain(argument_span)
         .tuple_windows()
-        .map(|(start, end)| start.between(end));
-
-    for between_span in between_spans {
-        let mut seen_comma = false;
-
-        let Some(snippet) = snippet_opt(cx, between_span) else {
-            return true;
-        };
-        for token in tokenize(&snippet) {
-            match token.kind {
-                TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace => {},
-                TokenKind::Comma if !seen_comma => seen_comma = true,
-                // named arguments, `start_val, name = end_val`
-                //                            ^^^^^^^^^ between_span
-                TokenKind::Ident | TokenKind::Eq if seen_comma => {},
-                // An unexpected token usually indicates that we crossed a macro boundary
-                //
-                // `println!(some_proc_macro!("input {}"), a)`
-                //                                      ^^^ between_span
-                // `println!("{}", val!(x))`
-                //               ^^^^^^^ between_span
-                _ => return true,
-            }
-        }
-
-        if !seen_comma {
-            return true;
-        }
-    }
-
-    false
+        .map(|(start, end)| start.between(end))
+        .all(|sp| {
+            sp.check_source_text(cx, |src| {
+                // text should be either `, name` or `, name =`
+                let mut iter = tokenize(src).filter(|t| {
+                    !matches!(
+                        t.kind,
+                        TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace
+                    )
+                });
+                iter.next().is_some_and(|t| matches!(t.kind, TokenKind::Comma))
+                    && iter.all(|t| matches!(t.kind, TokenKind::Ident | TokenKind::Eq))
+            })
+        })
 }
diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs
index 1d294c2944b2c..f662c7651f6bb 100644
--- a/clippy_lints/src/utils/internal_lints.rs
+++ b/clippy_lints/src/utils/internal_lints.rs
@@ -3,7 +3,6 @@ pub mod collapsible_calls;
 pub mod interning_defined_symbol;
 pub mod invalid_paths;
 pub mod lint_without_lint_pass;
-pub mod metadata_collector;
 pub mod msrv_attr_impl;
 pub mod outer_expn_data_pass;
 pub mod produce_ice;
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 df342e48d637f..20526113d69e3 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
@@ -9,7 +9,6 @@ use rustc_hir::intravisit::Visitor;
 use rustc_hir::{ExprKind, HirId, Item, MutTy, Mutability, Path, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
-use rustc_semver::RustcVersion;
 use rustc_session::impl_lint_pass;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::Symbol;
@@ -92,7 +91,12 @@ pub struct LintWithoutLintPass {
     registered_lints: FxHashSet<Symbol>,
 }
 
-impl_lint_pass!(LintWithoutLintPass => [DEFAULT_LINT, LINT_WITHOUT_LINT_PASS, INVALID_CLIPPY_VERSION_ATTRIBUTE, MISSING_CLIPPY_VERSION_ATTRIBUTE]);
+impl_lint_pass!(LintWithoutLintPass => [
+    DEFAULT_LINT,
+    LINT_WITHOUT_LINT_PASS,
+    INVALID_CLIPPY_VERSION_ATTRIBUTE,
+    MISSING_CLIPPY_VERSION_ATTRIBUTE,
+]);
 
 impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
@@ -220,7 +224,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'
             return;
         }
 
-        if RustcVersion::parse(value.as_str()).is_err() {
+        if rustc_attr::parse_version(value).is_none() {
             span_lint_and_help(
                 cx,
                 INVALID_CLIPPY_VERSION_ATTRIBUTE,
diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs
deleted file mode 100644
index 57f45aa3e4851..0000000000000
--- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ /dev/null
@@ -1,1078 +0,0 @@
-//! This lint is used to collect metadata about clippy lints. This metadata is exported as a json
-//! file and then used to generate the [clippy lint list](https://rust-lang.github.io/rust-clippy/master/index.html)
-//!
-//! This module and therefore the entire lint is guarded by a feature flag called `internal`
-//!
-//! The module transforms all lint names to ascii lowercase to ensure that we don't have mismatches
-//! during any comparison or mapping. (Please take care of this, it's not fun to spend time on such
-//! a simple mistake)
-
-use crate::utils::internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type};
-use clippy_config::{get_configuration_metadata, ClippyConfiguration};
-
-use clippy_utils::diagnostics::span_lint;
-use clippy_utils::ty::{match_type, walk_ptrs_ty_depth};
-use clippy_utils::{last_path_segment, match_function_call, match_path, paths};
-use itertools::Itertools;
-use rustc_ast as ast;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def::DefKind;
-use rustc_hir::intravisit::Visitor;
-use rustc_hir::{self as hir, intravisit, Closure, ExprKind, Item, ItemKind, Mutability, QPath};
-use rustc_lint::{unerased_lint_store, CheckLintNameResult, LateContext, LateLintPass, LintContext, LintId};
-use rustc_middle::hir::nested_filter;
-use rustc_session::impl_lint_pass;
-use rustc_span::symbol::Ident;
-use rustc_span::{sym, Loc, Span, Symbol};
-use serde::ser::SerializeStruct;
-use serde::{Serialize, Serializer};
-use std::collections::{BTreeSet, BinaryHeap};
-use std::fmt::Write as _;
-use std::fs::{self, File};
-use std::io::prelude::*;
-use std::path::{Path, PathBuf};
-use std::process::Command;
-use std::{env, fmt};
-
-/// This is the json output file of the lint collector.
-const JSON_OUTPUT_FILE: &str = "../util/gh-pages/lints.json";
-/// This is the markdown output file of the lint collector.
-const MARKDOWN_OUTPUT_FILE: &str = "../book/src/lint_configuration.md";
-/// These groups will be ignored by the lint group matcher. This is useful for collections like
-/// `clippy::all`
-const IGNORED_LINT_GROUPS: [&str; 1] = ["clippy::all"];
-/// Lints within this group will be excluded from the collection. These groups
-/// have to be defined without the `clippy::` prefix.
-const EXCLUDED_LINT_GROUPS: [&str; 1] = ["internal"];
-/// Collected deprecated lint will be assigned to this group in the JSON output
-const DEPRECATED_LINT_GROUP_STR: &str = "deprecated";
-/// This is the lint level for deprecated lints that will be displayed in the lint list
-const DEPRECATED_LINT_LEVEL: &str = "none";
-/// This array holds Clippy's lint groups with their corresponding default lint level. The
-/// lint level for deprecated lints is set in `DEPRECATED_LINT_LEVEL`.
-const DEFAULT_LINT_LEVELS: &[(&str, &str)] = &[
-    ("correctness", "deny"),
-    ("suspicious", "warn"),
-    ("restriction", "allow"),
-    ("style", "warn"),
-    ("pedantic", "allow"),
-    ("complexity", "warn"),
-    ("perf", "warn"),
-    ("cargo", "allow"),
-    ("nursery", "allow"),
-];
-/// This prefix is in front of the lint groups in the lint store. The prefix will be trimmed
-/// to only keep the actual lint group in the output.
-const CLIPPY_LINT_GROUP_PREFIX: &str = "clippy::";
-const LINT_EMISSION_FUNCTIONS: [&[&str]; 7] = [
-    &["clippy_utils", "diagnostics", "span_lint"],
-    &["clippy_utils", "diagnostics", "span_lint_and_help"],
-    &["clippy_utils", "diagnostics", "span_lint_and_note"],
-    &["clippy_utils", "diagnostics", "span_lint_hir"],
-    &["clippy_utils", "diagnostics", "span_lint_and_sugg"],
-    &["clippy_utils", "diagnostics", "span_lint_and_then"],
-    &["clippy_utils", "diagnostics", "span_lint_hir_and_then"],
-];
-const SUGGESTION_DIAG_METHODS: [(&str, bool); 9] = [
-    ("span_suggestion", false),
-    ("span_suggestion_short", false),
-    ("span_suggestion_verbose", false),
-    ("span_suggestion_hidden", false),
-    ("tool_only_span_suggestion", false),
-    ("multipart_suggestion", true),
-    ("multipart_suggestions", true),
-    ("tool_only_multipart_suggestion", true),
-    ("span_suggestions", true),
-];
-
-/// The index of the applicability name of `paths::APPLICABILITY_VALUES`
-const APPLICABILITY_NAME_INDEX: usize = 2;
-/// This applicability will be set for unresolved applicability values.
-const APPLICABILITY_UNRESOLVED_STR: &str = "Unresolved";
-/// The version that will be displayed if none has been defined
-const VERSION_DEFAULT_STR: &str = "Unknown";
-
-const CHANGELOG_PATH: &str = "../CHANGELOG.md";
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Collects metadata about clippy lints for the website.
-    ///
-    /// This lint will be used to report problems of syntax parsing. You should hopefully never
-    /// see this but never say never I guess ^^
-    ///
-    /// ### Why is this bad?
-    /// This is not a bad thing but definitely a hacky way to do it. See
-    /// issue [#4310](https://github.com/rust-lang/rust-clippy/issues/4310) for a discussion
-    /// about the implementation.
-    ///
-    /// ### Known problems
-    /// Hopefully none. It would be pretty uncool to have a problem here :)
-    ///
-    /// ### Example output
-    /// ```json,ignore
-    /// {
-    ///     "id": "metadata_collector",
-    ///     "id_span": {
-    ///         "path": "clippy_lints/src/utils/internal_lints/metadata_collector.rs",
-    ///         "line": 1
-    ///     },
-    ///     "group": "clippy::internal",
-    ///     "docs": " ### What it does\nCollects metadata about clippy lints for the website. [...] "
-    /// }
-    /// ```
-    #[clippy::version = "1.56.0"]
-    pub METADATA_COLLECTOR,
-    internal,
-    "A busy bee collection metadata about lints"
-}
-
-impl_lint_pass!(MetadataCollector => [METADATA_COLLECTOR]);
-
-#[allow(clippy::module_name_repetitions)]
-#[derive(Debug, Clone)]
-pub struct MetadataCollector {
-    /// All collected lints
-    ///
-    /// We use a Heap here to have the lints added in alphabetic order in the export
-    lints: BinaryHeap<LintMetadata>,
-    applicability_info: FxHashMap<String, ApplicabilityInfo>,
-    config: Vec<ClippyConfiguration>,
-    clippy_project_root: PathBuf,
-}
-
-impl MetadataCollector {
-    pub fn new() -> Self {
-        Self {
-            lints: BinaryHeap::<LintMetadata>::default(),
-            applicability_info: FxHashMap::<String, ApplicabilityInfo>::default(),
-            config: get_configuration_metadata(),
-            clippy_project_root: env::current_dir()
-                .expect("failed to get current dir")
-                .ancestors()
-                .nth(1)
-                .expect("failed to get project root")
-                .to_path_buf(),
-        }
-    }
-
-    fn get_lint_configs(&self, lint_name: &str) -> Option<String> {
-        self.config
-            .iter()
-            .filter(|config| config.lints.iter().any(|&lint| lint == lint_name))
-            .map(ToString::to_string)
-            .reduce(|acc, x| acc + "\n\n" + &x)
-            .map(|configurations| {
-                format!(
-                    r#"
-### Configuration
-This lint has the following configuration variables:
-
-{configurations}
-"#
-                )
-            })
-    }
-
-    fn configs_to_markdown(&self, map_fn: fn(&ClippyConfiguration) -> String) -> String {
-        self.config
-            .iter()
-            .filter(|config| config.deprecation_reason.is_none())
-            .filter(|config| !config.lints.is_empty())
-            .map(map_fn)
-            .join("\n")
-    }
-
-    fn get_markdown_docs(&self) -> String {
-        format!(
-            r#"# Lint Configuration Options
-
-The following list shows each configuration option, along with a description, its default value, an example
-and lints affected.
-
----
-
-{}"#,
-            self.configs_to_markdown(ClippyConfiguration::to_markdown_paragraph),
-        )
-    }
-}
-
-impl Drop for MetadataCollector {
-    /// You might ask: How hacky is this?
-    /// My answer:     YES
-    fn drop(&mut self) {
-        // The metadata collector gets dropped twice, this makes sure that we only write
-        // when the list is full
-        if self.lints.is_empty() {
-            return;
-        }
-
-        let mut applicability_info = std::mem::take(&mut self.applicability_info);
-
-        // Add deprecated lints
-        self.lints.extend(
-            crate::deprecated_lints::DEPRECATED
-                .iter()
-                .zip(crate::deprecated_lints::DEPRECATED_VERSION)
-                .filter_map(|((lint, reason), version)| LintMetadata::new_deprecated(lint, reason, version)),
-        );
-        // Mapping the final data
-        let mut lints = std::mem::take(&mut self.lints).into_sorted_vec();
-        for x in &mut lints {
-            x.applicability = Some(applicability_info.remove(&x.id).unwrap_or_default());
-            replace_produces(&x.id, &mut x.docs, &self.clippy_project_root);
-        }
-
-        collect_renames(&mut lints);
-
-        // Outputting json
-        fs::write(JSON_OUTPUT_FILE, serde_json::to_string_pretty(&lints).unwrap()).unwrap();
-
-        // Outputting markdown
-        let mut file = File::create(MARKDOWN_OUTPUT_FILE).unwrap();
-        writeln!(
-            file,
-            "<!--
-This file is generated by `cargo collect-metadata`.
-Please use that command to update the file and do not edit it by hand.
--->
-
-{}",
-            self.get_markdown_docs(),
-        )
-        .unwrap();
-
-        // Write configuration links to CHANGELOG.md
-        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 -->")
-            .unwrap();
-        writeln!(
-            changelog_file,
-            "{}<!-- begin autogenerated links to configuration documentation -->\n{}\n<!-- end autogenerated links to configuration documentation -->",
-            &changelog[..position],
-            self.configs_to_markdown(ClippyConfiguration::to_markdown_link)
-        )
-        .unwrap();
-    }
-}
-
-#[derive(Debug, Clone, Serialize, PartialEq, Eq, PartialOrd, Ord)]
-struct LintMetadata {
-    id: String,
-    id_span: Option<SerializableSpan>,
-    group: String,
-    level: String,
-    docs: String,
-    version: String,
-    /// This field is only used in the output and will only be
-    /// mapped shortly before the actual output.
-    applicability: Option<ApplicabilityInfo>,
-    /// All the past names of lints which have been renamed.
-    #[serde(skip_serializing_if = "BTreeSet::is_empty")]
-    former_ids: BTreeSet<String>,
-}
-
-impl LintMetadata {
-    fn new(
-        id: String,
-        id_span: SerializableSpan,
-        group: String,
-        level: &'static str,
-        version: String,
-        docs: String,
-    ) -> Self {
-        Self {
-            id,
-            id_span: Some(id_span),
-            group,
-            level: level.to_string(),
-            version,
-            docs,
-            applicability: None,
-            former_ids: BTreeSet::new(),
-        }
-    }
-
-    fn new_deprecated(name: &str, reason: &str, version: &str) -> Option<Self> {
-        // The reason starts with a lowercase letter and end without a period.
-        // This needs to be fixed for the website.
-        let mut reason = reason.to_owned();
-        if let Some(reason) = reason.get_mut(0..1) {
-            reason.make_ascii_uppercase();
-        }
-        name.strip_prefix("clippy::").map(|name| Self {
-            id: name.into(),
-            id_span: None,
-            group: DEPRECATED_LINT_GROUP_STR.into(),
-            level: DEPRECATED_LINT_LEVEL.into(),
-            version: version.into(),
-            docs: format!(
-                "### What it does\n\n\
-                Nothing. This lint has been deprecated\n\n\
-                ### Deprecation reason\n\n{reason}.\n",
-            ),
-            applicability: None,
-            former_ids: BTreeSet::new(),
-        })
-    }
-}
-
-fn replace_produces(lint_name: &str, docs: &mut String, clippy_project_root: &Path) {
-    let mut doc_lines = docs.lines().map(ToString::to_string).collect::<Vec<_>>();
-    let mut lines = doc_lines.iter_mut();
-
-    'outer: loop {
-        // Find the start of the example
-
-        // ```rust
-        loop {
-            match lines.next() {
-                Some(line) if line.trim_start().starts_with("```rust") => {
-                    if line.contains("ignore") || line.contains("no_run") {
-                        // A {{produces}} marker may have been put on a ignored code block by mistake,
-                        // just seek to the end of the code block and continue checking.
-                        if lines.any(|line| line.trim_start().starts_with("```")) {
-                            continue;
-                        }
-
-                        panic!("lint `{lint_name}` has an unterminated code block")
-                    }
-
-                    break;
-                },
-                Some(line) if line.trim_start() == "{{produces}}" => {
-                    panic!("lint `{lint_name}` has marker {{{{produces}}}} with an ignored or missing code block")
-                },
-                Some(line) => {
-                    let line = line.trim();
-                    // These are the two most common markers of the corrections section
-                    if line.eq_ignore_ascii_case("Use instead:") || line.eq_ignore_ascii_case("Could be written as:") {
-                        break 'outer;
-                    }
-                },
-                None => break 'outer,
-            }
-        }
-
-        // Collect the example
-        let mut example = Vec::new();
-        loop {
-            match lines.next() {
-                Some(line) if line.trim_start() == "```" => break,
-                Some(line) => example.push(line),
-                None => panic!("lint `{lint_name}` has an unterminated code block"),
-            }
-        }
-
-        // Find the {{produces}} and attempt to generate the output
-        loop {
-            match lines.next() {
-                Some(line) if line.is_empty() => {},
-                Some(line) if line.trim() == "{{produces}}" => {
-                    let output = get_lint_output(lint_name, &example, clippy_project_root);
-                    line.replace_range(
-                        ..,
-                        &format!(
-                            "<details>\
-                            <summary>Produces</summary>\n\
-                            \n\
-                            ```text\n\
-                            {output}\n\
-                            ```\n\
-                        </details>"
-                        ),
-                    );
-
-                    break;
-                },
-                // No {{produces}}, we can move on to the next example
-                Some(_) => break,
-                None => break 'outer,
-            }
-        }
-    }
-
-    *docs = cleanup_docs(&doc_lines);
-}
-
-fn get_lint_output(lint_name: &str, example: &[&mut String], clippy_project_root: &Path) -> String {
-    let dir = tempfile::tempdir().unwrap_or_else(|e| panic!("failed to create temp dir: {e}"));
-    let file = dir.path().join("lint_example.rs");
-
-    let mut source = String::new();
-    let unhidden = example
-        .iter()
-        .map(|line| line.trim_start().strip_prefix("# ").unwrap_or(line));
-
-    // Get any attributes
-    let mut lines = unhidden.peekable();
-    while let Some(line) = lines.peek() {
-        if line.starts_with("#!") {
-            source.push_str(line);
-            source.push('\n');
-            lines.next();
-        } else {
-            break;
-        }
-    }
-
-    let needs_main = !example.iter().any(|line| line.contains("fn main"));
-    if needs_main {
-        source.push_str("fn main() {\n");
-    }
-
-    for line in lines {
-        source.push_str(line);
-        source.push('\n');
-    }
-
-    if needs_main {
-        source.push_str("}\n");
-    }
-
-    if let Err(e) = fs::write(&file, &source) {
-        panic!("failed to write to `{}`: {e}", file.as_path().to_string_lossy());
-    }
-
-    let prefixed_name = format!("{CLIPPY_LINT_GROUP_PREFIX}{lint_name}");
-
-    let mut cmd = Command::new(env::var("CARGO").unwrap_or("cargo".into()));
-
-    cmd.current_dir(clippy_project_root)
-        .env("CARGO_INCREMENTAL", "0")
-        .env("CLIPPY_ARGS", "")
-        .env("CLIPPY_DISABLE_DOCS_LINKS", "1")
-        // We need to disable this to enable all lints
-        .env("ENABLE_METADATA_COLLECTION", "0")
-        .args(["run", "--bin", "clippy-driver"])
-        .args(["--target-dir", "./clippy_lints/target"])
-        .args(["--", "--error-format=json"])
-        .args(["--edition", "2021"])
-        .arg("-Cdebuginfo=0")
-        .args(["-A", "clippy::all"])
-        .args(["-W", &prefixed_name])
-        .args(["-L", "./target/debug"])
-        .args(["-Z", "no-codegen"]);
-
-    let output = cmd
-        .arg(file.as_path())
-        .output()
-        .unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}"));
-
-    let tmp_file_path = file.to_string_lossy();
-    let stderr = std::str::from_utf8(&output.stderr).unwrap();
-    let msgs = stderr
-        .lines()
-        .filter(|line| line.starts_with('{'))
-        .map(|line| serde_json::from_str(line).unwrap())
-        .collect::<Vec<serde_json::Value>>();
-
-    let mut rendered = String::new();
-    let iter = msgs
-        .iter()
-        .filter(|msg| matches!(&msg["code"]["code"], serde_json::Value::String(s) if s == &prefixed_name));
-
-    for message in iter {
-        let rendered_part = message["rendered"].as_str().expect("rendered field should exist");
-        rendered.push_str(rendered_part);
-    }
-
-    if rendered.is_empty() {
-        let rendered: Vec<&str> = msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
-        let non_json: Vec<&str> = stderr.lines().filter(|line| !line.starts_with('{')).collect();
-        panic!(
-            "did not find lint `{lint_name}` in output of example, got:\n{}\n{}",
-            non_json.join("\n"),
-            rendered.join("\n")
-        );
-    }
-
-    // The reader doesn't need to see `/tmp/.tmpfiy2Qd/lint_example.rs` :)
-    rendered.trim_end().replace(&*tmp_file_path, "lint_example.rs")
-}
-
-#[derive(Debug, Clone, Serialize, PartialEq, Eq, PartialOrd, Ord)]
-struct SerializableSpan {
-    path: String,
-    line: usize,
-}
-
-impl fmt::Display for SerializableSpan {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}:{}", self.path.rsplit('/').next().unwrap_or_default(), self.line)
-    }
-}
-
-impl SerializableSpan {
-    fn from_item(cx: &LateContext<'_>, item: &Item<'_>) -> Self {
-        Self::from_span(cx, item.ident.span)
-    }
-
-    fn from_span(cx: &LateContext<'_>, span: Span) -> Self {
-        let loc: Loc = cx.sess().source_map().lookup_char_pos(span.lo());
-
-        Self {
-            path: format!("{}", loc.file.name.prefer_remapped_unconditionaly()),
-            line: loc.line,
-        }
-    }
-}
-
-#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
-struct ApplicabilityInfo {
-    /// Indicates if any of the lint emissions uses multiple spans. This is related to
-    /// [rustfix#141](https://github.com/rust-lang/rustfix/issues/141) as such suggestions can
-    /// currently not be applied automatically.
-    is_multi_part_suggestion: bool,
-    applicability: Option<usize>,
-}
-
-impl Serialize for ApplicabilityInfo {
-    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    where
-        S: Serializer,
-    {
-        let mut s = serializer.serialize_struct("ApplicabilityInfo", 2)?;
-        s.serialize_field("is_multi_part_suggestion", &self.is_multi_part_suggestion)?;
-        if let Some(index) = self.applicability {
-            s.serialize_field(
-                "applicability",
-                &paths::APPLICABILITY_VALUES[index][APPLICABILITY_NAME_INDEX],
-            )?;
-        } else {
-            s.serialize_field("applicability", APPLICABILITY_UNRESOLVED_STR)?;
-        }
-        s.end()
-    }
-}
-
-// ==================================================================
-// Lint pass
-// ==================================================================
-impl<'hir> LateLintPass<'hir> for MetadataCollector {
-    /// Collecting lint declarations like:
-    /// ```rust, ignore
-    /// declare_clippy_lint! {
-    ///     /// ### What it does
-    ///     /// Something IDK.
-    ///     pub SOME_LINT,
-    ///     internal,
-    ///     "Who am I?"
-    /// }
-    /// ```
-    fn check_item(&mut self, cx: &LateContext<'hir>, item: &'hir Item<'_>) {
-        if let ItemKind::Static(ty, Mutability::Not, _) = item.kind {
-            // Normal lint
-            if is_lint_ref_type(cx, ty)
-                // item validation
-                // disallow check
-                && let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase()
-                // metadata extraction
-                && let Some((group, level)) = get_lint_group_and_level_or_lint(cx, &lint_name, item)
-                && let Some(mut raw_docs) = extract_attr_docs_or_lint(cx, item)
-            {
-                if let Some(configuration_section) = self.get_lint_configs(&lint_name) {
-                    raw_docs.push_str(&configuration_section);
-                }
-                let version = get_lint_version(cx, item);
-
-                self.lints.push(LintMetadata::new(
-                    lint_name,
-                    SerializableSpan::from_item(cx, item),
-                    group,
-                    level,
-                    version,
-                    raw_docs,
-                ));
-            }
-        }
-    }
-
-    /// Collecting constant applicability from the actual lint emissions
-    ///
-    /// Example:
-    /// ```rust, ignore
-    /// span_lint_and_sugg(
-    ///     cx,
-    ///     SOME_LINT,
-    ///     item.span,
-    ///     "Le lint message",
-    ///     "Here comes help:",
-    ///     "#![allow(clippy::all)]",
-    ///     Applicability::MachineApplicable, // <-- Extracts this constant value
-    /// );
-    /// ```
-    fn check_expr(&mut self, cx: &LateContext<'hir>, expr: &'hir hir::Expr<'_>) {
-        if let Some(args) = match_lint_emission(cx, expr) {
-            let emission_info = extract_emission_info(cx, args);
-            if emission_info.is_empty() {
-                // See:
-                // - src/misc.rs:734:9
-                // - src/methods/mod.rs:3545:13
-                // - src/methods/mod.rs:3496:13
-                // We are basically unable to resolve the lint name itself.
-                return;
-            }
-
-            for (lint_name, applicability, is_multi_part) in emission_info {
-                let app_info = self.applicability_info.entry(lint_name).or_default();
-                app_info.applicability = applicability;
-                app_info.is_multi_part_suggestion = is_multi_part;
-            }
-        }
-    }
-}
-
-// ==================================================================
-// Lint definition extraction
-// ==================================================================
-fn sym_to_string(sym: Symbol) -> String {
-    sym.as_str().to_string()
-}
-
-fn extract_attr_docs_or_lint(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
-    extract_attr_docs(cx, item).or_else(|| {
-        lint_collection_error_item(cx, item, "could not collect the lint documentation");
-        None
-    })
-}
-
-/// This function collects all documentation that has been added to an item using
-/// `#[doc = r""]` attributes. Several attributes are aggravated using line breaks
-///
-/// ```ignore
-/// #[doc = r"Hello world!"]
-/// #[doc = r"=^.^="]
-/// struct SomeItem {}
-/// ```
-///
-/// Would result in `Hello world!\n=^.^=\n`
-fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
-    let attrs = cx.tcx.hir().attrs(item.hir_id());
-    let mut lines = attrs.iter().filter_map(ast::Attribute::doc_str);
-
-    if let Some(line) = lines.next() {
-        let raw_docs = lines.fold(String::from(line.as_str()) + "\n", |s, line| s + line.as_str() + "\n");
-        return Some(raw_docs);
-    }
-
-    None
-}
-
-/// This function may modify the doc comment to ensure that the string can be displayed using a
-/// markdown viewer in Clippy's lint list. The following modifications could be applied:
-/// * Removal of leading space after a new line. (Important to display tables)
-/// * Ensures that code blocks only contain language information
-fn cleanup_docs(docs_collection: &Vec<String>) -> String {
-    let mut in_code_block = false;
-    let mut is_code_block_rust = false;
-
-    let mut docs = String::new();
-    for line in docs_collection {
-        // Rustdoc hides code lines starting with `# ` and this removes them from Clippy's lint list :)
-        if is_code_block_rust && line.trim_start().starts_with("# ") {
-            continue;
-        }
-
-        // The line should be represented in the lint list, even if it's just an empty line
-        docs.push('\n');
-        if let Some(info) = line.trim_start().strip_prefix("```") {
-            in_code_block = !in_code_block;
-            is_code_block_rust = false;
-            if in_code_block {
-                let lang = info
-                    .trim()
-                    .split(',')
-                    // remove rustdoc directives
-                    .find(|&s| !matches!(s, "" | "ignore" | "no_run" | "should_panic"))
-                    // if no language is present, fill in "rust"
-                    .unwrap_or("rust");
-                let len_diff = line.len() - line.trim_start().len();
-                if len_diff != 0 {
-                    // We put back the indentation.
-                    docs.push_str(&line[..len_diff]);
-                }
-                docs.push_str("```");
-                docs.push_str(lang);
-
-                is_code_block_rust = lang == "rust";
-                continue;
-            }
-        }
-        // This removes the leading space that the macro translation introduces
-        if let Some(stripped_doc) = line.strip_prefix(' ') {
-            docs.push_str(stripped_doc);
-        } else if !line.is_empty() {
-            docs.push_str(line);
-        }
-    }
-
-    docs
-}
-
-fn get_lint_version(cx: &LateContext<'_>, item: &Item<'_>) -> String {
-    extract_clippy_version_value(cx, item).map_or_else(
-        || VERSION_DEFAULT_STR.to_string(),
-        |version| version.as_str().to_string(),
-    )
-}
-
-fn get_lint_group_and_level_or_lint(
-    cx: &LateContext<'_>,
-    lint_name: &str,
-    item: &Item<'_>,
-) -> Option<(String, &'static str)> {
-    let result = unerased_lint_store(cx.tcx.sess).check_lint_name(
-        lint_name,
-        Some(sym::clippy),
-        &std::iter::once(Ident::with_dummy_span(sym::clippy)).collect(),
-    );
-    if let CheckLintNameResult::Tool(lint_lst, None) = result {
-        if let Some(group) = get_lint_group(cx, lint_lst[0]) {
-            if EXCLUDED_LINT_GROUPS.contains(&group.as_str()) {
-                return None;
-            }
-
-            if let Some(level) = get_lint_level_from_group(&group) {
-                Some((group, level))
-            } else {
-                lint_collection_error_item(
-                    cx,
-                    item,
-                    &format!("Unable to determine lint level for found group `{group}`"),
-                );
-                None
-            }
-        } else {
-            lint_collection_error_item(cx, item, "Unable to determine lint group");
-            None
-        }
-    } else {
-        lint_collection_error_item(cx, item, "Unable to find lint in lint_store");
-        None
-    }
-}
-
-fn get_lint_group(cx: &LateContext<'_>, lint_id: LintId) -> Option<String> {
-    for (group_name, lints, _) in unerased_lint_store(cx.tcx.sess).get_lint_groups() {
-        if IGNORED_LINT_GROUPS.contains(&group_name) {
-            continue;
-        }
-
-        if lints.iter().any(|group_lint| *group_lint == lint_id) {
-            let group = group_name.strip_prefix(CLIPPY_LINT_GROUP_PREFIX).unwrap_or(group_name);
-            return Some((*group).to_string());
-        }
-    }
-
-    None
-}
-
-fn get_lint_level_from_group(lint_group: &str) -> Option<&'static str> {
-    DEFAULT_LINT_LEVELS
-        .iter()
-        .find_map(|(group_name, group_level)| (*group_name == lint_group).then_some(*group_level))
-}
-
-fn collect_renames(lints: &mut Vec<LintMetadata>) {
-    for lint in lints {
-        let mut collected = String::new();
-        let mut names = vec![lint.id.clone()];
-
-        loop {
-            if let Some(lint_name) = names.pop() {
-                for (k, v) in crate::deprecated_lints::RENAMED {
-                    if let Some(name) = v.strip_prefix(CLIPPY_LINT_GROUP_PREFIX)
-                        && name == lint_name
-                        && let Some(past_name) = k.strip_prefix(CLIPPY_LINT_GROUP_PREFIX)
-                    {
-                        lint.former_ids.insert(past_name.to_owned());
-                        writeln!(collected, "* `{past_name}`").unwrap();
-                        names.push(past_name.to_string());
-                    }
-                }
-
-                continue;
-            }
-
-            break;
-        }
-
-        if !collected.is_empty() {
-            write!(
-                &mut lint.docs,
-                r#"
-### Past names
-
-{collected}
-"#
-            )
-            .unwrap();
-        }
-    }
-}
-
-// ==================================================================
-// Lint emission
-// ==================================================================
-fn lint_collection_error_item(cx: &LateContext<'_>, item: &Item<'_>, message: &str) {
-    span_lint(
-        cx,
-        METADATA_COLLECTOR,
-        item.ident.span,
-        format!("metadata collection error for `{}`: {message}", item.ident.name),
-    );
-}
-
-// ==================================================================
-// Applicability
-// ==================================================================
-/// This function checks if a given expression is equal to a simple lint emission function call.
-/// It will return the function arguments if the emission matched any function.
-fn match_lint_emission<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'_>) -> Option<&'hir [hir::Expr<'hir>]> {
-    LINT_EMISSION_FUNCTIONS
-        .iter()
-        .find_map(|emission_fn| match_function_call(cx, expr, emission_fn))
-}
-
-fn take_higher_applicability(a: Option<usize>, b: Option<usize>) -> Option<usize> {
-    a.map_or(b, |a| a.max(b.unwrap_or_default()).into())
-}
-
-fn extract_emission_info<'hir>(
-    cx: &LateContext<'hir>,
-    args: &'hir [hir::Expr<'hir>],
-) -> Vec<(String, Option<usize>, bool)> {
-    let mut lints = Vec::new();
-    let mut applicability = None;
-    let mut multi_part = false;
-
-    for arg in args {
-        let (arg_ty, _) = walk_ptrs_ty_depth(cx.typeck_results().expr_ty(arg));
-
-        if match_type(cx, arg_ty, &paths::LINT) {
-            // If we found the lint arg, extract the lint name
-            let mut resolved_lints = resolve_lints(cx, arg);
-            lints.append(&mut resolved_lints);
-        } else if match_type(cx, arg_ty, &paths::APPLICABILITY) {
-            applicability = resolve_applicability(cx, arg);
-        } else if arg_ty.is_closure() {
-            multi_part |= check_is_multi_part(cx, arg);
-            applicability = applicability.or_else(|| resolve_applicability(cx, arg));
-        }
-    }
-
-    lints
-        .into_iter()
-        .map(|lint_name| (lint_name, applicability, multi_part))
-        .collect()
-}
-
-/// Resolves the possible lints that this expression could reference
-fn resolve_lints<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -> Vec<String> {
-    let mut resolver = LintResolver::new(cx);
-    resolver.visit_expr(expr);
-    resolver.lints
-}
-
-/// This function tries to resolve the linked applicability to the given expression.
-fn resolve_applicability<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -> Option<usize> {
-    let mut resolver = ApplicabilityResolver::new(cx);
-    resolver.visit_expr(expr);
-    resolver.complete()
-}
-
-fn check_is_multi_part<'hir>(cx: &LateContext<'hir>, closure_expr: &'hir hir::Expr<'hir>) -> bool {
-    if let ExprKind::Closure(&Closure { body, .. }) = closure_expr.kind {
-        let mut scanner = IsMultiSpanScanner::new(cx);
-        intravisit::walk_body(&mut scanner, cx.tcx.hir().body(body));
-        return scanner.is_multi_part();
-    } else if let Some(local) = get_parent_local(cx, closure_expr) {
-        if let Some(local_init) = local.init {
-            return check_is_multi_part(cx, local_init);
-        }
-    }
-
-    false
-}
-
-struct LintResolver<'a, 'hir> {
-    cx: &'a LateContext<'hir>,
-    lints: Vec<String>,
-}
-
-impl<'a, 'hir> LintResolver<'a, 'hir> {
-    fn new(cx: &'a LateContext<'hir>) -> Self {
-        Self {
-            cx,
-            lints: Vec::<String>::default(),
-        }
-    }
-}
-
-impl<'a, 'hir> Visitor<'hir> for LintResolver<'a, 'hir> {
-    type NestedFilter = nested_filter::All;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
-    }
-
-    fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
-        if let ExprKind::Path(qpath) = &expr.kind
-            && let QPath::Resolved(_, path) = qpath
-            && let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr))
-            && match_type(self.cx, expr_ty, &paths::LINT)
-        {
-            if let hir::def::Res::Def(DefKind::Static { .. }, _) = path.res {
-                let lint_name = last_path_segment(qpath).ident.name;
-                self.lints.push(sym_to_string(lint_name).to_ascii_lowercase());
-            } else if let Some(local) = get_parent_local(self.cx, expr) {
-                if let Some(local_init) = local.init {
-                    intravisit::walk_expr(self, local_init);
-                }
-            }
-        }
-
-        intravisit::walk_expr(self, expr);
-    }
-}
-
-/// This visitor finds the highest applicability value in the visited expressions
-struct ApplicabilityResolver<'a, 'hir> {
-    cx: &'a LateContext<'hir>,
-    /// This is the index of highest `Applicability` for `paths::APPLICABILITY_VALUES`
-    applicability_index: Option<usize>,
-}
-
-impl<'a, 'hir> ApplicabilityResolver<'a, 'hir> {
-    fn new(cx: &'a LateContext<'hir>) -> Self {
-        Self {
-            cx,
-            applicability_index: None,
-        }
-    }
-
-    fn add_new_index(&mut self, new_index: usize) {
-        self.applicability_index = take_higher_applicability(self.applicability_index, Some(new_index));
-    }
-
-    fn complete(self) -> Option<usize> {
-        self.applicability_index
-    }
-}
-
-impl<'a, 'hir> Visitor<'hir> for ApplicabilityResolver<'a, 'hir> {
-    type NestedFilter = nested_filter::All;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
-    }
-
-    fn visit_path(&mut self, path: &hir::Path<'hir>, _id: hir::HirId) {
-        for (index, enum_value) in paths::APPLICABILITY_VALUES.iter().enumerate() {
-            if match_path(path, enum_value) {
-                self.add_new_index(index);
-                return;
-            }
-        }
-    }
-
-    fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
-        let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr));
-
-        if match_type(self.cx, expr_ty, &paths::APPLICABILITY)
-            && let Some(local) = get_parent_local(self.cx, expr)
-            && let Some(local_init) = local.init
-        {
-            intravisit::walk_expr(self, local_init);
-        };
-
-        intravisit::walk_expr(self, expr);
-    }
-}
-
-/// 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::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);
-        }
-    }
-
-    None
-}
-
-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),
-        _ => None,
-    }
-}
-
-/// This visitor finds the highest applicability value in the visited expressions
-struct IsMultiSpanScanner<'a, 'hir> {
-    cx: &'a LateContext<'hir>,
-    suggestion_count: usize,
-}
-
-impl<'a, 'hir> IsMultiSpanScanner<'a, 'hir> {
-    fn new(cx: &'a LateContext<'hir>) -> Self {
-        Self {
-            cx,
-            suggestion_count: 0,
-        }
-    }
-
-    /// Add a new single expression suggestion to the counter
-    fn add_single_span_suggestion(&mut self) {
-        self.suggestion_count += 1;
-    }
-
-    /// Signals that a suggestion with possible multiple spans was found
-    fn add_multi_part_suggestion(&mut self) {
-        self.suggestion_count += 2;
-    }
-
-    /// Checks if the suggestions include multiple spans
-    fn is_multi_part(&self) -> bool {
-        self.suggestion_count > 1
-    }
-}
-
-impl<'a, 'hir> Visitor<'hir> for IsMultiSpanScanner<'a, 'hir> {
-    type NestedFilter = nested_filter::All;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
-    }
-
-    fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
-        // Early return if the lint is already multi span
-        if self.is_multi_part() {
-            return;
-        }
-
-        if let ExprKind::MethodCall(path, recv, _, _arg_span) = &expr.kind {
-            let (self_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(recv));
-            if match_type(self.cx, self_ty, &paths::DIAG) {
-                let called_method = path.ident.name.as_str().to_string();
-                for (method_name, is_multi_part) in &SUGGESTION_DIAG_METHODS {
-                    if *method_name == called_method {
-                        if *is_multi_part {
-                            self.add_multi_part_suggestion();
-                        } else {
-                            self.add_single_span_suggestion();
-                        }
-                        break;
-                    }
-                }
-            }
-        }
-
-        intravisit::walk_expr(self, expr);
-    }
-}
diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs
index 228db14d1b7c3..d3e49bff422ca 100644
--- a/clippy_lints/src/vec.rs
+++ b/clippy_lints/src/vec.rs
@@ -5,7 +5,7 @@ use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint_hir_and_then;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::is_copy;
 use clippy_utils::visitors::for_each_local_use_after_expr;
 use clippy_utils::{get_parent_expr, higher, is_in_test, is_trait_method};
@@ -214,9 +214,11 @@ impl SuggestedType {
     }
 
     fn snippet(self, cx: &LateContext<'_>, args_span: Option<Span>, len_span: Option<Span>) -> String {
-        let maybe_args = args_span.and_then(|sp| snippet_opt(cx, sp)).unwrap_or_default();
+        let maybe_args = args_span
+            .and_then(|sp| sp.get_source_text(cx))
+            .map_or(String::new(), |x| x.to_owned());
         let maybe_len = len_span
-            .and_then(|sp| snippet_opt(cx, sp).map(|s| format!("; {s}")))
+            .and_then(|sp| sp.get_source_text(cx).map(|s| format!("; {s}")))
             .unwrap_or_default();
 
         match self {
diff --git a/clippy_lints/src/visibility.rs b/clippy_lints/src/visibility.rs
index 63f3a5d7f8305..7a85196cecaaa 100644
--- a/clippy_lints/src/visibility.rs
+++ b/clippy_lints/src/visibility.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::SpanRangeExt;
 use rustc_ast::ast::{Item, VisibilityKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
@@ -82,9 +82,7 @@ impl EarlyLintPass for Visibility {
         if !in_external_macro(cx.sess(), item.span)
             && let VisibilityKind::Restricted { path, shorthand, .. } = &item.vis.kind
         {
-            if **path == kw::SelfLower
-                && let Some(false) = is_from_proc_macro(cx, item.vis.span)
-            {
+            if **path == kw::SelfLower && !is_from_proc_macro(cx, item.vis.span) {
                 span_lint_and_then(
                     cx,
                     NEEDLESS_PUB_SELF,
@@ -104,7 +102,7 @@ impl EarlyLintPass for Visibility {
             if (**path == kw::Super || **path == kw::SelfLower || **path == kw::Crate)
                 && !*shorthand
                 && let [.., last] = &*path.segments
-                && let Some(false) = is_from_proc_macro(cx, item.vis.span)
+                && !is_from_proc_macro(cx, item.vis.span)
             {
                 #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
                 span_lint_and_then(
@@ -125,7 +123,7 @@ impl EarlyLintPass for Visibility {
 
             if *shorthand
                 && let [.., last] = &*path.segments
-                && let Some(false) = is_from_proc_macro(cx, item.vis.span)
+                && !is_from_proc_macro(cx, item.vis.span)
             {
                 #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
                 span_lint_and_then(
@@ -147,6 +145,6 @@ impl EarlyLintPass for Visibility {
     }
 }
 
-fn is_from_proc_macro(cx: &EarlyContext<'_>, span: Span) -> Option<bool> {
-    snippet_opt(cx, span).map(|s| !s.starts_with("pub"))
+fn is_from_proc_macro(cx: &EarlyContext<'_>, span: Span) -> bool {
+    !span.check_source_text(cx, |src| src.starts_with("pub"))
 }
diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs
index c4d64ee4609ee..7d9e58ad2f8d5 100644
--- a/clippy_lints/src/wildcard_imports.rs
+++ b/clippy_lints/src/wildcard_imports.rs
@@ -100,14 +100,14 @@ declare_clippy_lint! {
 
 pub struct WildcardImports {
     warn_on_all: bool,
-    allowed_segments: &'static FxHashSet<String>,
+    allowed_segments: FxHashSet<String>,
 }
 
 impl WildcardImports {
     pub fn new(conf: &'static Conf) -> Self {
         Self {
             warn_on_all: conf.warn_on_all_wildcard_imports,
-            allowed_segments: &conf.allowed_wildcard_imports,
+            allowed_segments: conf.allowed_wildcard_imports.iter().cloned().collect(),
         }
     }
 }
@@ -181,7 +181,7 @@ impl WildcardImports {
     fn check_exceptions(&self, cx: &LateContext<'_>, item: &Item<'_>, segments: &[PathSegment<'_>]) -> bool {
         item.span.from_expansion()
             || is_prelude_import(segments)
-            || is_allowed_via_config(segments, self.allowed_segments)
+            || is_allowed_via_config(segments, &self.allowed_segments)
             || (is_super_only_import(segments) && is_in_test(cx.tcx, item.hir_id()))
     }
 }
diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs
index 54e7e92f0c45d..ec5a5896fb2bf 100644
--- a/clippy_lints/src/write.rs
+++ b/clippy_lints/src/write.rs
@@ -2,7 +2,7 @@ use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::is_in_test;
 use clippy_utils::macros::{format_arg_removal_span, root_macro_call_first_node, FormatArgsStorage, MacroCall};
-use clippy_utils::source::{expand_past_previous_comma, snippet_opt};
+use clippy_utils::source::{expand_past_previous_comma, SpanRangeExt};
 use rustc_ast::token::LitKind;
 use rustc_ast::{
     FormatArgPosition, FormatArgPositionKind, FormatArgs, FormatArgsPiece, FormatOptions, FormatPlaceholder,
@@ -397,7 +397,7 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgs, macro_call: &Ma
             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 {
+                let Some(format_snippet) = format_string_span.get_source_text(cx) else {
                     return;
                 };
 
@@ -492,7 +492,7 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
             && let Some(arg) = format_args.arguments.by_index(index)
             && let rustc_ast::ExprKind::Lit(lit) = &arg.expr.kind
             && !arg.expr.span.from_expansion()
-            && let Some(value_string) = snippet_opt(cx, arg.expr.span)
+            && let Some(value_string) = arg.expr.span.get_source_text(cx)
         {
             let (replacement, replace_raw) = match lit.kind {
                 LitKind::Str | LitKind::StrRaw(_) => match extract_str_literal(&value_string) {
@@ -515,7 +515,7 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
                 _ => continue,
             };
 
-            let Some(format_string_snippet) = snippet_opt(cx, format_args.span) else {
+            let Some(format_string_snippet) = format_args.span.get_source_text(cx) else {
                 continue;
             };
             let format_string_is_raw = format_string_snippet.starts_with('r');
diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml
index 9fefd94d339be..629ce9d04d432 100644
--- a/clippy_utils/Cargo.toml
+++ b/clippy_utils/Cargo.toml
@@ -8,7 +8,6 @@ publish = false
 clippy_config = { path = "../clippy_config" }
 arrayvec = { version = "0.7", default-features = false }
 itertools = "0.12"
-rustc-semver = "1.1"
 # FIXME(f16_f128): remove when no longer needed for parsing
 rustc_apfloat = "0.2.0"
 
diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs
index d2200bcf7103b..42c8b218d14e8 100644
--- a/clippy_utils/src/attrs.rs
+++ b/clippy_utils/src/attrs.rs
@@ -7,7 +7,7 @@ use rustc_session::Session;
 use rustc_span::{sym, Span};
 use std::str::FromStr;
 
-use crate::source::snippet_opt;
+use crate::source::SpanRangeExt;
 use crate::tokenize_with_text;
 
 /// Deprecation status of attributes known by Clippy.
@@ -179,25 +179,23 @@ pub fn has_non_exhaustive_attr(tcx: TyCtxt<'_>, adt: AdtDef<'_>) -> bool {
 
 /// 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);
+    s.check_source_text(cx, |src| {
+        let mut iter = tokenize_with_text(src);
 
-    // 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;
+        // 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
+        false
+    })
 }
diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs
index 7f2234b310b42..2bd6837d973bb 100644
--- a/clippy_utils/src/check_proc_macro.rs
+++ b/clippy_utils/src/check_proc_macro.rs
@@ -123,16 +123,14 @@ fn qpath_search_pat(path: &QPath<'_>) -> (Pat, Pat) {
 
 fn path_search_pat(path: &Path<'_>) -> (Pat, Pat) {
     let (head, tail) = match path.segments {
-        [head, .., tail] => (head, tail),
-        [p] => (p, p),
         [] => return (Pat::Str(""), Pat::Str("")),
+        [p] => (Pat::Sym(p.ident.name), p),
+        // QPath::Resolved can have a path that looks like `<Foo as Bar>::baz` where
+        // the path (`Bar::baz`) has it's span covering the whole QPath.
+        [.., tail] => (Pat::Str(""), tail),
     };
     (
-        if head.ident.name == kw::PathRoot {
-            Pat::Str("::")
-        } else {
-            Pat::Sym(head.ident.name)
-        },
+        head,
         if tail.args.is_some() {
             Pat::Str(">")
         } else {
diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs
index e907e4058e5a2..760d5bc95f7fb 100644
--- a/clippy_utils/src/consts.rs
+++ b/clippy_utils/src/consts.rs
@@ -687,7 +687,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
                 if let Some(expr_span) = walk_span_to_context(expr.span, span.ctxt)
                     && let expr_lo = expr_span.lo()
                     && expr_lo >= span.lo
-                    && let Some(src) = (span.lo..expr_lo).get_source_text(&self.tcx)
+                    && let Some(src) = (span.lo..expr_lo).get_source_range(&self.tcx)
                     && let Some(src) = src.as_str()
                 {
                     use rustc_lexer::TokenKind::{BlockComment, LineComment, OpenBrace, Semi, Whitespace};
diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs
index f325e4eaf1544..f61ef9ac1b05e 100644
--- a/clippy_utils/src/hir_utils.rs
+++ b/clippy_utils/src/hir_utils.rs
@@ -1,6 +1,6 @@
 use crate::consts::ConstEvalCtxt;
 use crate::macros::macro_backtrace;
-use crate::source::{snippet_opt, walk_span_to_context, SpanRange, SpanRangeExt};
+use crate::source::{walk_span_to_context, SpanRange, SpanRangeExt};
 use crate::tokenize_with_text;
 use rustc_ast::ast::InlineAsmTemplatePiece;
 use rustc_data_structures::fx::FxHasher;
@@ -588,10 +588,9 @@ fn reduce_exprkind<'hir>(cx: &LateContext<'_>, kind: &'hir ExprKind<'hir>) -> &'
             // block with an empty span.
             ([], None) if block.span.is_empty() => &ExprKind::Tup(&[]),
             // `{}` => `()`
-            ([], None) => match snippet_opt(cx, block.span) {
-                // Don't reduce if there are any tokens contained in the braces
-                Some(snip)
-                    if tokenize(&snip)
+            ([], None)
+                if block.span.check_source_text(cx, |src| {
+                    tokenize(src)
                         .map(|t| t.kind)
                         .filter(|t| {
                             !matches!(
@@ -599,11 +598,10 @@ fn reduce_exprkind<'hir>(cx: &LateContext<'_>, kind: &'hir ExprKind<'hir>) -> &'
                                 TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace
                             )
                         })
-                        .ne([TokenKind::OpenBrace, TokenKind::CloseBrace].iter().copied()) =>
-                {
-                    kind
-                },
-                _ => &ExprKind::Tup(&[]),
+                        .eq([TokenKind::OpenBrace, TokenKind::CloseBrace].iter().copied())
+                }) =>
+            {
+                &ExprKind::Tup(&[])
             },
             ([], Some(expr)) => match expr.kind {
                 // `{ return .. }` => `return ..`
@@ -1191,9 +1189,9 @@ fn eq_span_tokens(
     pred: impl Fn(TokenKind) -> bool,
 ) -> bool {
     fn f(cx: &LateContext<'_>, left: Range<BytePos>, right: Range<BytePos>, pred: impl Fn(TokenKind) -> bool) -> bool {
-        if let Some(lsrc) = left.get_source_text(cx)
+        if let Some(lsrc) = left.get_source_range(cx)
             && let Some(lsrc) = lsrc.as_str()
-            && let Some(rsrc) = right.get_source_text(cx)
+            && let Some(rsrc) = right.get_source_range(cx)
             && let Some(rsrc) = rsrc.as_str()
         {
             let pred = |t: &(_, _)| pred(t.0);
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 28755ae0710ca..5db14872c36b0 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -149,6 +149,7 @@ macro_rules! extract_msrv_attr {
 
 /// If the given expression is a local binding, find the initializer expression.
 /// If that initializer expression is another local binding, find its initializer again.
+///
 /// This process repeats as long as possible (but usually no more than once). Initializer
 /// expressions with adjustments are ignored. If this is not desired, use [`find_binding_init`]
 /// instead.
@@ -179,6 +180,7 @@ pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr
 }
 
 /// Finds the initializer expression for a local binding. Returns `None` if the binding is mutable.
+///
 /// By only considering immutable bindings, we guarantee that the returned expression represents the
 /// value of the binding wherever it is referenced.
 ///
@@ -431,12 +433,12 @@ pub fn qpath_generic_tys<'tcx>(qpath: &QPath<'tcx>) -> impl Iterator<Item = &'tc
         })
 }
 
-/// THIS METHOD IS DEPRECATED and will eventually be removed since it does not match against the
+/// THIS METHOD IS DEPRECATED. Matches a `QPath` against a slice of segment string literals.
+///
+/// This method is deprecated and will eventually be removed since it does not match against the
 /// entire path or resolved `DefId`. Prefer using `match_def_path`. Consider getting a `DefId` from
 /// `QPath::Resolved.1.res.opt_def_id()`.
 ///
-/// Matches a `QPath` against a slice of segment string literals.
-///
 /// There is also `match_path` if you are dealing with a `rustc_hir::Path` instead of a
 /// `rustc_hir::QPath`.
 ///
@@ -485,12 +487,12 @@ pub fn is_path_diagnostic_item<'tcx>(
     path_def_id(cx, maybe_path).map_or(false, |id| cx.tcx.is_diagnostic_item(diag_item, id))
 }
 
-/// THIS METHOD IS DEPRECATED and will eventually be removed since it does not match against the
+/// THIS METHOD IS DEPRECATED. Matches a `Path` against a slice of segment string literals.
+///
+/// This method is deprecated and will eventually be removed since it does not match against the
 /// entire path or resolved `DefId`. Prefer using `match_def_path`. Consider getting a `DefId` from
 /// `QPath::Resolved.1.res.opt_def_id()`.
 ///
-/// Matches a `Path` against a slice of segment string literals.
-///
 /// There is also `match_qpath` if you are dealing with a `rustc_hir::QPath` instead of a
 /// `rustc_hir::Path`.
 ///
@@ -905,6 +907,7 @@ pub fn is_default_equivalent_call(cx: &LateContext<'_>, repl_func: &Expr<'_>) ->
 }
 
 /// Returns true if the expr is equal to `Default::default()` of it's type when evaluated.
+///
 /// It doesn't cover all cases, for example indirect function calls (some of std
 /// functions are supported) but it is the best we have.
 pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
@@ -1061,6 +1064,7 @@ impl std::ops::BitOrAssign for CaptureKind {
 }
 
 /// Given an expression referencing a local, determines how it would be captured in a closure.
+///
 /// Note as this will walk up to parent expressions until the capture can be determined it should
 /// only be used while making a closure somewhere a value is consumed. e.g. a block, match arm, or
 /// function argument (other than a receiver).
@@ -2365,8 +2369,9 @@ pub fn fn_def_id_with_node_args<'tcx>(
 }
 
 /// Returns `Option<String>` where String is a textual representation of the type encapsulated in
-/// the slice iff the given expression is a slice of primitives (as defined in the
-/// `is_recursively_primitive_type` function) and `None` otherwise.
+/// the slice iff the given expression is a slice of primitives.
+///
+/// (As defined in the `is_recursively_primitive_type` function.) Returns `None` otherwise.
 pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
     let expr_type = cx.typeck_results().expr_ty_adjusted(expr);
     let expr_kind = expr_type.kind();
diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs
index 455239cc37f35..1d7479bff82d9 100644
--- a/clippy_utils/src/macros.rs
+++ b/clippy_utils/src/macros.rs
@@ -150,10 +150,11 @@ pub fn first_node_macro_backtrace(cx: &LateContext<'_>, node: &impl HirNode) ->
 }
 
 /// If `node` is the "first node" in a macro expansion, returns `Some` with the `ExpnId` of the
-/// macro call site (i.e. the parent of the macro expansion). This generally means that `node`
-/// is the outermost node of an entire macro expansion, but there are some caveats noted below.
-/// This is useful for finding macro calls while visiting the HIR without processing the macro call
-/// at every node within its expansion.
+/// macro call site (i.e. the parent of the macro expansion).
+///
+/// This generally means that `node` is the outermost node of an entire macro expansion, but there
+/// are some caveats noted below. This is useful for finding macro calls while visiting the HIR
+/// without processing the macro call at every node within its expansion.
 ///
 /// If you already have immediate access to the parent node, it is simpler to
 /// just check the context of that span directly (e.g. `parent.span.from_expansion()`).
@@ -426,12 +427,8 @@ impl FormatArgsStorage {
     }
 }
 
-/// Attempt to find the [`rustc_hir::Expr`] that corresponds to the [`FormatArgument`]'s value, if
-/// it cannot be found it will return the [`rustc_ast::Expr`].
-pub fn find_format_arg_expr<'hir, 'ast>(
-    start: &'hir Expr<'hir>,
-    target: &'ast FormatArgument,
-) -> Result<&'hir Expr<'hir>, &'ast rustc_ast::Expr> {
+/// Attempt to find the [`rustc_hir::Expr`] that corresponds to the [`FormatArgument`]'s value
+pub fn find_format_arg_expr<'hir>(start: &'hir Expr<'hir>, target: &FormatArgument) -> Option<&'hir Expr<'hir>> {
     let SpanData {
         lo,
         hi,
@@ -449,7 +446,6 @@ pub fn find_format_arg_expr<'hir, 'ast>(
             ControlFlow::Continue(())
         }
     })
-    .ok_or(&target.expr)
 }
 
 /// Span of the `:` and format specifiers
diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs
index 95fbf0b2ea20a..d9befb3c157a3 100644
--- a/clippy_utils/src/qualify_min_const_fn.rs
+++ b/clippy_utils/src/qualify_min_const_fn.rs
@@ -18,7 +18,6 @@ use rustc_middle::mir::{
 use rustc_middle::traits::{BuiltinImplSource, ImplSource, ObligationCause};
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::{self, GenericArgKind, TraitRef, Ty, TyCtxt};
-use rustc_semver::RustcVersion;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_trait_selection::traits::{ObligationCtxt, SelectionContext};
@@ -391,11 +390,7 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool {
                     StableSince::Err => return false,
                 };
 
-                msrv.meets(RustcVersion::new(
-                    u32::from(const_stab_rust_version.major),
-                    u32::from(const_stab_rust_version.minor),
-                    u32::from(const_stab_rust_version.patch),
-                ))
+                msrv.meets(const_stab_rust_version)
             } else {
                 // Unstable const fn with the feature enabled.
                 msrv.current().is_none()
diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs
index 96dd3c55d37ae..482e1e0147b18 100644
--- a/clippy_utils/src/source.rs
+++ b/clippy_utils/src/source.rs
@@ -16,7 +16,7 @@ use rustc_span::{
 };
 use std::borrow::Cow;
 use std::fmt;
-use std::ops::Range;
+use std::ops::{Deref, Index, Range};
 
 pub trait HasSession {
     fn sess(&self) -> &Session;
@@ -94,10 +94,16 @@ impl IntoSpan for Range<BytePos> {
 }
 
 pub trait SpanRangeExt: SpanRange {
+    /// Attempts to get a handle to the source text. Returns `None` if either the span is malformed,
+    /// or the source text is not accessible.
+    fn get_source_text(self, cx: &impl HasSession) -> Option<SourceText> {
+        get_source_range(cx.sess().source_map(), self.into_range()).and_then(SourceText::new)
+    }
+
     /// Gets the source file, and range in the file, of the given span. Returns `None` if the span
     /// extends through multiple files, or is malformed.
-    fn get_source_text(self, cx: &impl HasSession) -> Option<SourceFileRange> {
-        get_source_text(cx.sess().source_map(), self.into_range())
+    fn get_source_range(self, cx: &impl HasSession) -> Option<SourceFileRange> {
+        get_source_range(cx.sess().source_map(), self.into_range())
     }
 
     /// Calls the given function with the source text referenced and returns the value. Returns
@@ -144,32 +150,70 @@ pub trait SpanRangeExt: SpanRange {
     fn trim_start(self, cx: &impl HasSession) -> Range<BytePos> {
         trim_start(cx.sess().source_map(), self.into_range())
     }
+}
+impl<T: SpanRange> SpanRangeExt for T {}
 
-    /// Writes the referenced source text to the given writer. Will return `Err` if the source text
-    /// could not be retrieved.
-    fn write_source_text_to(self, cx: &impl HasSession, dst: &mut impl fmt::Write) -> fmt::Result {
-        write_source_text_to(cx.sess().source_map(), self.into_range(), dst)
+/// Handle to a range of text in a source file.
+pub struct SourceText(SourceFileRange);
+impl SourceText {
+    /// Takes ownership of the source file handle if the source text is accessible.
+    pub fn new(text: SourceFileRange) -> Option<Self> {
+        if text.as_str().is_some() {
+            Some(Self(text))
+        } else {
+            None
+        }
     }
 
-    /// Extracts the referenced source text as an owned string.
-    fn source_text_to_string(self, cx: &impl HasSession) -> Option<String> {
-        self.with_source_text(cx, ToOwned::to_owned)
+    /// Gets the source text.
+    pub fn as_str(&self) -> &str {
+        self.0.as_str().unwrap()
+    }
+
+    /// Converts this into an owned string.
+    pub fn to_owned(&self) -> String {
+        self.as_str().to_owned()
+    }
+}
+impl Deref for SourceText {
+    type Target = str;
+    fn deref(&self) -> &Self::Target {
+        self.as_str()
+    }
+}
+impl AsRef<str> for SourceText {
+    fn as_ref(&self) -> &str {
+        self.as_str()
+    }
+}
+impl<T> Index<T> for SourceText
+where
+    str: Index<T>,
+{
+    type Output = <str as Index<T>>::Output;
+    fn index(&self, idx: T) -> &Self::Output {
+        &self.as_str()[idx]
+    }
+}
+impl fmt::Display for SourceText {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.as_str().fmt(f)
     }
 }
-impl<T: SpanRange> SpanRangeExt for T {}
 
-fn get_source_text(sm: &SourceMap, sp: Range<BytePos>) -> Option<SourceFileRange> {
+fn get_source_range(sm: &SourceMap, sp: Range<BytePos>) -> Option<SourceFileRange> {
     let start = sm.lookup_byte_offset(sp.start);
     let end = sm.lookup_byte_offset(sp.end);
     if !Lrc::ptr_eq(&start.sf, &end.sf) || start.pos > end.pos {
         return None;
     }
+    sm.ensure_source_file_source_present(&start.sf);
     let range = start.pos.to_usize()..end.pos.to_usize();
     Some(SourceFileRange { sf: start.sf, range })
 }
 
 fn with_source_text<T>(sm: &SourceMap, sp: Range<BytePos>, f: impl for<'a> FnOnce(&'a str) -> T) -> Option<T> {
-    if let Some(src) = get_source_text(sm, sp)
+    if let Some(src) = get_source_range(sm, sp)
         && let Some(src) = src.as_str()
     {
         Some(f(src))
@@ -183,7 +227,7 @@ fn with_source_text_and_range<T>(
     sp: Range<BytePos>,
     f: impl for<'a> FnOnce(&'a str, Range<usize>) -> T,
 ) -> Option<T> {
-    if let Some(src) = get_source_text(sm, sp)
+    if let Some(src) = get_source_range(sm, sp)
         && let Some(text) = &src.sf.src
     {
         Some(f(text, src.range))
@@ -198,7 +242,7 @@ fn map_range(
     sp: Range<BytePos>,
     f: impl for<'a> FnOnce(&'a str, Range<usize>) -> Option<Range<usize>>,
 ) -> Option<Range<BytePos>> {
-    if let Some(src) = get_source_text(sm, sp.clone())
+    if let Some(src) = get_source_range(sm, sp.clone())
         && let Some(text) = &src.sf.src
         && let Some(range) = f(text, src.range.clone())
     {
@@ -232,13 +276,6 @@ fn trim_start(sm: &SourceMap, sp: Range<BytePos>) -> Range<BytePos> {
     .unwrap_or(sp)
 }
 
-fn write_source_text_to(sm: &SourceMap, sp: Range<BytePos>, dst: &mut impl fmt::Write) -> fmt::Result {
-    match with_source_text(sm, sp, |src| dst.write_str(src)) {
-        Some(x) => x,
-        None => Err(fmt::Error),
-    }
-}
-
 pub struct SourceFileRange {
     pub sf: Lrc<SourceFile>,
     pub range: Range<usize>,
@@ -247,7 +284,11 @@ impl SourceFileRange {
     /// Attempts to get the text from the source file. This can fail if the source text isn't
     /// loaded.
     pub fn as_str(&self) -> Option<&str> {
-        self.sf.src.as_ref().and_then(|x| x.get(self.range.clone()))
+        self.sf
+            .src
+            .as_ref()
+            .or_else(|| self.sf.external_src.get().and_then(|src| src.get_source()))
+            .and_then(|x| x.get(self.range.clone()))
     }
 }
 
@@ -548,9 +589,10 @@ pub fn snippet_block_with_context<'a>(
     (reindent_multiline(snip, true, indent), from_macro)
 }
 
-/// Same as `snippet_with_applicability`, but first walks the span up to the given context. This
-/// will result in the macro call, rather than the expansion, if the span is from a child context.
-/// If the span is not from a child context, it will be used directly instead.
+/// Same as `snippet_with_applicability`, but first walks the span up to the given context.
+///
+/// This will result in the macro call, rather than the expansion, if the span is from a child
+/// context. If the span is not from a child context, it will be used directly instead.
 ///
 /// e.g. Given the expression `&vec![]`, getting a snippet from the span for `vec![]` as a HIR node
 /// would result in `box []`. If given the context of the address of expression, this function will
@@ -593,9 +635,10 @@ fn snippet_with_context_sess<'a>(
 }
 
 /// Walks the span up to the target context, thereby returning the macro call site if the span is
-/// inside a macro expansion, or the original span if it is not. Note this will return `None` in the
-/// case of the span being in a macro expansion, but the target context is from expanding a macro
-/// argument.
+/// inside a macro expansion, or the original span if it is not.
+///
+/// Note this will return `None` in the case of the span being in a macro expansion, but the target
+/// context is from expanding a macro argument.
 ///
 /// Given the following
 ///
diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs
index 2f6faba073e95..f80981c11af65 100644
--- a/clippy_utils/src/ty.rs
+++ b/clippy_utils/src/ty.rs
@@ -160,8 +160,10 @@ 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.
+/// 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),
@@ -398,8 +400,10 @@ fn is_normalizable_helper<'tcx>(
 }
 
 /// Returns `true` if the given type is a non aggregate primitive (a `bool` or `char`, any
-/// integer or floating-point number type). For checking aggregation of primitive types (e.g.
-/// tuples and slices of primitive type) see `is_recursively_primitive_type`
+/// integer or floating-point number type).
+///
+/// For checking aggregation of primitive types (e.g. tuples and slices of primitive type) see
+/// `is_recursively_primitive_type`
 pub fn is_non_aggregate_primitive_type(ty: Ty<'_>) -> bool {
     matches!(ty.kind(), ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_))
 }
@@ -455,11 +459,6 @@ pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: LangItem)
     }
 }
 
-/// Gets the diagnostic name of the type, if it has one
-pub fn type_diagnostic_name(cx: &LateContext<'_>, ty: Ty<'_>) -> Option<Symbol> {
-    ty.ty_adt_def().and_then(|adt| cx.tcx.get_diagnostic_name(adt.did()))
-}
-
 /// Return `true` if the passed `typ` is `isize` or `usize`.
 pub fn is_isize_or_usize(typ: Ty<'_>) -> bool {
     matches!(typ.kind(), ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize))
@@ -476,9 +475,10 @@ pub fn match_type(cx: &LateContext<'_>, ty: Ty<'_>, path: &[&str]) -> bool {
     }
 }
 
-/// Checks if the drop order for a type matters. Some std types implement drop solely to
-/// deallocate memory. For these types, and composites containing them, changing the drop order
-/// won't result in any observable side effects.
+/// Checks if the drop order for a type matters.
+///
+/// Some std types implement drop solely to deallocate memory. For these types, and composites
+/// containing them, changing the drop order won't result in any observable side effects.
 pub fn needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
     fn needs_ordered_drop_inner<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, seen: &mut FxHashSet<Ty<'tcx>>) -> bool {
         if !seen.insert(ty) {
@@ -1311,6 +1311,7 @@ pub fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl
 }
 
 /// Checks if a Ty<'_> has some inherent method Symbol.
+///
 /// This does not look for impls in the type's `Deref::Target` type.
 /// If you need this, you should wrap this call in `clippy_utils::ty::deref_chain().any(...)`.
 pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> Option<&'a AssocItem> {
diff --git a/declare_clippy_lint/src/lib.rs b/declare_clippy_lint/src/lib.rs
index ca070f6c250bf..6aa24329b0659 100644
--- a/declare_clippy_lint/src/lib.rs
+++ b/declare_clippy_lint/src/lib.rs
@@ -1,4 +1,4 @@
-#![feature(let_chains)]
+#![feature(let_chains, proc_macro_span)]
 // warn on lints, that are included in `rust-lang/rust`s bootstrap
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
@@ -23,6 +23,7 @@ fn parse_attr<const LEN: usize>(path: [&'static str; LEN], attr: &Attribute) ->
 
 struct ClippyLint {
     attrs: Vec<Attribute>,
+    version: Option<LitStr>,
     explanation: String,
     name: Ident,
     category: Ident,
@@ -41,8 +42,14 @@ impl Parse for ClippyLint {
                 let value = lit.value();
                 let line = value.strip_prefix(' ').unwrap_or(&value);
 
-                if line.starts_with("```") {
-                    explanation += "```\n";
+                if let Some(lang) = line.strip_prefix("```") {
+                    let tag = lang.split_once(',').map_or(lang, |(left, _)| left);
+                    if !in_code && matches!(tag, "" | "rust" | "ignore" | "should_panic" | "no_run" | "compile_fail") {
+                        explanation += "```rust\n";
+                    } else {
+                        explanation += line;
+                        explanation.push('\n');
+                    }
                     in_code = !in_code;
                 } else if !(in_code && line.starts_with("# ")) {
                     explanation += line;
@@ -68,6 +75,7 @@ impl Parse for ClippyLint {
 
         Ok(Self {
             attrs,
+            version,
             explanation,
             name,
             category,
@@ -123,6 +131,7 @@ impl Parse for ClippyLint {
 pub fn declare_clippy_lint(input: TokenStream) -> TokenStream {
     let ClippyLint {
         attrs,
+        version,
         explanation,
         name,
         category,
@@ -146,6 +155,14 @@ pub fn declare_clippy_lint(input: TokenStream) -> TokenStream {
     (&mut category[0..1]).make_ascii_uppercase();
     let category_variant = format_ident!("{category}");
 
+    let name_span = name.span().unwrap();
+    let location = format!("{}#L{}", name_span.source_file().path().display(), name_span.line());
+
+    let version = match version {
+        Some(version) => quote!(Some(#version)),
+        None => quote!(None),
+    };
+
     let output = quote! {
         rustc_session::declare_tool_lint! {
             #(#attrs)*
@@ -159,6 +176,8 @@ pub fn declare_clippy_lint(input: TokenStream) -> TokenStream {
             lint: &#name,
             category: crate::LintCategory::#category_variant,
             explanation: #explanation,
+            location: #location,
+            version: #version,
         };
     };
 
diff --git a/lintcheck/src/json.rs b/lintcheck/src/json.rs
index 4211bce90b2fb..ee0c80aea522e 100644
--- a/lintcheck/src/json.rs
+++ b/lintcheck/src/json.rs
@@ -12,21 +12,21 @@ const TRUNCATION_TOTAL_TARGET: usize = 1000;
 
 #[derive(Debug, Deserialize, Serialize)]
 struct LintJson {
-    lint: String,
-    krate: String,
-    file_name: String,
-    byte_pos: (u32, u32),
-    file_link: String,
+    /// The lint name e.g. `clippy::bytes_nth`
+    name: String,
+    /// The filename and line number e.g. `anyhow-1.0.86/src/error.rs:42`
+    file_line: String,
+    file_url: String,
     rendered: String,
 }
 
 impl LintJson {
     fn key(&self) -> impl Ord + '_ {
-        (self.lint.as_str(), self.file_name.as_str(), self.byte_pos)
+        (self.name.as_str(), self.file_line.as_str())
     }
 
     fn info_text(&self, action: &str) -> String {
-        format!("{action} `{}` in `{}` at {}", self.lint, self.krate, self.file_link)
+        format!("{action} `{}` at [`{}`]({})", self.name, self.file_line, self.file_url)
     }
 }
 
@@ -36,13 +36,16 @@ pub(crate) fn output(clippy_warnings: Vec<ClippyWarning>) -> String {
         .into_iter()
         .map(|warning| {
             let span = warning.span();
+            let file_name = span
+                .file_name
+                .strip_prefix("target/lintcheck/sources/")
+                .unwrap_or(&span.file_name);
+            let file_line = format!("{file_name}:{}", span.line_start);
             LintJson {
-                file_name: span.file_name.clone(),
-                byte_pos: (span.byte_start, span.byte_end),
-                krate: warning.krate,
-                file_link: warning.url,
-                lint: warning.lint,
-                rendered: warning.diag.rendered.unwrap(),
+                name: warning.name,
+                file_line,
+                file_url: warning.url,
+                rendered: warning.diag.rendered.unwrap().trim().to_string(),
             }
         })
         .collect();
@@ -63,7 +66,7 @@ pub(crate) fn diff(old_path: &Path, new_path: &Path, truncate: bool) {
     let mut lint_warnings = vec![];
 
     for (name, changes) in &itertools::merge_join_by(old_warnings, new_warnings, |old, new| old.key().cmp(&new.key()))
-        .chunk_by(|change| change.as_ref().into_left().lint.to_string())
+        .chunk_by(|change| change.as_ref().into_left().name.clone())
     {
         let mut added = Vec::new();
         let mut removed = Vec::new();
@@ -162,7 +165,7 @@ fn print_warnings(title: &str, warnings: &[LintJson], truncate_after: usize) {
         return;
     }
 
-    print_h3(&warnings[0].lint, title);
+    print_h3(&warnings[0].name, title);
     println!();
 
     let warnings = truncate(warnings, truncate_after);
@@ -171,7 +174,7 @@ fn print_warnings(title: &str, warnings: &[LintJson], truncate_after: usize) {
         println!("{}", warning.info_text(title));
         println!();
         println!("```");
-        println!("{}", warning.rendered.trim_end());
+        println!("{}", warning.rendered);
         println!("```");
         println!();
     }
@@ -182,7 +185,7 @@ fn print_changed_diff(changed: &[(LintJson, LintJson)], truncate_after: usize) {
         return;
     }
 
-    print_h3(&changed[0].0.lint, "Changed");
+    print_h3(&changed[0].0.name, "Changed");
     println!();
 
     let changed = truncate(changed, truncate_after);
@@ -191,7 +194,7 @@ fn print_changed_diff(changed: &[(LintJson, LintJson)], truncate_after: usize) {
         println!("{}", new.info_text("Changed"));
         println!();
         println!("```diff");
-        for change in diff::lines(old.rendered.trim_end(), new.rendered.trim_end()) {
+        for change in diff::lines(&old.rendered, &new.rendered) {
             use diff::Result::{Both, Left, Right};
 
             match change {
diff --git a/lintcheck/src/output.rs b/lintcheck/src/output.rs
index 153786306956a..e38036315c2ce 100644
--- a/lintcheck/src/output.rs
+++ b/lintcheck/src/output.rs
@@ -51,7 +51,7 @@ impl RustcIce {
 /// A single warning that clippy issued while checking a `Crate`
 #[derive(Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
 pub struct ClippyWarning {
-    pub lint: String,
+    pub name: String,
     pub diag: Diagnostic,
     pub krate: String,
     /// The URL that points to the file and line of the lint emission
@@ -60,8 +60,8 @@ pub struct ClippyWarning {
 
 impl ClippyWarning {
     pub fn new(mut diag: Diagnostic, base_url: &str, krate: &str) -> Option<Self> {
-        let lint = diag.code.clone()?.code;
-        if !(lint.contains("clippy") || diag.message.contains("clippy"))
+        let name = diag.code.clone()?.code;
+        if !(name.contains("clippy") || diag.message.contains("clippy"))
             || diag.message.contains("could not read cargo metadata")
         {
             return None;
@@ -92,7 +92,7 @@ impl ClippyWarning {
         };
 
         Some(Self {
-            lint,
+            name,
             diag,
             url,
             krate: krate.to_string(),
@@ -108,7 +108,7 @@ impl ClippyWarning {
         let mut file = span.file_name.clone();
         let file_with_pos = format!("{file}:{}:{}", span.line_start, span.line_end);
         match format {
-            OutputFormat::Text => format!("{file_with_pos} {} \"{}\"\n", self.lint, self.diag.message),
+            OutputFormat::Text => format!("{file_with_pos} {} \"{}\"\n", self.name, self.diag.message),
             OutputFormat::Markdown => {
                 if file.starts_with("target") {
                     file.insert_str(0, "../");
@@ -116,7 +116,7 @@ impl ClippyWarning {
 
                 let mut output = String::from("| ");
                 write!(output, "[`{file_with_pos}`]({file}#L{})", span.line_start).unwrap();
-                write!(output, r#" | `{:<50}` | "{}" |"#, self.lint, self.diag.message).unwrap();
+                write!(output, r#" | `{:<50}` | "{}" |"#, self.name, self.diag.message).unwrap();
                 output.push('\n');
                 output
             },
@@ -164,7 +164,7 @@ fn gather_stats(warnings: &[ClippyWarning]) -> (String, HashMap<&String, usize>)
     let mut counter: HashMap<&String, usize> = HashMap::new();
     warnings
         .iter()
-        .for_each(|wrn| *counter.entry(&wrn.lint).or_insert(0) += 1);
+        .for_each(|wrn| *counter.entry(&wrn.name).or_insert(0) += 1);
 
     // collect into a tupled list for sorting
     let mut stats: Vec<(&&String, &usize)> = counter.iter().collect();
diff --git a/rust-toolchain b/rust-toolchain
index 5fbe4e544a9e4..0be2e81810ebe 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,4 +1,4 @@
 [toolchain]
-channel = "nightly-2024-08-08"
+channel = "nightly-2024-08-23"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
 profile = "minimal"
diff --git a/tests/compile-test.rs b/tests/compile-test.rs
index 64253514fbe67..9754254cdd0df 100644
--- a/tests/compile-test.rs
+++ b/tests/compile-test.rs
@@ -1,25 +1,31 @@
-// We need this feature as it changes `dylib` linking behavior and allows us to link to
-// `rustc_driver`.
-#![feature(rustc_private)]
+#![feature(rustc_private, let_chains)]
 #![warn(rust_2018_idioms, unused_lifetimes)]
 #![allow(unused_extern_crates)]
 
+use cargo_metadata::diagnostic::{Applicability, Diagnostic};
+use cargo_metadata::Message;
+use clippy_config::ClippyConfiguration;
+use clippy_lints::declared_lints::LINTS;
+use clippy_lints::deprecated_lints::{DEPRECATED, DEPRECATED_VERSION, RENAMED};
+use clippy_lints::LintInfo;
+use serde::{Deserialize, Serialize};
+use test_utils::IS_RUSTC_TEST_SUITE;
 use ui_test::custom_flags::rustfix::RustfixMode;
+use ui_test::custom_flags::Flag;
 use ui_test::spanned::Spanned;
+use ui_test::test_result::TestRun;
 use ui_test::{status_emitter, Args, CommandBuilder, Config, Match, OutputConflictHandling};
 
-use std::collections::BTreeMap;
+use std::collections::{BTreeMap, HashMap};
 use std::env::{self, set_var, var_os};
 use std::ffi::{OsStr, OsString};
-use std::fs;
+use std::fmt::Write;
 use std::path::{Path, PathBuf};
-use std::sync::LazyLock;
-use test_utils::IS_RUSTC_TEST_SUITE;
+use std::sync::mpsc::{channel, Sender};
+use std::{fs, iter, thread};
 
 // Test dependencies may need an `extern crate` here to ensure that they show up
 // in the depinfo file (otherwise cargo thinks they are unused)
-extern crate clippy_lints;
-extern crate clippy_utils;
 extern crate futures;
 extern crate if_chain;
 extern crate itertools;
@@ -55,7 +61,7 @@ static TEST_DEPENDENCIES: &[&str] = &[
 /// dependencies must be added to Cargo.toml at the project root. Test
 /// dependencies that are not *directly* used by this test module require an
 /// `extern crate` declaration.
-static EXTERN_FLAGS: LazyLock<Vec<String>> = LazyLock::new(|| {
+fn extern_flags() -> Vec<String> {
     let current_exe_depinfo = {
         let mut path = env::current_exe().unwrap();
         path.set_extension("d");
@@ -103,70 +109,93 @@ static EXTERN_FLAGS: LazyLock<Vec<String>> = LazyLock::new(|| {
         .into_iter()
         .map(|(name, path)| format!("--extern={name}={path}"))
         .collect()
-});
+}
 
 // whether to run internal tests or not
 const RUN_INTERNAL_TESTS: bool = cfg!(feature = "internal");
 
-fn base_config(test_dir: &str) -> (Config, Args) {
-    let mut args = Args::test().unwrap();
-    args.bless |= var_os("RUSTC_BLESS").is_some_and(|v| v != "0");
-
-    let target_dir = PathBuf::from(var_os("CARGO_TARGET_DIR").unwrap_or_else(|| "target".into()));
-    let mut config = Config {
-        output_conflict_handling: OutputConflictHandling::Error,
-        filter_files: env::var("TESTNAME")
-            .map(|filters| filters.split(',').map(str::to_string).collect())
-            .unwrap_or_default(),
-        target: None,
-        bless_command: Some("cargo uibless".into()),
-        out_dir: target_dir.join("ui_test"),
-        ..Config::rustc(Path::new("tests").join(test_dir))
-    };
-    config.comment_defaults.base().exit_status = None.into();
-    config.comment_defaults.base().require_annotations = None.into();
-    config
-        .comment_defaults
-        .base()
-        .set_custom("rustfix", RustfixMode::Everything);
-    config.comment_defaults.base().diagnostic_code_prefix = Some(Spanned::dummy("clippy::".into())).into();
-    config.with_args(&args);
-    let current_exe_path = env::current_exe().unwrap();
-    let deps_path = current_exe_path.parent().unwrap();
-    let profile_path = deps_path.parent().unwrap();
-
-    config.program.args.extend(
-        [
-            "--emit=metadata",
-            "-Aunused",
-            "-Ainternal_features",
-            "-Zui-testing",
-            "-Zdeduplicate-diagnostics=no",
-            "-Dwarnings",
-            &format!("-Ldependency={}", deps_path.display()),
-        ]
-        .map(OsString::from),
-    );
-
-    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())));
+struct TestContext {
+    args: Args,
+    extern_flags: Vec<String>,
+    diagnostic_collector: Option<DiagnosticCollector>,
+    collector_thread: Option<thread::JoinHandle<()>>,
+}
 
-    if let Some(host_libs) = option_env!("HOST_LIBS") {
-        let dep = format!("-Ldependency={}", Path::new(host_libs).join("deps").display());
-        config.program.args.push(dep.into());
+impl TestContext {
+    fn new() -> Self {
+        let mut args = Args::test().unwrap();
+        args.bless |= var_os("RUSTC_BLESS").is_some_and(|v| v != "0");
+        let (diagnostic_collector, collector_thread) = var_os("COLLECT_METADATA")
+            .is_some()
+            .then(DiagnosticCollector::spawn)
+            .unzip();
+        Self {
+            args,
+            extern_flags: extern_flags(),
+            diagnostic_collector,
+            collector_thread,
+        }
     }
 
-    config.program.program = profile_path.join(if cfg!(windows) {
-        "clippy-driver.exe"
-    } else {
-        "clippy-driver"
-    });
-    (config, args)
+    fn base_config(&self, test_dir: &str) -> Config {
+        let target_dir = PathBuf::from(var_os("CARGO_TARGET_DIR").unwrap_or_else(|| "target".into()));
+        let mut config = Config {
+            output_conflict_handling: OutputConflictHandling::Error,
+            filter_files: env::var("TESTNAME")
+                .map(|filters| filters.split(',').map(str::to_string).collect())
+                .unwrap_or_default(),
+            target: None,
+            bless_command: Some("cargo uibless".into()),
+            out_dir: target_dir.join("ui_test"),
+            ..Config::rustc(Path::new("tests").join(test_dir))
+        };
+        let defaults = config.comment_defaults.base();
+        defaults.exit_status = None.into();
+        defaults.require_annotations = None.into();
+        defaults.diagnostic_code_prefix = Some(Spanned::dummy("clippy::".into())).into();
+        defaults.set_custom("rustfix", RustfixMode::Everything);
+        if let Some(collector) = self.diagnostic_collector.clone() {
+            defaults.set_custom("diagnostic-collector", collector);
+        }
+        config.with_args(&self.args);
+        let current_exe_path = env::current_exe().unwrap();
+        let deps_path = current_exe_path.parent().unwrap();
+        let profile_path = deps_path.parent().unwrap();
+
+        config.program.args.extend(
+            [
+                "--emit=metadata",
+                "-Aunused",
+                "-Ainternal_features",
+                "-Zui-testing",
+                "-Zdeduplicate-diagnostics=no",
+                "-Dwarnings",
+                &format!("-Ldependency={}", deps_path.display()),
+            ]
+            .map(OsString::from),
+        );
+
+        config.program.args.extend(self.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());
+            config.program.args.push(dep.into());
+        }
+
+        config.program.program = profile_path.join(if cfg!(windows) {
+            "clippy-driver.exe"
+        } else {
+            "clippy-driver"
+        });
+
+        config
+    }
 }
 
-fn run_ui() {
-    let (mut config, args) = base_config("ui");
+fn run_ui(cx: &TestContext) {
+    let mut config = cx.base_config("ui");
     config
         .program
         .envs
@@ -176,30 +205,29 @@ fn run_ui() {
         vec![config],
         ui_test::default_file_filter,
         ui_test::default_per_file_config,
-        status_emitter::Text::from(args.format),
+        status_emitter::Text::from(cx.args.format),
     )
     .unwrap();
 }
 
-fn run_internal_tests() {
-    // only run internal tests with the internal-tests feature
+fn run_internal_tests(cx: &TestContext) {
     if !RUN_INTERNAL_TESTS {
         return;
     }
-    let (mut config, args) = base_config("ui-internal");
+    let mut config = cx.base_config("ui-internal");
     config.bless_command = Some("cargo uitest --features internal -- -- --bless".into());
 
     ui_test::run_tests_generic(
         vec![config],
         ui_test::default_file_filter,
         ui_test::default_per_file_config,
-        status_emitter::Text::from(args.format),
+        status_emitter::Text::from(cx.args.format),
     )
     .unwrap();
 }
 
-fn run_ui_toml() {
-    let (mut config, args) = base_config("ui-toml");
+fn run_ui_toml(cx: &TestContext) {
+    let mut config = cx.base_config("ui-toml");
 
     config
         .comment_defaults
@@ -217,19 +245,19 @@ fn run_ui_toml() {
                 .envs
                 .push(("CLIPPY_CONF_DIR".into(), Some(path.parent().unwrap().into())));
         },
-        status_emitter::Text::from(args.format),
+        status_emitter::Text::from(cx.args.format),
     )
     .unwrap();
 }
 
 // Allow `Default::default` as `OptWithSpan` is not nameable
 #[allow(clippy::default_trait_access)]
-fn run_ui_cargo() {
+fn run_ui_cargo(cx: &TestContext) {
     if IS_RUSTC_TEST_SUITE {
         return;
     }
 
-    let (mut config, args) = base_config("ui-cargo");
+    let mut config = cx.base_config("ui-cargo");
     config.program.input_file_flag = CommandBuilder::cargo().input_file_flag;
     config.program.out_dir_flag = CommandBuilder::cargo().out_dir_flag;
     config.program.args = vec!["clippy".into(), "--color".into(), "never".into(), "--quiet".into()];
@@ -264,23 +292,25 @@ fn run_ui_cargo() {
                 .then(|| ui_test::default_any_file_filter(path, config) && !ignored_32bit(path))
         },
         |_config, _file_contents| {},
-        status_emitter::Text::from(args.format),
+        status_emitter::Text::from(cx.args.format),
     )
     .unwrap();
 }
 
 fn main() {
     set_var("CLIPPY_DISABLE_DOCS_LINKS", "true");
+
+    let cx = TestContext::new();
+
     // The SPEEDTEST_* env variables can be used to check Clippy's performance on your PR. It runs the
     // affected test 1000 times and gets the average.
     if let Ok(speedtest) = std::env::var("SPEEDTEST") {
         println!("----------- STARTING SPEEDTEST -----------");
         let f = match speedtest.as_str() {
-            "ui" => run_ui as fn(),
-            "cargo" => run_ui_cargo as fn(),
-            "toml" => run_ui_toml as fn(),
-            "internal" => run_internal_tests as fn(),
-            "ui-cargo-toml-metadata" => ui_cargo_toml_metadata as fn(),
+            "ui" => run_ui,
+            "cargo" => run_ui_cargo,
+            "toml" => run_ui_toml,
+            "internal" => run_internal_tests,
 
             _ => panic!("unknown speedtest: {speedtest} || accepted speedtests are: [ui, cargo, toml, internal]"),
         };
@@ -297,7 +327,7 @@ fn main() {
         let mut sum = 0;
         for _ in 0..iterations {
             let start = std::time::Instant::now();
-            f();
+            f(&cx);
             sum += start.elapsed().as_millis();
         }
         println!(
@@ -306,11 +336,17 @@ fn main() {
             sum / u128::from(iterations)
         );
     } else {
-        run_ui();
-        run_ui_toml();
-        run_ui_cargo();
-        run_internal_tests();
+        run_ui(&cx);
+        run_ui_toml(&cx);
+        run_ui_cargo(&cx);
+        run_internal_tests(&cx);
+        drop(cx.diagnostic_collector);
+
         ui_cargo_toml_metadata();
+
+        if let Some(thread) = cx.collector_thread {
+            thread.join().unwrap();
+        }
     }
 }
 
@@ -349,3 +385,180 @@ fn ui_cargo_toml_metadata() {
         );
     }
 }
+
+#[derive(Deserialize)]
+#[serde(untagged)]
+enum DiagnosticOrMessage {
+    Diagnostic(Diagnostic),
+    Message(Message),
+}
+
+/// Collects applicabilities from the diagnostics produced for each UI test, producing the
+/// `util/gh-pages/lints.json` file used by <https://rust-lang.github.io/rust-clippy/>
+#[derive(Debug, Clone)]
+struct DiagnosticCollector {
+    sender: Sender<Vec<u8>>,
+}
+
+impl DiagnosticCollector {
+    #[allow(clippy::assertions_on_constants)]
+    fn spawn() -> (Self, thread::JoinHandle<()>) {
+        assert!(!IS_RUSTC_TEST_SUITE && !RUN_INTERNAL_TESTS);
+
+        let (sender, receiver) = channel::<Vec<u8>>();
+
+        let handle = thread::spawn(|| {
+            let mut applicabilities = HashMap::new();
+
+            for stderr in receiver {
+                for line in stderr.split(|&byte| byte == b'\n') {
+                    let diag = match serde_json::from_slice(line) {
+                        Ok(DiagnosticOrMessage::Diagnostic(diag)) => diag,
+                        Ok(DiagnosticOrMessage::Message(Message::CompilerMessage(message))) => message.message,
+                        _ => continue,
+                    };
+
+                    if let Some(lint) = diag.code.as_ref().and_then(|code| code.code.strip_prefix("clippy::")) {
+                        let applicability = applicabilities
+                            .entry(lint.to_string())
+                            .or_insert(Applicability::Unspecified);
+                        let diag_applicability = diag
+                            .children
+                            .iter()
+                            .flat_map(|child| &child.spans)
+                            .filter_map(|span| span.suggestion_applicability.clone())
+                            .max_by_key(applicability_ord);
+                        if let Some(diag_applicability) = diag_applicability
+                            && applicability_ord(&diag_applicability) > applicability_ord(applicability)
+                        {
+                            *applicability = diag_applicability;
+                        }
+                    }
+                }
+            }
+
+            let configs = clippy_config::get_configuration_metadata();
+            let mut metadata: Vec<LintMetadata> = LINTS
+                .iter()
+                .map(|lint| LintMetadata::new(lint, &applicabilities, &configs))
+                .chain(
+                    iter::zip(DEPRECATED, DEPRECATED_VERSION)
+                        .map(|((lint, reason), version)| LintMetadata::new_deprecated(lint, reason, version)),
+                )
+                .collect();
+            metadata.sort_unstable_by(|a, b| a.id.cmp(&b.id));
+
+            let json = serde_json::to_string_pretty(&metadata).unwrap();
+            fs::write("util/gh-pages/lints.json", json).unwrap();
+        });
+
+        (Self { sender }, handle)
+    }
+}
+
+fn applicability_ord(applicability: &Applicability) -> u8 {
+    match applicability {
+        Applicability::MachineApplicable => 4,
+        Applicability::HasPlaceholders => 3,
+        Applicability::MaybeIncorrect => 2,
+        Applicability::Unspecified => 1,
+        _ => unimplemented!(),
+    }
+}
+
+impl Flag for DiagnosticCollector {
+    fn post_test_action(
+        &self,
+        _config: &ui_test::per_test_config::TestConfig<'_>,
+        _cmd: &mut std::process::Command,
+        output: &std::process::Output,
+        _build_manager: &ui_test::build_manager::BuildManager<'_>,
+    ) -> Result<Vec<TestRun>, ui_test::Errored> {
+        if !output.stderr.is_empty() {
+            self.sender.send(output.stderr.clone()).unwrap();
+        }
+        Ok(Vec::new())
+    }
+
+    fn clone_inner(&self) -> Box<dyn Flag> {
+        Box::new(self.clone())
+    }
+
+    fn must_be_unique(&self) -> bool {
+        true
+    }
+}
+
+#[derive(Debug, Serialize)]
+struct LintMetadata {
+    id: String,
+    id_location: Option<&'static str>,
+    group: &'static str,
+    level: &'static str,
+    docs: String,
+    version: &'static str,
+    applicability: Applicability,
+}
+
+impl LintMetadata {
+    fn new(lint: &LintInfo, applicabilities: &HashMap<String, Applicability>, configs: &[ClippyConfiguration]) -> Self {
+        let name = lint.name_lower();
+        let applicability = applicabilities
+            .get(&name)
+            .cloned()
+            .unwrap_or(Applicability::Unspecified);
+        let past_names = RENAMED
+            .iter()
+            .filter(|(_, new_name)| new_name.strip_prefix("clippy::") == Some(&name))
+            .map(|(old_name, _)| old_name.strip_prefix("clippy::").unwrap())
+            .collect::<Vec<_>>();
+        let mut docs = lint.explanation.to_string();
+        if !past_names.is_empty() {
+            docs.push_str("\n### Past names\n\n");
+            for past_name in past_names {
+                writeln!(&mut docs, " * {past_name}").unwrap();
+            }
+        }
+        let configs: Vec<_> = configs
+            .iter()
+            .filter(|conf| conf.lints.contains(&name.as_str()))
+            .collect();
+        if !configs.is_empty() {
+            docs.push_str("\n### Configuration\n\n");
+            for config in configs {
+                writeln!(&mut docs, "{config}").unwrap();
+            }
+        }
+        Self {
+            id: name,
+            id_location: Some(lint.location),
+            group: lint.category_str(),
+            level: lint.lint.default_level.as_str(),
+            docs,
+            version: lint.version.unwrap(),
+            applicability,
+        }
+    }
+
+    fn new_deprecated(name: &str, reason: &str, version: &'static str) -> Self {
+        // The reason starts with a lowercase letter and ends without a period.
+        // This needs to be fixed for the website.
+        let mut reason = reason.to_owned();
+        if let Some(reason) = reason.get_mut(0..1) {
+            reason.make_ascii_uppercase();
+        }
+        Self {
+            id: name.strip_prefix("clippy::").unwrap().into(),
+            id_location: None,
+            group: "deprecated",
+            level: "none",
+            version,
+            docs: format!(
+                "### What it does\n\n\
+                Nothing. This lint has been deprecated\n\n\
+                ### Deprecation reason\n\n{reason}.\n",
+            ),
+            applicability: Applicability::Unspecified,
+        }
+    }
+}
diff --git a/tests/config-metadata.rs b/tests/config-metadata.rs
new file mode 100644
index 0000000000000..3e3711873baa5
--- /dev/null
+++ b/tests/config-metadata.rs
@@ -0,0 +1,78 @@
+#![feature(rustc_private)]
+
+use clippy_config::{get_configuration_metadata, ClippyConfiguration};
+use itertools::Itertools;
+use regex::Regex;
+use std::borrow::Cow;
+use std::{env, fs};
+
+fn metadata() -> impl Iterator<Item = ClippyConfiguration> {
+    get_configuration_metadata()
+        .into_iter()
+        .filter(|config| config.deprecation_reason.is_none())
+        .filter(|config| !config.lints.is_empty())
+}
+
+#[test]
+fn book() {
+    let path = "book/src/lint_configuration.md";
+    let current = fs::read_to_string(path).unwrap();
+
+    let configs = metadata().map(|conf| conf.to_markdown_paragraph()).join("\n");
+    let expected = format!(
+        r#"<!--
+This file is generated by `cargo bless --test config-metadata`.
+Please use that command to update the file and do not edit it by hand.
+-->
+
+# Lint Configuration Options
+
+The following list shows each configuration option, along with a description, its default value, an example
+and lints affected.
+
+---
+
+{}
+"#,
+        configs.trim(),
+    );
+
+    if current != expected {
+        if env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0") {
+            fs::write(path, expected).unwrap();
+        } else {
+            panic!("`{path}` is out of date, run `cargo bless --test config-metadata` to update it");
+        }
+    }
+}
+
+#[test]
+fn changelog() {
+    let path = "CHANGELOG.md";
+    let current = fs::read_to_string(path).unwrap();
+
+    let configs = metadata().map(|conf| conf.to_markdown_link()).join("\n");
+
+    let re = Regex::new(
+        "(?s)\
+        (<!-- begin autogenerated links to configuration documentation -->)\
+        .*\
+        (<!-- end autogenerated links to configuration documentation -->)\
+        ",
+    )
+    .unwrap();
+    let expected = re.replace(&current, format!("$1\n{configs}\n$2"));
+
+    assert!(
+        matches!(expected, Cow::Owned(_)),
+        "failed to find configuration section in `{path}`"
+    );
+
+    if current != expected {
+        if env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0") {
+            fs::write(path, expected.as_bytes()).unwrap();
+        } else {
+            panic!("`{path}` is out of date, run `cargo bless --test config-metadata` to update it");
+        }
+    }
+}
diff --git a/tests/ui-toml/absolute_paths/absolute_paths.allow_crates.stderr b/tests/ui-toml/absolute_paths/absolute_paths.allow_crates.stderr
index 1cc1034cd89b3..d24b0cd616294 100644
--- a/tests/ui-toml/absolute_paths/absolute_paths.allow_crates.stderr
+++ b/tests/ui-toml/absolute_paths/absolute_paths.allow_crates.stderr
@@ -1,29 +1,44 @@
 error: consider bringing this path into scope with the `use` keyword
-  --> tests/ui-toml/absolute_paths/absolute_paths.rs:40:5
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:14:13
    |
-LL |     std::f32::MAX;
-   |     ^^^^^^^^^^^^^
+LL |     let _ = std::path::is_separator(' ');
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `-D clippy::absolute-paths` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::absolute_paths)]`
+note: the lint level is defined here
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:7:9
+   |
+LL | #![deny(clippy::absolute_paths)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:20:13
+   |
+LL |     let _ = ::std::path::MAIN_SEPARATOR;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:25:13
+   |
+LL |     let _ = std::collections::hash_map::HashMap::<i32, i32>::new();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: consider bringing this path into scope with the `use` keyword
-  --> tests/ui-toml/absolute_paths/absolute_paths.rs:41:5
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:31
    |
-LL |     core::f32::MAX;
-   |     ^^^^^^^^^^^^^^
+LL |     let _: &std::path::Path = std::path::Path::new("");
+   |                               ^^^^^^^^^^^^^^^
 
 error: consider bringing this path into scope with the `use` keyword
-  --> tests/ui-toml/absolute_paths/absolute_paths.rs:42:5
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:13
    |
-LL |     ::core::f32::MAX;
-   |     ^^^^^^^^^^^^^^^^
+LL |     let _: &std::path::Path = std::path::Path::new("");
+   |             ^^^^^^^^^^^^^^^
 
 error: consider bringing this path into scope with the `use` keyword
-  --> tests/ui-toml/absolute_paths/absolute_paths.rs:58:5
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:43:13
    |
-LL |     ::std::f32::MAX;
-   |     ^^^^^^^^^^^^^^^
+LL |     let _ = std::option::Option::None::<i32>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui-toml/absolute_paths/absolute_paths.allow_long.stderr b/tests/ui-toml/absolute_paths/absolute_paths.allow_long.stderr
new file mode 100644
index 0000000000000..0cc6566af3a96
--- /dev/null
+++ b/tests/ui-toml/absolute_paths/absolute_paths.allow_long.stderr
@@ -0,0 +1,14 @@
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:25:13
+   |
+LL |     let _ = std::collections::hash_map::HashMap::<i32, i32>::new();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:7:9
+   |
+LL | #![deny(clippy::absolute_paths)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui-toml/absolute_paths/absolute_paths.default.stderr b/tests/ui-toml/absolute_paths/absolute_paths.default.stderr
new file mode 100644
index 0000000000000..53aa9030e0dd5
--- /dev/null
+++ b/tests/ui-toml/absolute_paths/absolute_paths.default.stderr
@@ -0,0 +1,80 @@
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:14:13
+   |
+LL |     let _ = std::path::is_separator(' ');
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:7:9
+   |
+LL | #![deny(clippy::absolute_paths)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:20:13
+   |
+LL |     let _ = ::std::path::MAIN_SEPARATOR;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:25:13
+   |
+LL |     let _ = std::collections::hash_map::HashMap::<i32, i32>::new();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:31
+   |
+LL |     let _: &std::path::Path = std::path::Path::new("");
+   |                               ^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:13
+   |
+LL |     let _: &std::path::Path = std::path::Path::new("");
+   |             ^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:37:13
+   |
+LL |     let _ = ::core::clone::Clone::clone(&0i32);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:40:13
+   |
+LL |     let _ = <i32 as core::clone::Clone>::clone(&0i32);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:43:13
+   |
+LL |     let _ = std::option::Option::None::<i32>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:65:17
+   |
+LL |         impl<T: core::cmp::Eq> core::fmt::Display for X<T>
+   |                 ^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:70:18
+   |
+LL |         where T: core::clone::Clone
+   |                  ^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:65:32
+   |
+LL |         impl<T: core::cmp::Eq> core::fmt::Display for X<T>
+   |                                ^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:116:5
+   |
+LL |     crate::m1::S
+   |     ^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
+
diff --git a/tests/ui-toml/absolute_paths/absolute_paths.disallow_crates.stderr b/tests/ui-toml/absolute_paths/absolute_paths.disallow_crates.stderr
deleted file mode 100644
index f342ebf6632e8..0000000000000
--- a/tests/ui-toml/absolute_paths/absolute_paths.disallow_crates.stderr
+++ /dev/null
@@ -1,71 +0,0 @@
-error: consider bringing this path into scope with the `use` keyword
-  --> tests/ui-toml/absolute_paths/absolute_paths.rs:40:5
-   |
-LL |     std::f32::MAX;
-   |     ^^^^^^^^^^^^^
-   |
-   = note: `-D clippy::absolute-paths` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::absolute_paths)]`
-
-error: consider bringing this path into scope with the `use` keyword
-  --> tests/ui-toml/absolute_paths/absolute_paths.rs:41:5
-   |
-LL |     core::f32::MAX;
-   |     ^^^^^^^^^^^^^^
-
-error: consider bringing this path into scope with the `use` keyword
-  --> tests/ui-toml/absolute_paths/absolute_paths.rs:42:5
-   |
-LL |     ::core::f32::MAX;
-   |     ^^^^^^^^^^^^^^^^
-
-error: consider bringing this path into scope with the `use` keyword
-  --> tests/ui-toml/absolute_paths/absolute_paths.rs:43:5
-   |
-LL |     crate::a::b::c::C;
-   |     ^^^^^^^^^^^^^^^^^
-
-error: consider bringing this path into scope with the `use` keyword
-  --> tests/ui-toml/absolute_paths/absolute_paths.rs:44:5
-   |
-LL |     crate::a::b::c::d::e::f::F;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: consider bringing this path into scope with the `use` keyword
-  --> tests/ui-toml/absolute_paths/absolute_paths.rs:45:5
-   |
-LL |     crate::a::A;
-   |     ^^^^^^^^^^^
-
-error: consider bringing this path into scope with the `use` keyword
-  --> tests/ui-toml/absolute_paths/absolute_paths.rs:46:5
-   |
-LL |     crate::a::b::B;
-   |     ^^^^^^^^^^^^^^
-
-error: consider bringing this path into scope with the `use` keyword
-  --> tests/ui-toml/absolute_paths/absolute_paths.rs:47:5
-   |
-LL |     crate::a::b::c::C::ZERO;
-   |     ^^^^^^^^^^^^^^^^^
-
-error: consider bringing this path into scope with the `use` keyword
-  --> tests/ui-toml/absolute_paths/absolute_paths.rs:48:5
-   |
-LL |     helper::b::c::d::e::f();
-   |     ^^^^^^^^^^^^^^^^^^^^^
-
-error: consider bringing this path into scope with the `use` keyword
-  --> tests/ui-toml/absolute_paths/absolute_paths.rs:49:5
-   |
-LL |     ::helper::b::c::d::e::f();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: consider bringing this path into scope with the `use` keyword
-  --> tests/ui-toml/absolute_paths/absolute_paths.rs:58:5
-   |
-LL |     ::std::f32::MAX;
-   |     ^^^^^^^^^^^^^^^
-
-error: aborting due to 11 previous errors
-
diff --git a/tests/ui-toml/absolute_paths/absolute_paths.no_short.stderr b/tests/ui-toml/absolute_paths/absolute_paths.no_short.stderr
new file mode 100644
index 0000000000000..70d71f6c4ea16
--- /dev/null
+++ b/tests/ui-toml/absolute_paths/absolute_paths.no_short.stderr
@@ -0,0 +1,98 @@
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:14:13
+   |
+LL |     let _ = std::path::is_separator(' ');
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:7:9
+   |
+LL | #![deny(clippy::absolute_paths)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:20:13
+   |
+LL |     let _ = ::std::path::MAIN_SEPARATOR;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:25:13
+   |
+LL |     let _ = std::collections::hash_map::HashMap::<i32, i32>::new();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:31
+   |
+LL |     let _: &std::path::Path = std::path::Path::new("");
+   |                               ^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:13
+   |
+LL |     let _: &std::path::Path = std::path::Path::new("");
+   |             ^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:37:13
+   |
+LL |     let _ = ::core::clone::Clone::clone(&0i32);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:40:13
+   |
+LL |     let _ = <i32 as core::clone::Clone>::clone(&0i32);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:43:13
+   |
+LL |     let _ = std::option::Option::None::<i32>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:65:17
+   |
+LL |         impl<T: core::cmp::Eq> core::fmt::Display for X<T>
+   |                 ^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:70:18
+   |
+LL |         where T: core::clone::Clone
+   |                  ^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:65:32
+   |
+LL |         impl<T: core::cmp::Eq> core::fmt::Display for X<T>
+   |                                ^^^^^^^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:113:14
+   |
+LL | pub const _: crate::S = {
+   |              ^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:114:9
+   |
+LL |     let crate::S = m1::S;
+   |         ^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:116:5
+   |
+LL |     crate::m1::S
+   |     ^^^^^^^^^^^^
+
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths.rs:122:14
+   |
+LL |     let _ = <crate::S as Clone>::clone(&m1::S);
+   |              ^^^^^^^^
+
+error: aborting due to 15 previous errors
+
diff --git a/tests/ui-toml/absolute_paths/absolute_paths.rs b/tests/ui-toml/absolute_paths/absolute_paths.rs
index a828701bcee9f..c024f2f513ced 100644
--- a/tests/ui-toml/absolute_paths/absolute_paths.rs
+++ b/tests/ui-toml/absolute_paths/absolute_paths.rs
@@ -1,97 +1,123 @@
 //@aux-build:../../ui/auxiliary/proc_macros.rs
-//@aux-build:helper.rs
-//@revisions: allow_crates disallow_crates
+//@revisions: default allow_crates allow_long no_short
+//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/default
 //@[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, clippy::legacy_numeric_constants, unused)]
-#![warn(clippy::absolute_paths)]
-#![feature(decl_macro)]
+//@[allow_long] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/allow_long
+//@[no_short] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/no_short
+#![deny(clippy::absolute_paths)]
 
-extern crate helper;
-#[macro_use]
 extern crate proc_macros;
+use proc_macros::{external, inline_macros, with_span};
 
-pub mod a {
-    pub mod b {
-        pub mod c {
-            pub struct C;
+#[inline_macros]
+fn main() {
+    let _ = std::path::is_separator(' ');
+    //~[default]^ absolute_paths
+    //~[allow_crates]| absolute_paths
+    //~[no_short]| absolute_paths
 
-            impl C {
-                pub const ZERO: u32 = 0;
-            }
+    // Make sure this is treated as having three path segments, not four.
+    let _ = ::std::path::MAIN_SEPARATOR;
+    //~[default]^ absolute_paths
+    //~[allow_crates]| absolute_paths
+    //~[no_short]| absolute_paths
 
-            pub mod d {
-                pub mod e {
-                    pub mod f {
-                        pub struct F;
-                    }
-                }
-            }
-        }
+    let _ = std::collections::hash_map::HashMap::<i32, i32>::new(); //~ absolute_paths
 
-        pub struct B;
-    }
+    // Note `std::path::Path::new` is treated as having three parts
+    let _: &std::path::Path = std::path::Path::new("");
+    //~[default]^ absolute_paths
+    //~[default]| absolute_paths
+    //~[allow_crates]| absolute_paths
+    //~[allow_crates]| absolute_paths
+    //~[no_short]| absolute_paths
+    //~[no_short]| absolute_paths
 
-    pub struct A;
-}
+    // Treated as having three parts.
+    let _ = ::core::clone::Clone::clone(&0i32);
+    //~[default]^ absolute_paths
+    //~[no_short]| absolute_paths
+    let _ = <i32 as core::clone::Clone>::clone(&0i32);
+    //~[default]^ absolute_paths
+    //~[no_short]| absolute_paths
+    let _ = std::option::Option::None::<i32>;
+    //~[default]^ absolute_paths
+    //~[allow_crates]| absolute_paths
+    //~[no_short]| absolute_paths
 
-fn main() {
-    f32::max(1.0, 2.0);
-    std::f32::MAX;
-    core::f32::MAX;
-    ::core::f32::MAX;
-    crate::a::b::c::C;
-    crate::a::b::c::d::e::f::F;
-    crate::a::A;
-    crate::a::b::B;
-    crate::a::b::c::C::ZERO;
-    helper::b::c::d::e::f();
-    ::helper::b::c::d::e::f();
-    fn b() -> a::b::B {
-        todo!()
+    {
+        // FIXME: macro calls should be checked.
+        let x = 1i32;
+        let _ = core::ptr::addr_of!(x);
     }
-    std::println!("a");
-    let x = 1;
-    std::ptr::addr_of!(x);
-    // Test we handle max segments with `PathRoot` properly; this has 4 segments but we should say it
-    // has 3
-    ::std::f32::MAX;
-    // Do not lint due to the above
-    ::helper::a();
-    // Do not lint
-    helper::a();
-    use crate::a::b::c::C;
-    use a::b;
-    use std::f32::MAX;
-    a::b::c::d::e::f::F;
-    b::c::C;
-    fn a() -> a::A {
-        todo!()
-    }
-    use a::b::c;
 
-    fn c() -> c::C {
-        todo!()
+    {
+        // FIXME: derive macro paths should be checked.
+        #[derive(core::clone::Clone)]
+        struct S;
     }
-    fn d() -> Result<(), ()> {
-        todo!()
+
+    {
+        use core::fmt;
+        use core::marker::PhantomData;
+
+        struct X<T>(PhantomData<T>);
+        impl<T: core::cmp::Eq> core::fmt::Display for X<T>
+        //~[default]^ absolute_paths
+        //~[default]| absolute_paths
+        //~[no_short]| absolute_paths
+        //~[no_short]| absolute_paths
+        where T: core::clone::Clone
+        //~[no_short]^ absolute_paths
+        //~[default]| absolute_paths
+        {
+            fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
+                Ok(())
+            }
+        }
     }
-    external! {
-        crate::a::b::c::C::ZERO;
+
+    {
+        mod m1 {
+            pub(crate) mod m2 {
+                pub(crate) const FOO: i32 = 0;
+            }
+        }
+        let _ = m1::m2::FOO;
     }
-    // For some reason, `path.span.from_expansion()` takes care of this for us
+
     with_span! {
         span
-        crate::a::b::c::C::ZERO;
+        let _ = std::path::is_separator(' ');
     }
-    macro_rules! local_crate {
-        () => {
-            crate::a::b::c::C::ZERO;
-        };
+
+    external! {
+        let _ = std::path::is_separator(' ');
     }
-    macro local_crate_2_0() {
-        crate::a::b::c::C::ZERO;
+
+    inline! {
+        let _ = std::path::is_separator(' ');
     }
-    local_crate!();
-    local_crate_2_0!();
+}
+
+pub use core::cmp::Ordering;
+pub use std::fs::File;
+
+#[derive(Clone)]
+pub struct S;
+mod m1 {
+    pub use crate::S;
+}
+
+//~[no_short]v absolute_paths
+pub const _: crate::S = {
+    let crate::S = m1::S; //~[no_short] absolute_paths
+
+    crate::m1::S
+    //~[default]^ absolute_paths
+    //~[no_short]| absolute_paths
+};
+
+pub fn f() {
+    let _ = <crate::S as Clone>::clone(&m1::S); //~[no_short] absolute_paths
 }
diff --git a/tests/ui-toml/absolute_paths/absolute_paths_2015.default.stderr b/tests/ui-toml/absolute_paths/absolute_paths_2015.default.stderr
new file mode 100644
index 0000000000000..6fc495f018080
--- /dev/null
+++ b/tests/ui-toml/absolute_paths/absolute_paths_2015.default.stderr
@@ -0,0 +1,14 @@
+error: consider bringing this path into scope with the `use` keyword
+  --> tests/ui-toml/absolute_paths/absolute_paths_2015.rs:15:13
+   |
+LL |     let _ = ::m1::m2::X;
+   |             ^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> tests/ui-toml/absolute_paths/absolute_paths_2015.rs:6:9
+   |
+LL | #![deny(clippy::absolute_paths)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui-toml/absolute_paths/absolute_paths_2015.rs b/tests/ui-toml/absolute_paths/absolute_paths_2015.rs
new file mode 100644
index 0000000000000..033c47809191c
--- /dev/null
+++ b/tests/ui-toml/absolute_paths/absolute_paths_2015.rs
@@ -0,0 +1,16 @@
+//@revisions: default allow_crates
+//@[default]rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/default
+//@[allow_crates]rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/allow_crates
+//@edition:2015
+
+#![deny(clippy::absolute_paths)]
+
+mod m1 {
+    pub mod m2 {
+        pub struct X;
+    }
+}
+
+fn main() {
+    let _ = ::m1::m2::X; //~[default] absolute_paths
+}
diff --git a/tests/ui-toml/absolute_paths/allow_crates/clippy.toml b/tests/ui-toml/absolute_paths/allow_crates/clippy.toml
index 59a621e9d1dba..9da49abcd31f6 100644
--- a/tests/ui-toml/absolute_paths/allow_crates/clippy.toml
+++ b/tests/ui-toml/absolute_paths/allow_crates/clippy.toml
@@ -1,2 +1 @@
-absolute-paths-max-segments = 2
-absolute-paths-allowed-crates = ["crate", "helper"]
+absolute-paths-allowed-crates = ["core", "crate"]
diff --git a/tests/ui-toml/absolute_paths/allow_long/clippy.toml b/tests/ui-toml/absolute_paths/allow_long/clippy.toml
new file mode 100644
index 0000000000000..5992fd1ed8219
--- /dev/null
+++ b/tests/ui-toml/absolute_paths/allow_long/clippy.toml
@@ -0,0 +1 @@
+absolute-paths-max-segments = 3
diff --git a/tests/ui-toml/absolute_paths/auxiliary/helper.rs b/tests/ui-toml/absolute_paths/auxiliary/helper.rs
deleted file mode 100644
index 8e2678f5fe697..0000000000000
--- a/tests/ui-toml/absolute_paths/auxiliary/helper.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-pub fn a() {}
-
-pub mod b {
-    pub mod c {
-        pub mod d {
-            pub mod e {
-                pub fn f() {}
-            }
-        }
-    }
-}
diff --git a/tests/ui-toml/absolute_paths/default/clippy.toml b/tests/ui-toml/absolute_paths/default/clippy.toml
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/tests/ui-toml/absolute_paths/disallow_crates/clippy.toml b/tests/ui-toml/absolute_paths/disallow_crates/clippy.toml
deleted file mode 100644
index d44d648c64118..0000000000000
--- a/tests/ui-toml/absolute_paths/disallow_crates/clippy.toml
+++ /dev/null
@@ -1 +0,0 @@
-absolute-paths-max-segments = 2
diff --git a/tests/ui-toml/absolute_paths/no_short/clippy.toml b/tests/ui-toml/absolute_paths/no_short/clippy.toml
new file mode 100644
index 0000000000000..357524420c5a6
--- /dev/null
+++ b/tests/ui-toml/absolute_paths/no_short/clippy.toml
@@ -0,0 +1 @@
+absolute-paths-max-segments = 0
diff --git a/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs b/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs
index a312df5a43a07..3dafea56514db 100644
--- a/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs
+++ b/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs
@@ -1,7 +1,7 @@
 //! Tests macro_metavars_in_unsafe with default configuration
 #![feature(decl_macro)]
 #![warn(clippy::macro_metavars_in_unsafe)]
-#![allow(clippy::no_effect)]
+#![allow(clippy::no_effect, clippy::not_unsafe_ptr_arg_deref)]
 
 #[macro_export]
 macro_rules! allow_works {
@@ -237,6 +237,19 @@ macro_rules! nested_macros {
     }};
 }
 
+pub mod issue13219 {
+    #[macro_export]
+    macro_rules! m {
+        ($e:expr) => {
+            // Metavariable in a block tail expression
+            unsafe { $e }
+        };
+    }
+    pub fn f(p: *const i32) -> i32 {
+        m!(*p)
+    }
+}
+
 fn main() {
     allow_works!(1);
     simple!(1);
diff --git a/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr b/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr
index d6b97f6fde1e1..6f0ebcbba0239 100644
--- a/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr
+++ b/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr
@@ -1,3 +1,15 @@
+error: this macro expands metavariables in an unsafe block
+  --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:245:13
+   |
+LL |             unsafe { $e }
+   |             ^^^^^^^^^^^^^
+   |
+   = note: this allows the user of the macro to write unsafe code outside of an unsafe block
+   = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
+   = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
+   = note: `-D clippy::macro-metavars-in-unsafe` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::macro_metavars_in_unsafe)]`
+
 error: this macro expands metavariables in an unsafe block
   --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:19:9
    |
@@ -10,8 +22,6 @@ LL | |         }
    = note: this allows the user of the macro to write unsafe code outside of an unsafe block
    = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
    = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
-   = note: `-D clippy::macro-metavars-in-unsafe` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::macro_metavars_in_unsafe)]`
 
 error: this macro expands metavariables in an unsafe block
   --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:30:9
@@ -183,5 +193,5 @@ LL | |         }
    = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable
    = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite
 
-error: aborting due to 14 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/tests/ui/assigning_clones.fixed b/tests/ui/assigning_clones.fixed
index b376d55a40250..09732d1a50ce0 100644
--- a/tests/ui/assigning_clones.fixed
+++ b/tests/ui/assigning_clones.fixed
@@ -396,3 +396,23 @@ impl<T: Clone> Clone for DerefWrapperWithClone<T> {
         *self = Self(source.0.clone());
     }
 }
+
+#[cfg(test)]
+mod test {
+    #[derive(Default)]
+    struct Data {
+        field: String,
+    }
+
+    fn test_data() -> Data {
+        Data {
+            field: "default_value".to_string(),
+        }
+    }
+
+    #[test]
+    fn test() {
+        let mut data = test_data();
+        data.field = "override_value".to_owned();
+    }
+}
diff --git a/tests/ui/assigning_clones.rs b/tests/ui/assigning_clones.rs
index 11a5d4459c350..6be25ae17a55d 100644
--- a/tests/ui/assigning_clones.rs
+++ b/tests/ui/assigning_clones.rs
@@ -396,3 +396,23 @@ impl<T: Clone> Clone for DerefWrapperWithClone<T> {
         *self = Self(source.0.clone());
     }
 }
+
+#[cfg(test)]
+mod test {
+    #[derive(Default)]
+    struct Data {
+        field: String,
+    }
+
+    fn test_data() -> Data {
+        Data {
+            field: "default_value".to_string(),
+        }
+    }
+
+    #[test]
+    fn test() {
+        let mut data = test_data();
+        data.field = "override_value".to_owned();
+    }
+}
diff --git a/tests/ui/checked_unwrap/complex_conditionals_nested.stderr b/tests/ui/checked_unwrap/complex_conditionals_nested.stderr
index f7e659b10de07..329be4d366210 100644
--- a/tests/ui/checked_unwrap/complex_conditionals_nested.stderr
+++ b/tests/ui/checked_unwrap/complex_conditionals_nested.stderr
@@ -2,7 +2,7 @@ error: called `unwrap` on `x` after checking its variant with `is_some`
   --> tests/ui/checked_unwrap/complex_conditionals_nested.rs:13:13
    |
 LL |         if x.is_some() {
-   |         -------------- help: try: `if let Some(..) = x`
+   |         -------------- help: try: `if let Some(<item>) = x`
 LL |             // unnecessary
 LL |             x.unwrap();
    |             ^^^^^^^^^^
diff --git a/tests/ui/checked_unwrap/simple_conditionals.stderr b/tests/ui/checked_unwrap/simple_conditionals.stderr
index ddd600418afec..f7e338935a770 100644
--- a/tests/ui/checked_unwrap/simple_conditionals.stderr
+++ b/tests/ui/checked_unwrap/simple_conditionals.stderr
@@ -2,7 +2,7 @@ error: called `unwrap` on `x` after checking its variant with `is_some`
   --> tests/ui/checked_unwrap/simple_conditionals.rs:46:9
    |
 LL |     if x.is_some() {
-   |     -------------- help: try: `if let Some(..) = x`
+   |     -------------- help: try: `if let Some(<item>) = x`
 LL |         // unnecessary
 LL |         x.unwrap();
    |         ^^^^^^^^^^
@@ -17,7 +17,7 @@ error: called `expect` on `x` after checking its variant with `is_some`
   --> tests/ui/checked_unwrap/simple_conditionals.rs:49:9
    |
 LL |     if x.is_some() {
-   |     -------------- help: try: `if let Some(..) = x`
+   |     -------------- help: try: `if let Some(<item>) = x`
 ...
 LL |         x.expect("an error message");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -59,7 +59,7 @@ error: called `unwrap` on `x` after checking its variant with `is_none`
   --> tests/ui/checked_unwrap/simple_conditionals.rs:65:9
    |
 LL |     if x.is_none() {
-   |     -------------- help: try: `if let Some(..) = x`
+   |     -------------- help: try: `if let Some(<item>) = x`
 ...
 LL |         x.unwrap();
    |         ^^^^^^^^^^
@@ -68,7 +68,7 @@ error: called `unwrap` on `x` after checking its variant with `is_some`
   --> tests/ui/checked_unwrap/simple_conditionals.rs:13:13
    |
 LL |         if $a.is_some() {
-   |         --------------- help: try: `if let Some(..) = x`
+   |         --------------- help: try: `if let Some(<item>) = x`
 LL |             // unnecessary
 LL |             $a.unwrap();
    |             ^^^^^^^^^^^
@@ -82,7 +82,7 @@ error: called `unwrap` on `x` after checking its variant with `is_ok`
   --> tests/ui/checked_unwrap/simple_conditionals.rs:78:9
    |
 LL |     if x.is_ok() {
-   |     ------------ help: try: `if let Ok(..) = x`
+   |     ------------ help: try: `if let Ok(<item>) = x`
 LL |         // unnecessary
 LL |         x.unwrap();
    |         ^^^^^^^^^^
@@ -91,7 +91,7 @@ error: called `expect` on `x` after checking its variant with `is_ok`
   --> tests/ui/checked_unwrap/simple_conditionals.rs:81:9
    |
 LL |     if x.is_ok() {
-   |     ------------ help: try: `if let Ok(..) = x`
+   |     ------------ help: try: `if let Ok(<item>) = x`
 ...
 LL |         x.expect("an error message");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -127,7 +127,7 @@ error: called `unwrap_err` on `x` after checking its variant with `is_ok`
   --> tests/ui/checked_unwrap/simple_conditionals.rs:94:9
    |
 LL |     if x.is_ok() {
-   |     ------------ help: try: `if let Err(..) = x`
+   |     ------------ help: try: `if let Err(<item>) = x`
 ...
 LL |         x.unwrap_err();
    |         ^^^^^^^^^^^^^^
@@ -145,7 +145,7 @@ error: called `unwrap_err` on `x` after checking its variant with `is_err`
   --> tests/ui/checked_unwrap/simple_conditionals.rs:102:9
    |
 LL |     if x.is_err() {
-   |     ------------- help: try: `if let Err(..) = x`
+   |     ------------- help: try: `if let Err(<item>) = x`
 ...
 LL |         x.unwrap_err();
    |         ^^^^^^^^^^^^^^
@@ -154,7 +154,7 @@ error: called `unwrap` on `x` after checking its variant with `is_err`
   --> tests/ui/checked_unwrap/simple_conditionals.rs:106:9
    |
 LL |     if x.is_err() {
-   |     ------------- help: try: `if let Ok(..) = x`
+   |     ------------- help: try: `if let Ok(<item>) = x`
 ...
 LL |         x.unwrap();
    |         ^^^^^^^^^^
@@ -172,7 +172,7 @@ error: called `unwrap` on `option` after checking its variant with `is_some`
   --> tests/ui/checked_unwrap/simple_conditionals.rs:134:9
    |
 LL |     if option.is_some() {
-   |     ------------------- help: try: `if let Some(..) = &option`
+   |     ------------------- help: try: `if let Some(<item>) = &option`
 LL |         option.as_ref().unwrap();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -189,7 +189,7 @@ error: called `unwrap` on `result` after checking its variant with `is_ok`
   --> tests/ui/checked_unwrap/simple_conditionals.rs:144:9
    |
 LL |     if result.is_ok() {
-   |     ----------------- help: try: `if let Ok(..) = &result`
+   |     ----------------- help: try: `if let Ok(<item>) = &result`
 LL |         result.as_ref().unwrap();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -206,7 +206,7 @@ error: called `unwrap` on `option` after checking its variant with `is_some`
   --> tests/ui/checked_unwrap/simple_conditionals.rs:153:9
    |
 LL |     if option.is_some() {
-   |     ------------------- help: try: `if let Some(..) = &mut option`
+   |     ------------------- help: try: `if let Some(<item>) = &mut option`
 LL |         option.as_mut().unwrap();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -223,7 +223,7 @@ error: called `unwrap` on `result` after checking its variant with `is_ok`
   --> tests/ui/checked_unwrap/simple_conditionals.rs:162:9
    |
 LL |     if result.is_ok() {
-   |     ----------------- help: try: `if let Ok(..) = &mut result`
+   |     ----------------- help: try: `if let Ok(<item>) = &mut result`
 LL |         result.as_mut().unwrap();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/tests/ui/collapsible_match.stderr b/tests/ui/collapsible_match.stderr
index 01944baee79af..1da78b56239c7 100644
--- a/tests/ui/collapsible_match.stderr
+++ b/tests/ui/collapsible_match.stderr
@@ -223,7 +223,7 @@ help: the outer pattern can be modified to include the inner pattern
 LL |     if let Issue9647::A { a, .. } = x {
    |                           ^ replace this binding
 LL |         if let Some(u) = a {
-   |                ^^^^^^^ with this pattern, prefixed by a:
+   |                ^^^^^^^ with this pattern, prefixed by `a`:
 
 error: this `if let` can be collapsed into the outer `if let`
   --> tests/ui/collapsible_match.rs:292:9
diff --git a/tests/ui/crashes/ice-3717.fixed b/tests/ui/crashes/ice-3717.fixed
new file mode 100644
index 0000000000000..3f54b326979c9
--- /dev/null
+++ b/tests/ui/crashes/ice-3717.fixed
@@ -0,0 +1,11 @@
+#![deny(clippy::implicit_hasher)]
+
+use std::collections::HashSet;
+
+fn main() {}
+
+pub fn ice_3717<S: ::std::hash::BuildHasher + Default>(_: &HashSet<usize, S>) {
+    //~^ ERROR: parameter of type `HashSet` should be generalized over different hashers
+    let _ = [0u8; 0];
+    let _: HashSet<usize> = HashSet::default();
+}
diff --git a/tests/ui/crashes/ice-3717.rs b/tests/ui/crashes/ice-3717.rs
index 770f6cf448a63..2890a9277c719 100644
--- a/tests/ui/crashes/ice-3717.rs
+++ b/tests/ui/crashes/ice-3717.rs
@@ -1,7 +1,5 @@
 #![deny(clippy::implicit_hasher)]
 
-//@no-rustfix: need to change the suggestion to a multipart suggestion
-
 use std::collections::HashSet;
 
 fn main() {}
diff --git a/tests/ui/crashes/ice-3717.stderr b/tests/ui/crashes/ice-3717.stderr
index 4b4618ee1bbd0..aac72c669654a 100644
--- a/tests/ui/crashes/ice-3717.stderr
+++ b/tests/ui/crashes/ice-3717.stderr
@@ -1,5 +1,5 @@
 error: parameter of type `HashSet` should be generalized over different hashers
-  --> tests/ui/crashes/ice-3717.rs:9:21
+  --> tests/ui/crashes/ice-3717.rs:7:21
    |
 LL | pub fn ice_3717(_: &HashSet<usize>) {
    |                     ^^^^^^^^^^^^^^
diff --git a/tests/ui/declare_interior_mutable_const/others.rs b/tests/ui/declare_interior_mutable_const/others.rs
index 56a8d22cb1c81..9dafad8b784b9 100644
--- a/tests/ui/declare_interior_mutable_const/others.rs
+++ b/tests/ui/declare_interior_mutable_const/others.rs
@@ -3,6 +3,7 @@
 use std::borrow::Cow;
 use std::cell::Cell;
 use std::fmt::Display;
+use std::ptr;
 use std::sync::atomic::AtomicUsize;
 use std::sync::Once;
 
@@ -53,4 +54,20 @@ mod issue_8493 {
     issue_8493!();
 }
 
+#[repr(C, align(8))]
+struct NoAtomic(usize);
+#[repr(C, align(8))]
+struct WithAtomic(AtomicUsize);
+
+const fn with_non_null() -> *const WithAtomic {
+    const NO_ATOMIC: NoAtomic = NoAtomic(0);
+    (&NO_ATOMIC as *const NoAtomic).cast()
+}
+const WITH_ATOMIC: *const WithAtomic = with_non_null();
+
+struct Generic<T>(T);
+impl<T> Generic<T> {
+    const RAW_POINTER: *const Cell<T> = ptr::null();
+}
+
 fn main() {}
diff --git a/tests/ui/declare_interior_mutable_const/others.stderr b/tests/ui/declare_interior_mutable_const/others.stderr
index 1f2b9561ce509..4a7251471424e 100644
--- a/tests/ui/declare_interior_mutable_const/others.stderr
+++ b/tests/ui/declare_interior_mutable_const/others.stderr
@@ -1,5 +1,5 @@
 error: a `const` item should not be interior mutable
-  --> tests/ui/declare_interior_mutable_const/others.rs:9:1
+  --> tests/ui/declare_interior_mutable_const/others.rs:10:1
    |
 LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5);
    = help: to override `-D warnings` add `#[allow(clippy::declare_interior_mutable_const)]`
 
 error: a `const` item should not be interior mutable
-  --> tests/ui/declare_interior_mutable_const/others.rs:10:1
+  --> tests/ui/declare_interior_mutable_const/others.rs:11:1
    |
 LL | const CELL: Cell<usize> = Cell::new(6);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,7 +17,7 @@ LL | const CELL: Cell<usize> = Cell::new(6);
    = help: consider making this `Sync` so that it can go in a static item or using a `thread_local`
 
 error: a `const` item should not be interior mutable
-  --> tests/ui/declare_interior_mutable_const/others.rs:11:1
+  --> tests/ui/declare_interior_mutable_const/others.rs:12:1
    |
 LL | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], Vec::new(), 7);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -25,7 +25,7 @@ LL | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], V
    = help: consider making this a static item
 
 error: a `const` item should not be interior mutable
-  --> tests/ui/declare_interior_mutable_const/others.rs:16:9
+  --> tests/ui/declare_interior_mutable_const/others.rs:17:9
    |
 LL |         const $name: $ty = $e;
    |         ^^^^^^^^^^^^^^^^^^^^^^
@@ -36,7 +36,7 @@ LL | declare_const!(_ONCE: Once = Once::new());
    = note: this error originates in the macro `declare_const` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: a `const` item should not be interior mutable
-  --> tests/ui/declare_interior_mutable_const/others.rs:44:13
+  --> tests/ui/declare_interior_mutable_const/others.rs:45:13
    |
 LL |             const _BAZ: Cell<usize> = Cell::new(0);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/doc/doc_markdown-issue_13097.fixed b/tests/ui/doc/doc_markdown-issue_13097.fixed
new file mode 100644
index 0000000000000..fb0f40b34a4b8
--- /dev/null
+++ b/tests/ui/doc/doc_markdown-issue_13097.fixed
@@ -0,0 +1,13 @@
+// This test checks that words starting with capital letters and ending with "ified" don't
+// trigger the lint.
+
+#![deny(clippy::doc_markdown)]
+
+pub enum OutputFormat {
+    /// `HumaNified`
+    //~^ ERROR: item in documentation is missing backticks
+    Plain,
+    // Should not warn!
+    /// JSONified console output
+    Json,
+}
diff --git a/tests/ui/doc/doc_markdown-issue_13097.rs b/tests/ui/doc/doc_markdown-issue_13097.rs
new file mode 100644
index 0000000000000..8c1e1a3cd6c24
--- /dev/null
+++ b/tests/ui/doc/doc_markdown-issue_13097.rs
@@ -0,0 +1,13 @@
+// This test checks that words starting with capital letters and ending with "ified" don't
+// trigger the lint.
+
+#![deny(clippy::doc_markdown)]
+
+pub enum OutputFormat {
+    /// HumaNified
+    //~^ ERROR: item in documentation is missing backticks
+    Plain,
+    // Should not warn!
+    /// JSONified console output
+    Json,
+}
diff --git a/tests/ui/doc/doc_markdown-issue_13097.stderr b/tests/ui/doc/doc_markdown-issue_13097.stderr
new file mode 100644
index 0000000000000..ae68a767ec930
--- /dev/null
+++ b/tests/ui/doc/doc_markdown-issue_13097.stderr
@@ -0,0 +1,18 @@
+error: item in documentation is missing backticks
+  --> tests/ui/doc/doc_markdown-issue_13097.rs:7:9
+   |
+LL |     /// HumaNified
+   |         ^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> tests/ui/doc/doc_markdown-issue_13097.rs:4:9
+   |
+LL | #![deny(clippy::doc_markdown)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+help: try
+   |
+LL |     /// `HumaNified`
+   |         ~~~~~~~~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/double_must_use.rs b/tests/ui/double_must_use.rs
index 615de3e24743c..4460aeb075bf6 100644
--- a/tests/ui/double_must_use.rs
+++ b/tests/ui/double_must_use.rs
@@ -3,19 +3,19 @@
 
 #[must_use]
 pub fn must_use_result() -> Result<(), ()> {
-    //~^ ERROR: this function has an empty `#[must_use]` attribute, but returns a type already
+    //~^ ERROR: this function has a `#[must_use]` attribute with no message, but returns a type already
     unimplemented!();
 }
 
 #[must_use]
 pub fn must_use_tuple() -> (Result<(), ()>, u8) {
-    //~^ ERROR: this function has an empty `#[must_use]` attribute, but returns a type already
+    //~^ ERROR: this function has a `#[must_use]` attribute with no message, but returns a type already
     unimplemented!();
 }
 
 #[must_use]
 pub fn must_use_array() -> [Result<(), ()>; 1] {
-    //~^ ERROR: this function has an empty `#[must_use]` attribute, but returns a type already
+    //~^ ERROR: this function has a `#[must_use]` attribute with no message, but returns a type already
     unimplemented!();
 }
 
@@ -32,7 +32,7 @@ async fn async_must_use() -> usize {
 
 #[must_use]
 async fn async_must_use_result() -> Result<(), ()> {
-    //~^ ERROR: this function has an empty `#[must_use]` attribute, but returns a type already
+    //~^ ERROR: this function has a `#[must_use]` attribute with no message, but returns a type already
     Ok(())
 }
 
diff --git a/tests/ui/double_must_use.stderr b/tests/ui/double_must_use.stderr
index 0f2154ecbcfab..b26d1e48a8b86 100644
--- a/tests/ui/double_must_use.stderr
+++ b/tests/ui/double_must_use.stderr
@@ -1,36 +1,36 @@
-error: this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]`
+error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
   --> tests/ui/double_must_use.rs:5:1
    |
 LL | pub fn must_use_result() -> Result<(), ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: either add some descriptive text or remove the attribute
+   = help: either add some descriptive message or remove the attribute
    = note: `-D clippy::double-must-use` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::double_must_use)]`
 
-error: this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]`
+error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
   --> tests/ui/double_must_use.rs:11:1
    |
 LL | pub fn must_use_tuple() -> (Result<(), ()>, u8) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: either add some descriptive text or remove the attribute
+   = help: either add some descriptive message or remove the attribute
 
-error: this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]`
+error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
   --> tests/ui/double_must_use.rs:17:1
    |
 LL | pub fn must_use_array() -> [Result<(), ()>; 1] {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: either add some descriptive text or remove the attribute
+   = help: either add some descriptive message or remove the attribute
 
-error: this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]`
+error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
   --> tests/ui/double_must_use.rs:34:1
    |
 LL | async fn async_must_use_result() -> Result<(), ()> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: either add some descriptive text or remove the attribute
+   = help: either add some descriptive message or remove the attribute
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/explicit_iter_loop.fixed b/tests/ui/explicit_iter_loop.fixed
index f38b34c5a7c47..1148f0f6c6a63 100644
--- a/tests/ui/explicit_iter_loop.fixed
+++ b/tests/ui/explicit_iter_loop.fixed
@@ -153,3 +153,15 @@ fn main() {
     let r = &x;
     for _ in r {}
 }
+
+#[clippy::msrv = "1.79"]
+pub fn issue_13184() {
+    // https://github.com/rust-lang/rust-clippy/issues/13184
+    // No need to fix, as IntoIterator for Box is valid starting from 1.80
+    let mut values: Box<[u32]> = Box::new([1, 2]);
+    for _ in values.iter() {}
+    for _ in values.iter_mut() {}
+
+    let rvalues = &values;
+    for _ in rvalues.iter() {}
+}
diff --git a/tests/ui/explicit_iter_loop.rs b/tests/ui/explicit_iter_loop.rs
index 2e701ada5ac6d..4dda2f13e5b83 100644
--- a/tests/ui/explicit_iter_loop.rs
+++ b/tests/ui/explicit_iter_loop.rs
@@ -153,3 +153,15 @@ fn main() {
     let r = &x;
     for _ in r.iter() {}
 }
+
+#[clippy::msrv = "1.79"]
+pub fn issue_13184() {
+    // https://github.com/rust-lang/rust-clippy/issues/13184
+    // No need to fix, as IntoIterator for Box is valid starting from 1.80
+    let mut values: Box<[u32]> = Box::new([1, 2]);
+    for _ in values.iter() {}
+    for _ in values.iter_mut() {}
+
+    let rvalues = &values;
+    for _ in rvalues.iter() {}
+}
diff --git a/tests/ui/inconsistent_struct_constructor.fixed b/tests/ui/inconsistent_struct_constructor.fixed
index 5778f8f526f86..4c324587c96fa 100644
--- a/tests/ui/inconsistent_struct_constructor.fixed
+++ b/tests/ui/inconsistent_struct_constructor.fixed
@@ -15,6 +15,14 @@ struct Foo {
     z: i32,
 }
 
+#[derive(Default)]
+#[allow(clippy::inconsistent_struct_constructor)]
+struct Bar {
+    x: i32,
+    y: i32,
+    z: i32,
+}
+
 mod without_base {
     use super::Foo;
 
@@ -70,4 +78,17 @@ mod with_base {
     }
 }
 
+mod with_allow_ty_def {
+    use super::Bar;
+
+    fn test() {
+        let x = 1;
+        let y = 1;
+        let z = 1;
+
+        // Should NOT lint because `Bar` is defined with `#[allow(clippy::inconsistent_struct_constructor)]`
+        Bar { y, x, z };
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/inconsistent_struct_constructor.rs b/tests/ui/inconsistent_struct_constructor.rs
index 9efaf0689342f..d49f236b9b07b 100644
--- a/tests/ui/inconsistent_struct_constructor.rs
+++ b/tests/ui/inconsistent_struct_constructor.rs
@@ -15,6 +15,14 @@ struct Foo {
     z: i32,
 }
 
+#[derive(Default)]
+#[allow(clippy::inconsistent_struct_constructor)]
+struct Bar {
+    x: i32,
+    y: i32,
+    z: i32,
+}
+
 mod without_base {
     use super::Foo;
 
@@ -74,4 +82,17 @@ mod with_base {
     }
 }
 
+mod with_allow_ty_def {
+    use super::Bar;
+
+    fn test() {
+        let x = 1;
+        let y = 1;
+        let z = 1;
+
+        // Should NOT lint because `Bar` is defined with `#[allow(clippy::inconsistent_struct_constructor)]`
+        Bar { y, x, z };
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/inconsistent_struct_constructor.stderr b/tests/ui/inconsistent_struct_constructor.stderr
index 1192271f911fd..97bb7c789a720 100644
--- a/tests/ui/inconsistent_struct_constructor.stderr
+++ b/tests/ui/inconsistent_struct_constructor.stderr
@@ -1,5 +1,5 @@
 error: struct constructor field order is inconsistent with struct definition field order
-  --> tests/ui/inconsistent_struct_constructor.rs:28:9
+  --> tests/ui/inconsistent_struct_constructor.rs:36:9
    |
 LL |         Foo { y, x, z };
    |         ^^^^^^^^^^^^^^^ help: try: `Foo { x, y, z }`
@@ -8,7 +8,7 @@ LL |         Foo { y, x, z };
    = help: to override `-D warnings` add `#[allow(clippy::inconsistent_struct_constructor)]`
 
 error: struct constructor field order is inconsistent with struct definition field order
-  --> tests/ui/inconsistent_struct_constructor.rs:55:9
+  --> tests/ui/inconsistent_struct_constructor.rs:63:9
    |
 LL | /         Foo {
 LL | |             z,
diff --git a/tests/ui/min_rust_version_invalid_attr.rs b/tests/ui/min_rust_version_invalid_attr.rs
index 2dccadd9fceec..c8409d78ed77c 100644
--- a/tests/ui/min_rust_version_invalid_attr.rs
+++ b/tests/ui/min_rust_version_invalid_attr.rs
@@ -17,7 +17,7 @@ mod multiple {
     //~^ ERROR: `clippy::msrv` is defined multiple times
 
     mod foo {
-        #![clippy::msrv = "1"]
+        #![clippy::msrv = "1.0"]
         #![clippy::msrv = "1.0.0"]
         //~^ ERROR: `clippy::msrv` is defined multiple times
     }
diff --git a/tests/ui/min_rust_version_invalid_attr.stderr b/tests/ui/min_rust_version_invalid_attr.stderr
index b4cb1b5713f90..dbc276ed89df3 100644
--- a/tests/ui/min_rust_version_invalid_attr.stderr
+++ b/tests/ui/min_rust_version_invalid_attr.stderr
@@ -31,8 +31,8 @@ LL |         #![clippy::msrv = "1.0.0"]
 note: first definition found here
   --> tests/ui/min_rust_version_invalid_attr.rs:20:9
    |
-LL |         #![clippy::msrv = "1"]
-   |         ^^^^^^^^^^^^^^^^^^^^^^
+LL |         #![clippy::msrv = "1.0"]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/string_slice.rs b/tests/ui/string_slice.rs
index 440a86b104a3d..1d1911aaa1d91 100644
--- a/tests/ui/string_slice.rs
+++ b/tests/ui/string_slice.rs
@@ -1,3 +1,5 @@
+use std::borrow::Cow;
+
 #[warn(clippy::string_slice)]
 #[allow(clippy::no_effect)]
 
@@ -11,4 +13,7 @@ fn main() {
     let s = String::from(m);
     &s[0..2];
     //~^ ERROR: indexing into a string may panic if the index is within a UTF-8 character
+    let a = Cow::Borrowed("foo");
+    &a[0..3];
+    //~^ ERROR: indexing into a string may panic if the index is within a UTF-8 character
 }
diff --git a/tests/ui/string_slice.stderr b/tests/ui/string_slice.stderr
index 7a4596b5f2d25..bc0fcde34b826 100644
--- a/tests/ui/string_slice.stderr
+++ b/tests/ui/string_slice.stderr
@@ -1,5 +1,5 @@
 error: indexing into a string may panic if the index is within a UTF-8 character
-  --> tests/ui/string_slice.rs:5:6
+  --> tests/ui/string_slice.rs:7:6
    |
 LL |     &"Ölkanne"[1..];
    |      ^^^^^^^^^^^^^^
@@ -8,16 +8,22 @@ LL |     &"Ölkanne"[1..];
    = help: to override `-D warnings` add `#[allow(clippy::string_slice)]`
 
 error: indexing into a string may panic if the index is within a UTF-8 character
-  --> tests/ui/string_slice.rs:9:6
+  --> tests/ui/string_slice.rs:11:6
    |
 LL |     &m[2..5];
    |      ^^^^^^^
 
 error: indexing into a string may panic if the index is within a UTF-8 character
-  --> tests/ui/string_slice.rs:12:6
+  --> tests/ui/string_slice.rs:14:6
    |
 LL |     &s[0..2];
    |      ^^^^^^^
 
-error: aborting due to 3 previous errors
+error: indexing into a string may panic if the index is within a UTF-8 character
+  --> tests/ui/string_slice.rs:17:6
+   |
+LL |     &a[0..3];
+   |      ^^^^^^^
+
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/too_long_first_doc_paragraph-fix.fixed b/tests/ui/too_long_first_doc_paragraph-fix.fixed
new file mode 100644
index 0000000000000..d4a0cdf3447f1
--- /dev/null
+++ b/tests/ui/too_long_first_doc_paragraph-fix.fixed
@@ -0,0 +1,9 @@
+#![warn(clippy::too_long_first_doc_paragraph)]
+
+/// A very short summary.
+///
+/// A much longer explanation that goes into a lot more detail about
+/// how the thing works, possibly with doclinks and so one,
+/// and probably spanning a many rows. Blablabla, it needs to be over
+/// 200 characters so I needed to write something longeeeeeeer.
+pub struct Foo;
diff --git a/tests/ui/too_long_first_doc_paragraph-fix.rs b/tests/ui/too_long_first_doc_paragraph-fix.rs
new file mode 100644
index 0000000000000..5a3b6c42a328b
--- /dev/null
+++ b/tests/ui/too_long_first_doc_paragraph-fix.rs
@@ -0,0 +1,8 @@
+#![warn(clippy::too_long_first_doc_paragraph)]
+
+/// A very short summary.
+/// A much longer explanation that goes into a lot more detail about
+/// how the thing works, possibly with doclinks and so one,
+/// and probably spanning a many rows. Blablabla, it needs to be over
+/// 200 characters so I needed to write something longeeeeeeer.
+pub struct Foo;
diff --git a/tests/ui/too_long_first_doc_paragraph-fix.stderr b/tests/ui/too_long_first_doc_paragraph-fix.stderr
new file mode 100644
index 0000000000000..6403265a39c54
--- /dev/null
+++ b/tests/ui/too_long_first_doc_paragraph-fix.stderr
@@ -0,0 +1,20 @@
+error: first doc comment paragraph is too long
+  --> tests/ui/too_long_first_doc_paragraph-fix.rs:3:1
+   |
+LL | / /// A very short summary.
+LL | | /// A much longer explanation that goes into a lot more detail about
+LL | | /// how the thing works, possibly with doclinks and so one,
+LL | | /// and probably spanning a many rows. Blablabla, it needs to be over
+LL | | /// 200 characters so I needed to write something longeeeeeeer.
+   | |_
+   |
+   = note: `-D clippy::too-long-first-doc-paragraph` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::too_long_first_doc_paragraph)]`
+help: add an empty line
+   |
+LL ~ /// A very short summary.
+LL + ///
+   |
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/too_long_first_doc_paragraph.rs b/tests/ui/too_long_first_doc_paragraph.rs
new file mode 100644
index 0000000000000..1042249c5b7bd
--- /dev/null
+++ b/tests/ui/too_long_first_doc_paragraph.rs
@@ -0,0 +1,53 @@
+//@no-rustfix
+
+#![warn(clippy::too_long_first_doc_paragraph)]
+
+/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia
+/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero,
+/// gravida non lacinia at, rhoncus eu lacus.
+pub struct Bar;
+
+// Should not warn! (not an item visible on mod page)
+/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia
+/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero,
+/// gravida non lacinia at, rhoncus eu lacus.
+impl Bar {}
+
+// Should not warn! (less than 80 characters)
+/// Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+///
+/// Nunc turpis nunc, lacinia
+/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero,
+/// gravida non lacinia at, rhoncus eu lacus.
+pub enum Enum {
+    A,
+}
+
+/// Lorem
+/// ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia
+/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero,
+/// gravida non lacinia at, rhoncus eu lacus.
+pub union Union {
+    a: u8,
+    b: u8,
+}
+
+// Should not warn! (title)
+/// # bla
+/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia
+/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero,
+/// gravida non lacinia at, rhoncus eu lacus.
+pub union Union2 {
+    a: u8,
+    b: u8,
+}
+
+// Should not warn! (not public)
+/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia
+/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero,
+/// gravida non lacinia at, rhoncus eu lacus.
+fn f() {}
+
+fn main() {
+    // test code goes here
+}
diff --git a/tests/ui/too_long_first_doc_paragraph.stderr b/tests/ui/too_long_first_doc_paragraph.stderr
new file mode 100644
index 0000000000000..7f48e5cf884e6
--- /dev/null
+++ b/tests/ui/too_long_first_doc_paragraph.stderr
@@ -0,0 +1,22 @@
+error: first doc comment paragraph is too long
+  --> tests/ui/too_long_first_doc_paragraph.rs:5:1
+   |
+LL | / /// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia
+LL | | /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero,
+LL | | /// gravida non lacinia at, rhoncus eu lacus.
+   | |_
+   |
+   = note: `-D clippy::too-long-first-doc-paragraph` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::too_long_first_doc_paragraph)]`
+
+error: first doc comment paragraph is too long
+  --> tests/ui/too_long_first_doc_paragraph.rs:26:1
+   |
+LL | / /// Lorem
+LL | | /// ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia
+LL | | /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero,
+LL | | /// gravida non lacinia at, rhoncus eu lacus.
+   | |_
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/unnecessary_lazy_eval.stderr b/tests/ui/unnecessary_lazy_eval.stderr
index fcd60f48bccdd..bcdf65b217e51 100644
--- a/tests/ui/unnecessary_lazy_eval.stderr
+++ b/tests/ui/unnecessary_lazy_eval.stderr
@@ -2,316 +2,432 @@ error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:83:13
    |
 LL |     let _ = opt.unwrap_or_else(|| 2);
-   |             ^^^^--------------------
-   |                 |
-   |                 help: use `unwrap_or(..)` instead: `unwrap_or(2)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_lazy_evaluations)]`
+help: use `unwrap_or` instead
+   |
+LL |     let _ = opt.unwrap_or(2);
+   |                 ~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:84:13
    |
 LL |     let _ = opt.unwrap_or_else(|| astronomers_pi);
-   |             ^^^^---------------------------------
-   |                 |
-   |                 help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `unwrap_or` instead
+   |
+LL |     let _ = opt.unwrap_or(astronomers_pi);
+   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:85:13
    |
 LL |     let _ = opt.unwrap_or_else(|| ext_str.some_field);
-   |             ^^^^-------------------------------------
-   |                 |
-   |                 help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `unwrap_or` instead
+   |
+LL |     let _ = opt.unwrap_or(ext_str.some_field);
+   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:87:13
    |
 LL |     let _ = opt.and_then(|_| ext_opt);
-   |             ^^^^---------------------
-   |                 |
-   |                 help: use `and(..)` instead: `and(ext_opt)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `and` instead
+   |
+LL |     let _ = opt.and(ext_opt);
+   |                 ~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:88:13
    |
 LL |     let _ = opt.or_else(|| ext_opt);
-   |             ^^^^-------------------
-   |                 |
-   |                 help: use `or(..)` instead: `or(ext_opt)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `or` instead
+   |
+LL |     let _ = opt.or(ext_opt);
+   |                 ~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:89:13
    |
 LL |     let _ = opt.or_else(|| None);
-   |             ^^^^----------------
-   |                 |
-   |                 help: use `or(..)` instead: `or(None)`
+   |             ^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `or` instead
+   |
+LL |     let _ = opt.or(None);
+   |                 ~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:90:13
    |
 LL |     let _ = opt.get_or_insert_with(|| 2);
-   |             ^^^^------------------------
-   |                 |
-   |                 help: use `get_or_insert(..)` instead: `get_or_insert(2)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `get_or_insert` instead
+   |
+LL |     let _ = opt.get_or_insert(2);
+   |                 ~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:91:13
    |
 LL |     let _ = opt.ok_or_else(|| 2);
-   |             ^^^^----------------
-   |                 |
-   |                 help: use `ok_or(..)` instead: `ok_or(2)`
+   |             ^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `ok_or` instead
+   |
+LL |     let _ = opt.ok_or(2);
+   |                 ~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:92:13
    |
 LL |     let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
-   |             ^^^^^^^^^^^^^^^^^-------------------------------
-   |                              |
-   |                              help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `unwrap_or` instead
+   |
+LL |     let _ = nested_tuple_opt.unwrap_or(Some((1, 2)));
+   |                              ~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:93:13
    |
 LL |     let _ = cond.then(|| astronomers_pi);
-   |             ^^^^^-----------------------
-   |                  |
-   |                  help: use `then_some(..)` instead: `then_some(astronomers_pi)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _ = cond.then_some(astronomers_pi);
+   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:94:13
    |
 LL |     let _ = true.then(|| -> _ {});
-   |             ^^^^^----------------
-   |                  |
-   |                  help: use `then_some(..)` instead: `then_some({})`
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _ = true.then_some({});
+   |                  ~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:95:13
    |
 LL |     let _ = true.then(|| {});
-   |             ^^^^^-----------
-   |                  |
-   |                  help: use `then_some(..)` instead: `then_some({})`
+   |             ^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _ = true.then_some({});
+   |                  ~~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:99:13
    |
 LL |     let _ = Some(1).unwrap_or_else(|| *r);
-   |             ^^^^^^^^---------------------
-   |                     |
-   |                     help: use `unwrap_or(..)` instead: `unwrap_or(*r)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `unwrap_or` instead
+   |
+LL |     let _ = Some(1).unwrap_or(*r);
+   |                     ~~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:101:13
    |
 LL |     let _ = Some(1).unwrap_or_else(|| *b);
-   |             ^^^^^^^^---------------------
-   |                     |
-   |                     help: use `unwrap_or(..)` instead: `unwrap_or(*b)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `unwrap_or` instead
+   |
+LL |     let _ = Some(1).unwrap_or(*b);
+   |                     ~~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:103:13
    |
 LL |     let _ = Some(1).as_ref().unwrap_or_else(|| &r);
-   |             ^^^^^^^^^^^^^^^^^---------------------
-   |                              |
-   |                              help: use `unwrap_or(..)` instead: `unwrap_or(&r)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `unwrap_or` instead
+   |
+LL |     let _ = Some(1).as_ref().unwrap_or(&r);
+   |                              ~~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:104:13
    |
 LL |     let _ = Some(1).as_ref().unwrap_or_else(|| &b);
-   |             ^^^^^^^^^^^^^^^^^---------------------
-   |                              |
-   |                              help: use `unwrap_or(..)` instead: `unwrap_or(&b)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `unwrap_or` instead
+   |
+LL |     let _ = Some(1).as_ref().unwrap_or(&b);
+   |                              ~~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:107:13
    |
 LL |     let _ = Some(10).unwrap_or_else(|| 2);
-   |             ^^^^^^^^^--------------------
-   |                      |
-   |                      help: use `unwrap_or(..)` instead: `unwrap_or(2)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `unwrap_or` instead
+   |
+LL |     let _ = Some(10).unwrap_or(2);
+   |                      ~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:108:13
    |
 LL |     let _ = Some(10).and_then(|_| ext_opt);
-   |             ^^^^^^^^^---------------------
-   |                      |
-   |                      help: use `and(..)` instead: `and(ext_opt)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `and` instead
+   |
+LL |     let _ = Some(10).and(ext_opt);
+   |                      ~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:109:28
    |
 LL |     let _: Option<usize> = None.or_else(|| ext_opt);
-   |                            ^^^^^-------------------
-   |                                 |
-   |                                 help: use `or(..)` instead: `or(ext_opt)`
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `or` instead
+   |
+LL |     let _: Option<usize> = None.or(ext_opt);
+   |                                 ~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:110:13
    |
 LL |     let _ = None.get_or_insert_with(|| 2);
-   |             ^^^^^------------------------
-   |                  |
-   |                  help: use `get_or_insert(..)` instead: `get_or_insert(2)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `get_or_insert` instead
+   |
+LL |     let _ = None.get_or_insert(2);
+   |                  ~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:111:35
    |
 LL |     let _: Result<usize, usize> = None.ok_or_else(|| 2);
-   |                                   ^^^^^----------------
-   |                                        |
-   |                                        help: use `ok_or(..)` instead: `ok_or(2)`
+   |                                   ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `ok_or` instead
+   |
+LL |     let _: Result<usize, usize> = None.ok_or(2);
+   |                                        ~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:112:28
    |
 LL |     let _: Option<usize> = None.or_else(|| None);
-   |                            ^^^^^----------------
-   |                                 |
-   |                                 help: use `or(..)` instead: `or(None)`
+   |                            ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `or` instead
+   |
+LL |     let _: Option<usize> = None.or(None);
+   |                                 ~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:115:13
    |
 LL |     let _ = deep.0.unwrap_or_else(|| 2);
-   |             ^^^^^^^--------------------
-   |                    |
-   |                    help: use `unwrap_or(..)` instead: `unwrap_or(2)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `unwrap_or` instead
+   |
+LL |     let _ = deep.0.unwrap_or(2);
+   |                    ~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:116:13
    |
 LL |     let _ = deep.0.and_then(|_| ext_opt);
-   |             ^^^^^^^---------------------
-   |                    |
-   |                    help: use `and(..)` instead: `and(ext_opt)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `and` instead
+   |
+LL |     let _ = deep.0.and(ext_opt);
+   |                    ~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:117:13
    |
 LL |     let _ = deep.0.or_else(|| None);
-   |             ^^^^^^^----------------
-   |                    |
-   |                    help: use `or(..)` instead: `or(None)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `or` instead
+   |
+LL |     let _ = deep.0.or(None);
+   |                    ~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:118:13
    |
 LL |     let _ = deep.0.get_or_insert_with(|| 2);
-   |             ^^^^^^^------------------------
-   |                    |
-   |                    help: use `get_or_insert(..)` instead: `get_or_insert(2)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `get_or_insert` instead
+   |
+LL |     let _ = deep.0.get_or_insert(2);
+   |                    ~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:119:13
    |
 LL |     let _ = deep.0.ok_or_else(|| 2);
-   |             ^^^^^^^----------------
-   |                    |
-   |                    help: use `ok_or(..)` instead: `ok_or(2)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `ok_or` instead
+   |
+LL |     let _ = deep.0.ok_or(2);
+   |                    ~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:150:28
    |
 LL |     let _: Option<usize> = None.or_else(|| Some(3));
-   |                            ^^^^^-------------------
-   |                                 |
-   |                                 help: use `or(..)` instead: `or(Some(3))`
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `or` instead
+   |
+LL |     let _: Option<usize> = None.or(Some(3));
+   |                                 ~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:151:13
    |
 LL |     let _ = deep.0.or_else(|| Some(3));
-   |             ^^^^^^^-------------------
-   |                    |
-   |                    help: use `or(..)` instead: `or(Some(3))`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `or` instead
+   |
+LL |     let _ = deep.0.or(Some(3));
+   |                    ~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Option::None`
   --> tests/ui/unnecessary_lazy_eval.rs:152:13
    |
 LL |     let _ = opt.or_else(|| Some(3));
-   |             ^^^^-------------------
-   |                 |
-   |                 help: use `or(..)` instead: `or(Some(3))`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `or` instead
+   |
+LL |     let _ = opt.or(Some(3));
+   |                 ~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Result::Err`
   --> tests/ui/unnecessary_lazy_eval.rs:158:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| 2);
-   |             ^^^^^---------------------
-   |                  |
-   |                  help: use `unwrap_or(..)` instead: `unwrap_or(2)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `unwrap_or` instead
+   |
+LL |     let _ = res2.unwrap_or(2);
+   |                  ~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Result::Err`
   --> tests/ui/unnecessary_lazy_eval.rs:159:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| astronomers_pi);
-   |             ^^^^^----------------------------------
-   |                  |
-   |                  help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `unwrap_or` instead
+   |
+LL |     let _ = res2.unwrap_or(astronomers_pi);
+   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Result::Err`
   --> tests/ui/unnecessary_lazy_eval.rs:160:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| ext_str.some_field);
-   |             ^^^^^--------------------------------------
-   |                  |
-   |                  help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `unwrap_or` instead
+   |
+LL |     let _ = res2.unwrap_or(ext_str.some_field);
+   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Result::Err`
   --> tests/ui/unnecessary_lazy_eval.rs:182:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(2));
-   |                                   ^^^^--------------------
-   |                                       |
-   |                                       help: use `and(..)` instead: `and(Err(2))`
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `and` instead
+   |
+LL |     let _: Result<usize, usize> = res.and(Err(2));
+   |                                       ~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Result::Err`
   --> tests/ui/unnecessary_lazy_eval.rs:183:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
-   |                                   ^^^^---------------------------------
-   |                                       |
-   |                                       help: use `and(..)` instead: `and(Err(astronomers_pi))`
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `and` instead
+   |
+LL |     let _: Result<usize, usize> = res.and(Err(astronomers_pi));
+   |                                       ~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Result::Err`
   --> tests/ui/unnecessary_lazy_eval.rs:184:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field));
-   |                                   ^^^^-------------------------------------
-   |                                       |
-   |                                       help: use `and(..)` instead: `and(Err(ext_str.some_field))`
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `and` instead
+   |
+LL |     let _: Result<usize, usize> = res.and(Err(ext_str.some_field));
+   |                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Result::Err`
   --> tests/ui/unnecessary_lazy_eval.rs:186:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(2));
-   |                                   ^^^^------------------
-   |                                       |
-   |                                       help: use `or(..)` instead: `or(Ok(2))`
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `or` instead
+   |
+LL |     let _: Result<usize, usize> = res.or(Ok(2));
+   |                                       ~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Result::Err`
   --> tests/ui/unnecessary_lazy_eval.rs:187:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
-   |                                   ^^^^-------------------------------
-   |                                       |
-   |                                       help: use `or(..)` instead: `or(Ok(astronomers_pi))`
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `or` instead
+   |
+LL |     let _: Result<usize, usize> = res.or(Ok(astronomers_pi));
+   |                                       ~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Result::Err`
   --> tests/ui/unnecessary_lazy_eval.rs:188:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
-   |                                   ^^^^-----------------------------------
-   |                                       |
-   |                                       help: use `or(..)` instead: `or(Ok(ext_str.some_field))`
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `or` instead
+   |
+LL |     let _: Result<usize, usize> = res.or(Ok(ext_str.some_field));
+   |                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Result::Err`
   --> tests/ui/unnecessary_lazy_eval.rs:189:35
@@ -324,193 +440,265 @@ LL | |     // some lines
 ...  |
 LL | |     // some lines
 LL | |     or_else(|_| Ok(ext_str.some_field));
-   | |_____----------------------------------^
-   |       |
-   |       help: use `or(..)` instead: `or(Ok(ext_str.some_field))`
+   | |_______________________________________^
+   |
+help: use `or` instead
+   |
+LL |     or(Ok(ext_str.some_field));
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:219:14
    |
 LL |     let _x = false.then(|| i32::MAX + 1);
-   |              ^^^^^^---------------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(i32::MAX + 1)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(i32::MAX + 1);
+   |                    ~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:221:14
    |
 LL |     let _x = false.then(|| i32::MAX * 2);
-   |              ^^^^^^---------------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(i32::MAX * 2)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(i32::MAX * 2);
+   |                    ~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:223:14
    |
 LL |     let _x = false.then(|| i32::MAX - 1);
-   |              ^^^^^^---------------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(i32::MAX - 1)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(i32::MAX - 1);
+   |                    ~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:225:14
    |
 LL |     let _x = false.then(|| i32::MIN - 1);
-   |              ^^^^^^---------------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(i32::MIN - 1)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(i32::MIN - 1);
+   |                    ~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:227:14
    |
 LL |     let _x = false.then(|| (1 + 2 * 3 - 2 / 3 + 9) << 2);
-   |              ^^^^^^-------------------------------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some((1 + 2 * 3 - 2 / 3 + 9) << 2)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some((1 + 2 * 3 - 2 / 3 + 9) << 2);
+   |                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:229:14
    |
 LL |     let _x = false.then(|| 255u8 << 7);
-   |              ^^^^^^-------------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(255u8 << 7)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(255u8 << 7);
+   |                    ~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:231:14
    |
 LL |     let _x = false.then(|| 255u8 << 8);
-   |              ^^^^^^-------------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(255u8 << 8)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(255u8 << 8);
+   |                    ~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:233:14
    |
 LL |     let _x = false.then(|| 255u8 >> 8);
-   |              ^^^^^^-------------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(255u8 >> 8)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(255u8 >> 8);
+   |                    ~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:236:14
    |
 LL |     let _x = false.then(|| i32::MAX + -1);
-   |              ^^^^^^----------------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(i32::MAX + -1)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(i32::MAX + -1);
+   |                    ~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:238:14
    |
 LL |     let _x = false.then(|| -i32::MAX);
-   |              ^^^^^^------------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(-i32::MAX)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(-i32::MAX);
+   |                    ~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:240:14
    |
 LL |     let _x = false.then(|| -i32::MIN);
-   |              ^^^^^^------------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(-i32::MIN)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(-i32::MIN);
+   |                    ~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:243:14
    |
 LL |     let _x = false.then(|| 255 >> -7);
-   |              ^^^^^^------------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(255 >> -7)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(255 >> -7);
+   |                    ~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:245:14
    |
 LL |     let _x = false.then(|| 255 << -1);
-   |              ^^^^^^------------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(255 << -1)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(255 << -1);
+   |                    ~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:247:14
    |
 LL |     let _x = false.then(|| 1 / 0);
-   |              ^^^^^^--------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(1 / 0)`
+   |              ^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(1 / 0);
+   |                    ~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:249:14
    |
 LL |     let _x = false.then(|| x << -1);
-   |              ^^^^^^----------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(x << -1)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(x << -1);
+   |                    ~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:251:14
    |
 LL |     let _x = false.then(|| x << 2);
-   |              ^^^^^^---------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(x << 2)`
+   |              ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(x << 2);
+   |                    ~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:261:14
    |
 LL |     let _x = false.then(|| x / 0);
-   |              ^^^^^^--------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(x / 0)`
+   |              ^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(x / 0);
+   |                    ~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:263:14
    |
 LL |     let _x = false.then(|| x % 0);
-   |              ^^^^^^--------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(x % 0)`
+   |              ^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(x % 0);
+   |                    ~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:266:14
    |
 LL |     let _x = false.then(|| 1 / -1);
-   |              ^^^^^^---------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(1 / -1)`
+   |              ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(1 / -1);
+   |                    ~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:268:14
    |
 LL |     let _x = false.then(|| i32::MIN / -1);
-   |              ^^^^^^----------------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(i32::MIN / -1)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(i32::MIN / -1);
+   |                    ~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:271:14
    |
 LL |     let _x = false.then(|| i32::MIN / 0);
-   |              ^^^^^^---------------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(i32::MIN / 0)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(i32::MIN / 0);
+   |                    ~~~~~~~~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:273:14
    |
 LL |     let _x = false.then(|| 4 / 2);
-   |              ^^^^^^--------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(4 / 2)`
+   |              ^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(4 / 2);
+   |                    ~~~~~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval.rs:281:14
    |
 LL |     let _x = false.then(|| f1 + f2);
-   |              ^^^^^^----------------
-   |                    |
-   |                    help: use `then_some(..)` instead: `then_some(f1 + f2)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _x = false.then_some(f1 + f2);
+   |                    ~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 63 previous errors
 
diff --git a/tests/ui/unnecessary_lazy_eval_unfixable.stderr b/tests/ui/unnecessary_lazy_eval_unfixable.stderr
index b566b119571cb..390235b212474 100644
--- a/tests/ui/unnecessary_lazy_eval_unfixable.stderr
+++ b/tests/ui/unnecessary_lazy_eval_unfixable.stderr
@@ -2,36 +2,47 @@ error: unnecessary closure used to substitute value for `Result::Err`
   --> tests/ui/unnecessary_lazy_eval_unfixable.rs:13:13
    |
 LL |     let _ = Ok(1).unwrap_or_else(|()| 2);
-   |             ^^^^^^----------------------
-   |                   |
-   |                   help: use `unwrap_or(..)` instead: `unwrap_or(2)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_lazy_evaluations)]`
+help: use `unwrap_or` instead
+   |
+LL |     let _ = Ok(1).unwrap_or(2);
+   |                   ~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Result::Err`
   --> tests/ui/unnecessary_lazy_eval_unfixable.rs:19:13
    |
 LL |     let _ = Ok(1).unwrap_or_else(|e::E| 2);
-   |             ^^^^^^------------------------
-   |                   |
-   |                   help: use `unwrap_or(..)` instead: `unwrap_or(2)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `unwrap_or` instead
+   |
+LL |     let _ = Ok(1).unwrap_or(2);
+   |                   ~~~~~~~~~~~~
 
 error: unnecessary closure used to substitute value for `Result::Err`
   --> tests/ui/unnecessary_lazy_eval_unfixable.rs:21:13
    |
 LL |     let _ = Ok(1).unwrap_or_else(|SomeStruct { .. }| 2);
-   |             ^^^^^^-------------------------------------
-   |                   |
-   |                   help: use `unwrap_or(..)` instead: `unwrap_or(2)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `unwrap_or` instead
+   |
+LL |     let _ = Ok(1).unwrap_or(2);
+   |                   ~~~~~~~~~~~~
 
 error: unnecessary closure used with `bool::then`
   --> tests/ui/unnecessary_lazy_eval_unfixable.rs:31:13
    |
 LL |     let _ = true.then(|| -> &[u8] { &[] });
-   |             ^^^^^-------------------------
-   |                  |
-   |                  help: use `then_some(..)` instead: `then_some({ &[] })`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `then_some` instead
+   |
+LL |     let _ = true.then_some({ &[] });
+   |                  ~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 4 previous errors
 
diff --git a/triagebot.toml b/triagebot.toml
index dcf00e4e384b0..99b3560a06427 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -20,6 +20,7 @@ new_pr = true
 [assign]
 contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md"
 users_on_vacation = [
+    "flip1995",
     "matthiaskrgr",
     "giraffate",
 ]
diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html
index 300c9de178f2b..f3d7e504fdf80 100644
--- a/util/gh-pages/index.html
+++ b/util/gh-pages/index.html
@@ -23,378 +23,25 @@
     <link id="styleHighlight" rel="stylesheet" href="https://rust-lang.github.io/mdBook/highlight.css">
     <link id="styleNight" rel="stylesheet" href="https://rust-lang.github.io/mdBook/tomorrow-night.css" disabled="true">
     <link id="styleAyu" rel="stylesheet" href="https://rust-lang.github.io/mdBook/ayu-highlight.css" disabled="true">
-    <style>
-        blockquote { font-size: 1em; }
-        [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { display: none !important; }
-
-        .dropdown-menu {
-            color: var(--fg);
-            background: var(--theme-popup-bg);
-            border: 1px solid var(--theme-popup-border);
-        }
-
-        .dropdown-menu .divider {
-            background-color: var(--theme-popup-border);
-        }
-
-        .dropdown-menu .checkbox {
-            display: block;
-            white-space: nowrap;
-            margin: 0;
-        }
-        .dropdown-menu .checkbox label {
-            padding: 3px 20px;
-            width: 100%;
-        }
-
-        .dropdown-menu .checkbox input {
-            position: relative;
-            margin: 0 0.5rem 0;
-            padding: 0;
-        }
-
-        .dropdown-menu .checkbox:hover {
-            background-color: var(--theme-hover);
-        }
-
-        div.panel div.panel-body button {
-            background: var(--searchbar-bg);
-            color: var(--searchbar-fg);
-            border-color: var(--theme-popup-border);
-        }
-
-        div.panel div.panel-body button:hover {
-            box-shadow: 0 0 3px var(--searchbar-shadow-color);
-        }
-
-        div.panel div.panel-body  button.open {
-            filter: brightness(90%);
-        }
-
-        .dropdown-toggle .badge {
-            background-color: #777;
-        }
-
-        .panel-heading { cursor: pointer; }
-
-        .panel-title { display: flex; flex-wrap: wrap;}
-        .panel-title .label { display: inline-block; }
-
-        .panel-title-name { flex: 1; min-width: 400px;}
-        .panel-title-name span { vertical-align: bottom; }
-
-        .panel .panel-title-name .anchor { display: none; }
-        .panel:hover .panel-title-name .anchor { display: inline;}
-
-        .search-control {
-            margin-top: 15px;
-        }
-
-        @media (min-width: 992px) {
-            .search-control {
-                margin-top: 0;
-            }
-        }
-
-        @media (min-width: 405px) {
-            #upper-filters {
-                display: flex;
-                flex-wrap: wrap;
-            }
-        }
-
-        @media (max-width: 430px) {
-            /* Turn the version filter list to the left */
-            #version-filter-selector {
-                right: 0;
-                left: auto;
-            }
-        }
-
-        @media (max-width: 412px) {
-            #upper-filters,
-            .panel-body .search-control  {
-                padding-right: 8px;
-                padding-left: 8px;
-            }
-        }
-
-        .label {
-            padding-top: 0.3em;
-            padding-bottom: 0.3em;
-        }
-
-        .label-lint-group {
-            min-width: 8em;
-        }
-        .label-lint-level {
-            min-width: 4em;
-        }
-
-        .label-lint-level-allow {
-            background-color: #5cb85c;
-        }
-        .label-lint-level-warn {
-            background-color: #f0ad4e;
-        }
-        .label-lint-level-deny {
-            background-color: #d9534f;
-        }
-        .label-lint-level-none {
-            background-color: #777777;
-            opacity: 0.5;
-        }
-
-        .label-group-deprecated {
-            opacity: 0.5;
-        }
-
-        .label-doc-folding {
-            color: #000;
-            background-color: #fff;
-            border: 1px solid var(--theme-popup-border);
-        }
-        .label-doc-folding:hover {
-            background-color: #e6e6e6;
-        }
-
-        .lint-doc-md > h3 {
-            border-top: 1px solid var(--theme-popup-border);
-            padding: 10px 15px;
-            margin: 0 -15px;
-            font-size: 18px;
-        }
-        .lint-doc-md > h3:first-child {
-            border-top: none;
-            padding-top: 0px;
-        }
-
-        @media (max-width:749px) {
-            .lint-additional-info-container {
-                display: flex;
-                flex-flow: column;
-            }
-            .lint-additional-info-item + .lint-additional-info-item {
-                border-top: 1px solid var(--theme-popup-border);
-            }
-        }
-        @media (min-width:750px) {
-            .lint-additional-info-container {
-                display: flex;
-                flex-flow: row;
-            }
-            .lint-additional-info-item + .lint-additional-info-item {
-                border-left: 1px solid var(--theme-popup-border);
-            }
-        }
-
-        .lint-additional-info-item {
-            display: inline-flex;
-            min-width: 200px;
-            flex-grow: 1;
-            padding: 9px 5px 5px 15px;
-        }
-
-        .label-applicability {
-            background-color: #777777;
-            margin: auto 5px;
-        }
-
-        .label-version {
-            background-color: #777777;
-            margin: auto 5px;
-            font-family: monospace;
-        }
-
-        details {
-            border-radius: 4px;
-            padding: .5em .5em 0;
-        }
-
-        code {
-            white-space: pre !important;
-        }
-
-        summary {
-            font-weight: bold;
-            margin: -.5em -.5em 0;
-            padding: .5em;
-            display: revert;
-        }
-
-        details[open] {
-            padding: .5em;
-        }
-    </style>
-    <style>
-        /* Expanding the mdBoom theme*/
-        .light {
-            --inline-code-bg: #f6f7f6;
-        }
-        .rust {
-            --inline-code-bg: #f6f7f6;
-        }
-        .coal {
-            --inline-code-bg: #1d1f21;
-        }
-        .navy {
-            --inline-code-bg: #1d1f21;
-        }
-        .ayu {
-            --inline-code-bg: #191f26;
-        }
-
-        .theme-dropdown {
-            position: absolute;
-            margin: 0.7em;
-            z-index: 10;
-        }
-
-        /* Applying the mdBook theme */
-        .theme-icon {
-            text-align: center;
-            width: 2em;
-            height: 2em;
-            line-height: 2em;
-            border: solid 1px var(--icons);
-            border-radius: 5px;
-            user-select: none;
-            cursor: pointer;
-        }
-        .theme-icon:hover {
-            background: var(--theme-hover);
-        }
-        .theme-choice {
-            display: none;
-            list-style: none;
-            border: 1px solid var(--theme-popup-border);
-            border-radius: 5px;
-            color: var(--fg);
-            background: var(--theme-popup-bg);
-            padding: 0 0;
-            overflow: hidden;
-        }
-
-        .theme-dropdown.open .theme-choice {
-            display: block;
-        }
-
-        .theme-choice > li {
-            padding: 5px 10px;
-            font-size: 0.8em;
-            user-select: none;
-            cursor: pointer;
-        }
-
-        .theme-choice > li:hover {
-            background: var(--theme-hover);
-        }
-
-        .alert {
-            color: var(--fg);
-            background: var(--theme-hover);
-            border: 1px solid var(--theme-popup-border);
-        }
-        .page-header {
-            border-color: var(--theme-popup-border);
-        }
-        .panel-default > .panel-heading {
-            background: var(--theme-hover);
-            color: var(--fg);
-            border: 1px solid var(--theme-popup-border);
-        }
-        .panel-default > .panel-heading:hover {
-            filter: brightness(90%);
-        }
-        .list-group-item {
-            background: 0%;
-            border: 1px solid var(--theme-popup-border);
-        }
-        .panel, pre, hr {
-            background: var(--bg);
-            border: 1px solid var(--theme-popup-border);
-        }
-
-        #version-filter-selector .checkbox {
-            display: flex;
-        }
-
-        #version-filter {
-            min-width: available;
-        }
-
-        #version-filter li label {
-            padding-right: 0;
-            width: 35%;
-        }
-
-        .version-filter-input {
-            height: 60%;
-            width: 30%;
-            text-align: center;
-            border: none;
-            border-bottom: 1px solid #000000;
-        }
-
-        #filter-label, .filter-clear {
-            background: var(--searchbar-bg);
-            color: var(--searchbar-fg);
-            border-color: var(--theme-popup-border);
-            filter: brightness(95%);
-        }
-        #filter-label:hover, .filter-clear:hover {
-            filter: brightness(90%);
-        }
-        .filter-input {
-            background: var(--searchbar-bg);
-            color: var(--searchbar-fg);
-            border-color: var(--theme-popup-border);
-        }
-
-        .filter-input::-webkit-input-placeholder,
-        .filter-input::-moz-placeholder {
-            color: var(--searchbar-fg);
-            opacity: 30%;
-        }
-
-        .expansion-group {
-            margin-top: 15px;
-            padding: 0px 8px;
-            display: flex;
-            flex-wrap: nowrap;
-        }
-
-        @media (min-width: 992px) {
-            .expansion-group {
-                margin-top: 0;
-                padding: 0px 15px;
-            }
-        }
-
-        .expansion-control {
-            width: 50%;
-        }
-
-        :not(pre) > code {
-            color: var(--inline-code-color);
-            background-color: var(--inline-code-bg);
-        }
-        html {
-            scrollbar-color: var(--scrollbar) var(--bg);
-        }
-        body {
-            background: var(--bg);
-            color: var(--fg);
-        }
-
-    </style>
+    <link rel="stylesheet" href="style.css">
 </head>
 <body ng-app="clippy" ng-controller="lintList">
-    <div theme-dropdown class="theme-dropdown">
-        <div id="theme-icon" class="theme-icon">&#128396;</div>
-        <ul id="theme-menu" class="theme-choice">
-            <li id="{{id}}" ng-repeat="(id, name) in themes" ng-click="selectTheme(id)">{{name}}</li>
-        </ul>
+    <div id="settings-dropdown">
+        <div class="settings-icon" tabindex="-1"></div>
+        <div class="settings-menu" tabindex="-1">
+            <div class="setting-radio-name">Theme</div>
+            <select id="theme-choice" onchange="setTheme(this.value, true)">
+                <option value="ayu">Ayu</option>
+                <option value="coal">Coal</option>
+                <option value="light">Light</option>
+                <option value="navy">Navy</option>
+                <option value="rust">Rust</option>
+            </select>
+            <label>
+                <input type="checkbox" id="disable-shortcuts" onchange="changeSetting(this)">
+                <span>Disable keyboard shortcuts</span>
+            </label>
+        </div>
     </div>
 
     <div class="container">
@@ -592,7 +239,7 @@ <h2 class="panel-title">
                         <!-- Applicability -->
                         <div class="lint-additional-info-item">
                             <span> Applicability: </span>
-                            <span class="label label-default label-applicability">{{lint.applicability.applicability}}</span>
+                            <span class="label label-default label-applicability">{{lint.applicability}}</span>
                             <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/enum.Applicability.html#variants">(?)</a>
                         </div>
                         <!-- Clippy version -->
@@ -605,8 +252,8 @@ <h2 class="panel-title">
                             <a href="https://github.com/rust-lang/rust-clippy/issues?q=is%3Aissue+{{lint.id}}">Related Issues</a>
                         </div>
                         <!-- Jump to source -->
-                        <div class="lint-additional-info-item" ng-if="lint.id_span">
-                            <a href="https://github.com/rust-lang/rust-clippy/blob/{{docVersion}}/clippy_lints/{{lint.id_span.path}}#L{{lint.id_span.line}}">View Source</a>
+                        <div class="lint-additional-info-item" ng-if="lint.id_location">
+                            <a href="https://github.com/rust-lang/rust-clippy/blob/{{docVersion}}/{{lint.id_location}}">View Source</a>
                         </div>
                     </div>
                 </div>
diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js
index ed1e090e1b540..1a5330bc0e571 100644
--- a/util/gh-pages/script.js
+++ b/util/gh-pages/script.js
@@ -50,24 +50,6 @@
                 );
             };
         })
-        .directive('themeDropdown', function ($document) {
-            return {
-                restrict: 'A',
-                link: function ($scope, $element, $attr) {
-                    $element.bind('click', function () {
-                        $element.toggleClass('open');
-                        $element.addClass('open-recent');
-                    });
-
-                    $document.bind('click', function () {
-                        if (!$element.hasClass('open-recent')) {
-                            $element.removeClass('open');
-                        }
-                        $element.removeClass('open-recent');
-                    })
-                }
-            }
-        })
         .directive('filterDropdown', function ($document) {
             return {
                 restrict: 'A',
@@ -114,28 +96,19 @@
                 cargo: true,
                 complexity: true,
                 correctness: true,
-                deprecated: false,
                 nursery: true,
                 pedantic: true,
                 perf: true,
                 restriction: true,
                 style: true,
                 suspicious: true,
+                deprecated: false,
             }
 
             $scope.groups = {
                 ...GROUPS_FILTER_DEFAULT
             };
 
-            const THEMES_DEFAULT = {
-                light: "Light",
-                rust: "Rust",
-                coal: "Coal",
-                navy: "Navy",
-                ayu: "Ayu"
-            };
-            $scope.themes = THEMES_DEFAULT;
-
             $scope.versionFilters = {
                 "≥": {enabled: false, minorVersion: null },
                 "≤": {enabled: false, minorVersion: null },
@@ -153,11 +126,10 @@
             );
 
             const APPLICABILITIES_FILTER_DEFAULT = {
-                Unspecified: true,
-                Unresolved: true,
                 MachineApplicable: true,
                 MaybeIncorrect: true,
-                HasPlaceholders: true
+                HasPlaceholders: true,
+                Unspecified: true,
             };
 
             $scope.applicabilities = {
@@ -321,10 +293,6 @@
                 $location.path($scope.search);
             }
 
-            $scope.selectTheme = function (theme) {
-                setTheme(theme, true);
-            }
-
             $scope.toggleLevels = function (value) {
                 const levels = $scope.levels;
                 for (const key in levels) {
@@ -456,7 +424,7 @@
             }
 
             $scope.byApplicabilities = function (lint) {
-                return $scope.applicabilities[lint.applicability.applicability];
+                return $scope.applicabilities[lint.applicability];
             };
 
             // Show details for one lint
@@ -537,6 +505,16 @@ function getQueryVariable(variable) {
     }
 }
 
+function storeValue(settingName, value) {
+    try {
+        localStorage.setItem(`clippy-lint-list-${settingName}`, value);
+    } catch (e) { }
+}
+
+function loadValue(settingName) {
+    return localStorage.getItem(`clippy-lint-list-${settingName}`);
+}
+
 function setTheme(theme, store) {
     let enableHighlight = false;
     let enableNight = false;
@@ -569,14 +547,14 @@ function setTheme(theme, store) {
     document.getElementById("styleAyu").disabled = !enableAyu;
 
     if (store) {
-        try {
-            localStorage.setItem('clippy-lint-list-theme', theme);
-        } catch (e) { }
+        storeValue("theme", theme);
+    } else {
+        document.getElementById(`theme-choice`).value = theme;
     }
 }
 
 function handleShortcut(ev) {
-    if (ev.ctrlKey || ev.altKey || ev.metaKey) {
+    if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts) {
         return;
     }
 
@@ -601,11 +579,51 @@ function handleShortcut(ev) {
 document.addEventListener("keypress", handleShortcut);
 document.addEventListener("keydown", handleShortcut);
 
+function changeSetting(elem) {
+    if (elem.id === "disable-shortcuts") {
+        disableShortcuts = elem.checked;
+        storeValue(elem.id, elem.checked);
+    }
+}
+
+function onEachLazy(lazyArray, func) {
+    const arr = Array.prototype.slice.call(lazyArray);
+    for (const el of arr) {
+        func(el);
+    }
+}
+
+function handleBlur(event) {
+    const parent = document.getElementById("settings-dropdown");
+    if (!parent.contains(document.activeElement) &&
+        !parent.contains(event.relatedTarget)
+    ) {
+        parent.classList.remove("open");
+    }
+}
+
+function generateSettings() {
+    const settings = document.getElementById("settings-dropdown");
+    const settingsButton = settings.querySelector(".settings-icon")
+    settingsButton.onclick = () => settings.classList.toggle("open");
+    settingsButton.onblur = handleBlur;
+    const settingsMenu = settings.querySelector(".settings-menu");
+    settingsMenu.onblur = handleBlur;
+    onEachLazy(
+        settingsMenu.querySelectorAll("input"),
+        el => el.onblur = handleBlur,
+    );
+}
+
+generateSettings();
+
 // loading the theme after the initial load
 const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
-const theme = localStorage.getItem('clippy-lint-list-theme');
+const theme = loadValue('theme');
 if (prefersDark.matches && !theme) {
     setTheme("coal", false);
 } else {
     setTheme(theme, false);
 }
+let disableShortcuts = loadValue('disable-shortcuts') === "true";
+document.getElementById("disable-shortcuts").checked = disableShortcuts;
diff --git a/util/gh-pages/style.css b/util/gh-pages/style.css
new file mode 100644
index 0000000000000..a9485d511047a
--- /dev/null
+++ b/util/gh-pages/style.css
@@ -0,0 +1,398 @@
+blockquote { font-size: 1em; }
+
+[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
+    display: none !important;
+}
+
+.dropdown-menu {
+    color: var(--fg);
+    background: var(--theme-popup-bg);
+    border: 1px solid var(--theme-popup-border);
+}
+
+.dropdown-menu .divider {
+    background-color: var(--theme-popup-border);
+}
+
+.dropdown-menu .checkbox {
+    display: block;
+    white-space: nowrap;
+    margin: 0;
+}
+.dropdown-menu .checkbox label {
+    padding: 3px 20px;
+    width: 100%;
+}
+
+.dropdown-menu .checkbox input {
+    position: relative;
+    margin: 0 0.5rem 0;
+    padding: 0;
+}
+
+.dropdown-menu .checkbox:hover {
+    background-color: var(--theme-hover);
+}
+
+div.panel div.panel-body button {
+    background: var(--searchbar-bg);
+    color: var(--searchbar-fg);
+    border-color: var(--theme-popup-border);
+}
+
+div.panel div.panel-body button:hover {
+    box-shadow: 0 0 3px var(--searchbar-shadow-color);
+}
+
+div.panel div.panel-body  button.open {
+    filter: brightness(90%);
+}
+
+.dropdown-toggle .badge {
+    background-color: #777;
+}
+
+.panel-heading { cursor: pointer; }
+
+.panel-title { display: flex; flex-wrap: wrap;}
+.panel-title .label { display: inline-block; }
+
+.panel-title-name { flex: 1; min-width: 400px;}
+.panel-title-name span { vertical-align: bottom; }
+
+.panel .panel-title-name .anchor { display: none; }
+.panel:hover .panel-title-name .anchor { display: inline;}
+
+.search-control {
+    margin-top: 15px;
+}
+
+@media (min-width: 992px) {
+    .search-control {
+        margin-top: 0;
+    }
+}
+
+@media (min-width: 405px) {
+    #upper-filters {
+        display: flex;
+        flex-wrap: wrap;
+    }
+}
+
+@media (max-width: 430px) {
+    /* Turn the version filter list to the left */
+    #version-filter-selector {
+        right: 0;
+        left: auto;
+    }
+}
+
+@media (max-width: 412px) {
+    #upper-filters,
+    .panel-body .search-control  {
+        padding-right: 8px;
+        padding-left: 8px;
+    }
+}
+
+.label {
+    padding-top: 0.3em;
+    padding-bottom: 0.3em;
+}
+
+.label-lint-group {
+    min-width: 8em;
+}
+.label-lint-level {
+    min-width: 4em;
+}
+
+.label-lint-level-allow {
+    background-color: #5cb85c;
+}
+.label-lint-level-warn {
+    background-color: #f0ad4e;
+}
+.label-lint-level-deny {
+    background-color: #d9534f;
+}
+.label-lint-level-none {
+    background-color: #777777;
+    opacity: 0.5;
+}
+
+.label-group-deprecated {
+    opacity: 0.5;
+}
+
+.label-doc-folding {
+    color: #000;
+    background-color: #fff;
+    border: 1px solid var(--theme-popup-border);
+}
+.label-doc-folding:hover {
+    background-color: #e6e6e6;
+}
+
+.lint-doc-md > h3 {
+    border-top: 1px solid var(--theme-popup-border);
+    padding: 10px 15px;
+    margin: 0 -15px;
+    font-size: 18px;
+}
+.lint-doc-md > h3:first-child {
+    border-top: none;
+    padding-top: 0px;
+}
+
+@media (max-width:749px) {
+    .lint-additional-info-container {
+        display: flex;
+        flex-flow: column;
+    }
+    .lint-additional-info-item + .lint-additional-info-item {
+        border-top: 1px solid var(--theme-popup-border);
+    }
+}
+@media (min-width:750px) {
+    .lint-additional-info-container {
+        display: flex;
+        flex-flow: row;
+    }
+    .lint-additional-info-item + .lint-additional-info-item {
+        border-left: 1px solid var(--theme-popup-border);
+    }
+}
+
+.lint-additional-info-item {
+    display: inline-flex;
+    min-width: 200px;
+    flex-grow: 1;
+    padding: 9px 5px 5px 15px;
+}
+
+.label-applicability {
+    background-color: #777777;
+    margin: auto 5px;
+}
+
+.label-version {
+    background-color: #777777;
+    margin: auto 5px;
+    font-family: monospace;
+}
+
+details {
+    border-radius: 4px;
+    padding: .5em .5em 0;
+}
+
+code {
+    white-space: pre !important;
+}
+
+summary {
+    font-weight: bold;
+    margin: -.5em -.5em 0;
+    padding: .5em;
+    display: revert;
+}
+
+details[open] {
+    padding: .5em;
+}
+
+/* Expanding the mdBook theme*/
+.light {
+    --inline-code-bg: #f6f7f6;
+}
+.rust {
+    --inline-code-bg: #f6f7f6;
+}
+.coal {
+    --inline-code-bg: #1d1f21;
+}
+.navy {
+    --inline-code-bg: #1d1f21;
+}
+.ayu {
+    --inline-code-bg: #191f26;
+}
+
+#settings-dropdown {
+    position: absolute;
+    margin: 0.7em;
+    z-index: 10;
+    display: flex;
+}
+
+/* Applying the mdBook theme */
+.settings-icon {
+    text-align: center;
+    width: 2em;
+    height: 2em;
+    line-height: 2em;
+    border: solid 1px var(--icons);
+    border-radius: 5px;
+    user-select: none;
+    cursor: pointer;
+    background: var(--theme-hover);
+}
+.settings-menu {
+    display: none;
+    list-style: none;
+    border: 1px solid var(--theme-popup-border);
+    border-radius: 5px;
+    color: var(--fg);
+    background: var(--theme-popup-bg);
+    overflow: hidden;
+    padding: 9px;
+    width: 207px;
+    position: absolute;
+    top: 28px;
+}
+
+.settings-icon::before {
+    /* Wheel <https://www.svgrepo.com/svg/384069/settings-cog-gear> */
+    content: url('data:image/svg+xml,<svg width="18" height="18" viewBox="0 0 12 12" \
+enable-background="new 0 0 12 12" xmlns="http://www.w3.org/2000/svg">\
+<path d="M10.25,6c0-0.1243286-0.0261841-0.241333-0.0366211-0.362915l1.6077881-1.5545654l\
+-1.25-2.1650391  c0,0-1.2674561,0.3625488-2.1323853,0.6099854c-0.2034912-0.1431885-0.421875\
+-0.2639771-0.6494751-0.3701782L7.25,0h-2.5 c0,0-0.3214111,1.2857666-0.5393066,2.1572876\
+C3.9830933,2.2634888,3.7647095,2.3842773,3.5612183,2.5274658L1.428833,1.9174805 \
+l-1.25,2.1650391c0,0,0.9641113,0.9321899,1.6077881,1.5545654C1.7761841,5.758667,\
+1.75,5.8756714,1.75,6  s0.0261841,0.241333,0.0366211,0.362915L0.178833,7.9174805l1.25,\
+2.1650391l2.1323853-0.6099854  c0.2034912,0.1432495,0.421875,0.2639771,0.6494751,0.3701782\
+L4.75,12h2.5l0.5393066-2.1572876  c0.2276001-0.1062012,0.4459839-0.2269287,0.6494751\
+-0.3701782l2.1323853,0.6099854l1.25-2.1650391L10.2133789,6.362915  C10.2238159,6.241333,\
+10.25,6.1243286,10.25,6z M6,7.5C5.1715698,7.5,4.5,6.8284302,4.5,6S5.1715698,4.5,6,4.5S7.5\
+,5.1715698,7.5,6  S6.8284302,7.5,6,7.5z" fill="black"/></svg>');
+  width: 18px;
+  height: 18px;
+  display: block;
+  filter: invert(0.7);
+  padding-left: 4px;
+  padding-top: 3px;
+}
+
+.settings-menu * {
+    font-weight: normal;
+}
+
+.settings-menu label {
+    cursor: pointer;
+}
+
+#settings-dropdown.open .settings-menu {
+    display: block;
+}
+
+#theme-choice {
+    margin-bottom: 10px;
+    background: var(--searchbar-bg);
+    color: var(--searchbar-fg);
+    border-color: var(--theme-popup-border);
+    border-radius: 5px;
+    cursor: pointer;
+    width: 100%;
+    border-width: 1px;
+    padding: 5px;
+}
+
+.alert {
+    color: var(--fg);
+    background: var(--theme-hover);
+    border: 1px solid var(--theme-popup-border);
+}
+.page-header {
+    border-color: var(--theme-popup-border);
+}
+.panel-default > .panel-heading {
+    background: var(--theme-hover);
+    color: var(--fg);
+    border: 1px solid var(--theme-popup-border);
+}
+.panel-default > .panel-heading:hover {
+    filter: brightness(90%);
+}
+.list-group-item {
+    background: 0%;
+    border: 1px solid var(--theme-popup-border);
+}
+.panel, pre, hr {
+    background: var(--bg);
+    border: 1px solid var(--theme-popup-border);
+}
+
+#version-filter-selector .checkbox {
+    display: flex;
+}
+
+#version-filter {
+    min-width: available;
+}
+
+#version-filter li label {
+    padding-right: 0;
+    width: 35%;
+}
+
+.version-filter-input {
+    height: 60%;
+    width: 30%;
+    text-align: center;
+    border: none;
+    border-bottom: 1px solid #000000;
+}
+
+#filter-label, .filter-clear {
+    background: var(--searchbar-bg);
+    color: var(--searchbar-fg);
+    border-color: var(--theme-popup-border);
+    filter: brightness(95%);
+}
+#filter-label:hover, .filter-clear:hover {
+    filter: brightness(90%);
+}
+.filter-input {
+    background: var(--searchbar-bg);
+    color: var(--searchbar-fg);
+    border-color: var(--theme-popup-border);
+}
+
+.filter-input::-webkit-input-placeholder,
+.filter-input::-moz-placeholder {
+    color: var(--searchbar-fg);
+    opacity: 30%;
+}
+
+.expansion-group {
+    margin-top: 15px;
+    padding: 0px 8px;
+    display: flex;
+    flex-wrap: nowrap;
+}
+
+@media (min-width: 992px) {
+    .expansion-group {
+        margin-top: 0;
+        padding: 0px 15px;
+    }
+}
+
+.expansion-control {
+    width: 50%;
+}
+
+:not(pre) > code {
+    color: var(--inline-code-color);
+    background-color: var(--inline-code-bg);
+}
+html {
+    scrollbar-color: var(--scrollbar) var(--bg);
+}
+body {
+    background: var(--bg);
+    color: var(--fg);
+}

From d40e04a1cb08d00736909bfb81be01e4cca9d6d6 Mon Sep 17 00:00:00 2001
From: WeiTheShinobi <weitheshinobi@gmail.com>
Date: Sun, 25 Aug 2024 20:51:26 +0800
Subject: [PATCH 014/114] `used_underscore_items` will not lint exteranl item

---
 clippy_lints/src/misc.rs              |  8 +++++-
 tests/ui/auxiliary/external_item.rs   |  7 ++++++
 tests/ui/used_underscore_items.rs     | 12 +++++++++
 tests/ui/used_underscore_items.stderr | 36 +++++++++++++--------------
 4 files changed, 44 insertions(+), 19 deletions(-)
 create mode 100644 tests/ui/auxiliary/external_item.rs

diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs
index 3fc3f2b3b7fa7..3e80e48a9485d 100644
--- a/clippy_lints/src/misc.rs
+++ b/clippy_lints/src/misc.rs
@@ -7,6 +7,7 @@ use clippy_utils::{
 };
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
     BinOpKind, BindingMode, Body, ByRef, Expr, ExprKind, FnDecl, Mutability, PatKind, QPath, Stmt, StmtKind,
@@ -281,9 +282,14 @@ fn used_underscore_items<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         },
         _ => return,
     };
+
     let name = ident.name.as_str();
     let definition_span = cx.tcx.def_span(def_id);
-    if name.starts_with('_') && !name.starts_with("__") && !definition_span.from_expansion() {
+    if name.starts_with('_')
+        && !name.starts_with("__")
+        && !definition_span.from_expansion()
+        && def_id.krate == LOCAL_CRATE
+    {
         span_lint_and_then(
             cx,
             USED_UNDERSCORE_ITEMS,
diff --git a/tests/ui/auxiliary/external_item.rs b/tests/ui/auxiliary/external_item.rs
new file mode 100644
index 0000000000000..ca4bc369e4494
--- /dev/null
+++ b/tests/ui/auxiliary/external_item.rs
@@ -0,0 +1,7 @@
+pub struct _ExternalStruct {}
+
+impl _ExternalStruct {
+    pub fn _foo(self) {}
+}
+
+pub fn _exernal_foo() {}
diff --git a/tests/ui/used_underscore_items.rs b/tests/ui/used_underscore_items.rs
index 6b2ca44e32c4e..223016a5c9667 100644
--- a/tests/ui/used_underscore_items.rs
+++ b/tests/ui/used_underscore_items.rs
@@ -1,6 +1,9 @@
+//@aux-build:external_item.rs
 #![allow(unused)]
 #![warn(clippy::used_underscore_items)]
 
+extern crate external_item;
+
 // should not lint macro
 macro_rules! macro_wrap_func {
     () => {
@@ -49,3 +52,12 @@ fn main() {
     let foo_struct2 = a::b::c::_FooStruct2 {};
     foo_struct2._method_call();
 }
+
+// should not lint exteranl crate.
+// user cannot control how others name their items
+fn external_item_call() {
+    let foo_struct3 = external_item::_ExternalStruct {};
+    foo_struct3._foo();
+
+    external_item::_exernal_foo();
+}
diff --git a/tests/ui/used_underscore_items.stderr b/tests/ui/used_underscore_items.stderr
index 127d8248a943d..93ac3a6fec6be 100644
--- a/tests/ui/used_underscore_items.stderr
+++ b/tests/ui/used_underscore_items.stderr
@@ -1,11 +1,11 @@
 error: used underscore-prefixed item
-  --> tests/ui/used_underscore_items.rs:40:5
+  --> tests/ui/used_underscore_items.rs:43:5
    |
 LL |     _foo1();
    |     ^^^^^^^
    |
 note: item is defined here
-  --> tests/ui/used_underscore_items.rs:19:1
+  --> tests/ui/used_underscore_items.rs:22:1
    |
 LL | fn _foo1() {}
    | ^^^^^^^^^^
@@ -13,97 +13,97 @@ LL | fn _foo1() {}
    = help: to override `-D warnings` add `#[allow(clippy::used_underscore_items)]`
 
 error: used underscore-prefixed item
-  --> tests/ui/used_underscore_items.rs:41:13
+  --> tests/ui/used_underscore_items.rs:44:13
    |
 LL |     let _ = _foo2();
    |             ^^^^^^^
    |
 note: item is defined here
-  --> tests/ui/used_underscore_items.rs:21:1
+  --> tests/ui/used_underscore_items.rs:24:1
    |
 LL | fn _foo2() -> i32 {
    | ^^^^^^^^^^^^^^^^^
 
 error: used underscore-prefixed item
-  --> tests/ui/used_underscore_items.rs:42:5
+  --> tests/ui/used_underscore_items.rs:45:5
    |
 LL |     a::b::c::_foo3();
    |     ^^^^^^^^^^^^^^^^
    |
 note: item is defined here
-  --> tests/ui/used_underscore_items.rs:28:13
+  --> tests/ui/used_underscore_items.rs:31:13
    |
 LL |             pub fn _foo3() {}
    |             ^^^^^^^^^^^^^^
 
 error: used underscore-prefixed item
-  --> tests/ui/used_underscore_items.rs:43:14
+  --> tests/ui/used_underscore_items.rs:46:14
    |
 LL |     let _ = &_FooStruct {};
    |              ^^^^^^^^^^^^^
    |
 note: item is defined here
-  --> tests/ui/used_underscore_items.rs:13:1
+  --> tests/ui/used_underscore_items.rs:16:1
    |
 LL | struct _FooStruct {}
    | ^^^^^^^^^^^^^^^^^
 
 error: used underscore-prefixed item
-  --> tests/ui/used_underscore_items.rs:44:13
+  --> tests/ui/used_underscore_items.rs:47:13
    |
 LL |     let _ = _FooStruct {};
    |             ^^^^^^^^^^^^^
    |
 note: item is defined here
-  --> tests/ui/used_underscore_items.rs:13:1
+  --> tests/ui/used_underscore_items.rs:16:1
    |
 LL | struct _FooStruct {}
    | ^^^^^^^^^^^^^^^^^
 
 error: used underscore-prefixed item
-  --> tests/ui/used_underscore_items.rs:46:22
+  --> tests/ui/used_underscore_items.rs:49:22
    |
 LL |     let foo_struct = _FooStruct {};
    |                      ^^^^^^^^^^^^^
    |
 note: item is defined here
-  --> tests/ui/used_underscore_items.rs:13:1
+  --> tests/ui/used_underscore_items.rs:16:1
    |
 LL | struct _FooStruct {}
    | ^^^^^^^^^^^^^^^^^
 
 error: used underscore-prefixed item
-  --> tests/ui/used_underscore_items.rs:47:5
+  --> tests/ui/used_underscore_items.rs:50:5
    |
 LL |     foo_struct._method_call();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: item is defined here
-  --> tests/ui/used_underscore_items.rs:16:5
+  --> tests/ui/used_underscore_items.rs:19:5
    |
 LL |     fn _method_call(self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: used underscore-prefixed item
-  --> tests/ui/used_underscore_items.rs:49:23
+  --> tests/ui/used_underscore_items.rs:52:23
    |
 LL |     let foo_struct2 = a::b::c::_FooStruct2 {};
    |                       ^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: item is defined here
-  --> tests/ui/used_underscore_items.rs:30:13
+  --> tests/ui/used_underscore_items.rs:33:13
    |
 LL |             pub struct _FooStruct2 {}
    |             ^^^^^^^^^^^^^^^^^^^^^^
 
 error: used underscore-prefixed item
-  --> tests/ui/used_underscore_items.rs:50:5
+  --> tests/ui/used_underscore_items.rs:53:5
    |
 LL |     foo_struct2._method_call();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: item is defined here
-  --> tests/ui/used_underscore_items.rs:33:17
+  --> tests/ui/used_underscore_items.rs:36:17
    |
 LL |                 pub fn _method_call(self) {}
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^

From 494112e51f7a2b59866c835810c3e87a10912c0a Mon Sep 17 00:00:00 2001
From: Alexey Semenyuk <alexsemenyuk88@gmail.com>
Date: Mon, 26 Aug 2024 20:01:29 +0500
Subject: [PATCH 015/114] Fix manual_range_patterns case with one element at OR

---
 clippy_lints/src/manual_range_patterns.rs | 5 +++--
 tests/ui/manual_range_patterns.fixed      | 8 ++++++++
 tests/ui/manual_range_patterns.rs         | 8 ++++++++
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/clippy_lints/src/manual_range_patterns.rs b/clippy_lints/src/manual_range_patterns.rs
index 9afb2b5bc84cd..66d2ab6b24a4c 100644
--- a/clippy_lints/src/manual_range_patterns.rs
+++ b/clippy_lints/src/manual_range_patterns.rs
@@ -77,9 +77,10 @@ impl Num {
 impl LateLintPass<'_> for ManualRangePatterns {
     fn check_pat(&mut self, cx: &LateContext<'_>, pat: &'_ rustc_hir::Pat<'_>) {
         // a pattern like 1 | 2 seems fine, lint if there are at least 3 alternatives
-        // or at least one range
+        // or more then one range (exclude triggering on stylistic using OR with one element
+        // like described https://github.com/rust-lang/rust-clippy/issues/11825)
         if let PatKind::Or(pats) = pat.kind
-            && (pats.len() >= 3 || pats.iter().any(|p| matches!(p.kind, PatKind::Range(..))))
+            && (pats.len() >= 3 || (pats.len() > 1 && pats.iter().any(|p| matches!(p.kind, PatKind::Range(..)))))
             && !in_external_macro(cx.sess(), pat.span)
         {
             let mut min = Num::dummy(i128::MAX);
diff --git a/tests/ui/manual_range_patterns.fixed b/tests/ui/manual_range_patterns.fixed
index f1b99637afdba..60467bf9e8848 100644
--- a/tests/ui/manual_range_patterns.fixed
+++ b/tests/ui/manual_range_patterns.fixed
@@ -45,4 +45,12 @@ fn main() {
         };
     }
     mac!(f);
+
+    #[rustfmt::skip]
+    let _ = match f {
+        | 2..=15 => 4,
+        | 241..=254 => 5,
+        | 255 => 6,
+        | _ => 7,
+    };
 }
diff --git a/tests/ui/manual_range_patterns.rs b/tests/ui/manual_range_patterns.rs
index 869ffbe80b973..9cd803334499d 100644
--- a/tests/ui/manual_range_patterns.rs
+++ b/tests/ui/manual_range_patterns.rs
@@ -45,4 +45,12 @@ fn main() {
         };
     }
     mac!(f);
+
+    #[rustfmt::skip]
+    let _ = match f {
+        | 2..=15 => 4,
+        | 241..=254 => 5,
+        | 255 => 6,
+        | _ => 7,
+    };
 }

From e8ac4ea4187498052849531b86114a1eec5314a1 Mon Sep 17 00:00:00 2001
From: y21 <30553356+y21@users.noreply.github.com>
Date: Sun, 10 Sep 2023 16:14:20 +0200
Subject: [PATCH 016/114] new lint: `zombie_processes`

---
 CHANGELOG.md                                 |   1 +
 clippy_dev/src/serve.rs                      |   3 +-
 clippy_lints/src/declared_lints.rs           |   1 +
 clippy_lints/src/lib.rs                      |   2 +
 clippy_lints/src/zombie_processes.rs         | 334 +++++++++++++++++++
 clippy_utils/src/paths.rs                    |   4 +
 tests/ui/suspicious_command_arg_space.fixed  |   1 +
 tests/ui/suspicious_command_arg_space.rs     |   1 +
 tests/ui/suspicious_command_arg_space.stderr |   4 +-
 tests/ui/zombie_processes.rs                 | 138 ++++++++
 tests/ui/zombie_processes.stderr             |  64 ++++
 tests/ui/zombie_processes_fixable.fixed      |  26 ++
 tests/ui/zombie_processes_fixable.rs         |  26 ++
 tests/ui/zombie_processes_fixable.stderr     |  40 +++
 14 files changed, 642 insertions(+), 3 deletions(-)
 create mode 100644 clippy_lints/src/zombie_processes.rs
 create mode 100644 tests/ui/zombie_processes.rs
 create mode 100644 tests/ui/zombie_processes.stderr
 create mode 100644 tests/ui/zombie_processes_fixable.fixed
 create mode 100644 tests/ui/zombie_processes_fixable.rs
 create mode 100644 tests/ui/zombie_processes_fixable.stderr

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c5d7991e073fd..21252a3f43a00 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6048,6 +6048,7 @@ Released 2018-09-13
 [`zero_repeat_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_repeat_side_effects
 [`zero_sized_map_values`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_sized_map_values
 [`zero_width_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_width_space
+[`zombie_processes`]: https://rust-lang.github.io/rust-clippy/master/index.html#zombie_processes
 [`zst_offset`]: https://rust-lang.github.io/rust-clippy/master/index.html#zst_offset
 <!-- end autogenerated links to lint list -->
 <!-- begin autogenerated links to configuration documentation -->
diff --git a/clippy_dev/src/serve.rs b/clippy_dev/src/serve.rs
index 19560b31fd3e2..cc14cd8dae69e 100644
--- a/clippy_dev/src/serve.rs
+++ b/clippy_dev/src/serve.rs
@@ -29,7 +29,7 @@ pub fn run(port: u16, lint: Option<String>) -> ! {
         }
         if let Some(url) = url.take() {
             thread::spawn(move || {
-                Command::new(PYTHON)
+                let mut child = Command::new(PYTHON)
                     .arg("-m")
                     .arg("http.server")
                     .arg(port.to_string())
@@ -40,6 +40,7 @@ pub fn run(port: u16, lint: Option<String>) -> ! {
                 thread::sleep(Duration::from_millis(500));
                 // Launch browser after first export.py has completed and http.server is up
                 let _result = opener::open(url);
+                child.wait().unwrap();
             });
         }
         thread::sleep(Duration::from_millis(1000));
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index 94da5752bebf6..10e041fbc09a2 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -768,4 +768,5 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::zero_div_zero::ZERO_DIVIDED_BY_ZERO_INFO,
     crate::zero_repeat_side_effects::ZERO_REPEAT_SIDE_EFFECTS_INFO,
     crate::zero_sized_map_values::ZERO_SIZED_MAP_VALUES_INFO,
+    crate::zombie_processes::ZOMBIE_PROCESSES_INFO,
 ];
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 2ac06b360bea4..f24933683b1a0 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -386,6 +386,7 @@ mod write;
 mod zero_div_zero;
 mod zero_repeat_side_effects;
 mod zero_sized_map_values;
+mod zombie_processes;
 // end lints modules, do not remove this comment, it’s used in `update_lints`
 
 use clippy_config::{get_configuration_metadata, Conf};
@@ -933,5 +934,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(set_contains_or_insert::SetContainsOrInsert));
     store.register_early_pass(|| Box::new(byte_char_slices::ByteCharSlice));
     store.register_early_pass(|| Box::new(cfg_not_test::CfgNotTest));
+    store.register_late_pass(|_| Box::new(zombie_processes::ZombieProcesses));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
diff --git a/clippy_lints/src/zombie_processes.rs b/clippy_lints/src/zombie_processes.rs
new file mode 100644
index 0000000000000..eda3d7820c169
--- /dev/null
+++ b/clippy_lints/src/zombie_processes.rs
@@ -0,0 +1,334 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::{fn_def_id, get_enclosing_block, match_any_def_paths, match_def_path, path_to_local_id, paths};
+use rustc_ast::Mutability;
+use rustc_errors::Applicability;
+use rustc_hir::intravisit::{walk_block, walk_expr, walk_local, Visitor};
+use rustc_hir::{Expr, ExprKind, HirId, LetStmt, Node, PatKind, Stmt, StmtKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::declare_lint_pass;
+use rustc_span::sym;
+use std::ops::ControlFlow;
+use ControlFlow::{Break, Continue};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Looks for code that spawns a process but never calls `wait()` on the child.
+    ///
+    /// ### Why is this bad?
+    /// As explained in the [standard library documentation](https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning),
+    /// calling `wait()` is necessary on Unix platforms to properly release all OS resources associated with the process.
+    /// Not doing so will effectively leak process IDs and/or other limited global resources,
+    /// which can eventually lead to resource exhaustion, so it's recommended to call `wait()` in long-running applications.
+    /// Such processes are called "zombie processes".
+    ///
+    /// ### Example
+    /// ```rust
+    /// use std::process::Command;
+    ///
+    /// let _child = Command::new("ls").spawn().expect("failed to execute child");
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// use std::process::Command;
+    ///
+    /// let mut child = Command::new("ls").spawn().expect("failed to execute child");
+    /// child.wait().expect("failed to wait on child");
+    /// ```
+    #[clippy::version = "1.74.0"]
+    pub ZOMBIE_PROCESSES,
+    suspicious,
+    "not waiting on a spawned child process"
+}
+declare_lint_pass!(ZombieProcesses => [ZOMBIE_PROCESSES]);
+
+impl<'tcx> LateLintPass<'tcx> for ZombieProcesses {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        if let ExprKind::Call(..) | ExprKind::MethodCall(..) = expr.kind
+            && let Some(child_adt) = cx.typeck_results().expr_ty(expr).ty_adt_def()
+            && match_def_path(cx, child_adt.did(), &paths::CHILD)
+        {
+            match cx.tcx.parent_hir_node(expr.hir_id) {
+                Node::LetStmt(local)
+                    if let PatKind::Binding(_, local_id, ..) = local.pat.kind
+                        && let Some(enclosing_block) = get_enclosing_block(cx, expr.hir_id) =>
+                {
+                    let mut vis = WaitFinder::WalkUpTo(cx, local_id);
+
+                    // If it does have a `wait()` call, we're done. Don't lint.
+                    if let Break(BreakReason::WaitFound) = walk_block(&mut vis, enclosing_block) {
+                        return;
+                    }
+
+                    // Don't emit a suggestion since the binding is used later
+                    check(cx, expr, false);
+                },
+                Node::LetStmt(&LetStmt { pat, .. }) if let PatKind::Wild = pat.kind => {
+                    // `let _ = child;`, also dropped immediately without `wait()`ing
+                    check(cx, expr, true);
+                },
+                Node::Stmt(&Stmt {
+                    kind: StmtKind::Semi(_),
+                    ..
+                }) => {
+                    // Immediately dropped. E.g. `std::process::Command::new("echo").spawn().unwrap();`
+                    check(cx, expr, true);
+                },
+                _ => {},
+            }
+        }
+    }
+}
+
+enum BreakReason {
+    WaitFound,
+    EarlyReturn,
+}
+
+/// A visitor responsible for finding a `wait()` call on a local variable.
+///
+/// Conditional `wait()` calls are assumed to not call wait:
+/// ```ignore
+/// let mut c = Command::new("").spawn().unwrap();
+/// if true {
+///     c.wait();
+/// }
+/// ```
+///
+/// Note that this visitor does NOT explicitly look for `wait()` calls directly, but rather does the
+/// inverse -- checking if all uses of the local are either:
+/// - a field access (`child.{stderr,stdin,stdout}`)
+/// - calling `id` or `kill`
+/// - no use at all (e.g. `let _x = child;`)
+/// - taking a shared reference (`&`), `wait()` can't go through that
+///
+/// None of these are sufficient to prevent zombie processes.
+/// Doing it like this means more FNs, but FNs are better than FPs.
+///
+/// `return` expressions, conditional or not, short-circuit the visitor because
+/// if a `wait()` call hadn't been found at that point, it might never reach one at a later point:
+/// ```ignore
+/// let mut c = Command::new("").spawn().unwrap();
+/// if true {
+///     return; // Break(BreakReason::EarlyReturn)
+/// }
+/// c.wait(); // this might not be reachable
+/// ```
+enum WaitFinder<'a, 'tcx> {
+    WalkUpTo(&'a LateContext<'tcx>, HirId),
+    Found(&'a LateContext<'tcx>, HirId),
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for WaitFinder<'a, 'tcx> {
+    type Result = ControlFlow<BreakReason>;
+
+    fn visit_local(&mut self, l: &'tcx LetStmt<'tcx>) -> Self::Result {
+        if let Self::WalkUpTo(cx, local_id) = *self
+            && let PatKind::Binding(_, pat_id, ..) = l.pat.kind
+            && local_id == pat_id
+        {
+            *self = Self::Found(cx, local_id);
+        }
+
+        walk_local(self, l)
+    }
+
+    fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) -> Self::Result {
+        let Self::Found(cx, local_id) = *self else {
+            return walk_expr(self, ex);
+        };
+
+        if path_to_local_id(ex, local_id) {
+            match cx.tcx.parent_hir_node(ex.hir_id) {
+                Node::Stmt(Stmt {
+                    kind: StmtKind::Semi(_),
+                    ..
+                }) => {},
+                Node::Expr(expr) if let ExprKind::Field(..) = expr.kind => {},
+                Node::Expr(expr) if let ExprKind::AddrOf(_, Mutability::Not, _) = expr.kind => {},
+                Node::Expr(expr)
+                    if let Some(fn_did) = fn_def_id(cx, expr)
+                        && match_any_def_paths(cx, fn_did, &[&paths::CHILD_ID, &paths::CHILD_KILL]).is_some() => {},
+
+                // Conservatively assume that all other kinds of nodes call `.wait()` somehow.
+                _ => return Break(BreakReason::WaitFound),
+            }
+        } else {
+            match ex.kind {
+                ExprKind::Ret(..) => return Break(BreakReason::EarlyReturn),
+                ExprKind::If(cond, then, None) => {
+                    walk_expr(self, cond)?;
+
+                    // A `wait()` call in an if expression with no else is not enough:
+                    //
+                    // let c = spawn();
+                    // if true {
+                    //   c.wait();
+                    // }
+                    //
+                    // This might not call wait(). However, early returns are propagated,
+                    // because they might lead to a later wait() not being called.
+                    if let Break(BreakReason::EarlyReturn) = walk_expr(self, then) {
+                        return Break(BreakReason::EarlyReturn);
+                    }
+
+                    return Continue(());
+                },
+
+                ExprKind::If(cond, then, Some(else_)) => {
+                    walk_expr(self, cond)?;
+
+                    #[expect(clippy::unnested_or_patterns)]
+                    match (walk_expr(self, then), walk_expr(self, else_)) {
+                        (Continue(()), Continue(()))
+
+                        // `wait()` in one branch but nothing in the other does not count
+                        | (Continue(()), Break(BreakReason::WaitFound))
+                        | (Break(BreakReason::WaitFound), Continue(())) => {},
+
+                        // `wait()` in both branches is ok
+                        (Break(BreakReason::WaitFound), Break(BreakReason::WaitFound)) => {
+                            return Break(BreakReason::WaitFound);
+                        },
+
+                        // Propagate early returns in either branch
+                        (Break(BreakReason::EarlyReturn), _) | (_, Break(BreakReason::EarlyReturn)) => {
+                            return Break(BreakReason::EarlyReturn);
+                        },
+                    }
+
+                    return Continue(());
+                },
+                _ => {},
+            }
+        }
+
+        walk_expr(self, ex)
+    }
+}
+
+/// This function has shared logic between the different kinds of nodes that can trigger the lint.
+///
+/// In particular, `let <binding> = <expr that spawns child>;` requires some custom additional logic
+/// such as checking that the binding is not used in certain ways, which isn't necessary for
+/// `let _ = <expr that spawns child>;`.
+///
+/// This checks if the program doesn't unconditionally exit after the spawn expression.
+fn check<'tcx>(cx: &LateContext<'tcx>, spawn_expr: &'tcx Expr<'tcx>, emit_suggestion: bool) {
+    let Some(block) = get_enclosing_block(cx, spawn_expr.hir_id) else {
+        return;
+    };
+
+    let mut vis = ExitPointFinder {
+        cx,
+        state: ExitPointState::WalkUpTo(spawn_expr.hir_id),
+    };
+    if let Break(ExitCallFound) = vis.visit_block(block) {
+        // Visitor found an unconditional `exit()` call, so don't lint.
+        return;
+    }
+
+    span_lint_and_then(
+        cx,
+        ZOMBIE_PROCESSES,
+        spawn_expr.span,
+        "spawned process is never `wait()`ed on",
+        |diag| {
+            if emit_suggestion {
+                diag.span_suggestion(
+                    spawn_expr.span.shrink_to_hi(),
+                    "try",
+                    ".wait()",
+                    Applicability::MaybeIncorrect,
+                );
+            } else {
+                diag.note("consider calling `.wait()`");
+            }
+
+            diag.note("not doing so might leave behind zombie processes")
+                .note("see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning");
+        },
+    );
+}
+
+/// Checks if the given expression exits the process.
+fn is_exit_expression(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    fn_def_id(cx, expr).is_some_and(|fn_did| {
+        cx.tcx.is_diagnostic_item(sym::process_exit, fn_did) || match_def_path(cx, fn_did, &paths::ABORT)
+    })
+}
+
+#[derive(Debug)]
+enum ExitPointState {
+    /// Still walking up to the expression that initiated the visitor.
+    WalkUpTo(HirId),
+    /// We're inside of a control flow construct (e.g. `if`, `match`, `loop`)
+    /// Within this, we shouldn't accept any `exit()` calls in here, but we can leave all of these
+    /// constructs later and still continue looking for an `exit()` call afterwards. Example:
+    /// ```ignore
+    /// Command::new("").spawn().unwrap();
+    ///
+    /// if true {                // depth=1
+    ///     if true {            // depth=2
+    ///         match () {       // depth=3
+    ///             () => loop { // depth=4
+    ///
+    ///                 std::process::exit();
+    ///                 ^^^^^^^^^^^^^^^^^^^^^ conditional exit call, ignored
+    ///
+    ///             }           // depth=3
+    ///         }               // depth=2
+    ///     }                   // depth=1
+    /// }                       // depth=0
+    ///
+    /// std::process::exit();
+    /// ^^^^^^^^^^^^^^^^^^^^^ this exit call is accepted because we're now unconditionally calling it
+    /// ```
+    /// We can only get into this state from `NoExit`.
+    InControlFlow { depth: u32 },
+    /// No exit call found yet, but looking for one.
+    NoExit,
+}
+
+fn expr_enters_control_flow(expr: &Expr<'_>) -> bool {
+    matches!(expr.kind, ExprKind::If(..) | ExprKind::Match(..) | ExprKind::Loop(..))
+}
+
+struct ExitPointFinder<'a, 'tcx> {
+    state: ExitPointState,
+    cx: &'a LateContext<'tcx>,
+}
+
+struct ExitCallFound;
+
+impl<'a, 'tcx> Visitor<'tcx> for ExitPointFinder<'a, 'tcx> {
+    type Result = ControlFlow<ExitCallFound>;
+
+    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> Self::Result {
+        match self.state {
+            ExitPointState::WalkUpTo(id) if expr.hir_id == id => {
+                self.state = ExitPointState::NoExit;
+                walk_expr(self, expr)
+            },
+            ExitPointState::NoExit if expr_enters_control_flow(expr) => {
+                self.state = ExitPointState::InControlFlow { depth: 1 };
+                walk_expr(self, expr)?;
+                if let ExitPointState::InControlFlow { .. } = self.state {
+                    self.state = ExitPointState::NoExit;
+                }
+                Continue(())
+            },
+            ExitPointState::NoExit if is_exit_expression(self.cx, expr) => Break(ExitCallFound),
+            ExitPointState::InControlFlow { ref mut depth } if expr_enters_control_flow(expr) => {
+                *depth += 1;
+                walk_expr(self, expr)?;
+                match self.state {
+                    ExitPointState::InControlFlow { depth: 1 } => self.state = ExitPointState::NoExit,
+                    ExitPointState::InControlFlow { ref mut depth } => *depth -= 1,
+                    _ => {},
+                }
+                Continue(())
+            },
+            _ => Continue(()),
+        }
+    }
+}
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index a767798a9c36e..930fb9fb6f2d5 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -4,6 +4,7 @@
 //! Whenever possible, please consider diagnostic items over hardcoded paths.
 //! See <https://github.com/rust-lang/rust-clippy/issues/5393> for more information.
 
+pub const ABORT: [&str; 3] = ["std", "process", "abort"];
 pub const APPLICABILITY: [&str; 2] = ["rustc_lint_defs", "Applicability"];
 pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
     ["rustc_lint_defs", "Applicability", "Unspecified"],
@@ -23,6 +24,9 @@ pub const CORE_RESULT_OK_METHOD: [&str; 4] = ["core", "result", "Result", "ok"];
 pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"];
 pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
 pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"];
+pub const CHILD: [&str; 3] = ["std", "process", "Child"];
+pub const CHILD_ID: [&str; 4] = ["std", "process", "Child", "id"];
+pub const CHILD_KILL: [&str; 4] = ["std", "process", "Child", "kill"];
 pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"];
 pub const F64_EPSILON: [&str; 4] = ["core", "f64", "<impl f64>", "EPSILON"];
 pub const FILE_OPTIONS: [&str; 4] = ["std", "fs", "File", "options"];
diff --git a/tests/ui/suspicious_command_arg_space.fixed b/tests/ui/suspicious_command_arg_space.fixed
index 5d7b1e0c17f25..704d6ea1bb837 100644
--- a/tests/ui/suspicious_command_arg_space.fixed
+++ b/tests/ui/suspicious_command_arg_space.fixed
@@ -1,3 +1,4 @@
+#![allow(clippy::zombie_processes)]
 fn main() {
     // Things it should warn about:
     std::process::Command::new("echo").args(["-n", "hello"]).spawn().unwrap();
diff --git a/tests/ui/suspicious_command_arg_space.rs b/tests/ui/suspicious_command_arg_space.rs
index 8abd9803a0c6f..2a2a7557381c4 100644
--- a/tests/ui/suspicious_command_arg_space.rs
+++ b/tests/ui/suspicious_command_arg_space.rs
@@ -1,3 +1,4 @@
+#![allow(clippy::zombie_processes)]
 fn main() {
     // Things it should warn about:
     std::process::Command::new("echo").arg("-n hello").spawn().unwrap();
diff --git a/tests/ui/suspicious_command_arg_space.stderr b/tests/ui/suspicious_command_arg_space.stderr
index d2517b66b5661..6fd07d07d7be6 100644
--- a/tests/ui/suspicious_command_arg_space.stderr
+++ b/tests/ui/suspicious_command_arg_space.stderr
@@ -1,5 +1,5 @@
 error: single argument that looks like it should be multiple arguments
-  --> tests/ui/suspicious_command_arg_space.rs:3:44
+  --> tests/ui/suspicious_command_arg_space.rs:4:44
    |
 LL |     std::process::Command::new("echo").arg("-n hello").spawn().unwrap();
    |                                            ^^^^^^^^^^
@@ -12,7 +12,7 @@ LL |     std::process::Command::new("echo").args(["-n", "hello"]).spawn().unwrap
    |                                        ~~~~ ~~~~~~~~~~~~~~~
 
 error: single argument that looks like it should be multiple arguments
-  --> tests/ui/suspicious_command_arg_space.rs:6:43
+  --> tests/ui/suspicious_command_arg_space.rs:7:43
    |
 LL |     std::process::Command::new("cat").arg("--number file").spawn().unwrap();
    |                                           ^^^^^^^^^^^^^^^
diff --git a/tests/ui/zombie_processes.rs b/tests/ui/zombie_processes.rs
new file mode 100644
index 0000000000000..a2abc7fc3a179
--- /dev/null
+++ b/tests/ui/zombie_processes.rs
@@ -0,0 +1,138 @@
+#![warn(clippy::zombie_processes)]
+#![allow(clippy::if_same_then_else, clippy::ifs_same_cond)]
+
+use std::process::{Child, Command};
+
+fn main() {
+    {
+        // Check that #[expect] works
+        #[expect(clippy::zombie_processes)]
+        let mut x = Command::new("").spawn().unwrap();
+    }
+
+    {
+        let mut x = Command::new("").spawn().unwrap();
+        //~^ ERROR: spawned process is never `wait()`ed on
+        x.kill();
+        x.id();
+    }
+    {
+        let mut x = Command::new("").spawn().unwrap();
+        x.wait().unwrap(); // OK
+    }
+    {
+        let x = Command::new("").spawn().unwrap();
+        x.wait_with_output().unwrap(); // OK
+    }
+    {
+        let mut x = Command::new("").spawn().unwrap();
+        x.try_wait().unwrap(); // OK
+    }
+    {
+        let mut x = Command::new("").spawn().unwrap();
+        let mut r = &mut x;
+        r.wait().unwrap(); // OK, not calling `.wait()` directly on `x` but through `r` -> `x`
+    }
+    {
+        let mut x = Command::new("").spawn().unwrap();
+        process_child(x); // OK, other function might call `.wait()` so assume it does
+    }
+    {
+        let mut x = Command::new("").spawn().unwrap();
+        //~^ ERROR: spawned process is never `wait()`ed on
+        let v = &x;
+        // (allow shared refs is fine because one cannot call `.wait()` through that)
+    }
+
+    // https://github.com/rust-lang/rust-clippy/pull/11476#issuecomment-1718456033
+    // Unconditionally exiting the process in various ways (should not lint)
+    {
+        let mut x = Command::new("").spawn().unwrap();
+        std::process::exit(0);
+    }
+    {
+        let mut x = Command::new("").spawn().unwrap();
+        std::process::abort(); // same as above, but abort instead of exit
+    }
+    {
+        let mut x = Command::new("").spawn().unwrap();
+        if true { /* nothing */ }
+        std::process::abort(); // still unconditionally exits
+    }
+
+    // Conditionally exiting
+    // It should assume that it might not exit and still lint
+    {
+        let mut x = Command::new("").spawn().unwrap();
+        //~^ ERROR: spawned process is never `wait()`ed on
+        if true {
+            std::process::exit(0);
+        }
+    }
+    {
+        let mut x = Command::new("").spawn().unwrap();
+        //~^ ERROR: spawned process is never `wait()`ed on
+        if true {
+            while false {}
+            // Calling `exit()` after leaving a while loop should still be linted.
+            std::process::exit(0);
+        }
+    }
+
+    {
+        let mut x = { Command::new("").spawn().unwrap() };
+        x.wait().unwrap();
+    }
+
+    {
+        struct S {
+            c: Child,
+        }
+
+        let mut s = S {
+            c: Command::new("").spawn().unwrap(),
+        };
+        s.c.wait().unwrap();
+    }
+
+    {
+        let mut x = Command::new("").spawn().unwrap();
+        //~^ ERROR: spawned process is never `wait()`ed on
+        if true {
+            return;
+        }
+        x.wait().unwrap();
+    }
+
+    {
+        let mut x = Command::new("").spawn().unwrap();
+        //~^ ERROR: spawned process is never `wait()`ed on
+        if true {
+            x.wait().unwrap();
+        }
+    }
+
+    {
+        let mut x = Command::new("").spawn().unwrap();
+        if true {
+            x.wait().unwrap();
+        } else if true {
+            x.wait().unwrap();
+        } else {
+            x.wait().unwrap();
+        }
+    }
+
+    {
+        let mut x = Command::new("").spawn().unwrap();
+        if true {
+            x.wait().unwrap();
+            return;
+        }
+        x.wait().unwrap();
+    }
+}
+
+fn process_child(c: Child) {
+    todo!()
+}
diff --git a/tests/ui/zombie_processes.stderr b/tests/ui/zombie_processes.stderr
new file mode 100644
index 0000000000000..eec821a4c8f18
--- /dev/null
+++ b/tests/ui/zombie_processes.stderr
@@ -0,0 +1,64 @@
+error: spawned process is never `wait()`ed on
+  --> tests/ui/zombie_processes.rs:14:21
+   |
+LL |         let mut x = Command::new("").spawn().unwrap();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: consider calling `.wait()`
+   = note: not doing so might leave behind zombie processes
+   = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+   = note: `-D clippy::zombie-processes` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::zombie_processes)]`
+
+error: spawned process is never `wait()`ed on
+  --> tests/ui/zombie_processes.rs:41:21
+   |
+LL |         let mut x = Command::new("").spawn().unwrap();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: consider calling `.wait()`
+   = note: not doing so might leave behind zombie processes
+   = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+
+error: spawned process is never `wait()`ed on
+  --> tests/ui/zombie_processes.rs:66:21
+   |
+LL |         let mut x = Command::new("").spawn().unwrap();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: consider calling `.wait()`
+   = note: not doing so might leave behind zombie processes
+   = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+
+error: spawned process is never `wait()`ed on
+  --> tests/ui/zombie_processes.rs:73:21
+   |
+LL |         let mut x = Command::new("").spawn().unwrap();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: consider calling `.wait()`
+   = note: not doing so might leave behind zombie processes
+   = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+
+error: spawned process is never `wait()`ed on
+  --> tests/ui/zombie_processes.rs:99:21
+   |
+LL |         let mut x = Command::new("").spawn().unwrap();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: consider calling `.wait()`
+   = note: not doing so might leave behind zombie processes
+   = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+
+error: spawned process is never `wait()`ed on
+  --> tests/ui/zombie_processes.rs:108:21
+   |
+LL |         let mut x = Command::new("").spawn().unwrap();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: consider calling `.wait()`
+   = note: not doing so might leave behind zombie processes
+   = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/zombie_processes_fixable.fixed b/tests/ui/zombie_processes_fixable.fixed
new file mode 100644
index 0000000000000..6045262f519a7
--- /dev/null
+++ b/tests/ui/zombie_processes_fixable.fixed
@@ -0,0 +1,26 @@
+#![warn(clippy::zombie_processes)]
+#![allow(clippy::needless_return)]
+
+use std::process::{Child, Command};
+
+fn main() {
+    let _ = Command::new("").spawn().unwrap().wait();
+    //~^ ERROR: spawned process is never `wait()`ed on
+    Command::new("").spawn().unwrap().wait();
+    //~^ ERROR: spawned process is never `wait()`ed on
+    spawn_proc().wait();
+    //~^ ERROR: spawned process is never `wait()`ed on
+    spawn_proc().wait().unwrap(); // OK
+}
+
+fn not_main() {
+    Command::new("").spawn().unwrap().wait();
+}
+
+fn spawn_proc() -> Child {
+    Command::new("").spawn().unwrap()
+}
+
+fn spawn_proc_2() -> Child {
+    return Command::new("").spawn().unwrap();
+}
diff --git a/tests/ui/zombie_processes_fixable.rs b/tests/ui/zombie_processes_fixable.rs
new file mode 100644
index 0000000000000..e1ecb771641e2
--- /dev/null
+++ b/tests/ui/zombie_processes_fixable.rs
@@ -0,0 +1,26 @@
+#![warn(clippy::zombie_processes)]
+#![allow(clippy::needless_return)]
+
+use std::process::{Child, Command};
+
+fn main() {
+    let _ = Command::new("").spawn().unwrap();
+    //~^ ERROR: spawned process is never `wait()`ed on
+    Command::new("").spawn().unwrap();
+    //~^ ERROR: spawned process is never `wait()`ed on
+    spawn_proc();
+    //~^ ERROR: spawned process is never `wait()`ed on
+    spawn_proc().wait().unwrap(); // OK
+}
+
+fn not_main() {
+    Command::new("").spawn().unwrap();
+}
+
+fn spawn_proc() -> Child {
+    Command::new("").spawn().unwrap()
+}
+
+fn spawn_proc_2() -> Child {
+    return Command::new("").spawn().unwrap();
+}
diff --git a/tests/ui/zombie_processes_fixable.stderr b/tests/ui/zombie_processes_fixable.stderr
new file mode 100644
index 0000000000000..e1c40472c325e
--- /dev/null
+++ b/tests/ui/zombie_processes_fixable.stderr
@@ -0,0 +1,40 @@
+error: spawned process is never `wait()`ed on
+  --> tests/ui/zombie_processes_fixable.rs:7:13
+   |
+LL |     let _ = Command::new("").spawn().unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try: `.wait()`
+   |
+   = note: not doing so might leave behind zombie processes
+   = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+   = note: `-D clippy::zombie-processes` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::zombie_processes)]`
+
+error: spawned process is never `wait()`ed on
+  --> tests/ui/zombie_processes_fixable.rs:9:5
+   |
+LL |     Command::new("").spawn().unwrap();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try: `.wait()`
+   |
+   = note: not doing so might leave behind zombie processes
+   = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+
+error: spawned process is never `wait()`ed on
+  --> tests/ui/zombie_processes_fixable.rs:11:5
+   |
+LL |     spawn_proc();
+   |     ^^^^^^^^^^^^- help: try: `.wait()`
+   |
+   = note: not doing so might leave behind zombie processes
+   = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+
+error: spawned process is never `wait()`ed on
+  --> tests/ui/zombie_processes_fixable.rs:17:5
+   |
+LL |     Command::new("").spawn().unwrap();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try: `.wait()`
+   |
+   = note: not doing so might leave behind zombie processes
+   = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+
+error: aborting due to 4 previous errors
+

From 5bbb0d41f1637d3b6a54ded065e807a48c67aec0 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Thu, 29 Aug 2024 00:17:40 -0400
Subject: [PATCH 017/114] Stop using ty::GenericPredicates for
 non-predicates_of queries

---
 clippy_lints/src/implied_bounds_in_impls.rs | 2 +-
 clippy_lints/src/methods/type_id_on_box.rs  | 3 +--
 clippy_lints/src/needless_maybe_sized.rs    | 2 +-
 3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/clippy_lints/src/implied_bounds_in_impls.rs b/clippy_lints/src/implied_bounds_in_impls.rs
index 67b48878ca513..6794c6cabfeef 100644
--- a/clippy_lints/src/implied_bounds_in_impls.rs
+++ b/clippy_lints/src/implied_bounds_in_impls.rs
@@ -246,7 +246,7 @@ fn collect_supertrait_bounds<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds
                 && let [.., path] = poly_trait.trait_ref.path.segments
                 && poly_trait.bound_generic_params.is_empty()
                 && let Some(trait_def_id) = path.res.opt_def_id()
-                && let predicates = cx.tcx.explicit_super_predicates_of(trait_def_id).predicates
+                && let predicates = cx.tcx.explicit_super_predicates_of(trait_def_id).skip_binder()
                 // If the trait has no supertrait, there is no need to collect anything from that bound
                 && !predicates.is_empty()
             {
diff --git a/clippy_lints/src/methods/type_id_on_box.rs b/clippy_lints/src/methods/type_id_on_box.rs
index b62ecef0069af..db8cc4595d4df 100644
--- a/clippy_lints/src/methods/type_id_on_box.rs
+++ b/clippy_lints/src/methods/type_id_on_box.rs
@@ -25,8 +25,7 @@ fn is_subtrait_of_any(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
                     || cx
                         .tcx
                         .explicit_super_predicates_of(tr.def_id)
-                        .predicates
-                        .iter()
+                        .iter_identity_copied()
                         .any(|(clause, _)| {
                             matches!(clause.kind().skip_binder(), ty::ClauseKind::Trait(super_tr)
                             if cx.tcx.is_diagnostic_item(sym::Any, super_tr.def_id()))
diff --git a/clippy_lints/src/needless_maybe_sized.rs b/clippy_lints/src/needless_maybe_sized.rs
index a1d8ec3b32ec9..62e41088f3708 100644
--- a/clippy_lints/src/needless_maybe_sized.rs
+++ b/clippy_lints/src/needless_maybe_sized.rs
@@ -91,7 +91,7 @@ fn path_to_sized_bound(cx: &LateContext<'_>, trait_bound: &PolyTraitRef<'_>) ->
             return true;
         }
 
-        for &(predicate, _) in cx.tcx.explicit_super_predicates_of(trait_def_id).predicates {
+        for (predicate, _) in cx.tcx.explicit_super_predicates_of(trait_def_id).iter_identity_copied() {
             if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder()
                 && trait_predicate.polarity == PredicatePolarity::Positive
                 && !path.contains(&trait_predicate.def_id())

From 74a2344dc12b5659357272f4cd8b6e837195ab24 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Tue, 19 Mar 2024 16:51:40 +0100
Subject: [PATCH 018/114] Extend `implicit_saturation_sub` lint

---
 clippy_lints/src/implicit_saturating_sub.rs | 278 +++++++++++++++-----
 1 file changed, 218 insertions(+), 60 deletions(-)

diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs
index 127c73ed637b2..453ff09bf4fb2 100644
--- a/clippy_lints/src/implicit_saturating_sub.rs
+++ b/clippy_lints/src/implicit_saturating_sub.rs
@@ -1,11 +1,13 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::{higher, is_integer_literal, peel_blocks_with_stmt, SpanlessEq};
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::source::snippet_opt;
+use clippy_utils::{higher, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt, SpanlessEq};
 use rustc_ast::ast::LitKind;
 use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
-use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
+use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, HirId, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
+use rustc_span::Span;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -50,73 +52,229 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
 
             // Check if the conditional expression is a binary operation
             && let ExprKind::Binary(ref cond_op, cond_left, cond_right) = cond.kind
+        {
+            check_with_condition(cx, expr, cond_op.node, cond_left, cond_right, then);
+        } else if let Some(higher::If {
+            cond,
+            then: if_block,
+            r#else: Some(else_block),
+        }) = higher::If::hir(expr)
+            && let ExprKind::Binary(ref cond_op, cond_left, cond_right) = cond.kind
+        {
+            check_manual_check(cx, expr, cond_op, cond_left, cond_right, if_block, else_block);
+        }
+    }
+}
 
-            // Ensure that the binary operator is >, !=, or <
-            && (BinOpKind::Ne == cond_op.node || BinOpKind::Gt == cond_op.node || BinOpKind::Lt == cond_op.node)
+fn check_manual_check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &Expr<'tcx>,
+    condition: &BinOp,
+    left_hand: &Expr<'tcx>,
+    right_hand: &Expr<'tcx>,
+    if_block: &Expr<'tcx>,
+    else_block: &Expr<'tcx>,
+) {
+    let ty = cx.typeck_results().expr_ty(left_hand);
+    if ty.is_numeric() && !ty.is_signed() {
+        match condition.node {
+            BinOpKind::Gt | BinOpKind::Ge => check_gt(
+                cx,
+                condition.span,
+                expr.span,
+                left_hand,
+                right_hand,
+                if_block,
+                else_block,
+            ),
+            BinOpKind::Lt | BinOpKind::Le => check_gt(
+                cx,
+                condition.span,
+                expr.span,
+                right_hand,
+                left_hand,
+                if_block,
+                else_block,
+            ),
+            _ => {},
+        }
+    }
+}
 
-            // Check if assign operation is done
-            && let Some(target) = subtracts_one(cx, then)
+fn check_gt(
+    cx: &LateContext<'_>,
+    condition_span: Span,
+    expr_span: Span,
+    big_var: &Expr<'_>,
+    little_var: &Expr<'_>,
+    if_block: &Expr<'_>,
+    else_block: &Expr<'_>,
+) {
+    if let Some(big_var) = Var::new(big_var)
+        && let Some(little_var) = Var::new(little_var)
+    {
+        check_subtraction(cx, condition_span, expr_span, big_var, little_var, if_block, else_block);
+    }
+}
 
-            // Extracting out the variable name
-            && let ExprKind::Path(QPath::Resolved(_, ares_path)) = target.kind
+struct Var {
+    span: Span,
+    hir_id: HirId,
+}
+
+impl Var {
+    fn new(expr: &Expr<'_>) -> Option<Self> {
+        path_to_local(expr).map(|hir_id| Self {
+            span: expr.span,
+            hir_id,
+        })
+    }
+}
+
+fn check_subtraction(
+    cx: &LateContext<'_>,
+    condition_span: Span,
+    expr_span: Span,
+    big_var: Var,
+    little_var: Var,
+    if_block: &Expr<'_>,
+    else_block: &Expr<'_>,
+) {
+    let if_block = peel_blocks(if_block);
+    let else_block = peel_blocks(else_block);
+    if is_integer_literal(if_block, 0) {
+        // We need to check this case as well to prevent infinite recursion.
+        if is_integer_literal(else_block, 0) {
+            // Well, seems weird but who knows?
+            return;
+        }
+        // If the subtraction is done in the `else` block, then we need to also revert the two
+        // variables as it means that the check was reverted too.
+        check_subtraction(cx, condition_span, expr_span, little_var, big_var, else_block, if_block);
+        return;
+    }
+    if is_integer_literal(else_block, 0)
+        && let ExprKind::Binary(op, left, right) = if_block.kind
+        && let BinOpKind::Sub = op.node
+    {
+        let local_left = path_to_local(left);
+        let local_right = path_to_local(right);
+        if Some(big_var.hir_id) == local_left && Some(little_var.hir_id) == local_right {
+            // This part of the condition is voluntarily split from the one before to ensure that
+            // if `snippet_opt` fails, it won't try the next conditions.
+            if let Some(big_var_snippet) = snippet_opt(cx, big_var.span)
+                && let Some(little_var_snippet) = snippet_opt(cx, little_var.span)
+            {
+                span_lint_and_sugg(
+                    cx,
+                    IMPLICIT_SATURATING_SUB,
+                    expr_span,
+                    "manual arithmetic check found",
+                    "replace it with",
+                    format!("{big_var_snippet}.saturating_sub({little_var_snippet})"),
+                    Applicability::MachineApplicable,
+                );
+            }
+        } else if Some(little_var.hir_id) == local_left
+            && Some(big_var.hir_id) == local_right
+            && let Some(big_var_snippet) = snippet_opt(cx, big_var.span)
+            && let Some(little_var_snippet) = snippet_opt(cx, little_var.span)
         {
-            // Handle symmetric conditions in the if statement
-            let (cond_var, cond_num_val) = if SpanlessEq::new(cx).eq_expr(cond_left, target) {
-                if BinOpKind::Gt == cond_op.node || BinOpKind::Ne == cond_op.node {
-                    (cond_left, cond_right)
-                } else {
-                    return;
-                }
-            } else if SpanlessEq::new(cx).eq_expr(cond_right, target) {
-                if BinOpKind::Lt == cond_op.node || BinOpKind::Ne == cond_op.node {
-                    (cond_right, cond_left)
-                } else {
-                    return;
-                }
+            span_lint_and_then(
+                cx,
+                IMPLICIT_SATURATING_SUB,
+                condition_span,
+                "inverted arithmetic check before subtraction",
+                |diag| {
+                    diag.span_note(
+                        if_block.span,
+                        format!("this subtraction underflows when `{little_var_snippet} < {big_var_snippet}`"),
+                    );
+                    diag.span_suggestion(
+                        if_block.span,
+                        "try replacing it with",
+                        format!("{big_var_snippet} - {little_var_snippet}"),
+                        Applicability::MaybeIncorrect,
+                    );
+                },
+            );
+        }
+    }
+}
+
+fn check_with_condition<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &Expr<'tcx>,
+    cond_op: BinOpKind,
+    cond_left: &Expr<'tcx>,
+    cond_right: &Expr<'tcx>,
+    then: &Expr<'tcx>,
+) {
+    // Ensure that the binary operator is >, !=, or <
+    if (BinOpKind::Ne == cond_op || BinOpKind::Gt == cond_op || BinOpKind::Lt == cond_op)
+
+        // Check if assign operation is done
+        && let Some(target) = subtracts_one(cx, then)
+
+        // Extracting out the variable name
+        && let ExprKind::Path(QPath::Resolved(_, ares_path)) = target.kind
+    {
+        // Handle symmetric conditions in the if statement
+        let (cond_var, cond_num_val) = if SpanlessEq::new(cx).eq_expr(cond_left, target) {
+            if BinOpKind::Gt == cond_op || BinOpKind::Ne == cond_op {
+                (cond_left, cond_right)
             } else {
                 return;
-            };
-
-            // Check if the variable in the condition statement is an integer
-            if !cx.typeck_results().expr_ty(cond_var).is_integral() {
+            }
+        } else if SpanlessEq::new(cx).eq_expr(cond_right, target) {
+            if BinOpKind::Lt == cond_op || BinOpKind::Ne == cond_op {
+                (cond_right, cond_left)
+            } else {
                 return;
             }
+        } else {
+            return;
+        };
 
-            // Get the variable name
-            let var_name = ares_path.segments[0].ident.name.as_str();
-            match cond_num_val.kind {
-                ExprKind::Lit(cond_lit) => {
-                    // Check if the constant is zero
-                    if let LitKind::Int(Pu128(0), _) = cond_lit.node {
-                        if cx.typeck_results().expr_ty(cond_left).is_signed() {
-                        } else {
-                            print_lint_and_sugg(cx, var_name, expr);
-                        };
-                    }
-                },
-                ExprKind::Path(QPath::TypeRelative(_, name)) => {
-                    if name.ident.as_str() == "MIN"
-                        && let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id)
-                        && let Some(impl_id) = cx.tcx.impl_of_method(const_id)
-                        && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl
-                        && cx.tcx.type_of(impl_id).instantiate_identity().is_integral()
-                    {
-                        print_lint_and_sugg(cx, var_name, expr);
-                    }
-                },
-                ExprKind::Call(func, []) => {
-                    if let ExprKind::Path(QPath::TypeRelative(_, name)) = func.kind
-                        && name.ident.as_str() == "min_value"
-                        && let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id)
-                        && let Some(impl_id) = cx.tcx.impl_of_method(func_id)
-                        && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl
-                        && cx.tcx.type_of(impl_id).instantiate_identity().is_integral()
-                    {
+        // Check if the variable in the condition statement is an integer
+        if !cx.typeck_results().expr_ty(cond_var).is_integral() {
+            return;
+        }
+
+        // Get the variable name
+        let var_name = ares_path.segments[0].ident.name.as_str();
+        match cond_num_val.kind {
+            ExprKind::Lit(cond_lit) => {
+                // Check if the constant is zero
+                if let LitKind::Int(Pu128(0), _) = cond_lit.node {
+                    if cx.typeck_results().expr_ty(cond_left).is_signed() {
+                    } else {
                         print_lint_and_sugg(cx, var_name, expr);
-                    }
-                },
-                _ => (),
-            }
+                    };
+                }
+            },
+            ExprKind::Path(QPath::TypeRelative(_, name)) => {
+                if name.ident.as_str() == "MIN"
+                    && let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id)
+                    && let Some(impl_id) = cx.tcx.impl_of_method(const_id)
+                    && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl
+                    && cx.tcx.type_of(impl_id).instantiate_identity().is_integral()
+                {
+                    print_lint_and_sugg(cx, var_name, expr);
+                }
+            },
+            ExprKind::Call(func, []) => {
+                if let ExprKind::Path(QPath::TypeRelative(_, name)) = func.kind
+                    && name.ident.as_str() == "min_value"
+                    && let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id)
+                    && let Some(impl_id) = cx.tcx.impl_of_method(func_id)
+                    && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl
+                    && cx.tcx.type_of(impl_id).instantiate_identity().is_integral()
+                {
+                    print_lint_and_sugg(cx, var_name, expr);
+                }
+            },
+            _ => (),
         }
     }
 }

From 2622a87587ada00d6aac1d036da8a2f579a675ba Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Tue, 19 Mar 2024 16:59:08 +0100
Subject: [PATCH 019/114] Add ui regression tests for `implicit_saturation_sub`
 lint extension

---
 tests/ui/implicit_saturating_sub.rs       |  7 +++
 tests/ui/manual_arithmetic_check-2.rs     | 35 +++++++++++
 tests/ui/manual_arithmetic_check-2.stderr | 76 +++++++++++++++++++++++
 tests/ui/manual_arithmetic_check.fixed    | 16 +++++
 tests/ui/manual_arithmetic_check.rs       | 20 ++++++
 tests/ui/manual_arithmetic_check.stderr   | 29 +++++++++
 6 files changed, 183 insertions(+)
 create mode 100644 tests/ui/manual_arithmetic_check-2.rs
 create mode 100644 tests/ui/manual_arithmetic_check-2.stderr
 create mode 100644 tests/ui/manual_arithmetic_check.fixed
 create mode 100644 tests/ui/manual_arithmetic_check.rs
 create mode 100644 tests/ui/manual_arithmetic_check.stderr

diff --git a/tests/ui/implicit_saturating_sub.rs b/tests/ui/implicit_saturating_sub.rs
index 5d7b95d2c652f..05f7d85238307 100644
--- a/tests/ui/implicit_saturating_sub.rs
+++ b/tests/ui/implicit_saturating_sub.rs
@@ -260,4 +260,11 @@ fn main() {
     } else if u_32 > 0 {
         u_32 -= 1;
     }
+
+    let result = if a < b {
+        println!("we shouldn't remove this");
+        0
+    } else {
+        a - b
+    };
 }
diff --git a/tests/ui/manual_arithmetic_check-2.rs b/tests/ui/manual_arithmetic_check-2.rs
new file mode 100644
index 0000000000000..e97e3bdfef769
--- /dev/null
+++ b/tests/ui/manual_arithmetic_check-2.rs
@@ -0,0 +1,35 @@
+//@no-rustfix
+#![warn(clippy::implicit_saturating_sub)]
+#![allow(arithmetic_overflow)]
+
+fn main() {
+    let a = 12u32;
+    let b = 13u32;
+
+    let result = if a > b { b - a } else { 0 };
+    //~^ ERROR: inverted arithmetic check before subtraction
+    let result = if b < a { b - a } else { 0 };
+    //~^ ERROR: inverted arithmetic check before subtraction
+
+    let result = if a > b { 0 } else { a - b };
+    //~^ ERROR: inverted arithmetic check before subtraction
+    let result = if a >= b { 0 } else { a - b };
+    //~^ ERROR: inverted arithmetic check before subtraction
+    let result = if b < a { 0 } else { a - b };
+    //~^ ERROR: inverted arithmetic check before subtraction
+    let result = if b <= a { 0 } else { a - b };
+    //~^ ERROR: inverted arithmetic check before subtraction
+
+    let af = 12f32;
+    let bf = 13f32;
+    // Should not lint!
+    let result = if bf < af { 0. } else { af - bf };
+
+    // Should not lint!
+    let result = if a < b {
+        println!("we shouldn't remove this");
+        0
+    } else {
+        a - b
+    };
+}
diff --git a/tests/ui/manual_arithmetic_check-2.stderr b/tests/ui/manual_arithmetic_check-2.stderr
new file mode 100644
index 0000000000000..d49e536ce3fbf
--- /dev/null
+++ b/tests/ui/manual_arithmetic_check-2.stderr
@@ -0,0 +1,76 @@
+error: inverted arithmetic check before subtraction
+  --> tests/ui/manual_arithmetic_check-2.rs:9:23
+   |
+LL |     let result = if a > b { b - a } else { 0 };
+   |                       ^     ----- help: try replacing it with: `a - b`
+   |
+note: this subtraction underflows when `b < a`
+  --> tests/ui/manual_arithmetic_check-2.rs:9:29
+   |
+LL |     let result = if a > b { b - a } else { 0 };
+   |                             ^^^^^
+   = note: `-D clippy::implicit-saturating-sub` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::implicit_saturating_sub)]`
+
+error: inverted arithmetic check before subtraction
+  --> tests/ui/manual_arithmetic_check-2.rs:11:23
+   |
+LL |     let result = if b < a { b - a } else { 0 };
+   |                       ^     ----- help: try replacing it with: `a - b`
+   |
+note: this subtraction underflows when `b < a`
+  --> tests/ui/manual_arithmetic_check-2.rs:11:29
+   |
+LL |     let result = if b < a { b - a } else { 0 };
+   |                             ^^^^^
+
+error: inverted arithmetic check before subtraction
+  --> tests/ui/manual_arithmetic_check-2.rs:14:23
+   |
+LL |     let result = if a > b { 0 } else { a - b };
+   |                       ^                ----- help: try replacing it with: `b - a`
+   |
+note: this subtraction underflows when `a < b`
+  --> tests/ui/manual_arithmetic_check-2.rs:14:40
+   |
+LL |     let result = if a > b { 0 } else { a - b };
+   |                                        ^^^^^
+
+error: inverted arithmetic check before subtraction
+  --> tests/ui/manual_arithmetic_check-2.rs:16:23
+   |
+LL |     let result = if a >= b { 0 } else { a - b };
+   |                       ^^                ----- help: try replacing it with: `b - a`
+   |
+note: this subtraction underflows when `a < b`
+  --> tests/ui/manual_arithmetic_check-2.rs:16:41
+   |
+LL |     let result = if a >= b { 0 } else { a - b };
+   |                                         ^^^^^
+
+error: inverted arithmetic check before subtraction
+  --> tests/ui/manual_arithmetic_check-2.rs:18:23
+   |
+LL |     let result = if b < a { 0 } else { a - b };
+   |                       ^                ----- help: try replacing it with: `b - a`
+   |
+note: this subtraction underflows when `a < b`
+  --> tests/ui/manual_arithmetic_check-2.rs:18:40
+   |
+LL |     let result = if b < a { 0 } else { a - b };
+   |                                        ^^^^^
+
+error: inverted arithmetic check before subtraction
+  --> tests/ui/manual_arithmetic_check-2.rs:20:23
+   |
+LL |     let result = if b <= a { 0 } else { a - b };
+   |                       ^^                ----- help: try replacing it with: `b - a`
+   |
+note: this subtraction underflows when `a < b`
+  --> tests/ui/manual_arithmetic_check-2.rs:20:41
+   |
+LL |     let result = if b <= a { 0 } else { a - b };
+   |                                         ^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/manual_arithmetic_check.fixed b/tests/ui/manual_arithmetic_check.fixed
new file mode 100644
index 0000000000000..afb2abcbe9071
--- /dev/null
+++ b/tests/ui/manual_arithmetic_check.fixed
@@ -0,0 +1,16 @@
+#![warn(clippy::implicit_saturating_sub)]
+
+fn main() {
+    let a = 12u32;
+    let b = 13u32;
+
+    let result = a.saturating_sub(b);
+    //~^ ERROR: manual arithmetic check found
+    let result = a.saturating_sub(b);
+    //~^ ERROR: manual arithmetic check found
+
+    let result = a.saturating_sub(b);
+    //~^ ERROR: manual arithmetic check found
+    let result = a.saturating_sub(b);
+    //~^ ERROR: manual arithmetic check found
+}
diff --git a/tests/ui/manual_arithmetic_check.rs b/tests/ui/manual_arithmetic_check.rs
new file mode 100644
index 0000000000000..c11ac7097fc4e
--- /dev/null
+++ b/tests/ui/manual_arithmetic_check.rs
@@ -0,0 +1,20 @@
+#![warn(clippy::implicit_saturating_sub)]
+
+fn main() {
+    let a = 12u32;
+    let b = 13u32;
+    let c = 8u32;
+
+    let result = if a > b { a - b } else { 0 };
+    //~^ ERROR: manual arithmetic check found
+    let result = if b < a { a - b } else { 0 };
+    //~^ ERROR: manual arithmetic check found
+
+    let result = if a < b { 0 } else { a - b };
+    //~^ ERROR: manual arithmetic check found
+    let result = if b > a { 0 } else { a - b };
+    //~^ ERROR: manual arithmetic check found
+
+    // Should not warn!
+    let result = if a > b { a - b } else { a - c };
+}
diff --git a/tests/ui/manual_arithmetic_check.stderr b/tests/ui/manual_arithmetic_check.stderr
new file mode 100644
index 0000000000000..153a8bb57346f
--- /dev/null
+++ b/tests/ui/manual_arithmetic_check.stderr
@@ -0,0 +1,29 @@
+error: manual arithmetic check found
+  --> tests/ui/manual_arithmetic_check.rs:7:18
+   |
+LL |     let result = if a > b { a - b } else { 0 };
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)`
+   |
+   = note: `-D clippy::implicit-saturating-sub` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::implicit_saturating_sub)]`
+
+error: manual arithmetic check found
+  --> tests/ui/manual_arithmetic_check.rs:9:18
+   |
+LL |     let result = if b < a { a - b } else { 0 };
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)`
+
+error: manual arithmetic check found
+  --> tests/ui/manual_arithmetic_check.rs:12:18
+   |
+LL |     let result = if a < b { 0 } else { a - b };
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)`
+
+error: manual arithmetic check found
+  --> tests/ui/manual_arithmetic_check.rs:14:18
+   |
+LL |     let result = if b > a { 0 } else { a - b };
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)`
+
+error: aborting due to 4 previous errors
+

From 27c63433659773c70dca86a3d6f3b9bd7654c2c3 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Tue, 19 Mar 2024 17:00:31 +0100
Subject: [PATCH 020/114] Add ui test to ensure that if `0` is returned from
 both `if` and `else`, it will not break clippy

---
 tests/ui/implicit_saturating_sub.fixed  | 13 ++++++++++---
 tests/ui/implicit_saturating_sub.rs     |  6 +++---
 tests/ui/manual_arithmetic_check.fixed  |  8 ++++++++
 tests/ui/manual_arithmetic_check.rs     |  4 ++++
 tests/ui/manual_arithmetic_check.stderr |  8 ++++----
 5 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/tests/ui/implicit_saturating_sub.fixed b/tests/ui/implicit_saturating_sub.fixed
index 27f679797dd9e..81cc149491442 100644
--- a/tests/ui/implicit_saturating_sub.fixed
+++ b/tests/ui/implicit_saturating_sub.fixed
@@ -184,18 +184,18 @@ fn main() {
     let mut m = Mock;
     let mut u_32 = 3000;
     let a = 200;
-    let mut _b = 8;
+    let mut b = 8;
 
     if m != 0 {
         m -= 1;
     }
 
     if a > 0 {
-        _b -= 1;
+        b -= 1;
     }
 
     if 0 > a {
-        _b -= 1;
+        b -= 1;
     }
 
     if u_32 > 0 {
@@ -214,4 +214,11 @@ fn main() {
     } else if u_32 > 0 {
         u_32 -= 1;
     }
+
+    let result = if a < b {
+        println!("we shouldn't remove this");
+        0
+    } else {
+        a - b
+    };
 }
diff --git a/tests/ui/implicit_saturating_sub.rs b/tests/ui/implicit_saturating_sub.rs
index 05f7d85238307..f73396ebd27e2 100644
--- a/tests/ui/implicit_saturating_sub.rs
+++ b/tests/ui/implicit_saturating_sub.rs
@@ -230,18 +230,18 @@ fn main() {
     let mut m = Mock;
     let mut u_32 = 3000;
     let a = 200;
-    let mut _b = 8;
+    let mut b = 8;
 
     if m != 0 {
         m -= 1;
     }
 
     if a > 0 {
-        _b -= 1;
+        b -= 1;
     }
 
     if 0 > a {
-        _b -= 1;
+        b -= 1;
     }
 
     if u_32 > 0 {
diff --git a/tests/ui/manual_arithmetic_check.fixed b/tests/ui/manual_arithmetic_check.fixed
index afb2abcbe9071..600fcd3765d81 100644
--- a/tests/ui/manual_arithmetic_check.fixed
+++ b/tests/ui/manual_arithmetic_check.fixed
@@ -1,8 +1,10 @@
 #![warn(clippy::implicit_saturating_sub)]
+#![allow(clippy::if_same_then_else)]
 
 fn main() {
     let a = 12u32;
     let b = 13u32;
+    let c = 8u32;
 
     let result = a.saturating_sub(b);
     //~^ ERROR: manual arithmetic check found
@@ -13,4 +15,10 @@ fn main() {
     //~^ ERROR: manual arithmetic check found
     let result = a.saturating_sub(b);
     //~^ ERROR: manual arithmetic check found
+
+    // Should not warn!
+    let result = if a > b { a - b } else { a - c };
+
+    // Just to check it won't break clippy.
+    let result = if b > a { 0 } else { 0 };
 }
diff --git a/tests/ui/manual_arithmetic_check.rs b/tests/ui/manual_arithmetic_check.rs
index c11ac7097fc4e..33f5adafe7e40 100644
--- a/tests/ui/manual_arithmetic_check.rs
+++ b/tests/ui/manual_arithmetic_check.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::implicit_saturating_sub)]
+#![allow(clippy::if_same_then_else)]
 
 fn main() {
     let a = 12u32;
@@ -17,4 +18,7 @@ fn main() {
 
     // Should not warn!
     let result = if a > b { a - b } else { a - c };
+
+    // Just to check it won't break clippy.
+    let result = if b > a { 0 } else { 0 };
 }
diff --git a/tests/ui/manual_arithmetic_check.stderr b/tests/ui/manual_arithmetic_check.stderr
index 153a8bb57346f..b0cf73cd9151d 100644
--- a/tests/ui/manual_arithmetic_check.stderr
+++ b/tests/ui/manual_arithmetic_check.stderr
@@ -1,5 +1,5 @@
 error: manual arithmetic check found
-  --> tests/ui/manual_arithmetic_check.rs:7:18
+  --> tests/ui/manual_arithmetic_check.rs:9:18
    |
 LL |     let result = if a > b { a - b } else { 0 };
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)`
@@ -8,19 +8,19 @@ LL |     let result = if a > b { a - b } else { 0 };
    = help: to override `-D warnings` add `#[allow(clippy::implicit_saturating_sub)]`
 
 error: manual arithmetic check found
-  --> tests/ui/manual_arithmetic_check.rs:9:18
+  --> tests/ui/manual_arithmetic_check.rs:11:18
    |
 LL |     let result = if b < a { a - b } else { 0 };
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)`
 
 error: manual arithmetic check found
-  --> tests/ui/manual_arithmetic_check.rs:12:18
+  --> tests/ui/manual_arithmetic_check.rs:14:18
    |
 LL |     let result = if a < b { 0 } else { a - b };
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)`
 
 error: manual arithmetic check found
-  --> tests/ui/manual_arithmetic_check.rs:14:18
+  --> tests/ui/manual_arithmetic_check.rs:16:18
    |
 LL |     let result = if b > a { 0 } else { a - b };
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)`

From d20fc38f0a17561166fb57c83ff5660b3cd41392 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Fri, 19 Jul 2024 14:51:56 +0200
Subject: [PATCH 021/114] Create new `inverted_saturating_sub` lint

---
 CHANGELOG.md                                |  1 +
 clippy_lints/src/declared_lints.rs          |  1 +
 clippy_lints/src/implicit_saturating_sub.rs | 34 +++++++++++++++++++--
 tests/ui/manual_arithmetic_check-2.stderr   |  3 +-
 tests/ui/manual_arithmetic_check.fixed      |  2 +-
 tests/ui/manual_arithmetic_check.rs         |  2 +-
 6 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fddc2fd994e87..0bef35529662a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5500,6 +5500,7 @@ Released 2018-09-13
 [`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex
 [`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons
 [`invalid_utf8_in_unchecked`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_utf8_in_unchecked
+[`inverted_saturating_sub`]: https://rust-lang.github.io/rust-clippy/master/index.html#inverted_saturating_sub
 [`invisible_characters`]: https://rust-lang.github.io/rust-clippy/master/index.html#invisible_characters
 [`is_digit_ascii_radix`]: https://rust-lang.github.io/rust-clippy/master/index.html#is_digit_ascii_radix
 [`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index 8754a4dff87b1..a6dd6ae731289 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -216,6 +216,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::implicit_return::IMPLICIT_RETURN_INFO,
     crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO,
     crate::implicit_saturating_sub::IMPLICIT_SATURATING_SUB_INFO,
+    crate::implicit_saturating_sub::INVERTED_SATURATING_SUB_INFO,
     crate::implied_bounds_in_impls::IMPLIED_BOUNDS_IN_IMPLS_INFO,
     crate::incompatible_msrv::INCOMPATIBLE_MSRV_INFO,
     crate::inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR_INFO,
diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs
index 453ff09bf4fb2..04c890620396d 100644
--- a/clippy_lints/src/implicit_saturating_sub.rs
+++ b/clippy_lints/src/implicit_saturating_sub.rs
@@ -41,7 +41,37 @@ declare_clippy_lint! {
     "Perform saturating subtraction instead of implicitly checking lower bound of data type"
 }
 
-declare_lint_pass!(ImplicitSaturatingSub => [IMPLICIT_SATURATING_SUB]);
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for comparisons between integers, followed by subtracting the greater value from the
+    /// lower one.
+    ///
+    /// ### Why is this bad?
+    /// This could result in an underflow and is most likely not what the user wants. If this was
+    /// intended to be a saturated subtraction, consider using the `saturating_sub` method directly.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// let a = 12u32;
+    /// let b = 13u32;
+    ///
+    /// let result = if a > b { b - a } else { 0 };
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// let a = 12u32;
+    /// let b = 13u32;
+    ///
+    /// let result = a.saturating_sub(b);
+    /// ```
+    #[clippy::version = "1.44.0"]
+    pub INVERTED_SATURATING_SUB,
+    correctness,
+    "Check if a variable is smaller than another one and still subtract from it even if smaller"
+}
+
+declare_lint_pass!(ImplicitSaturatingSub => [IMPLICIT_SATURATING_SUB, INVERTED_SATURATING_SUB]);
 
 impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
@@ -182,7 +212,7 @@ fn check_subtraction(
         {
             span_lint_and_then(
                 cx,
-                IMPLICIT_SATURATING_SUB,
+                INVERTED_SATURATING_SUB,
                 condition_span,
                 "inverted arithmetic check before subtraction",
                 |diag| {
diff --git a/tests/ui/manual_arithmetic_check-2.stderr b/tests/ui/manual_arithmetic_check-2.stderr
index d49e536ce3fbf..4121aa7464f05 100644
--- a/tests/ui/manual_arithmetic_check-2.stderr
+++ b/tests/ui/manual_arithmetic_check-2.stderr
@@ -9,8 +9,7 @@ note: this subtraction underflows when `b < a`
    |
 LL |     let result = if a > b { b - a } else { 0 };
    |                             ^^^^^
-   = note: `-D clippy::implicit-saturating-sub` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::implicit_saturating_sub)]`
+   = note: `#[deny(clippy::inverted_saturating_sub)]` on by default
 
 error: inverted arithmetic check before subtraction
   --> tests/ui/manual_arithmetic_check-2.rs:11:23
diff --git a/tests/ui/manual_arithmetic_check.fixed b/tests/ui/manual_arithmetic_check.fixed
index 600fcd3765d81..29ecbb9ad2adb 100644
--- a/tests/ui/manual_arithmetic_check.fixed
+++ b/tests/ui/manual_arithmetic_check.fixed
@@ -1,4 +1,4 @@
-#![warn(clippy::implicit_saturating_sub)]
+#![warn(clippy::implicit_saturating_sub, clippy::inverted_saturating_sub)]
 #![allow(clippy::if_same_then_else)]
 
 fn main() {
diff --git a/tests/ui/manual_arithmetic_check.rs b/tests/ui/manual_arithmetic_check.rs
index 33f5adafe7e40..69554c6b61caa 100644
--- a/tests/ui/manual_arithmetic_check.rs
+++ b/tests/ui/manual_arithmetic_check.rs
@@ -1,4 +1,4 @@
-#![warn(clippy::implicit_saturating_sub)]
+#![warn(clippy::implicit_saturating_sub, clippy::inverted_saturating_sub)]
 #![allow(clippy::if_same_then_else)]
 
 fn main() {

From 9e7473f08daf4a8ab1fec5186376ad1299555344 Mon Sep 17 00:00:00 2001
From: xFrednet <xFrednet@gmail.com>
Date: Thu, 29 Aug 2024 21:31:46 +0200
Subject: [PATCH 022/114] Update version attribute for 1.81 lints

---
 clippy_lints/src/byte_char_slices.rs                  | 2 +-
 clippy_lints/src/cfg_not_test.rs                      | 2 +-
 clippy_lints/src/field_scoped_visibility_modifiers.rs | 2 +-
 clippy_lints/src/methods/mod.rs                       | 4 ++--
 clippy_lints/src/needless_maybe_sized.rs              | 2 +-
 clippy_lints/src/set_contains_or_insert.rs            | 2 +-
 clippy_lints/src/string_patterns.rs                   | 2 +-
 7 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/clippy_lints/src/byte_char_slices.rs b/clippy_lints/src/byte_char_slices.rs
index a9fe190f1777e..dd2620b0b9df9 100644
--- a/clippy_lints/src/byte_char_slices.rs
+++ b/clippy_lints/src/byte_char_slices.rs
@@ -22,7 +22,7 @@ declare_clippy_lint! {
     /// ```ignore
     /// b"Hello"
     /// ```
-    #[clippy::version = "1.68.0"]
+    #[clippy::version = "1.81.0"]
     pub BYTE_CHAR_SLICES,
     style,
     "hard to read byte char slice"
diff --git a/clippy_lints/src/cfg_not_test.rs b/clippy_lints/src/cfg_not_test.rs
index d820c1e0720b8..884d15cabffcb 100644
--- a/clippy_lints/src/cfg_not_test.rs
+++ b/clippy_lints/src/cfg_not_test.rs
@@ -22,7 +22,7 @@ declare_clippy_lint! {
     /// # fn important_check() {}
     /// important_check();
     /// ```
-    #[clippy::version = "1.73.0"]
+    #[clippy::version = "1.81.0"]
     pub CFG_NOT_TEST,
     restriction,
     "enforce against excluding code from test builds"
diff --git a/clippy_lints/src/field_scoped_visibility_modifiers.rs b/clippy_lints/src/field_scoped_visibility_modifiers.rs
index 95b8e882da792..ba2b37fbf11a3 100644
--- a/clippy_lints/src/field_scoped_visibility_modifiers.rs
+++ b/clippy_lints/src/field_scoped_visibility_modifiers.rs
@@ -41,7 +41,7 @@ declare_clippy_lint! {
     ///     }
     /// }
     /// ```
-    #[clippy::version = "1.78.0"]
+    #[clippy::version = "1.81.0"]
     pub FIELD_SCOPED_VISIBILITY_MODIFIERS,
     restriction,
     "checks for usage of a scoped visibility modifier, like `pub(crate)`, on fields"
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index d7126990edb1d..0420f5c7628d3 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -3964,7 +3964,7 @@ declare_clippy_lint! {
     /// ```no_run
     /// let _ = 0;
     /// ```
-    #[clippy::version = "1.78.0"]
+    #[clippy::version = "1.81.0"]
     pub UNNECESSARY_MIN_OR_MAX,
     complexity,
     "using 'min()/max()' when there is no need for it"
@@ -4099,7 +4099,7 @@ declare_clippy_lint! {
     /// ```no_run
     /// "foo".is_ascii();
     /// ```
-    #[clippy::version = "1.80.0"]
+    #[clippy::version = "1.81.0"]
     pub NEEDLESS_CHARACTER_ITERATION,
     suspicious,
     "is_ascii() called on a char iterator"
diff --git a/clippy_lints/src/needless_maybe_sized.rs b/clippy_lints/src/needless_maybe_sized.rs
index a1d8ec3b32ec9..c0847342caf12 100644
--- a/clippy_lints/src/needless_maybe_sized.rs
+++ b/clippy_lints/src/needless_maybe_sized.rs
@@ -26,7 +26,7 @@ declare_clippy_lint! {
     ///
     /// // or choose alternative bounds for `T` so that it can be unsized
     /// ```
-    #[clippy::version = "1.79.0"]
+    #[clippy::version = "1.81.0"]
     pub NEEDLESS_MAYBE_SIZED,
     suspicious,
     "a `?Sized` bound that is unusable due to a `Sized` requirement"
diff --git a/clippy_lints/src/set_contains_or_insert.rs b/clippy_lints/src/set_contains_or_insert.rs
index e6fe76493974a..bc2a71c42b9f8 100644
--- a/clippy_lints/src/set_contains_or_insert.rs
+++ b/clippy_lints/src/set_contains_or_insert.rs
@@ -42,7 +42,7 @@ declare_clippy_lint! {
     ///     println!("inserted {value:?}");
     /// }
     /// ```
-    #[clippy::version = "1.80.0"]
+    #[clippy::version = "1.81.0"]
     pub SET_CONTAINS_OR_INSERT,
     nursery,
     "call to `<set>::contains` followed by `<set>::insert`"
diff --git a/clippy_lints/src/string_patterns.rs b/clippy_lints/src/string_patterns.rs
index 7e211d64da141..8af50ca87d631 100644
--- a/clippy_lints/src/string_patterns.rs
+++ b/clippy_lints/src/string_patterns.rs
@@ -33,7 +33,7 @@ declare_clippy_lint! {
     /// ```no_run
     /// "Hello World!".trim_end_matches(['.', ',', '!', '?']);
     /// ```
-    #[clippy::version = "1.80.0"]
+    #[clippy::version = "1.81.0"]
     pub MANUAL_PATTERN_CHAR_COMPARISON,
     style,
     "manual char comparison in string patterns"

From 9aa23b8317de0fe68415f120b1cbf589fcf3d052 Mon Sep 17 00:00:00 2001
From: xFrednet <xFrednet@gmail.com>
Date: Thu, 29 Aug 2024 21:38:41 +0200
Subject: [PATCH 023/114] Changelog for Clippy 1.81 :beginner:

---
 CHANGELOG.md | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 21252a3f43a00..4364e0f7085c0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,7 +6,61 @@ document.
 
 ## Unreleased / Beta / In Rust Nightly
 
-[c9139bd5...master](https://github.com/rust-lang/rust-clippy/compare/c9139bd5...master)
+[b794b8e0...master](https://github.com/rust-lang/rust-clippy/compare/b794b8e0...master)
+
+## Rust 1.81
+
+Current stable, released 2024-09-05
+
+### New Lints
+
+* Added [`cfg_not_test`] to `restriction`
+  [#11293](https://github.com/rust-lang/rust-clippy/pull/11293)
+* Added [`byte_char_slices`] to `style`
+  [#10155](https://github.com/rust-lang/rust-clippy/pull/10155)
+* Added [`set_contains_or_insert`] to `nursery`
+  [#12873](https://github.com/rust-lang/rust-clippy/pull/12873)
+* Added [`manual_rotate`] to `style`
+  [#12983](https://github.com/rust-lang/rust-clippy/pull/12983)
+* Added [`unnecessary_min_or_max`] to `complexity`
+  [#12368](https://github.com/rust-lang/rust-clippy/pull/12368)
+* Added [`manual_inspect`] to `complexity`
+  [#12287](https://github.com/rust-lang/rust-clippy/pull/12287)
+* Added [`field_scoped_visibility_modifiers`] to `restriction`
+  [#12893](https://github.com/rust-lang/rust-clippy/pull/12893)
+* Added [`manual_pattern_char_comparison`] to `style`
+  [#12849](https://github.com/rust-lang/rust-clippy/pull/12849)
+* Added [`needless_maybe_sized`] to `suspicious`
+  [#10632](https://github.com/rust-lang/rust-clippy/pull/10632)
+* Added [`needless_character_iteration`] to `suspicious`
+  [#12815](https://github.com/rust-lang/rust-clippy/pull/12815)
+
+### Moves and Deprecations
+
+* [`allow_attributes`], [`allow_attributes_without_reason`]: Now work on stable
+  [rust#120924](https://github.com/rust-lang/rust/pull/120924)
+* Renamed `overflow_check_conditional` to [`panicking_overflow_checks`]
+  [#12944](https://github.com/rust-lang/rust-clippy/pull/12944)
+* Moved [`panicking_overflow_checks`] to `correctness` (From `complexity` now warn-by-default)
+  [#12944](https://github.com/rust-lang/rust-clippy/pull/12944)
+* Renamed `thread_local_initializer_can_be_made_const` to [`missing_const_for_thread_local`]
+  [#12974](https://github.com/rust-lang/rust-clippy/pull/12974)
+* Deprecated [`maybe_misused_cfg`] and [`mismatched_target_os`] as they are now caught by cargo
+  and rustc
+  [#12875](https://github.com/rust-lang/rust-clippy/pull/12875)
+
+### Enhancements
+
+* [`significant_drop_in_scrutinee`]: Now also checks scrutinies of `while let` and `for let`
+  expressions
+  [#12870](https://github.com/rust-lang/rust-clippy/pull/12870)
+* [`std_instead_of_core`]: Now respects the `msrv` configuration
+  [#13168](https://github.com/rust-lang/rust-clippy/pull/13168)
+
+### ICE Fixes
+
+* [`suboptimal_flops`]: No longer crashes on custom `.log()` functions
+  [#12884](https://github.com/rust-lang/rust-clippy/pull/12884)
 
 ## Rust 1.80
 

From cbc6910c35ddb682275c9ea83d94037cacc47a77 Mon Sep 17 00:00:00 2001
From: Fridtjof Stoldt <xFrednet@gmail.com>
Date: Thu, 29 Aug 2024 22:15:18 +0200
Subject: [PATCH 024/114] Changelog: Correct lint level

Co-authored-by: Timo <30553356+y21@users.noreply.github.com>
---
 CHANGELOG.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4364e0f7085c0..2488da057b58e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -41,7 +41,7 @@ Current stable, released 2024-09-05
   [rust#120924](https://github.com/rust-lang/rust/pull/120924)
 * Renamed `overflow_check_conditional` to [`panicking_overflow_checks`]
   [#12944](https://github.com/rust-lang/rust-clippy/pull/12944)
-* Moved [`panicking_overflow_checks`] to `correctness` (From `complexity` now warn-by-default)
+* Moved [`panicking_overflow_checks`] to `correctness` (From `complexity` now deny-by-default)
   [#12944](https://github.com/rust-lang/rust-clippy/pull/12944)
 * Renamed `thread_local_initializer_can_be_made_const` to [`missing_const_for_thread_local`]
   [#12974](https://github.com/rust-lang/rust-clippy/pull/12974)

From 04d70d04fcf9412d7006ee4646f56f8bf5f2149f Mon Sep 17 00:00:00 2001
From: WeiTheShinobi <weitheshinobi@gmail.com>
Date: Sat, 31 Aug 2024 05:02:07 +0800
Subject: [PATCH 025/114] [`single_match`, `single_match_else`] fix suggestion
 when `match` irrefutable

---
 clippy_lints/src/matches/single_match.rs |  7 +++++
 tests/ui/single_match.fixed              | 18 +++++++++++
 tests/ui/single_match.rs                 | 27 ++++++++++++++++
 tests/ui/single_match.stderr             | 40 +++++++++++++++++++++++-
 tests/ui/single_match_else.fixed         |  4 +++
 tests/ui/single_match_else.rs            | 10 ++++++
 tests/ui/single_match_else.stderr        | 14 ++++++++-
 7 files changed, 118 insertions(+), 2 deletions(-)

diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs
index b6930f7b9d10f..4bd46bced38e3 100644
--- a/clippy_lints/src/matches/single_match.rs
+++ b/clippy_lints/src/matches/single_match.rs
@@ -91,6 +91,13 @@ fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, exp
         format!(" else {}", expr_block(cx, els, ctxt, "..", Some(expr.span), &mut app))
     });
 
+    if snippet(cx, ex.span, "..") == snippet(cx, arm.pat.span, "..") {
+        let msg = "this pattern is irrefutable, `match` is useless";
+        let sugg = expr_block(cx, arm.body, ctxt, "..", Some(expr.span), &mut app);
+        span_lint_and_sugg(cx, lint, expr.span, msg, "try", sugg, app);
+        return;
+    }
+
     let (pat, pat_ref_count) = peel_hir_pat_refs(arm.pat);
     let (msg, sugg) = if let PatKind::Path(_) | PatKind::Lit(_) = pat.kind
         && let (ty, ty_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(ex))
diff --git a/tests/ui/single_match.fixed b/tests/ui/single_match.fixed
index 5249c4408899a..04129ec0f13b9 100644
--- a/tests/ui/single_match.fixed
+++ b/tests/ui/single_match.fixed
@@ -296,3 +296,21 @@ fn issue11365() {
 
     if let Some(A | B) = &Some(A) { println!() }
 }
+
+#[derive(Eq, PartialEq)]
+pub struct Data([u8; 4]);
+
+const DATA: Data = Data([1, 2, 3, 4]);
+const CONST_I32: i32 = 1;
+
+fn irrefutable_match() {
+    { println!() }
+
+    { println!() }
+
+    let i = 0;
+    {
+        let a = 1;
+        let b = 2;
+    }
+}
diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs
index 882098a56e780..2d51cee3fd995 100644
--- a/tests/ui/single_match.rs
+++ b/tests/ui/single_match.rs
@@ -360,3 +360,30 @@ fn issue11365() {
         None | Some(_) => {},
     }
 }
+
+#[derive(Eq, PartialEq)]
+pub struct Data([u8; 4]);
+
+const DATA: Data = Data([1, 2, 3, 4]);
+const CONST_I32: i32 = 1;
+
+fn irrefutable_match() {
+    match DATA {
+        DATA => println!(),
+        _ => {},
+    }
+
+    match CONST_I32 {
+        CONST_I32 => println!(),
+        _ => {},
+    }
+
+    let i = 0;
+    match i {
+        i => {
+            let a = 1;
+            let b = 2;
+        },
+        _ => {},
+    }
+}
diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr
index ceb2a193bf7b1..9578421d2cec5 100644
--- a/tests/ui/single_match.stderr
+++ b/tests/ui/single_match.stderr
@@ -216,5 +216,43 @@ LL | |         None | Some(_) => {},
 LL | |     }
    | |_____^ help: try: `if let Some(A | B) = &Some(A) { println!() }`
 
-error: aborting due to 20 previous errors
+error: this pattern is irrefutable, `match` is useless
+  --> tests/ui/single_match.rs:371:5
+   |
+LL | /     match DATA {
+LL | |         DATA => println!(),
+LL | |         _ => {},
+LL | |     }
+   | |_____^ help: try: `{ println!() }`
+
+error: this pattern is irrefutable, `match` is useless
+  --> tests/ui/single_match.rs:376:5
+   |
+LL | /     match CONST_I32 {
+LL | |         CONST_I32 => println!(),
+LL | |         _ => {},
+LL | |     }
+   | |_____^ help: try: `{ println!() }`
+
+error: this pattern is irrefutable, `match` is useless
+  --> tests/ui/single_match.rs:382:5
+   |
+LL | /     match i {
+LL | |         i => {
+LL | |             let a = 1;
+LL | |             let b = 2;
+LL | |         },
+LL | |         _ => {},
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     {
+LL +         let a = 1;
+LL +         let b = 2;
+LL +     }
+   |
+
+error: aborting due to 23 previous errors
 
diff --git a/tests/ui/single_match_else.fixed b/tests/ui/single_match_else.fixed
index 163be16ad8be7..fb57411aaa426 100644
--- a/tests/ui/single_match_else.fixed
+++ b/tests/ui/single_match_else.fixed
@@ -171,3 +171,7 @@ fn issue_10808(bar: Option<i32>) {
         },
     }
 }
+
+fn irrefutable_match() -> Option<&'static ExprNode> {
+    { Some(&NODE) }
+}
diff --git a/tests/ui/single_match_else.rs b/tests/ui/single_match_else.rs
index 3f1fd2b31832f..2d9e877ee0fee 100644
--- a/tests/ui/single_match_else.rs
+++ b/tests/ui/single_match_else.rs
@@ -199,3 +199,13 @@ fn issue_10808(bar: Option<i32>) {
         },
     }
 }
+
+fn irrefutable_match() -> Option<&'static ExprNode> {
+    match ExprNode::Butterflies {
+        ExprNode::Butterflies => Some(&NODE),
+        _ => {
+            let x = 5;
+            None
+        },
+    }
+}
diff --git a/tests/ui/single_match_else.stderr b/tests/ui/single_match_else.stderr
index 61c348260d05e..61209053fd0fc 100644
--- a/tests/ui/single_match_else.stderr
+++ b/tests/ui/single_match_else.stderr
@@ -197,5 +197,17 @@ LL +         println!("None");
 LL +     }
    |
 
-error: aborting due to 9 previous errors
+error: this pattern is irrefutable, `match` is useless
+  --> tests/ui/single_match_else.rs:204:5
+   |
+LL | /     match ExprNode::Butterflies {
+LL | |         ExprNode::Butterflies => Some(&NODE),
+LL | |         _ => {
+LL | |             let x = 5;
+LL | |             None
+LL | |         },
+LL | |     }
+   | |_____^ help: try: `{ Some(&NODE) }`
+
+error: aborting due to 10 previous errors
 

From 9957101f3afd0d1dedfdc9eab81b9aa95cec7771 Mon Sep 17 00:00:00 2001
From: Pavel Grigorenko <GrigorenkoPV@ya.ru>
Date: Sat, 31 Aug 2024 15:31:31 +0300
Subject: [PATCH 026/114] elided_named_lifetimes: bless & add tests

---
 tests/ui/needless_lifetimes.stderr | 13 ++++++++++++-
 tests/ui/ptr_arg.stderr            | 11 ++++++++++-
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/tests/ui/needless_lifetimes.stderr b/tests/ui/needless_lifetimes.stderr
index f325d27b8c753..50f845e2d9291 100644
--- a/tests/ui/needless_lifetimes.stderr
+++ b/tests/ui/needless_lifetimes.stderr
@@ -1,3 +1,14 @@
+error: elided lifetime has a name
+  --> tests/ui/needless_lifetimes.rs:266:52
+   |
+LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
+   |                              --                    ^ this elided lifetime gets resolved as `'a`
+   |                              |
+   |                              lifetime `'a` declared here
+   |
+   = note: `-D elided-named-lifetimes` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(elided_named_lifetimes)]`
+
 error: the following explicit lifetimes could be elided: 'a, 'b
   --> tests/ui/needless_lifetimes.rs:17:23
    |
@@ -553,5 +564,5 @@ LL -         fn one_input<'a>(x: &'a u8) -> &'a u8 {
 LL +         fn one_input(x: &u8) -> &u8 {
    |
 
-error: aborting due to 46 previous errors
+error: aborting due to 47 previous errors
 
diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr
index 1848ef80fc495..4246453e64ca7 100644
--- a/tests/ui/ptr_arg.stderr
+++ b/tests/ui/ptr_arg.stderr
@@ -1,3 +1,12 @@
+error: elided lifetime has a name
+  --> tests/ui/ptr_arg.rs:295:56
+   |
+LL |     fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str {
+   |                        -- lifetime `'a` declared here  ^ this elided lifetime gets resolved as `'a`
+   |
+   = note: `-D elided-named-lifetimes` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(elided_named_lifetimes)]`
+
 error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
   --> tests/ui/ptr_arg.rs:13:14
    |
@@ -212,5 +221,5 @@ error: using a reference to `Cow` is not recommended
 LL |     fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str {
    |                                        ^^^^^^^^^^^^^^^^ help: change this to: `&str`
 
-error: aborting due to 24 previous errors
+error: aborting due to 25 previous errors
 

From e845366c82ada0466a9801363064357ad22daf12 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Mon, 22 Jul 2024 11:44:40 +0200
Subject: [PATCH 027/114] Add MSRV check for `saturating_sub` lints in const
 contexts

---
 clippy_config/src/msrvs.rs                  |  2 +-
 clippy_lints/src/implicit_saturating_sub.rs | 27 ++++++++++++++++++---
 clippy_lints/src/lib.rs                     |  2 +-
 3 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs
index 5b9707efd2634..db4c13fe33a29 100644
--- a/clippy_config/src/msrvs.rs
+++ b/clippy_config/src/msrvs.rs
@@ -35,7 +35,7 @@ msrv_aliases! {
     1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST }
     1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS }
     1,50,0 { BOOL_THEN, CLAMP }
-    1,47,0 { TAU, IS_ASCII_DIGIT_CONST, ARRAY_IMPL_ANY_LEN }
+    1,47,0 { TAU, IS_ASCII_DIGIT_CONST, ARRAY_IMPL_ANY_LEN, SATURATING_SUB_CONST }
     1,46,0 { CONST_IF_MATCH }
     1,45,0 { STR_STRIP_PREFIX }
     1,43,0 { LOG2_10, LOG10_2, NUMERIC_ASSOCIATED_CONSTANTS }
diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs
index 04c890620396d..5a42802e6bbda 100644
--- a/clippy_lints/src/implicit_saturating_sub.rs
+++ b/clippy_lints/src/implicit_saturating_sub.rs
@@ -1,12 +1,16 @@
+use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet_opt;
-use clippy_utils::{higher, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt, SpanlessEq};
+use clippy_utils::{
+    higher, in_constant, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt, SpanlessEq,
+};
 use rustc_ast::ast::LitKind;
 use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, HirId, QPath};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::declare_lint_pass;
+use rustc_session::impl_lint_pass;
 use rustc_span::Span;
 
 declare_clippy_lint! {
@@ -71,13 +75,28 @@ declare_clippy_lint! {
     "Check if a variable is smaller than another one and still subtract from it even if smaller"
 }
 
-declare_lint_pass!(ImplicitSaturatingSub => [IMPLICIT_SATURATING_SUB, INVERTED_SATURATING_SUB]);
+pub struct ImplicitSaturatingSub {
+    msrv: Msrv,
+}
+
+impl_lint_pass!(ImplicitSaturatingSub => [IMPLICIT_SATURATING_SUB, INVERTED_SATURATING_SUB]);
+
+impl ImplicitSaturatingSub {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
+    }
+}
 
 impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         if expr.span.from_expansion() {
             return;
         }
+        if in_constant(cx, expr.hir_id) && !self.msrv.meets(msrvs::SATURATING_SUB_CONST) {
+            return;
+        }
         if let Some(higher::If { cond, then, r#else: None }) = higher::If::hir(expr)
 
             // Check if the conditional expression is a binary operation
@@ -94,6 +113,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
             check_manual_check(cx, expr, cond_op, cond_left, cond_right, if_block, else_block);
         }
     }
+
+    extract_msrv_attr!(LateContext);
 }
 
 fn check_manual_check<'tcx>(
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 2ac06b360bea4..80e314dd402da 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -623,7 +623,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(unit_return_expecting_ord::UnitReturnExpectingOrd));
     store.register_late_pass(|_| Box::new(strings::StringAdd));
     store.register_late_pass(|_| Box::new(implicit_return::ImplicitReturn));
-    store.register_late_pass(|_| Box::new(implicit_saturating_sub::ImplicitSaturatingSub));
+    store.register_late_pass(move |_| Box::new(implicit_saturating_sub::ImplicitSaturatingSub::new(conf)));
     store.register_late_pass(|_| Box::new(default_numeric_fallback::DefaultNumericFallback));
     store.register_late_pass(|_| Box::new(inconsistent_struct_constructor::InconsistentStructConstructor));
     store.register_late_pass(|_| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions));

From 2832faf8959932a25fda883ed3f7dfde8b2d2817 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Fri, 2 Aug 2024 11:17:14 +0200
Subject: [PATCH 028/114] Move MSRV check later in `implicit_saturating_sub`

---
 clippy_lints/src/implicit_saturating_sub.rs | 40 +++++++++++++++++----
 1 file changed, 33 insertions(+), 7 deletions(-)

diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs
index 5a42802e6bbda..3536309d83ca0 100644
--- a/clippy_lints/src/implicit_saturating_sub.rs
+++ b/clippy_lints/src/implicit_saturating_sub.rs
@@ -3,7 +3,7 @@ use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet_opt;
 use clippy_utils::{
-    higher, in_constant, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt, SpanlessEq,
+    higher, is_in_const_context, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt, SpanlessEq,
 };
 use rustc_ast::ast::LitKind;
 use rustc_data_structures::packed::Pu128;
@@ -94,9 +94,6 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
         if expr.span.from_expansion() {
             return;
         }
-        if in_constant(cx, expr.hir_id) && !self.msrv.meets(msrvs::SATURATING_SUB_CONST) {
-            return;
-        }
         if let Some(higher::If { cond, then, r#else: None }) = higher::If::hir(expr)
 
             // Check if the conditional expression is a binary operation
@@ -110,13 +107,16 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
         }) = higher::If::hir(expr)
             && let ExprKind::Binary(ref cond_op, cond_left, cond_right) = cond.kind
         {
-            check_manual_check(cx, expr, cond_op, cond_left, cond_right, if_block, else_block);
+            check_manual_check(
+                cx, expr, cond_op, cond_left, cond_right, if_block, else_block, &self.msrv,
+            );
         }
     }
 
     extract_msrv_attr!(LateContext);
 }
 
+#[allow(clippy::too_many_arguments)]
 fn check_manual_check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &Expr<'tcx>,
@@ -125,6 +125,7 @@ fn check_manual_check<'tcx>(
     right_hand: &Expr<'tcx>,
     if_block: &Expr<'tcx>,
     else_block: &Expr<'tcx>,
+    msrv: &Msrv,
 ) {
     let ty = cx.typeck_results().expr_ty(left_hand);
     if ty.is_numeric() && !ty.is_signed() {
@@ -137,6 +138,7 @@ fn check_manual_check<'tcx>(
                 right_hand,
                 if_block,
                 else_block,
+                msrv,
             ),
             BinOpKind::Lt | BinOpKind::Le => check_gt(
                 cx,
@@ -146,12 +148,14 @@ fn check_manual_check<'tcx>(
                 left_hand,
                 if_block,
                 else_block,
+                msrv,
             ),
             _ => {},
         }
     }
 }
 
+#[allow(clippy::too_many_arguments)]
 fn check_gt(
     cx: &LateContext<'_>,
     condition_span: Span,
@@ -160,11 +164,21 @@ fn check_gt(
     little_var: &Expr<'_>,
     if_block: &Expr<'_>,
     else_block: &Expr<'_>,
+    msrv: &Msrv,
 ) {
     if let Some(big_var) = Var::new(big_var)
         && let Some(little_var) = Var::new(little_var)
     {
-        check_subtraction(cx, condition_span, expr_span, big_var, little_var, if_block, else_block);
+        check_subtraction(
+            cx,
+            condition_span,
+            expr_span,
+            big_var,
+            little_var,
+            if_block,
+            else_block,
+            msrv,
+        );
     }
 }
 
@@ -182,6 +196,7 @@ impl Var {
     }
 }
 
+#[allow(clippy::too_many_arguments)]
 fn check_subtraction(
     cx: &LateContext<'_>,
     condition_span: Span,
@@ -190,6 +205,7 @@ fn check_subtraction(
     little_var: Var,
     if_block: &Expr<'_>,
     else_block: &Expr<'_>,
+    msrv: &Msrv,
 ) {
     let if_block = peel_blocks(if_block);
     let else_block = peel_blocks(else_block);
@@ -201,7 +217,16 @@ fn check_subtraction(
         }
         // If the subtraction is done in the `else` block, then we need to also revert the two
         // variables as it means that the check was reverted too.
-        check_subtraction(cx, condition_span, expr_span, little_var, big_var, else_block, if_block);
+        check_subtraction(
+            cx,
+            condition_span,
+            expr_span,
+            little_var,
+            big_var,
+            else_block,
+            if_block,
+            msrv,
+        );
         return;
     }
     if is_integer_literal(else_block, 0)
@@ -215,6 +240,7 @@ fn check_subtraction(
             // if `snippet_opt` fails, it won't try the next conditions.
             if let Some(big_var_snippet) = snippet_opt(cx, big_var.span)
                 && let Some(little_var_snippet) = snippet_opt(cx, little_var.span)
+                && (!is_in_const_context(cx) || msrv.meets(msrvs::SATURATING_SUB_CONST))
             {
                 span_lint_and_sugg(
                     cx,

From 989ebae2ba5b79e259ee6267a390acd446cb5bff Mon Sep 17 00:00:00 2001
From: alexey semenyuk <alexsemenyuk88@gmail.com>
Date: Thu, 29 Aug 2024 10:55:42 +0500
Subject: [PATCH 029/114] Provide more clear example for WRONG_SELF_CONVENTION

---
 clippy_lints/src/methods/mod.rs | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index d7126990edb1d..e1f1df4eecba4 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -441,6 +441,17 @@ declare_clippy_lint! {
     ///     }
     /// }
     /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// # struct X;
+    /// impl X {
+    ///     fn as_str(&self) -> &'static str {
+    ///         // ..
+    /// # ""
+    ///     }
+    /// }
+    /// ```
     #[clippy::version = "pre 1.29.0"]
     pub WRONG_SELF_CONVENTION,
     style,

From ba2577f23c0014c171235692ca4d8b6b71fbce7e Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sun, 25 Aug 2024 15:15:15 +0200
Subject: [PATCH 030/114] stabilize const_float_bits_conv

---
 clippy_lints/src/transmute/mod.rs             |   6 +-
 .../src/transmute/transmute_float_to_int.rs   |   3 +-
 .../src/transmute/transmute_int_to_float.rs   |   3 +-
 .../src/transmute/transmute_num_to_bytes.rs   |   6 -
 tests/ui/transmute.rs                         |  12 ++
 tests/ui/transmute.stderr                     | 112 ++++++++++++++----
 tests/ui/transmute_float_to_int.fixed         |  28 +++--
 tests/ui/transmute_float_to_int.rs            |  12 +-
 tests/ui/transmute_float_to_int.stderr        |  50 +++++++-
 9 files changed, 186 insertions(+), 46 deletions(-)

diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs
index 373bf61d8ff94..a2ae36cc484ad 100644
--- a/clippy_lints/src/transmute/mod.rs
+++ b/clippy_lints/src/transmute/mod.rs
@@ -619,10 +619,10 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
                 | 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, &self.msrv)
                 | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg)
-                | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context)
+                | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg)
                 | transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg)
-                | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context)
-                | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context)
+                | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg)
+                | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg)
                 | (unsound_collection_transmute::check(cx, e, from_ty, to_ty)
                     || transmute_undefined_repr::check(cx, e, from_ty, to_ty))
                 | (eager_transmute::check(cx, e, arg, from_ty, to_ty));
diff --git a/clippy_lints/src/transmute/transmute_float_to_int.rs b/clippy_lints/src/transmute/transmute_float_to_int.rs
index ab3bb5e1062d3..cb46109c27e2f 100644
--- a/clippy_lints/src/transmute/transmute_float_to_int.rs
+++ b/clippy_lints/src/transmute/transmute_float_to_int.rs
@@ -15,10 +15,9 @@ pub(super) fn check<'tcx>(
     from_ty: Ty<'tcx>,
     to_ty: Ty<'tcx>,
     mut arg: &'tcx Expr<'_>,
-    const_context: bool,
 ) -> bool {
     match (&from_ty.kind(), &to_ty.kind()) {
-        (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) if !const_context => {
+        (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) => {
             span_lint_and_then(
                 cx,
                 TRANSMUTE_FLOAT_TO_INT,
diff --git a/clippy_lints/src/transmute/transmute_int_to_float.rs b/clippy_lints/src/transmute/transmute_int_to_float.rs
index d51888e30971b..e00fb90c3074e 100644
--- a/clippy_lints/src/transmute/transmute_int_to_float.rs
+++ b/clippy_lints/src/transmute/transmute_int_to_float.rs
@@ -14,10 +14,9 @@ pub(super) fn check<'tcx>(
     from_ty: Ty<'tcx>,
     to_ty: Ty<'tcx>,
     arg: &'tcx Expr<'_>,
-    const_context: bool,
 ) -> bool {
     match (&from_ty.kind(), &to_ty.kind()) {
-        (ty::Int(_) | ty::Uint(_), ty::Float(_)) if !const_context => {
+        (ty::Int(_) | ty::Uint(_), ty::Float(_)) => {
             span_lint_and_then(
                 cx,
                 TRANSMUTE_INT_TO_FLOAT,
diff --git a/clippy_lints/src/transmute/transmute_num_to_bytes.rs b/clippy_lints/src/transmute/transmute_num_to_bytes.rs
index 88b0ac5a36887..362f2bb6960a2 100644
--- a/clippy_lints/src/transmute/transmute_num_to_bytes.rs
+++ b/clippy_lints/src/transmute/transmute_num_to_bytes.rs
@@ -14,18 +14,12 @@ pub(super) fn check<'tcx>(
     from_ty: Ty<'tcx>,
     to_ty: Ty<'tcx>,
     arg: &'tcx Expr<'_>,
-    const_context: bool,
 ) -> bool {
     match (&from_ty.kind(), &to_ty.kind()) {
         (ty::Int(_) | ty::Uint(_) | ty::Float(_), ty::Array(arr_ty, _)) => {
             if !matches!(arr_ty.kind(), ty::Uint(UintTy::U8)) {
                 return false;
             }
-            if matches!(from_ty.kind(), ty::Float(_)) && const_context {
-                // TODO: Remove when const_float_bits_conv is stabilized
-                // rust#72447
-                return false;
-            }
 
             span_lint_and_then(
                 cx,
diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs
index 46629526367ec..eeea3f080b1c9 100644
--- a/tests/ui/transmute.rs
+++ b/tests/ui/transmute.rs
@@ -140,24 +140,32 @@ mod int_to_float {
 
     mod issue_5747 {
         const VALUE16: f16 = unsafe { std::mem::transmute(0_u16) };
+        //~^ ERROR: transmute from a `u16` to a `f16`
         const VALUE32: f32 = unsafe { std::mem::transmute(0_u32) };
+        //~^ ERROR: transmute from a `u32` to a `f32`
         const VALUE64: f64 = unsafe { std::mem::transmute(0_i64) };
+        //~^ ERROR: transmute from a `i64` to a `f64`
         const VALUE128: f128 = unsafe { std::mem::transmute(0_i128) };
+        //~^ ERROR: transmute from a `i128` to a `f128`
 
         const fn from_bits_16(v: i16) -> f16 {
             unsafe { std::mem::transmute(v) }
+            //~^ ERROR: transmute from a `i16` to a `f16`
         }
 
         const fn from_bits_32(v: i32) -> f32 {
             unsafe { std::mem::transmute(v) }
+            //~^ ERROR: transmute from a `i32` to a `f32`
         }
 
         const fn from_bits_64(v: u64) -> f64 {
             unsafe { std::mem::transmute(v) }
+            //~^ ERROR: transmute from a `u64` to a `f64`
         }
 
         const fn from_bits_128(v: u128) -> f128 {
             unsafe { std::mem::transmute(v) }
+            //~^ ERROR: transmute from a `u128` to a `f128`
         }
     }
 }
@@ -205,9 +213,13 @@ mod num_to_bytes {
             //~^ ERROR: transmute from a `i128` to a `[u8; 16]`
 
             let _: [u8; 2] = std::mem::transmute(0.0f16);
+            //~^ ERROR: transmute from a `f16` to a `[u8; 2]`
             let _: [u8; 4] = std::mem::transmute(0.0f32);
+            //~^ ERROR: transmute from a `f32` to a `[u8; 4]`
             let _: [u8; 8] = std::mem::transmute(0.0f64);
+            //~^ ERROR: transmute from a `f64` to a `[u8; 8]`
             let _: [u8; 16] = std::mem::transmute(0.0f128);
+            //~^ ERROR: transmute from a `f128` to a `[u8; 16]`
         }
     }
 }
diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr
index 0072f62962a7d..41a10f381dc53 100644
--- a/tests/ui/transmute.stderr
+++ b/tests/ui/transmute.stderr
@@ -148,8 +148,56 @@ error: transmute from a `i128` to a `f128`
 LL |         let _: f128 = unsafe { std::mem::transmute(0_i128) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_i128 as u128)`
 
+error: transmute from a `u16` to a `f16`
+  --> tests/ui/transmute.rs:142:39
+   |
+LL |         const VALUE16: f16 = unsafe { std::mem::transmute(0_u16) };
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(0_u16)`
+
+error: transmute from a `u32` to a `f32`
+  --> tests/ui/transmute.rs:144:39
+   |
+LL |         const VALUE32: f32 = unsafe { std::mem::transmute(0_u32) };
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)`
+
+error: transmute from a `i64` to a `f64`
+  --> tests/ui/transmute.rs:146:39
+   |
+LL |         const VALUE64: f64 = unsafe { std::mem::transmute(0_i64) };
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)`
+
+error: transmute from a `i128` to a `f128`
+  --> tests/ui/transmute.rs:148:41
+   |
+LL |         const VALUE128: f128 = unsafe { std::mem::transmute(0_i128) };
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_i128 as u128)`
+
+error: transmute from a `i16` to a `f16`
+  --> tests/ui/transmute.rs:152:22
+   |
+LL |             unsafe { std::mem::transmute(v) }
+   |                      ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(v as u16)`
+
+error: transmute from a `i32` to a `f32`
+  --> tests/ui/transmute.rs:157:22
+   |
+LL |             unsafe { std::mem::transmute(v) }
+   |                      ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(v as u32)`
+
+error: transmute from a `u64` to a `f64`
+  --> tests/ui/transmute.rs:162:22
+   |
+LL |             unsafe { std::mem::transmute(v) }
+   |                      ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(v)`
+
+error: transmute from a `u128` to a `f128`
+  --> tests/ui/transmute.rs:167:22
+   |
+LL |             unsafe { std::mem::transmute(v) }
+   |                      ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(v)`
+
 error: transmute from a `u8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:168:30
+  --> tests/ui/transmute.rs:176:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0u8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()`
@@ -158,97 +206,121 @@ 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:171:30
+  --> tests/ui/transmute.rs:179: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:173:31
+  --> tests/ui/transmute.rs:181: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:175:30
+  --> tests/ui/transmute.rs:183: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:177:30
+  --> tests/ui/transmute.rs:185: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:179:31
+  --> tests/ui/transmute.rs:187:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0i128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()`
 
 error: transmute from a `f16` to a `[u8; 2]`
-  --> tests/ui/transmute.rs:182:30
+  --> tests/ui/transmute.rs:190:30
    |
 LL |             let _: [u8; 2] = std::mem::transmute(0.0f16);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f16.to_ne_bytes()`
 
 error: transmute from a `f32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:184:30
+  --> tests/ui/transmute.rs:192: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:186:30
+  --> tests/ui/transmute.rs:194: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 `f128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:188:31
+  --> tests/ui/transmute.rs:196:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0.0f128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f128.to_ne_bytes()`
 
 error: transmute from a `u8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:194:30
+  --> tests/ui/transmute.rs:202: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:196:30
+  --> tests/ui/transmute.rs:204: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:198:31
+  --> tests/ui/transmute.rs:206: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:200:30
+  --> tests/ui/transmute.rs:208: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:202:30
+  --> tests/ui/transmute.rs:210: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:204:31
+  --> tests/ui/transmute.rs:212:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0i128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()`
 
+error: transmute from a `f16` to a `[u8; 2]`
+  --> tests/ui/transmute.rs:215:30
+   |
+LL |             let _: [u8; 2] = std::mem::transmute(0.0f16);
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f16.to_ne_bytes()`
+
+error: transmute from a `f32` to a `[u8; 4]`
+  --> tests/ui/transmute.rs:217: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:219: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 `f128` to a `[u8; 16]`
+  --> tests/ui/transmute.rs:221:31
+   |
+LL |             let _: [u8; 16] = std::mem::transmute(0.0f128);
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f128.to_ne_bytes()`
+
 error: transmute from a `&[u8]` to a `&str`
-  --> tests/ui/transmute.rs:218:28
+  --> tests/ui/transmute.rs:230:28
    |
 LL |     let _: &str = unsafe { std::mem::transmute(B) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()`
@@ -257,16 +329,16 @@ 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:221:32
+  --> tests/ui/transmute.rs:233: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:223:30
+  --> tests/ui/transmute.rs:235:30
    |
 LL |     const _: &str = unsafe { std::mem::transmute(B) };
    |                              ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)`
 
-error: aborting due to 42 previous errors
+error: aborting due to 54 previous errors
 
diff --git a/tests/ui/transmute_float_to_int.fixed b/tests/ui/transmute_float_to_int.fixed
index 4361a7407d115..83814ca43b96d 100644
--- a/tests/ui/transmute_float_to_int.fixed
+++ b/tests/ui/transmute_float_to_int.fixed
@@ -1,7 +1,7 @@
 #![warn(clippy::transmute_float_to_int)]
 #![allow(clippy::missing_transmute_annotations)]
-#![feature(f128)]
-#![feature(f16)]
+#![feature(f128, f128_const)]
+#![feature(f16, f16_const)]
 
 fn float_to_int() {
     let _: u32 = unsafe { 1f32.to_bits() };
@@ -20,25 +20,33 @@ fn float_to_int() {
 }
 
 mod issue_5747 {
-    const VALUE16: i16 = unsafe { std::mem::transmute(1f16) };
-    const VALUE32: i32 = unsafe { std::mem::transmute(1f32) };
-    const VALUE64: u64 = unsafe { std::mem::transmute(1f64) };
-    const VALUE128: u128 = unsafe { std::mem::transmute(1f128) };
+    const VALUE16: i16 = unsafe { 1f16.to_bits() as i16 };
+    //~^ ERROR: transmute from a `f16` to a `i16`
+    const VALUE32: i32 = unsafe { 1f32.to_bits() as i32 };
+    //~^ ERROR: transmute from a `f32` to a `i32`
+    const VALUE64: u64 = unsafe { 1f64.to_bits() };
+    //~^ ERROR: transmute from a `f64` to a `u64`
+    const VALUE128: u128 = unsafe { 1f128.to_bits() };
+    //~^ ERROR: transmute from a `f128` to a `u128`
 
     const fn to_bits_16(v: f16) -> u16 {
-        unsafe { std::mem::transmute(v) }
+        unsafe { v.to_bits() }
+        //~^ ERROR: transmute from a `f16` to a `u16`
     }
 
     const fn to_bits_32(v: f32) -> u32 {
-        unsafe { std::mem::transmute(v) }
+        unsafe { v.to_bits() }
+        //~^ ERROR: transmute from a `f32` to a `u32`
     }
 
     const fn to_bits_64(v: f64) -> i64 {
-        unsafe { std::mem::transmute(v) }
+        unsafe { v.to_bits() as i64 }
+        //~^ ERROR: transmute from a `f64` to a `i64`
     }
 
     const fn to_bits_128(v: f128) -> i128 {
-        unsafe { std::mem::transmute(v) }
+        unsafe { v.to_bits() as i128 }
+        //~^ ERROR: transmute from a `f128` to a `i128`
     }
 }
 
diff --git a/tests/ui/transmute_float_to_int.rs b/tests/ui/transmute_float_to_int.rs
index 363ce0bcb16d0..64d6e9172039d 100644
--- a/tests/ui/transmute_float_to_int.rs
+++ b/tests/ui/transmute_float_to_int.rs
@@ -1,7 +1,7 @@
 #![warn(clippy::transmute_float_to_int)]
 #![allow(clippy::missing_transmute_annotations)]
-#![feature(f128)]
-#![feature(f16)]
+#![feature(f128, f128_const)]
+#![feature(f16, f16_const)]
 
 fn float_to_int() {
     let _: u32 = unsafe { std::mem::transmute(1f32) };
@@ -21,24 +21,32 @@ fn float_to_int() {
 
 mod issue_5747 {
     const VALUE16: i16 = unsafe { std::mem::transmute(1f16) };
+    //~^ ERROR: transmute from a `f16` to a `i16`
     const VALUE32: i32 = unsafe { std::mem::transmute(1f32) };
+    //~^ ERROR: transmute from a `f32` to a `i32`
     const VALUE64: u64 = unsafe { std::mem::transmute(1f64) };
+    //~^ ERROR: transmute from a `f64` to a `u64`
     const VALUE128: u128 = unsafe { std::mem::transmute(1f128) };
+    //~^ ERROR: transmute from a `f128` to a `u128`
 
     const fn to_bits_16(v: f16) -> u16 {
         unsafe { std::mem::transmute(v) }
+        //~^ ERROR: transmute from a `f16` to a `u16`
     }
 
     const fn to_bits_32(v: f32) -> u32 {
         unsafe { std::mem::transmute(v) }
+        //~^ ERROR: transmute from a `f32` to a `u32`
     }
 
     const fn to_bits_64(v: f64) -> i64 {
         unsafe { std::mem::transmute(v) }
+        //~^ ERROR: transmute from a `f64` to a `i64`
     }
 
     const fn to_bits_128(v: f128) -> i128 {
         unsafe { std::mem::transmute(v) }
+        //~^ ERROR: transmute from a `f128` to a `i128`
     }
 }
 
diff --git a/tests/ui/transmute_float_to_int.stderr b/tests/ui/transmute_float_to_int.stderr
index 9cac75f72cdd7..0cabab58ab08c 100644
--- a/tests/ui/transmute_float_to_int.stderr
+++ b/tests/ui/transmute_float_to_int.stderr
@@ -37,5 +37,53 @@ error: transmute from a `f64` to a `u64`
 LL |     let _: u64 = unsafe { std::mem::transmute(-1.0) };
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-1.0f64).to_bits()`
 
-error: aborting due to 6 previous errors
+error: transmute from a `f16` to a `i16`
+  --> tests/ui/transmute_float_to_int.rs:23:35
+   |
+LL |     const VALUE16: i16 = unsafe { std::mem::transmute(1f16) };
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f16.to_bits() as i16`
+
+error: transmute from a `f32` to a `i32`
+  --> tests/ui/transmute_float_to_int.rs:25:35
+   |
+LL |     const VALUE32: 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:27:35
+   |
+LL |     const VALUE64: u64 = unsafe { std::mem::transmute(1f64) };
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits()`
+
+error: transmute from a `f128` to a `u128`
+  --> tests/ui/transmute_float_to_int.rs:29:37
+   |
+LL |     const VALUE128: u128 = unsafe { std::mem::transmute(1f128) };
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f128.to_bits()`
+
+error: transmute from a `f16` to a `u16`
+  --> tests/ui/transmute_float_to_int.rs:33:18
+   |
+LL |         unsafe { std::mem::transmute(v) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits()`
+
+error: transmute from a `f32` to a `u32`
+  --> tests/ui/transmute_float_to_int.rs:38:18
+   |
+LL |         unsafe { std::mem::transmute(v) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits()`
+
+error: transmute from a `f64` to a `i64`
+  --> tests/ui/transmute_float_to_int.rs:43:18
+   |
+LL |         unsafe { std::mem::transmute(v) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits() as i64`
+
+error: transmute from a `f128` to a `i128`
+  --> tests/ui/transmute_float_to_int.rs:48:18
+   |
+LL |         unsafe { std::mem::transmute(v) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits() as i128`
+
+error: aborting due to 14 previous errors
 

From cd28176025ef5f00ed58680ac4c346c3b0c19020 Mon Sep 17 00:00:00 2001
From: Yuri Astrakhan <YuriAstrakhan@gmail.com>
Date: Sun, 1 Sep 2024 20:58:14 -0400
Subject: [PATCH 031/114] Minor code simplification

---
 .../attrs/allow_attributes_without_reason.rs  |  2 +-
 clippy_utils/src/sugg.rs                      | 38 ++++++++-----------
 2 files changed, 17 insertions(+), 23 deletions(-)

diff --git a/clippy_lints/src/attrs/allow_attributes_without_reason.rs b/clippy_lints/src/attrs/allow_attributes_without_reason.rs
index 4ab97118df1d4..4c7e07478c129 100644
--- a/clippy_lints/src/attrs/allow_attributes_without_reason.rs
+++ b/clippy_lints/src/attrs/allow_attributes_without_reason.rs
@@ -26,7 +26,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!("`{name}` attribute without specifying a reason"),
         |diag| {
             diag.help("try adding a reason at the end with `, reason = \"..\"`");
         },
diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs
index 0f86d89c980d7..3255c51d009ca 100644
--- a/clippy_utils/src/sugg.rs
+++ b/clippy_utils/src/sugg.rs
@@ -180,8 +180,10 @@ impl<'a> Sugg<'a> {
     ) -> Self {
         use rustc_ast::ast::RangeLimits;
 
+        let mut snippet = |span: Span| snippet_with_context(cx, span, ctxt, default, app).0;
+
         match expr.kind {
-            _ if expr.span.ctxt() != ctxt => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0),
+            _ if expr.span.ctxt() != ctxt => Sugg::NonParen(snippet(expr.span)),
             ast::ExprKind::AddrOf(..)
             | ast::ExprKind::Closure { .. }
             | ast::ExprKind::If(..)
@@ -224,46 +226,38 @@ impl<'a> Sugg<'a> {
             | ast::ExprKind::While(..)
             | ast::ExprKind::Await(..)
             | ast::ExprKind::Err(_)
-            | ast::ExprKind::Dummy => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0),
+            | ast::ExprKind::Dummy => Sugg::NonParen(snippet(expr.span)),
             ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp(
                 AssocOp::DotDot,
-                lhs.as_ref().map_or("".into(), |lhs| {
-                    snippet_with_context(cx, lhs.span, ctxt, default, app).0
-                }),
-                rhs.as_ref().map_or("".into(), |rhs| {
-                    snippet_with_context(cx, rhs.span, ctxt, default, app).0
-                }),
+                lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),
+                rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)),
             ),
             ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::Closed) => Sugg::BinOp(
                 AssocOp::DotDotEq,
-                lhs.as_ref().map_or("".into(), |lhs| {
-                    snippet_with_context(cx, lhs.span, ctxt, default, app).0
-                }),
-                rhs.as_ref().map_or("".into(), |rhs| {
-                    snippet_with_context(cx, rhs.span, ctxt, default, app).0
-                }),
+                lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),
+                rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)),
             ),
             ast::ExprKind::Assign(ref lhs, ref rhs, _) => Sugg::BinOp(
                 AssocOp::Assign,
-                snippet_with_context(cx, lhs.span, ctxt, default, app).0,
-                snippet_with_context(cx, rhs.span, ctxt, default, app).0,
+                snippet(lhs.span),
+                snippet(rhs.span),
             ),
             ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp(
                 astbinop2assignop(op),
-                snippet_with_context(cx, lhs.span, ctxt, default, app).0,
-                snippet_with_context(cx, rhs.span, ctxt, default, app).0,
+                snippet(lhs.span),
+                snippet(rhs.span),
             ),
             ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp(
                 AssocOp::from_ast_binop(op.node),
-                snippet_with_context(cx, lhs.span, ctxt, default, app).0,
-                snippet_with_context(cx, rhs.span, ctxt, default, app).0,
+                snippet(lhs.span),
+                snippet(rhs.span),
             ),
             ast::ExprKind::Cast(ref lhs, ref ty) |
             //FIXME(chenyukang), remove this after type ascription is removed from AST
             ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp(
                 AssocOp::As,
-                snippet_with_context(cx, lhs.span, ctxt, default, app).0,
-                snippet_with_context(cx, ty.span, ctxt, default, app).0,
+                snippet(lhs.span),
+                snippet(ty.span),
             ),
         }
     }

From 273b561609de64131af3d59a38e38eceb76e4a29 Mon Sep 17 00:00:00 2001
From: Soveu <marx.tomasz@gmail.com>
Date: Fri, 12 Jul 2024 12:12:58 +0200
Subject: [PATCH 032/114] add pointers_in_nomem_asm_block lint

---
 CHANGELOG.md                                  |  1 +
 clippy_lints/src/declared_lints.rs            |  1 +
 clippy_lints/src/lib.rs                       |  2 +
 .../src/pointers_in_nomem_asm_block.rs        | 88 +++++++++++++++++++
 tests/ui/pointers_in_nomem_asm_block.rs       | 33 +++++++
 tests/ui/pointers_in_nomem_asm_block.stderr   | 34 +++++++
 6 files changed, 159 insertions(+)
 create mode 100644 clippy_lints/src/pointers_in_nomem_asm_block.rs
 create mode 100644 tests/ui/pointers_in_nomem_asm_block.rs
 create mode 100644 tests/ui/pointers_in_nomem_asm_block.stderr

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 682c3cfe0151c..fc51694ff57f4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5758,6 +5758,7 @@ Released 2018-09-13
 [`pathbuf_init_then_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#pathbuf_init_then_push
 [`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch
 [`permissions_set_readonly_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#permissions_set_readonly_false
+[`pointers_in_nomem_asm_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#pointers_in_nomem_asm_block
 [`positional_named_format_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#positional_named_format_parameters
 [`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma
 [`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index aded9e276c4a8..e478ab330e8bc 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -600,6 +600,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::pathbuf_init_then_push::PATHBUF_INIT_THEN_PUSH_INFO,
     crate::pattern_type_mismatch::PATTERN_TYPE_MISMATCH_INFO,
     crate::permissions_set_readonly_false::PERMISSIONS_SET_READONLY_FALSE_INFO,
+    crate::pointers_in_nomem_asm_block::POINTERS_IN_NOMEM_ASM_BLOCK_INFO,
     crate::precedence::PRECEDENCE_INFO,
     crate::ptr::CMP_NULL_INFO,
     crate::ptr::INVALID_NULL_PTR_USAGE_INFO,
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 078f38656ece8..58ad9f645d6a5 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -287,6 +287,7 @@ mod pass_by_ref_or_value;
 mod pathbuf_init_then_push;
 mod pattern_type_mismatch;
 mod permissions_set_readonly_false;
+mod pointers_in_nomem_asm_block;
 mod precedence;
 mod ptr;
 mod ptr_offset_with_cast;
@@ -935,5 +936,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_early_pass(|| Box::new(byte_char_slices::ByteCharSlice));
     store.register_early_pass(|| Box::new(cfg_not_test::CfgNotTest));
     store.register_late_pass(|_| Box::new(zombie_processes::ZombieProcesses));
+    store.register_late_pass(|_| Box::new(pointers_in_nomem_asm_block::PointersInNomemAsmBlock));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
diff --git a/clippy_lints/src/pointers_in_nomem_asm_block.rs b/clippy_lints/src/pointers_in_nomem_asm_block.rs
new file mode 100644
index 0000000000000..385f634a15050
--- /dev/null
+++ b/clippy_lints/src/pointers_in_nomem_asm_block.rs
@@ -0,0 +1,88 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use rustc_ast::InlineAsmOptions;
+use rustc_hir::{Expr, ExprKind, InlineAsm, InlineAsmOperand};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::declare_lint_pass;
+use rustc_span::Span;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks if any pointer is being passed to an asm! block with `nomem` option.
+    ///
+    /// ### Why is this bad?
+    /// `nomem` forbids any reads or writes to memory and passing a pointer suggests
+    /// that either of those will happen.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// fn f(p: *mut u32) {
+    ///     unsafe { core::arch::asm!("mov [{p}], 42", p = in(reg) p, options(nomem, nostack)); }
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// fn f(p: *mut u32) {
+    ///     unsafe { core::arch::asm!("mov [{p}], 42", p = in(reg) p, options(nostack)); }
+    /// }
+    /// ```
+    #[clippy::version = "1.81.0"]
+    pub POINTERS_IN_NOMEM_ASM_BLOCK,
+    suspicious,
+    "pointers in nomem asm block"
+}
+
+declare_lint_pass!(PointersInNomemAsmBlock => [POINTERS_IN_NOMEM_ASM_BLOCK]);
+
+impl<'tcx> LateLintPass<'tcx> for PointersInNomemAsmBlock {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+        if let ExprKind::InlineAsm(asm) = &expr.kind {
+            check_asm(cx, asm);
+        }
+    }
+}
+
+fn check_asm(cx: &LateContext<'_>, asm: &InlineAsm<'_>) {
+    if !asm.options.contains(InlineAsmOptions::NOMEM) {
+        return;
+    }
+
+    let spans = asm
+        .operands
+        .iter()
+        .filter(|(op, _span)| has_in_operand_pointer(cx, op))
+        .map(|(_op, span)| *span)
+        .collect::<Vec<Span>>();
+
+    if spans.is_empty() {
+        return;
+    }
+
+    span_lint_and_then(
+        cx,
+        POINTERS_IN_NOMEM_ASM_BLOCK,
+        spans,
+        "passing pointers to nomem asm block",
+        additional_notes,
+    );
+}
+
+fn has_in_operand_pointer(cx: &LateContext<'_>, asm_op: &InlineAsmOperand<'_>) -> bool {
+    let asm_in_expr = match asm_op {
+        InlineAsmOperand::SymStatic { .. }
+        | InlineAsmOperand::Out { .. }
+        | InlineAsmOperand::Const { .. }
+        | InlineAsmOperand::SymFn { .. }
+        | InlineAsmOperand::Label { .. } => return false,
+        InlineAsmOperand::SplitInOut { in_expr, .. } => in_expr,
+        InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => expr,
+    };
+
+    // This checks for raw ptrs, refs and function pointers - the last one
+    // also technically counts as reading memory.
+    cx.typeck_results().expr_ty(asm_in_expr).is_any_ptr()
+}
+
+fn additional_notes(diag: &mut rustc_errors::Diag<'_, ()>) {
+    diag.note("`nomem` means that no memory write or read happens inside the asm! block");
+    diag.note("if this is intentional and no pointers are read or written to, consider allowing the lint");
+}
diff --git a/tests/ui/pointers_in_nomem_asm_block.rs b/tests/ui/pointers_in_nomem_asm_block.rs
new file mode 100644
index 0000000000000..b5abcbb3474c2
--- /dev/null
+++ b/tests/ui/pointers_in_nomem_asm_block.rs
@@ -0,0 +1,33 @@
+//@ needs-asm-support
+#![warn(clippy::pointers_in_nomem_asm_block)]
+#![crate_type = "lib"]
+#![no_std]
+
+use core::arch::asm;
+
+unsafe fn nomem_bad(p: &i32) {
+    asm!(
+        "asdf {p1}, {p2}, {p3}",
+        p1 = in(reg) p,
+        //~^ ERROR: passing pointers to nomem asm block
+        p2 = in(reg) p as *const _ as usize,
+        p3 = in(reg) p,
+        options(nomem, nostack, preserves_flags)
+    );
+}
+
+unsafe fn nomem_good(p: &i32) {
+    asm!("asdf {p}", p = in(reg) p, options(readonly, nostack, preserves_flags));
+    let p = p as *const i32 as usize;
+    asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags));
+}
+
+unsafe fn nomem_bad2(p: &mut i32) {
+    asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags));
+    //~^ ERROR: passing pointers to nomem asm block
+}
+
+unsafe fn nomem_fn(p: extern "C" fn()) {
+    asm!("call {p}", p = in(reg) p, options(nomem));
+    //~^ ERROR: passing pointers to nomem asm block
+}
diff --git a/tests/ui/pointers_in_nomem_asm_block.stderr b/tests/ui/pointers_in_nomem_asm_block.stderr
new file mode 100644
index 0000000000000..cabeb37344f2b
--- /dev/null
+++ b/tests/ui/pointers_in_nomem_asm_block.stderr
@@ -0,0 +1,34 @@
+error: passing pointers to nomem asm block
+  --> tests/ui/pointers_in_nomem_asm_block.rs:11:9
+   |
+LL |         p1 = in(reg) p,
+   |         ^^^^^^^^^^^^^^
+...
+LL |         p3 = in(reg) p,
+   |         ^^^^^^^^^^^^^^
+   |
+   = note: `nomem` means that no memory write or read happens inside the asm! block
+   = note: if this is intentional and no pointers are read or written to, consider allowing the lint
+   = note: `-D clippy::pointers-in-nomem-asm-block` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::pointers_in_nomem_asm_block)]`
+
+error: passing pointers to nomem asm block
+  --> tests/ui/pointers_in_nomem_asm_block.rs:26:22
+   |
+LL |     asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags));
+   |                      ^^^^^^^^^^^^^
+   |
+   = note: `nomem` means that no memory write or read happens inside the asm! block
+   = note: if this is intentional and no pointers are read or written to, consider allowing the lint
+
+error: passing pointers to nomem asm block
+  --> tests/ui/pointers_in_nomem_asm_block.rs:31:22
+   |
+LL |     asm!("call {p}", p = in(reg) p, options(nomem));
+   |                      ^^^^^^^^^^^^^
+   |
+   = note: `nomem` means that no memory write or read happens inside the asm! block
+   = note: if this is intentional and no pointers are read or written to, consider allowing the lint
+
+error: aborting due to 3 previous errors
+

From cdb442362b464472f1ede46f5b2763811978c2bf Mon Sep 17 00:00:00 2001
From: Philipp Krones <hello@philkrones.com>
Date: Wed, 4 Sep 2024 18:17:31 +0200
Subject: [PATCH 033/114] Bump actions/download-artifact from 3 to 4

---
 .github/workflows/clippy_bors.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml
index 2aa13313fa518..026771e6fcf42 100644
--- a/.github/workflows/clippy_bors.yml
+++ b/.github/workflows/clippy_bors.yml
@@ -162,7 +162,7 @@ jobs:
         find $DIR ! -executable -o -type d ! -path $DIR | xargs rm -rf
 
     - name: Upload Binaries
-      uses: actions/upload-artifact@v3
+      uses: actions/upload-artifact@v4
       with:
         name: binaries
         path: target/debug
@@ -202,7 +202,7 @@ jobs:
 
     # Download
     - name: Download target dir
-      uses: actions/download-artifact@v3
+      uses: actions/download-artifact@v4
       with:
         name: binaries
         path: target/debug

From 7d2e6ebcbeb2ca161b4b0f8a88bd41bf4c1381f5 Mon Sep 17 00:00:00 2001
From: Lukas Lueg <lukas.lueg@gmail.com>
Date: Wed, 4 Sep 2024 19:37:59 +0200
Subject: [PATCH 034/114] Expand missing_transmute_annotations docs

Fixes #13339
---
 clippy_lints/src/transmute/mod.rs | 32 +++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs
index 373bf61d8ff94..6e62668fd5272 100644
--- a/clippy_lints/src/transmute/mod.rs
+++ b/clippy_lints/src/transmute/mod.rs
@@ -527,24 +527,44 @@ declare_clippy_lint! {
     /// 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.
+    /// If not, one or more unexpected types could be used during `transmute()`, potentially leading
+    /// to Undefined Behavior or other problems.
     ///
-    /// 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.
+    /// This is particularly dangerous in case a seemingly innocent/unrelated change causes type
+    /// inference to result in a different type. For example, if `transmute()` is the tail
+    /// expression of an `if`-branch, and the `else`-branch type changes, the compiler may silently
+    /// infer a different type to be returned by `transmute()`. That is because the compiler is
+    /// free to change the inference of a type as long as that inference is technically correct,
+    /// regardless of the programmer's unknown expectation.
+    ///
+    /// Both type-parameters, the input- and the output-type, to any `transmute()` should
+    /// be given explicitly: Setting the input-type explicitly avoids confusion about what the
+    /// argument's type actually is. Setting the output-type explicitly avoids type-inference
+    /// to infer a technically correct yet unexpected type.
     ///
     /// ### Example
     /// ```no_run
     /// # unsafe {
+    /// // Avoid "naked" calls to `transmute()`!
     /// let x: i32 = std::mem::transmute([1u16, 2u16]);
+    ///
+    /// // `first_answers` is intended to transmute a slice of bool to a slice of u8.
+    /// // But the programmer forgot to index the first element of the outer slice,
+    /// // so we are actually transmuting from "pointers to slices" instead of
+    /// // transmuting from "a slice of bool", causing a nonsensical result.
+    /// let the_answers: &[&[bool]] = &[&[true, false, true]];
+    /// let first_answers: &[u8] = std::mem::transmute(the_answers);
     /// # }
     /// ```
     /// Use instead:
     /// ```no_run
     /// # unsafe {
     /// let x = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+    ///
+    /// // The explicit type parameters on `transmute()` makes the intention clear,
+    /// // and cause a type-error if the actual types don't match our expectation.
+    /// let the_answers: &[&[bool]] = &[&[true, false, true]];
+    /// let first_answers: &[u8] = std::mem::transmute::<&[bool], &[u8]>(the_answers[0]);
     /// # }
     /// ```
     #[clippy::version = "1.79.0"]

From f7f550561e801fa1adb74377fd95a151820d8d0e Mon Sep 17 00:00:00 2001
From: Alex Macleod <alex@macleod.io>
Date: Wed, 4 Sep 2024 21:22:28 +0000
Subject: [PATCH 035/114] Only lint `manual_non_exhaustive` for exported types

---
 clippy_lints/src/lib.rs                      |   3 +-
 clippy_lints/src/manual_non_exhaustive.rs    | 182 ++++++++-----------
 tests/ui/manual_non_exhaustive_enum.rs       |  24 ++-
 tests/ui/manual_non_exhaustive_enum.stderr   |  22 ++-
 tests/ui/manual_non_exhaustive_struct.rs     |  50 ++---
 tests/ui/manual_non_exhaustive_struct.stderr |  64 ++++---
 6 files changed, 166 insertions(+), 179 deletions(-)

diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 078f38656ece8..747119e114795 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -633,8 +633,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     let format_args = format_args_storage.clone();
     store.register_late_pass(move |_| Box::new(methods::Methods::new(conf, format_args.clone())));
     store.register_late_pass(move |_| Box::new(matches::Matches::new(conf)));
-    store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(conf)));
-    store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(conf)));
+    store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustive::new(conf)));
     store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(conf)));
     store.register_early_pass(move || Box::new(redundant_static_lifetimes::RedundantStaticLifetimes::new(conf)));
     store.register_early_pass(move || Box::new(redundant_field_names::RedundantFieldNames::new(conf)));
diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs
index 6b1d90483ccd1..01f1d9c3beba2 100644
--- a/clippy_lints/src/manual_non_exhaustive.rs
+++ b/clippy_lints/src/manual_non_exhaustive.rs
@@ -2,16 +2,16 @@ use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
 use clippy_utils::is_doc_hidden;
-use clippy_utils::source::SpanRangeExt;
-use rustc_ast::ast::{self, VisibilityKind};
+use clippy_utils::source::snippet_indent;
+use itertools::Itertools;
 use rustc_ast::attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
-use rustc_hir::{self as hir, Expr, ExprKind, QPath};
-use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+use rustc_hir::{Expr, ExprKind, Item, ItemKind, QPath, TyKind, VariantData};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
-use rustc_span::def_id::{DefId, LocalDefId};
+use rustc_span::def_id::LocalDefId;
 use rustc_span::{sym, Span};
 
 declare_clippy_lint! {
@@ -62,29 +62,13 @@ declare_clippy_lint! {
     "manual implementations of the non-exhaustive pattern can be simplified using #[non_exhaustive]"
 }
 
-#[expect(clippy::module_name_repetitions)]
-pub struct ManualNonExhaustiveStruct {
+pub struct ManualNonExhaustive {
     msrv: Msrv,
-}
-
-impl ManualNonExhaustiveStruct {
-    pub fn new(conf: &'static Conf) -> Self {
-        Self {
-            msrv: conf.msrv.clone(),
-        }
-    }
-}
-
-impl_lint_pass!(ManualNonExhaustiveStruct => [MANUAL_NON_EXHAUSTIVE]);
-
-#[expect(clippy::module_name_repetitions)]
-pub struct ManualNonExhaustiveEnum {
-    msrv: Msrv,
-    constructed_enum_variants: FxHashSet<(DefId, DefId)>,
+    constructed_enum_variants: FxHashSet<LocalDefId>,
     potential_enums: Vec<(LocalDefId, LocalDefId, Span, Span)>,
 }
 
-impl ManualNonExhaustiveEnum {
+impl ManualNonExhaustive {
     pub fn new(conf: &'static Conf) -> Self {
         Self {
             msrv: conf.msrv.clone(),
@@ -94,96 +78,78 @@ impl ManualNonExhaustiveEnum {
     }
 }
 
-impl_lint_pass!(ManualNonExhaustiveEnum => [MANUAL_NON_EXHAUSTIVE]);
-
-impl EarlyLintPass for ManualNonExhaustiveStruct {
-    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
-        if let ast::ItemKind::Struct(variant_data, _) = &item.kind
-            && let (fields, delimiter) = match variant_data {
-                ast::VariantData::Struct { fields, .. } => (&**fields, '{'),
-                ast::VariantData::Tuple(fields, _) => (&**fields, '('),
-                ast::VariantData::Unit(_) => return,
-            }
-            && fields.len() > 1
-            && self.msrv.meets(msrvs::NON_EXHAUSTIVE)
-        {
-            let mut iter = fields.iter().filter_map(|f| match f.vis.kind {
-                VisibilityKind::Public => None,
-                VisibilityKind::Inherited => Some(Ok(f)),
-                VisibilityKind::Restricted { .. } => Some(Err(())),
-            });
-            if let Some(Ok(field)) = iter.next()
-                && iter.next().is_none()
-                && field.ty.kind.is_unit()
-            {
-                span_lint_and_then(
-                    cx,
-                    MANUAL_NON_EXHAUSTIVE,
-                    item.span,
-                    "this seems like a manual implementation of the non-exhaustive pattern",
-                    |diag| {
-                        if !item.attrs.iter().any(|attr| attr.has_name(sym::non_exhaustive))
-                            && let header_span = cx.sess().source_map().span_until_char(item.span, delimiter)
-                            && let Some(snippet) = header_span.get_source_text(cx)
-                        {
-                            diag.span_suggestion(
-                                header_span,
-                                "add the attribute",
-                                format!("#[non_exhaustive] {snippet}"),
-                                Applicability::Unspecified,
-                            );
-                        }
-                        diag.span_help(field.span, "remove this field");
-                    },
-                );
-            }
-        }
-    }
+impl_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]);
 
-    extract_msrv_attr!(EarlyContext);
-}
-
-impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum {
-    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
-        if !self.msrv.meets(msrvs::NON_EXHAUSTIVE) {
+impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
+        if !self.msrv.meets(msrvs::NON_EXHAUSTIVE) || !cx.effective_visibilities.is_exported(item.owner_id.def_id) {
             return;
         }
 
-        if let hir::ItemKind::Enum(def, _) = &item.kind
-            && def.variants.len() > 1
-        {
-            let mut iter = def.variants.iter().filter_map(|v| {
-                (matches!(v.data, hir::VariantData::Unit(_, _))
-                    && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id))
-                    && !attr::contains_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive))
-                .then_some((v.def_id, v.span))
-            });
-            if let Some((id, span)) = iter.next()
-                && iter.next().is_none()
-            {
-                self.potential_enums.push((item.owner_id.def_id, id, item.span, span));
-            }
+        match item.kind {
+            ItemKind::Enum(def, _) if def.variants.len() > 1 => {
+                let iter = def.variants.iter().filter_map(|v| {
+                    (matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id)))
+                        .then_some((v.def_id, v.span))
+                });
+                if let Ok((id, span)) = iter.exactly_one()
+                    && !attr::contains_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive)
+                {
+                    self.potential_enums.push((item.owner_id.def_id, id, item.span, span));
+                }
+            },
+            ItemKind::Struct(variant_data, _) => {
+                let fields = variant_data.fields();
+                let private_fields = fields
+                    .iter()
+                    .filter(|field| !cx.effective_visibilities.is_exported(field.def_id));
+                if fields.len() > 1
+                    && let Ok(field) = private_fields.exactly_one()
+                    && let TyKind::Tup([]) = field.ty.kind
+                {
+                    span_lint_and_then(
+                        cx,
+                        MANUAL_NON_EXHAUSTIVE,
+                        item.span,
+                        "this seems like a manual implementation of the non-exhaustive pattern",
+                        |diag| {
+                            if let Some(non_exhaustive) =
+                                attr::find_by_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive)
+                            {
+                                diag.span_note(non_exhaustive.span, "the struct is already non-exhaustive");
+                            } else {
+                                let indent = snippet_indent(cx, item.span).unwrap_or_default();
+                                diag.span_suggestion_verbose(
+                                    item.span.shrink_to_lo(),
+                                    "use the `#[non_exhaustive]` attribute instead",
+                                    format!("#[non_exhaustive]\n{indent}"),
+                                    Applicability::MaybeIncorrect,
+                                );
+                            }
+                            diag.span_help(field.span, "remove this field");
+                        },
+                    );
+                }
+            },
+            _ => {},
         }
     }
 
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         if let ExprKind::Path(QPath::Resolved(None, p)) = &e.kind
-            && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = p.res
+            && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), ctor_id) = p.res
+            && let Some(local_ctor) = ctor_id.as_local()
         {
-            let variant_id = cx.tcx.parent(id);
-            let enum_id = cx.tcx.parent(variant_id);
-
-            self.constructed_enum_variants.insert((enum_id, variant_id));
+            let variant_id = cx.tcx.local_parent(local_ctor);
+            self.constructed_enum_variants.insert(variant_id);
         }
     }
 
     fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
-        for &(enum_id, _, enum_span, variant_span) in
-            self.potential_enums.iter().filter(|&&(enum_id, variant_id, _, _)| {
-                !self
-                    .constructed_enum_variants
-                    .contains(&(enum_id.to_def_id(), variant_id.to_def_id()))
-            })
+        for &(enum_id, _, enum_span, variant_span) in self
+            .potential_enums
+            .iter()
+            .filter(|(_, variant_id, _, _)| !self.constructed_enum_variants.contains(variant_id))
         {
             let hir_id = cx.tcx.local_def_id_to_hir_id(enum_id);
             span_lint_hir_and_then(
@@ -193,15 +159,13 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum {
                 enum_span,
                 "this seems like a manual implementation of the non-exhaustive pattern",
                 |diag| {
-                    let header_span = cx.sess().source_map().span_until_char(enum_span, '{');
-                    if let Some(snippet) = header_span.get_source_text(cx) {
-                        diag.span_suggestion(
-                            header_span,
-                            "add the attribute",
-                            format!("#[non_exhaustive] {snippet}"),
-                            Applicability::Unspecified,
-                        );
-                    }
+                    let indent = snippet_indent(cx, enum_span).unwrap_or_default();
+                    diag.span_suggestion_verbose(
+                        enum_span.shrink_to_lo(),
+                        "use the `#[non_exhaustive]` attribute instead",
+                        format!("#[non_exhaustive]\n{indent}"),
+                        Applicability::MaybeIncorrect,
+                    );
                     diag.span_help(variant_span, "remove this variant");
                 },
             );
diff --git a/tests/ui/manual_non_exhaustive_enum.rs b/tests/ui/manual_non_exhaustive_enum.rs
index 31c3cc8013722..ffe2bb9246737 100644
--- a/tests/ui/manual_non_exhaustive_enum.rs
+++ b/tests/ui/manual_non_exhaustive_enum.rs
@@ -1,8 +1,8 @@
 #![warn(clippy::manual_non_exhaustive)]
 #![allow(unused)]
 //@no-rustfix
-enum E {
-    //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern
+pub enum E {
+    //~^ manual_non_exhaustive
     A,
     B,
     #[doc(hidden)]
@@ -11,7 +11,7 @@ enum E {
 
 // if the user explicitly marks as nonexhaustive we shouldn't warn them
 #[non_exhaustive]
-enum Ep {
+pub enum Ep {
     A,
     B,
     #[doc(hidden)]
@@ -19,14 +19,14 @@ enum Ep {
 }
 
 // marker variant does not have doc hidden attribute, should be ignored
-enum NoDocHidden {
+pub enum NoDocHidden {
     A,
     B,
     _C,
 }
 
 // name of variant with doc hidden does not start with underscore
-enum NoUnderscore {
+pub enum NoUnderscore {
     A,
     B,
     #[doc(hidden)]
@@ -34,7 +34,7 @@ enum NoUnderscore {
 }
 
 // variant with doc hidden is not unit, should be ignored
-enum NotUnit {
+pub enum NotUnit {
     A,
     B,
     #[doc(hidden)]
@@ -42,13 +42,13 @@ enum NotUnit {
 }
 
 // variant with doc hidden is the only one, should be ignored
-enum OnlyMarker {
+pub enum OnlyMarker {
     #[doc(hidden)]
     _A,
 }
 
 // variant with multiple markers, should be ignored
-enum MultipleMarkers {
+pub enum MultipleMarkers {
     A,
     #[doc(hidden)]
     _B,
@@ -58,13 +58,13 @@ enum MultipleMarkers {
 
 // already non_exhaustive and no markers, should be ignored
 #[non_exhaustive]
-enum NonExhaustive {
+pub enum NonExhaustive {
     A,
     B,
 }
 
 // marked is used, don't lint
-enum UsedHidden {
+pub enum UsedHidden {
     #[doc(hidden)]
     _A,
     B,
@@ -77,11 +77,9 @@ fn foo(x: &mut UsedHidden) {
 }
 
 #[expect(clippy::manual_non_exhaustive)]
-enum ExpectLint {
+pub enum ExpectLint {
     A,
     B,
     #[doc(hidden)]
     _C,
 }
-
-fn main() {}
diff --git a/tests/ui/manual_non_exhaustive_enum.stderr b/tests/ui/manual_non_exhaustive_enum.stderr
index dc669568dd2d4..0a9ac157f8502 100644
--- a/tests/ui/manual_non_exhaustive_enum.stderr
+++ b/tests/ui/manual_non_exhaustive_enum.stderr
@@ -1,11 +1,7 @@
 error: this seems like a manual implementation of the non-exhaustive pattern
   --> tests/ui/manual_non_exhaustive_enum.rs:4:1
    |
-LL |   enum E {
-   |   ^-----
-   |   |
-   |  _help: add the attribute: `#[non_exhaustive] enum E`
-   | |
+LL | / pub enum E {
 LL | |
 LL | |     A,
 LL | |     B,
@@ -21,15 +17,16 @@ LL |     _C,
    |     ^^
    = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::manual_non_exhaustive)]`
+help: use the `#[non_exhaustive]` attribute instead
+   |
+LL + #[non_exhaustive]
+LL | pub enum E {
+   |
 
 error: this seems like a manual implementation of the non-exhaustive pattern
   --> tests/ui/manual_non_exhaustive_enum.rs:29:1
    |
-LL |   enum NoUnderscore {
-   |   ^----------------
-   |   |
-   |  _help: add the attribute: `#[non_exhaustive] enum NoUnderscore`
-   | |
+LL | / pub enum NoUnderscore {
 LL | |     A,
 LL | |     B,
 LL | |     #[doc(hidden)]
@@ -42,6 +39,11 @@ help: remove this variant
    |
 LL |     C,
    |     ^
+help: use the `#[non_exhaustive]` attribute instead
+   |
+LL + #[non_exhaustive]
+LL | pub enum NoUnderscore {
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/manual_non_exhaustive_struct.rs b/tests/ui/manual_non_exhaustive_struct.rs
index 4b2803ccc4a79..31dd50281fa1d 100644
--- a/tests/ui/manual_non_exhaustive_struct.rs
+++ b/tests/ui/manual_non_exhaustive_struct.rs
@@ -1,9 +1,9 @@
 #![warn(clippy::manual_non_exhaustive)]
 #![allow(unused)]
 //@no-rustfix
-mod structs {
-    struct S {
-        //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern
+pub mod structs {
+    pub struct S {
+        //~^ manual_non_exhaustive
         pub a: i32,
         pub b: i32,
         _c: (),
@@ -11,68 +11,76 @@ mod structs {
 
     // user forgot to remove the private field
     #[non_exhaustive]
-    struct Sp {
-        //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern
+    pub struct Sp {
+        //~^ manual_non_exhaustive
         pub a: i32,
         pub b: i32,
         _c: (),
     }
 
     // some other fields are private, should be ignored
-    struct PrivateFields {
+    pub struct PrivateFields {
         a: i32,
         pub b: i32,
         _c: (),
     }
 
-    // private field name does not start with underscore, should be ignored
-    struct NoUnderscore {
+    pub struct NoUnderscore {
+        //~^ manual_non_exhaustive
         pub a: i32,
         pub b: i32,
         c: (),
     }
 
     // private field is not unit type, should be ignored
-    struct NotUnit {
+    pub struct NotUnit {
         pub a: i32,
         pub b: i32,
         _c: i32,
     }
 
     // private field is the only field, should be ignored
-    struct OnlyMarker {
+    pub struct OnlyMarker {
         _a: (),
     }
 
     // already non exhaustive and no private fields, should be ignored
     #[non_exhaustive]
-    struct NonExhaustive {
+    pub struct NonExhaustive {
         pub a: i32,
         pub b: i32,
     }
 }
 
-mod tuple_structs {
-    struct T(pub i32, pub i32, ());
-    //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern
+pub mod tuple_structs {
+    pub struct T(pub i32, pub i32, ());
+    //~^ manual_non_exhaustive
 
     // user forgot to remove the private field
     #[non_exhaustive]
-    struct Tp(pub i32, pub i32, ());
-    //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern
+    pub struct Tp(pub i32, pub i32, ());
+    //~^ manual_non_exhaustive
 
     // some other fields are private, should be ignored
-    struct PrivateFields(pub i32, i32, ());
+    pub struct PrivateFields(pub i32, i32, ());
 
     // private field is not unit type, should be ignored
-    struct NotUnit(pub i32, pub i32, i32);
+    pub struct NotUnit(pub i32, pub i32, i32);
 
     // private field is the only field, should be ignored
-    struct OnlyMarker(());
+    pub struct OnlyMarker(());
 
     // already non exhaustive and no private fields, should be ignored
     #[non_exhaustive]
-    struct NonExhaustive(pub i32, pub i32);
+    pub struct NonExhaustive(pub i32, pub i32);
 }
 
-fn main() {}
+mod private {
+    // Don't lint structs that are not actually public as `#[non_exhaustive]` only applies to
+    // external crates. The manual pattern can still be used to get module local non exhaustiveness
+    pub struct NotPublic {
+        pub a: i32,
+        pub b: i32,
+        _c: (),
+    }
+}
diff --git a/tests/ui/manual_non_exhaustive_struct.stderr b/tests/ui/manual_non_exhaustive_struct.stderr
index 1cab812988a34..81de1e4f27190 100644
--- a/tests/ui/manual_non_exhaustive_struct.stderr
+++ b/tests/ui/manual_non_exhaustive_struct.stderr
@@ -1,11 +1,7 @@
 error: this seems like a manual implementation of the non-exhaustive pattern
   --> tests/ui/manual_non_exhaustive_struct.rs:5:5
    |
-LL |       struct S {
-   |       ^-------
-   |       |
-   |  _____help: add the attribute: `#[non_exhaustive] struct S`
-   | |
+LL | /     pub struct S {
 LL | |
 LL | |         pub a: i32,
 LL | |         pub b: i32,
@@ -20,11 +16,16 @@ LL |         _c: (),
    |         ^^^^^^
    = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::manual_non_exhaustive)]`
+help: use the `#[non_exhaustive]` attribute instead
+   |
+LL ~     #[non_exhaustive]
+LL ~     pub struct S {
+   |
 
 error: this seems like a manual implementation of the non-exhaustive pattern
   --> tests/ui/manual_non_exhaustive_struct.rs:14:5
    |
-LL | /     struct Sp {
+LL | /     pub struct Sp {
 LL | |
 LL | |         pub a: i32,
 LL | |         pub b: i32,
@@ -32,6 +33,11 @@ LL | |         _c: (),
 LL | |     }
    | |_____^
    |
+note: the struct is already non-exhaustive
+  --> tests/ui/manual_non_exhaustive_struct.rs:13:5
+   |
+LL |     #[non_exhaustive]
+   |     ^^^^^^^^^^^^^^^^^
 help: remove this field
   --> tests/ui/manual_non_exhaustive_struct.rs:18:9
    |
@@ -39,13 +45,10 @@ LL |         _c: (),
    |         ^^^^^^
 
 error: this seems like a manual implementation of the non-exhaustive pattern
-  --> tests/ui/manual_non_exhaustive_struct.rs:29:5
+  --> tests/ui/manual_non_exhaustive_struct.rs:28:5
    |
-LL |       struct NoUnderscore {
-   |       ^------------------
-   |       |
-   |  _____help: add the attribute: `#[non_exhaustive] struct NoUnderscore`
-   | |
+LL | /     pub struct NoUnderscore {
+LL | |
 LL | |         pub a: i32,
 LL | |         pub b: i32,
 LL | |         c: (),
@@ -57,32 +60,45 @@ help: remove this field
    |
 LL |         c: (),
    |         ^^^^^
+help: use the `#[non_exhaustive]` attribute instead
+   |
+LL ~     #[non_exhaustive]
+LL ~     pub struct NoUnderscore {
+   |
 
 error: this seems like a manual implementation of the non-exhaustive pattern
   --> tests/ui/manual_non_exhaustive_struct.rs:56:5
    |
-LL |     struct T(pub i32, pub i32, ());
-   |     --------^^^^^^^^^^^^^^^^^^^^^^^
-   |     |
-   |     help: add the attribute: `#[non_exhaustive] struct T`
+LL |     pub struct T(pub i32, pub i32, ());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: remove this field
-  --> tests/ui/manual_non_exhaustive_struct.rs:56:32
+  --> tests/ui/manual_non_exhaustive_struct.rs:56:36
+   |
+LL |     pub struct T(pub i32, pub i32, ());
+   |                                    ^^
+help: use the `#[non_exhaustive]` attribute instead
+   |
+LL ~     #[non_exhaustive]
+LL ~     pub struct T(pub i32, pub i32, ());
    |
-LL |     struct T(pub i32, pub i32, ());
-   |                                ^^
 
 error: this seems like a manual implementation of the non-exhaustive pattern
   --> tests/ui/manual_non_exhaustive_struct.rs:61:5
    |
-LL |     struct Tp(pub i32, pub i32, ());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     pub struct Tp(pub i32, pub i32, ());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the struct is already non-exhaustive
+  --> tests/ui/manual_non_exhaustive_struct.rs:60:5
    |
+LL |     #[non_exhaustive]
+   |     ^^^^^^^^^^^^^^^^^
 help: remove this field
-  --> tests/ui/manual_non_exhaustive_struct.rs:61:33
+  --> tests/ui/manual_non_exhaustive_struct.rs:61:37
    |
-LL |     struct Tp(pub i32, pub i32, ());
-   |                                 ^^
+LL |     pub struct Tp(pub i32, pub i32, ());
+   |                                     ^^
 
 error: aborting due to 5 previous errors
 

From 40fca8f7a8131129b75694109138891e607baab0 Mon Sep 17 00:00:00 2001
From: Philipp Krones <hello@philkrones.com>
Date: Thu, 5 Sep 2024 17:00:55 +0200
Subject: [PATCH 036/114] Bump Clippy version -> 0.1.83

---
 Cargo.toml                     | 2 +-
 clippy_config/Cargo.toml       | 2 +-
 clippy_lints/Cargo.toml        | 2 +-
 clippy_utils/Cargo.toml        | 2 +-
 declare_clippy_lint/Cargo.toml | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index b48b881097f47..5b62e387ac631 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy"
-version = "0.1.82"
+version = "0.1.83"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml
index 5c4e0761dbca7..9da7112345de9 100644
--- a/clippy_config/Cargo.toml
+++ b/clippy_config/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_config"
-version = "0.1.82"
+version = "0.1.83"
 edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml
index fbd4566da58c7..d1188940b46a8 100644
--- a/clippy_lints/Cargo.toml
+++ b/clippy_lints/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_lints"
-version = "0.1.82"
+version = "0.1.83"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml
index 629ce9d04d432..fe30b10c435ed 100644
--- a/clippy_utils/Cargo.toml
+++ b/clippy_utils/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_utils"
-version = "0.1.82"
+version = "0.1.83"
 edition = "2021"
 publish = false
 
diff --git a/declare_clippy_lint/Cargo.toml b/declare_clippy_lint/Cargo.toml
index 31270241b0b2e..67a1f7cc72c54 100644
--- a/declare_clippy_lint/Cargo.toml
+++ b/declare_clippy_lint/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "declare_clippy_lint"
-version = "0.1.82"
+version = "0.1.83"
 edition = "2021"
 publish = false
 

From 3d027d75aff29983cb95da07352bcb8a55487400 Mon Sep 17 00:00:00 2001
From: Philipp Krones <hello@philkrones.com>
Date: Thu, 5 Sep 2024 17:01:08 +0200
Subject: [PATCH 037/114] Bump nightly version -> 2024-09-05

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

diff --git a/rust-toolchain b/rust-toolchain
index 0be2e81810ebe..854fcda2dabda 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,4 +1,4 @@
 [toolchain]
-channel = "nightly-2024-08-23"
+channel = "nightly-2024-09-05"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
 profile = "minimal"

From 79081f1271222d4ea12c923d949fc4f1aece2362 Mon Sep 17 00:00:00 2001
From: Kevin Reid <kpreid@switchb.org>
Date: Thu, 5 Sep 2024 14:30:27 -0700
Subject: [PATCH 038/114] Correct version of `too_long_first_doc_paragraph`

`too_long_first_doc_paragraph` is, empirically, not in the Rust 1.81.0 release.
---
 clippy_lints/src/doc/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs
index 6db63b59e020e..f2c87f0fd70b3 100644
--- a/clippy_lints/src/doc/mod.rs
+++ b/clippy_lints/src/doc/mod.rs
@@ -450,7 +450,7 @@ declare_clippy_lint! {
     /// /// and probably spanning a many rows.
     /// struct Foo {}
     /// ```
-    #[clippy::version = "1.81.0"]
+    #[clippy::version = "1.82.0"]
     pub TOO_LONG_FIRST_DOC_PARAGRAPH,
     style,
     "ensure that the first line of a documentation paragraph isn't too long"

From 0b8cb4a1ebdf3bb9b03f7befe48b3d5e36ba080b Mon Sep 17 00:00:00 2001
From: Pavel Grigorenko <GrigorenkoPV@ya.ru>
Date: Thu, 5 Sep 2024 00:34:04 +0300
Subject: [PATCH 039/114] Make `Ty::boxed_ty` return an `Option`

---
 clippy_lints/src/escape.rs                  | 6 +++---
 clippy_lints/src/methods/mod.rs             | 4 ++--
 clippy_lints/src/methods/utils.rs           | 4 ++--
 clippy_lints/src/unnecessary_box_returns.rs | 6 ++----
 clippy_utils/src/ty.rs                      | 4 ++--
 5 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs
index a5da52b0be50a..803606979410b 100644
--- a/clippy_lints/src/escape.rs
+++ b/clippy_lints/src/escape.rs
@@ -50,7 +50,7 @@ declare_clippy_lint! {
 }
 
 fn is_non_trait_box(ty: Ty<'_>) -> bool {
-    ty.is_box() && !ty.boxed_ty().is_trait()
+    ty.boxed_ty().is_some_and(|boxed| !boxed.is_trait())
 }
 
 struct EscapeDelegate<'a, 'tcx> {
@@ -191,8 +191,8 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
 impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {
     fn is_large_box(&self, ty: Ty<'tcx>) -> bool {
         // Large types need to be boxed to avoid stack overflows.
-        if ty.is_box() {
-            self.cx.layout_of(ty.boxed_ty()).map_or(0, |l| l.size.bytes()) > self.too_large_for_stack
+        if let Some(boxed_ty) = ty.boxed_ty() {
+            self.cx.layout_of(boxed_ty).map_or(0, |l| l.size.bytes()) > self.too_large_for_stack
         } else {
             false
         }
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index d7126990edb1d..f61bb3a6bf481 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -5187,8 +5187,8 @@ impl SelfKind {
         fn matches_value<'a>(cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
             if ty == parent_ty {
                 true
-            } else if ty.is_box() {
-                ty.boxed_ty() == parent_ty
+            } else if let Some(boxed_ty) = ty.boxed_ty() {
+                boxed_ty == parent_ty
             } else if is_type_diagnostic_item(cx, ty, sym::Rc) || is_type_diagnostic_item(cx, ty, sym::Arc) {
                 if let ty::Adt(_, args) = ty.kind() {
                     args.types().next().map_or(false, |t| t == parent_ty)
diff --git a/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs
index 0d2b0a3131763..fe860e5ae2601 100644
--- a/clippy_lints/src/methods/utils.rs
+++ b/clippy_lints/src/methods/utils.rs
@@ -16,7 +16,7 @@ pub(super) fn derefs_to_slice<'tcx>(
     fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool {
         match ty.kind() {
             ty::Slice(_) => true,
-            ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()),
+            ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => may_slice(cx, boxed),
             ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::Vec),
             ty::Array(_, size) => size.try_eval_target_usize(cx.tcx, cx.param_env).is_some(),
             ty::Ref(_, inner, _) => may_slice(cx, *inner),
@@ -33,7 +33,7 @@ pub(super) fn derefs_to_slice<'tcx>(
     } else {
         match ty.kind() {
             ty::Slice(_) => Some(expr),
-            ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => Some(expr),
+            _ if ty.boxed_ty().is_some_and(|boxed| may_slice(cx, boxed)) => Some(expr),
             ty::Ref(_, inner, _) => {
                 if may_slice(cx, *inner) {
                     Some(expr)
diff --git a/clippy_lints/src/unnecessary_box_returns.rs b/clippy_lints/src/unnecessary_box_returns.rs
index 3f130bf5a6731..14f4aa6676b65 100644
--- a/clippy_lints/src/unnecessary_box_returns.rs
+++ b/clippy_lints/src/unnecessary_box_returns.rs
@@ -75,11 +75,9 @@ impl UnnecessaryBoxReturns {
             .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(def_id).skip_binder())
             .output();
 
-        if !return_ty.is_box() {
+        let Some(boxed_ty) = return_ty.boxed_ty() else {
             return;
-        }
-
-        let boxed_ty = return_ty.boxed_ty();
+        };
 
         // It's sometimes useful to return Box<T> if T is unsized, so don't lint those.
         // Also, don't lint if we know that T is very large, in which case returning
diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs
index f80981c11af65..585134209ca3a 100644
--- a/clippy_utils/src/ty.rs
+++ b/clippy_utils/src/ty.rs
@@ -704,8 +704,8 @@ pub fn expr_sig<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option<ExprFnS
 
 /// If the type is function like, get the signature for it.
 pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'tcx>> {
-    if ty.is_box() {
-        return ty_sig(cx, ty.boxed_ty());
+    if let Some(boxed_ty) = ty.boxed_ty() {
+        return ty_sig(cx, boxed_ty);
     }
     match *ty.kind() {
         ty::Closure(id, subs) => {

From 9415e6e6eb9a570acecebd3dda0ed2b5db9fb910 Mon Sep 17 00:00:00 2001
From: Artem Belyakov <artm.belyakov@gmail.com>
Date: Sat, 27 Jul 2024 13:33:08 +0300
Subject: [PATCH 040/114] Add `manual_div_ceil`

---
 CHANGELOG.md                                 |   1 +
 clippy_config/src/conf.rs                    |   2 +-
 clippy_config/src/msrvs.rs                   |   1 +
 clippy_lints/src/declared_lints.rs           |   1 +
 clippy_lints/src/lib.rs                      |   2 +
 clippy_lints/src/manual_div_ceil.rs          | 158 +++++++++++++++++++
 tests/ui/manual_div_ceil.fixed               |  30 ++++
 tests/ui/manual_div_ceil.rs                  |  30 ++++
 tests/ui/manual_div_ceil.stderr              |  35 ++++
 tests/ui/manual_div_ceil_with_feature.fixed  |  25 +++
 tests/ui/manual_div_ceil_with_feature.rs     |  25 +++
 tests/ui/manual_div_ceil_with_feature.stderr |  47 ++++++
 12 files changed, 356 insertions(+), 1 deletion(-)
 create mode 100644 clippy_lints/src/manual_div_ceil.rs
 create mode 100644 tests/ui/manual_div_ceil.fixed
 create mode 100644 tests/ui/manual_div_ceil.rs
 create mode 100644 tests/ui/manual_div_ceil.stderr
 create mode 100644 tests/ui/manual_div_ceil_with_feature.fixed
 create mode 100644 tests/ui/manual_div_ceil_with_feature.rs
 create mode 100644 tests/ui/manual_div_ceil_with_feature.stderr

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 31fc74192ab11..44a569d1ab54a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5614,6 +5614,7 @@ Released 2018-09-13
 [`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
+[`manual_div_ceil`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_div_ceil
 [`manual_filter`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter
 [`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map
 [`manual_find`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find
diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs
index a6f1b958bfb17..6c1dd232593a1 100644
--- a/clippy_config/src/conf.rs
+++ b/clippy_config/src/conf.rs
@@ -864,7 +864,7 @@ fn calculate_dimensions(fields: &[&str]) -> (usize, Vec<usize>) {
             cmp::max(1, terminal_width / (SEPARATOR_WIDTH + max_field_width))
         });
 
-    let rows = (fields.len() + (columns - 1)) / columns;
+    let rows = fields.len().div_ceil(columns);
 
     let column_widths = (0..columns)
         .map(|column| {
diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs
index 0c673ba8046e6..a70effd637699 100644
--- a/clippy_config/src/msrvs.rs
+++ b/clippy_config/src/msrvs.rs
@@ -21,6 +21,7 @@ msrv_aliases! {
     1,80,0 { BOX_INTO_ITER}
     1,77,0 { C_STR_LITERALS }
     1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT }
+    1,73,0 { MANUAL_DIV_CEIL }
     1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE }
     1,70,0 { OPTION_RESULT_IS_VARIANT_AND, BINARY_HEAP_RETAIN }
     1,68,0 { PATH_MAIN_SEPARATOR_STR }
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index e478ab330e8bc..4804399ef7da1 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -301,6 +301,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::manual_async_fn::MANUAL_ASYNC_FN_INFO,
     crate::manual_bits::MANUAL_BITS_INFO,
     crate::manual_clamp::MANUAL_CLAMP_INFO,
+    crate::manual_div_ceil::MANUAL_DIV_CEIL_INFO,
     crate::manual_float_methods::MANUAL_IS_FINITE_INFO,
     crate::manual_float_methods::MANUAL_IS_INFINITE_INFO,
     crate::manual_hash_one::MANUAL_HASH_ONE_INFO,
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index a9d5f82dfd2cf..9514ba8c315db 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -203,6 +203,7 @@ mod manual_assert;
 mod manual_async_fn;
 mod manual_bits;
 mod manual_clamp;
+mod manual_div_ceil;
 mod manual_float_methods;
 mod manual_hash_one;
 mod manual_is_ascii_check;
@@ -936,5 +937,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_early_pass(|| Box::new(cfg_not_test::CfgNotTest));
     store.register_late_pass(|_| Box::new(zombie_processes::ZombieProcesses));
     store.register_late_pass(|_| Box::new(pointers_in_nomem_asm_block::PointersInNomemAsmBlock));
+    store.register_late_pass(move |_| Box::new(manual_div_ceil::ManualDivCeil::new(conf)));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
diff --git a/clippy_lints/src/manual_div_ceil.rs b/clippy_lints/src/manual_div_ceil.rs
new file mode 100644
index 0000000000000..024c2547dc6eb
--- /dev/null
+++ b/clippy_lints/src/manual_div_ceil.rs
@@ -0,0 +1,158 @@
+use clippy_config::msrvs::{self, Msrv};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::sugg::Sugg;
+use clippy_utils::SpanlessEq;
+use rustc_ast::{BinOpKind, LitKind};
+use rustc_data_structures::packed::Pu128;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{self};
+use rustc_session::impl_lint_pass;
+use rustc_span::symbol::Symbol;
+
+use clippy_config::Conf;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for an expression like `(x + (y - 1)) / y` which is a common manual reimplementation
+    /// of `x.div_ceil(y)`.
+    ///
+    /// ### Why is this bad?
+    /// It's simpler, clearer and more readable.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// let x: i32 = 7;
+    /// let y: i32 = 4;
+    /// let div = (x + (y - 1)) / y;
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// #![feature(int_roundings)]
+    /// let x: i32 = 7;
+    /// let y: i32 = 4;
+    /// let div = x.div_ceil(y);
+    /// ```
+    #[clippy::version = "1.81.0"]
+    pub MANUAL_DIV_CEIL,
+    complexity,
+    "manually reimplementing `div_ceil`"
+}
+
+pub struct ManualDivCeil {
+    msrv: Msrv,
+}
+
+impl ManualDivCeil {
+    #[must_use]
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
+    }
+}
+
+impl_lint_pass!(ManualDivCeil => [MANUAL_DIV_CEIL]);
+
+impl<'tcx> LateLintPass<'tcx> for ManualDivCeil {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
+        if !self.msrv.meets(msrvs::MANUAL_DIV_CEIL) {
+            return;
+        }
+
+        let mut applicability = Applicability::MachineApplicable;
+
+        if let ExprKind::Binary(div_op, div_lhs, div_rhs) = expr.kind
+            && div_op.node == BinOpKind::Div
+            && check_int_ty_and_feature(cx, div_lhs)
+            && check_int_ty_and_feature(cx, div_rhs)
+            && let ExprKind::Binary(inner_op, inner_lhs, inner_rhs) = div_lhs.kind
+        {
+            // (x + (y - 1)) / y
+            if let ExprKind::Binary(sub_op, sub_lhs, sub_rhs) = inner_rhs.kind
+                && inner_op.node == BinOpKind::Add
+                && sub_op.node == BinOpKind::Sub
+                && check_literal(sub_rhs)
+                && check_eq_expr(cx, sub_lhs, div_rhs)
+            {
+                build_suggestion(cx, expr, inner_lhs, div_rhs, &mut applicability);
+                return;
+            }
+
+            // ((y - 1) + x) / y
+            if let ExprKind::Binary(sub_op, sub_lhs, sub_rhs) = inner_lhs.kind
+                && inner_op.node == BinOpKind::Add
+                && sub_op.node == BinOpKind::Sub
+                && check_literal(sub_rhs)
+                && check_eq_expr(cx, sub_lhs, div_rhs)
+            {
+                build_suggestion(cx, expr, inner_rhs, div_rhs, &mut applicability);
+                return;
+            }
+
+            // (x + y - 1) / y
+            if let ExprKind::Binary(add_op, add_lhs, add_rhs) = inner_lhs.kind
+                && inner_op.node == BinOpKind::Sub
+                && add_op.node == BinOpKind::Add
+                && check_literal(inner_rhs)
+                && check_eq_expr(cx, add_rhs, div_rhs)
+            {
+                build_suggestion(cx, expr, add_lhs, div_rhs, &mut applicability);
+            }
+        }
+    }
+
+    extract_msrv_attr!(LateContext);
+}
+
+fn check_int_ty_and_feature(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    let expr_ty = cx.typeck_results().expr_ty(expr);
+    match expr_ty.peel_refs().kind() {
+        ty::Uint(_) => true,
+        ty::Int(_) => cx
+            .tcx
+            .features()
+            .declared_features
+            .contains(&Symbol::intern("int_roundings")),
+
+        _ => false,
+    }
+}
+
+fn check_literal(expr: &Expr<'_>) -> bool {
+    if let ExprKind::Lit(lit) = expr.kind
+        && let LitKind::Int(Pu128(1), _) = lit.node
+    {
+        return true;
+    }
+    false
+}
+
+fn check_eq_expr(cx: &LateContext<'_>, lhs: &Expr<'_>, rhs: &Expr<'_>) -> bool {
+    SpanlessEq::new(cx).eq_expr(lhs, rhs)
+}
+
+fn build_suggestion(
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
+    lhs: &Expr<'_>,
+    rhs: &Expr<'_>,
+    applicability: &mut Applicability,
+) {
+    let dividend_sugg = Sugg::hir_with_applicability(cx, lhs, "..", applicability).maybe_par();
+    let divisor_snippet = snippet_with_applicability(cx, rhs.span.source_callsite(), "..", applicability);
+
+    let sugg = format!("{dividend_sugg}.div_ceil({divisor_snippet})");
+
+    span_lint_and_sugg(
+        cx,
+        MANUAL_DIV_CEIL,
+        expr.span,
+        "manually reimplementing `div_ceil`",
+        "consider using `.div_ceil()`",
+        sugg,
+        *applicability,
+    );
+}
diff --git a/tests/ui/manual_div_ceil.fixed b/tests/ui/manual_div_ceil.fixed
new file mode 100644
index 0000000000000..e7801f7376aaf
--- /dev/null
+++ b/tests/ui/manual_div_ceil.fixed
@@ -0,0 +1,30 @@
+#![warn(clippy::manual_div_ceil)]
+
+fn main() {
+    let x = 7_u32;
+    let y = 4_u32;
+    let z = 11_u32;
+
+    // Lint
+    let _ = x.div_ceil(y); //~ ERROR: manually reimplementing `div_ceil`
+    let _ = x.div_ceil(y); //~ ERROR: manually reimplementing `div_ceil`
+    let _ = x.div_ceil(y); //~ ERROR: manually reimplementing `div_ceil`
+
+    let _ = 7_u32.div_ceil(4); //~ ERROR: manually reimplementing `div_ceil`
+    let _ = (7_i32 as u32).div_ceil(4); //~ ERROR: manually reimplementing `div_ceil`
+
+    // No lint
+    let _ = (x + (y - 2)) / y;
+    let _ = (x + (y + 1)) / y;
+
+    let _ = (x + (y - 1)) / z;
+
+    let x_i = 7_i32;
+    let y_i = 4_i32;
+    let z_i = 11_i32;
+
+    // No lint because `int_roundings` feature is not enabled.
+    let _ = (z as i32 + (y_i - 1)) / y_i;
+    let _ = (7_u32 as i32 + (y_i - 1)) / y_i;
+    let _ = (7_u32 as i32 + (4 - 1)) / 4;
+}
diff --git a/tests/ui/manual_div_ceil.rs b/tests/ui/manual_div_ceil.rs
new file mode 100644
index 0000000000000..2de74c7eaa881
--- /dev/null
+++ b/tests/ui/manual_div_ceil.rs
@@ -0,0 +1,30 @@
+#![warn(clippy::manual_div_ceil)]
+
+fn main() {
+    let x = 7_u32;
+    let y = 4_u32;
+    let z = 11_u32;
+
+    // Lint
+    let _ = (x + (y - 1)) / y; //~ ERROR: manually reimplementing `div_ceil`
+    let _ = ((y - 1) + x) / y; //~ ERROR: manually reimplementing `div_ceil`
+    let _ = (x + y - 1) / y; //~ ERROR: manually reimplementing `div_ceil`
+
+    let _ = (7_u32 + (4 - 1)) / 4; //~ ERROR: manually reimplementing `div_ceil`
+    let _ = (7_i32 as u32 + (4 - 1)) / 4; //~ ERROR: manually reimplementing `div_ceil`
+
+    // No lint
+    let _ = (x + (y - 2)) / y;
+    let _ = (x + (y + 1)) / y;
+
+    let _ = (x + (y - 1)) / z;
+
+    let x_i = 7_i32;
+    let y_i = 4_i32;
+    let z_i = 11_i32;
+
+    // No lint because `int_roundings` feature is not enabled.
+    let _ = (z as i32 + (y_i - 1)) / y_i;
+    let _ = (7_u32 as i32 + (y_i - 1)) / y_i;
+    let _ = (7_u32 as i32 + (4 - 1)) / 4;
+}
diff --git a/tests/ui/manual_div_ceil.stderr b/tests/ui/manual_div_ceil.stderr
new file mode 100644
index 0000000000000..dc652dff405f2
--- /dev/null
+++ b/tests/ui/manual_div_ceil.stderr
@@ -0,0 +1,35 @@
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil.rs:9:13
+   |
+LL |     let _ = (x + (y - 1)) / y;
+   |             ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)`
+   |
+   = note: `-D clippy::manual-div-ceil` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::manual_div_ceil)]`
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil.rs:10:13
+   |
+LL |     let _ = ((y - 1) + x) / y;
+   |             ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)`
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil.rs:11:13
+   |
+LL |     let _ = (x + y - 1) / y;
+   |             ^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)`
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil.rs:13:13
+   |
+LL |     let _ = (7_u32 + (4 - 1)) / 4;
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `7_u32.div_ceil(4)`
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil.rs:14:13
+   |
+LL |     let _ = (7_i32 as u32 + (4 - 1)) / 4;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `(7_i32 as u32).div_ceil(4)`
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/manual_div_ceil_with_feature.fixed b/tests/ui/manual_div_ceil_with_feature.fixed
new file mode 100644
index 0000000000000..a1d678c66898c
--- /dev/null
+++ b/tests/ui/manual_div_ceil_with_feature.fixed
@@ -0,0 +1,25 @@
+#![warn(clippy::manual_div_ceil)]
+#![feature(int_roundings)]
+
+fn main() {
+    let x = 7_i32;
+    let y = 4_i32;
+    let z = 3_i32;
+    let z_u: u32 = 11;
+
+    // Lint.
+    let _ = x.div_ceil(y);
+    let _ = x.div_ceil(y);
+    let _ = x.div_ceil(y);
+
+    let _ = 7_i32.div_ceil(4);
+    let _ = (7_i32 as u32).div_ceil(4);
+    let _ = (7_u32 as i32).div_ceil(4);
+    let _ = z_u.div_ceil(4);
+
+    // No lint.
+    let _ = (x + (y - 2)) / y;
+    let _ = (x + (y + 1)) / y;
+
+    let _ = (x + (y - 1)) / z;
+}
diff --git a/tests/ui/manual_div_ceil_with_feature.rs b/tests/ui/manual_div_ceil_with_feature.rs
new file mode 100644
index 0000000000000..58cb1dbe34d1c
--- /dev/null
+++ b/tests/ui/manual_div_ceil_with_feature.rs
@@ -0,0 +1,25 @@
+#![warn(clippy::manual_div_ceil)]
+#![feature(int_roundings)]
+
+fn main() {
+    let x = 7_i32;
+    let y = 4_i32;
+    let z = 3_i32;
+    let z_u: u32 = 11;
+
+    // Lint.
+    let _ = (x + (y - 1)) / y;
+    let _ = ((y - 1) + x) / y;
+    let _ = (x + y - 1) / y;
+
+    let _ = (7_i32 + (4 - 1)) / 4;
+    let _ = (7_i32 as u32 + (4 - 1)) / 4;
+    let _ = (7_u32 as i32 + (4 - 1)) / 4;
+    let _ = (z_u + (4 - 1)) / 4;
+
+    // No lint.
+    let _ = (x + (y - 2)) / y;
+    let _ = (x + (y + 1)) / y;
+
+    let _ = (x + (y - 1)) / z;
+}
diff --git a/tests/ui/manual_div_ceil_with_feature.stderr b/tests/ui/manual_div_ceil_with_feature.stderr
new file mode 100644
index 0000000000000..361ef9bd9f42a
--- /dev/null
+++ b/tests/ui/manual_div_ceil_with_feature.stderr
@@ -0,0 +1,47 @@
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil_with_feature.rs:11:13
+   |
+LL |     let _ = (x + (y - 1)) / y;
+   |             ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)`
+   |
+   = note: `-D clippy::manual-div-ceil` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::manual_div_ceil)]`
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil_with_feature.rs:12:13
+   |
+LL |     let _ = ((y - 1) + x) / y;
+   |             ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)`
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil_with_feature.rs:13:13
+   |
+LL |     let _ = (x + y - 1) / y;
+   |             ^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)`
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil_with_feature.rs:15:13
+   |
+LL |     let _ = (7_i32 + (4 - 1)) / 4;
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `7_i32.div_ceil(4)`
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil_with_feature.rs:16:13
+   |
+LL |     let _ = (7_i32 as u32 + (4 - 1)) / 4;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `(7_i32 as u32).div_ceil(4)`
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil_with_feature.rs:17:13
+   |
+LL |     let _ = (7_u32 as i32 + (4 - 1)) / 4;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `(7_u32 as i32).div_ceil(4)`
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil_with_feature.rs:18:13
+   |
+LL |     let _ = (z_u + (4 - 1)) / 4;
+   |             ^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `z_u.div_ceil(4)`
+
+error: aborting due to 7 previous errors
+

From d7996da9dae165c7d6e700f8b734392db30f9697 Mon Sep 17 00:00:00 2001
From: Sour1emon <isaac.bess@outlook.com>
Date: Sat, 31 Aug 2024 16:30:03 -0700
Subject: [PATCH 041/114] Add `manual_is_power_of_two`

---
 CHANGELOG.md                               |  1 +
 clippy_lints/src/declared_lints.rs         |  1 +
 clippy_lints/src/lib.rs                    |  2 +
 clippy_lints/src/manual_is_power_of_two.rs | 88 ++++++++++++++++++++++
 tests/ui/manual_is_power_of_two.fixed      | 14 ++++
 tests/ui/manual_is_power_of_two.rs         | 14 ++++
 tests/ui/manual_is_power_of_two.stderr     | 17 +++++
 7 files changed, 137 insertions(+)
 create mode 100644 clippy_lints/src/manual_is_power_of_two.rs
 create mode 100644 tests/ui/manual_is_power_of_two.fixed
 create mode 100644 tests/ui/manual_is_power_of_two.rs
 create mode 100644 tests/ui/manual_is_power_of_two.stderr

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 44a569d1ab54a..f1de51c936ea0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5626,6 +5626,7 @@ Released 2018-09-13
 [`manual_is_ascii_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check
 [`manual_is_finite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_finite
 [`manual_is_infinite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_infinite
+[`manual_is_power_of_two`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_power_of_two
 [`manual_is_variant_and`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_variant_and
 [`manual_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else
 [`manual_main_separator_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_main_separator_str
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index 4804399ef7da1..6f468f01b2fde 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -306,6 +306,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::manual_float_methods::MANUAL_IS_INFINITE_INFO,
     crate::manual_hash_one::MANUAL_HASH_ONE_INFO,
     crate::manual_is_ascii_check::MANUAL_IS_ASCII_CHECK_INFO,
+    crate::manual_is_power_of_two::MANUAL_IS_POWER_OF_TWO_INFO,
     crate::manual_let_else::MANUAL_LET_ELSE_INFO,
     crate::manual_main_separator_str::MANUAL_MAIN_SEPARATOR_STR_INFO,
     crate::manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE_INFO,
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 9514ba8c315db..bc16a3b0c014e 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -207,6 +207,7 @@ mod manual_div_ceil;
 mod manual_float_methods;
 mod manual_hash_one;
 mod manual_is_ascii_check;
+mod manual_is_power_of_two;
 mod manual_let_else;
 mod manual_main_separator_str;
 mod manual_non_exhaustive;
@@ -938,5 +939,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(zombie_processes::ZombieProcesses));
     store.register_late_pass(|_| Box::new(pointers_in_nomem_asm_block::PointersInNomemAsmBlock));
     store.register_late_pass(move |_| Box::new(manual_div_ceil::ManualDivCeil::new(conf)));
+    store.register_late_pass(|_| Box::new(manual_is_power_of_two::ManualIsPowerOfTwo));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
diff --git a/clippy_lints/src/manual_is_power_of_two.rs b/clippy_lints/src/manual_is_power_of_two.rs
new file mode 100644
index 0000000000000..a65401fc571aa
--- /dev/null
+++ b/clippy_lints/src/manual_is_power_of_two.rs
@@ -0,0 +1,88 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use rustc_ast::LitKind;
+use rustc_data_structures::packed::Pu128;
+use rustc_errors::Applicability;
+use rustc_hir::{BinOpKind, Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::Uint;
+use rustc_session::declare_lint_pass;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for expressions like `x.count_ones() == 1` or `x & (x - 1) == 0` which are manual
+    /// reimplementations of `x.is_power_of_two()``
+    /// ### Why is this bad?
+    /// It's simpler and clearer
+    /// ### Example
+    /// ```no_run
+    /// let x: u32 = 1;
+    /// let result = x.count_ones() == 1;
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// let x: u32 = 1;
+    /// let result = x.is_power_of_two();
+    /// ```
+    #[clippy::version = "1.82.0"]
+    pub MANUAL_IS_POWER_OF_TWO,
+    complexity,
+    "manually reimplementing `is_power_of_two`"
+}
+
+declare_lint_pass!(ManualIsPowerOfTwo => [MANUAL_IS_POWER_OF_TWO]);
+
+impl LateLintPass<'_> for ManualIsPowerOfTwo {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        let mut applicability = Applicability::MachineApplicable;
+
+        // x.count_ones() == 1
+        if let ExprKind::Binary(op, left, right) = expr.kind
+            && BinOpKind::Eq == op.node
+            && let ExprKind::MethodCall(method_name, reciever, _, _) = left.kind
+            && method_name.ident.as_str() == "count_ones"
+            && let ExprKind::Lit(lit) = right.kind
+            && let LitKind::Int(Pu128(1), _) = lit.node
+            && let &Uint(_) = cx.typeck_results().expr_ty(reciever).kind()
+        {
+            let snippet = snippet_with_applicability(cx, reciever.span, "..", &mut applicability);
+            let sugg = format!("{snippet}.is_power_of_two()");
+            span_lint_and_sugg(
+                cx,
+                MANUAL_IS_POWER_OF_TWO,
+                expr.span,
+                "manually reimplementing `is_power_of_two`",
+                "consider using `.is_power_of_two()`",
+                sugg,
+                applicability,
+            );
+        }
+
+        // x & (x - 1) == 0
+        if let ExprKind::Binary(op, left, right) = expr.kind
+            && BinOpKind::Eq == op.node
+            && let ExprKind::Binary(op1, left1, right1) = left.kind
+            && BinOpKind::BitAnd == op1.node
+            && let ExprKind::Binary(op2, left2, right2) = right1.kind
+            && BinOpKind::Sub == op2.node
+            && left1.span.eq_ctxt(left2.span)
+            && let &Uint(_) = cx.typeck_results().expr_ty(left1).kind()
+            && let ExprKind::Lit(lit) = right2.kind
+            && let LitKind::Int(Pu128(1), _) = lit.node
+            && let ExprKind::Lit(lit1) = right.kind
+            && let LitKind::Int(Pu128(0), _) = lit1.node
+        {
+            let snippet = snippet_with_applicability(cx, left1.span, "..", &mut applicability);
+            let sugg = format!("{snippet}.is_power_of_two()");
+            span_lint_and_sugg(
+                cx,
+                MANUAL_IS_POWER_OF_TWO,
+                expr.span,
+                "manually reimplementing `is_power_of_two`",
+                "consider using `.is_power_of_two()`",
+                sugg,
+                applicability,
+            );
+        }
+    }
+}
diff --git a/tests/ui/manual_is_power_of_two.fixed b/tests/ui/manual_is_power_of_two.fixed
new file mode 100644
index 0000000000000..beee2eaf665a9
--- /dev/null
+++ b/tests/ui/manual_is_power_of_two.fixed
@@ -0,0 +1,14 @@
+#![warn(clippy::manual_is_power_of_two)]
+
+fn main() {
+    let a = 16_u64;
+
+    let _ = a.is_power_of_two();
+    let _ = a.is_power_of_two();
+
+    let b = 4_i64;
+
+    // is_power_of_two only works for unsigned integers
+    let _ = b.count_ones() == 1;
+    let _ = b & (b - 1) == 0;
+}
diff --git a/tests/ui/manual_is_power_of_two.rs b/tests/ui/manual_is_power_of_two.rs
new file mode 100644
index 0000000000000..0810b4c28da75
--- /dev/null
+++ b/tests/ui/manual_is_power_of_two.rs
@@ -0,0 +1,14 @@
+#![warn(clippy::manual_is_power_of_two)]
+
+fn main() {
+    let a = 16_u64;
+
+    let _ = a.count_ones() == 1;
+    let _ = a & (a - 1) == 0;
+
+    let b = 4_i64;
+
+    // is_power_of_two only works for unsigned integers
+    let _ = b.count_ones() == 1;
+    let _ = b & (b - 1) == 0;
+}
diff --git a/tests/ui/manual_is_power_of_two.stderr b/tests/ui/manual_is_power_of_two.stderr
new file mode 100644
index 0000000000000..c7dfe6b11b99e
--- /dev/null
+++ b/tests/ui/manual_is_power_of_two.stderr
@@ -0,0 +1,17 @@
+error: manually reimplementing `is_power_of_two`
+  --> tests/ui/manual_is_power_of_two.rs:6:13
+   |
+LL |     let _ = a.count_ones() == 1;
+   |             ^^^^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
+   |
+   = note: `-D clippy::manual-is-power-of-two` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::manual_is_power_of_two)]`
+
+error: manually reimplementing `is_power_of_two`
+  --> tests/ui/manual_is_power_of_two.rs:7:13
+   |
+LL |     let _ = a & (a - 1) == 0;
+   |             ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
+
+error: aborting due to 2 previous errors
+

From 5515566829f3b7ba3c302c5058e986657c01cc7e Mon Sep 17 00:00:00 2001
From: Isaac Bess <isaac.bess@outlook.com>
Date: Mon, 2 Sep 2024 17:00:32 -0700
Subject: [PATCH 042/114] Improve "Why this is bad" section

Co-authored-by: Ruby Lazuli <general@patchmixolydic.com>
---
 clippy_lints/src/manual_is_power_of_two.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clippy_lints/src/manual_is_power_of_two.rs b/clippy_lints/src/manual_is_power_of_two.rs
index a65401fc571aa..daa1abf61f1a6 100644
--- a/clippy_lints/src/manual_is_power_of_two.rs
+++ b/clippy_lints/src/manual_is_power_of_two.rs
@@ -13,7 +13,7 @@ declare_clippy_lint! {
     /// Checks for expressions like `x.count_ones() == 1` or `x & (x - 1) == 0` which are manual
     /// reimplementations of `x.is_power_of_two()``
     /// ### Why is this bad?
-    /// It's simpler and clearer
+    /// Manual reimplementations of `is_power_of_two` increase code complexity for little benefit.
     /// ### Example
     /// ```no_run
     /// let x: u32 = 1;

From 6ecb48f6d0becb8ff365b787106a8be429b4637a Mon Sep 17 00:00:00 2001
From: Isaac Bess <isaac.bess@outlook.com>
Date: Mon, 2 Sep 2024 17:01:20 -0700
Subject: [PATCH 043/114] Fixed extra backtick

Co-authored-by: Ruby Lazuli <general@patchmixolydic.com>
---
 clippy_lints/src/manual_is_power_of_two.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clippy_lints/src/manual_is_power_of_two.rs b/clippy_lints/src/manual_is_power_of_two.rs
index daa1abf61f1a6..c7ac668267afb 100644
--- a/clippy_lints/src/manual_is_power_of_two.rs
+++ b/clippy_lints/src/manual_is_power_of_two.rs
@@ -10,8 +10,8 @@ use rustc_session::declare_lint_pass;
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for expressions like `x.count_ones() == 1` or `x & (x - 1) == 0` which are manual
-    /// reimplementations of `x.is_power_of_two()``
+    /// Checks for expressions like `x.count_ones() == 1` or `x & (x - 1) == 0`, which are manual
+    /// reimplementations of `x.is_power_of_two()`.
     /// ### Why is this bad?
     /// Manual reimplementations of `is_power_of_two` increase code complexity for little benefit.
     /// ### Example

From f994797e4612f97a0f489e794f30c2113ce8d61e Mon Sep 17 00:00:00 2001
From: Sour1emon <isaac.bess@outlook.com>
Date: Thu, 5 Sep 2024 18:23:00 -0700
Subject: [PATCH 044/114] Add support for different orders of expression

---
 clippy_lints/src/manual_is_power_of_two.rs | 154 ++++++++++++++-------
 tests/ui/manual_is_power_of_two.fixed      |   6 +
 tests/ui/manual_is_power_of_two.rs         |   6 +
 tests/ui/manual_is_power_of_two.stderr     |  26 +++-
 4 files changed, 141 insertions(+), 51 deletions(-)

diff --git a/clippy_lints/src/manual_is_power_of_two.rs b/clippy_lints/src/manual_is_power_of_two.rs
index c7ac668267afb..d7879403ebb5a 100644
--- a/clippy_lints/src/manual_is_power_of_two.rs
+++ b/clippy_lints/src/manual_is_power_of_two.rs
@@ -1,5 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::SpanlessEq;
 use rustc_ast::LitKind;
 use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
@@ -10,19 +11,19 @@ use rustc_session::declare_lint_pass;
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for expressions like `x.count_ones() == 1` or `x & (x - 1) == 0`, which are manual
+    /// Checks for expressions like `x.count_ones() == 1` or `x & (x - 1) == 0`, with x and unsigned integer, which are manual
     /// reimplementations of `x.is_power_of_two()`.
     /// ### Why is this bad?
     /// Manual reimplementations of `is_power_of_two` increase code complexity for little benefit.
     /// ### Example
     /// ```no_run
-    /// let x: u32 = 1;
-    /// let result = x.count_ones() == 1;
+    /// let a: u32 = 4;
+    /// let result = a.count_ones() == 1;
     /// ```
     /// Use instead:
     /// ```no_run
-    /// let x: u32 = 1;
-    /// let result = x.is_power_of_two();
+    /// let a: u32 = 4;
+    /// let result = a.is_power_of_two();
     /// ```
     #[clippy::version = "1.82.0"]
     pub MANUAL_IS_POWER_OF_TWO,
@@ -36,53 +37,106 @@ impl LateLintPass<'_> for ManualIsPowerOfTwo {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
         let mut applicability = Applicability::MachineApplicable;
 
-        // x.count_ones() == 1
-        if let ExprKind::Binary(op, left, right) = expr.kind
-            && BinOpKind::Eq == op.node
-            && let ExprKind::MethodCall(method_name, reciever, _, _) = left.kind
-            && method_name.ident.as_str() == "count_ones"
-            && let ExprKind::Lit(lit) = right.kind
-            && let LitKind::Int(Pu128(1), _) = lit.node
-            && let &Uint(_) = cx.typeck_results().expr_ty(reciever).kind()
+        if let ExprKind::Binary(bin_op, left, right) = expr.kind
+            && bin_op.node == BinOpKind::Eq
         {
-            let snippet = snippet_with_applicability(cx, reciever.span, "..", &mut applicability);
-            let sugg = format!("{snippet}.is_power_of_two()");
-            span_lint_and_sugg(
-                cx,
-                MANUAL_IS_POWER_OF_TWO,
-                expr.span,
-                "manually reimplementing `is_power_of_two`",
-                "consider using `.is_power_of_two()`",
-                sugg,
-                applicability,
-            );
-        }
+            // a.count_ones() == 1
+            if let ExprKind::MethodCall(method_name, reciever, _, _) = left.kind
+                && method_name.ident.as_str() == "count_ones"
+                && let &Uint(_) = cx.typeck_results().expr_ty(reciever).kind()
+                && check_lit(right, 1)
+            {
+                build_sugg(cx, expr, reciever, &mut applicability);
+            }
 
-        // x & (x - 1) == 0
-        if let ExprKind::Binary(op, left, right) = expr.kind
-            && BinOpKind::Eq == op.node
-            && let ExprKind::Binary(op1, left1, right1) = left.kind
-            && BinOpKind::BitAnd == op1.node
-            && let ExprKind::Binary(op2, left2, right2) = right1.kind
-            && BinOpKind::Sub == op2.node
-            && left1.span.eq_ctxt(left2.span)
-            && let &Uint(_) = cx.typeck_results().expr_ty(left1).kind()
-            && let ExprKind::Lit(lit) = right2.kind
-            && let LitKind::Int(Pu128(1), _) = lit.node
-            && let ExprKind::Lit(lit1) = right.kind
-            && let LitKind::Int(Pu128(0), _) = lit1.node
-        {
-            let snippet = snippet_with_applicability(cx, left1.span, "..", &mut applicability);
-            let sugg = format!("{snippet}.is_power_of_two()");
-            span_lint_and_sugg(
-                cx,
-                MANUAL_IS_POWER_OF_TWO,
-                expr.span,
-                "manually reimplementing `is_power_of_two`",
-                "consider using `.is_power_of_two()`",
-                sugg,
-                applicability,
-            );
+            // 1 == a.count_ones()
+            if let ExprKind::MethodCall(method_name, reciever, _, _) = right.kind
+                && method_name.ident.as_str() == "count_ones"
+                && let &Uint(_) = cx.typeck_results().expr_ty(reciever).kind()
+                && check_lit(left, 1)
+            {
+                build_sugg(cx, expr, reciever, &mut applicability);
+            }
+
+            // a & (a - 1) == 0
+            if let ExprKind::Binary(op1, left1, right1) = left.kind
+                && op1.node == BinOpKind::BitAnd
+                && let ExprKind::Binary(op2, left2, right2) = right1.kind
+                && op2.node == BinOpKind::Sub
+                && check_eq_expr(cx, left1, left2)
+                && let &Uint(_) = cx.typeck_results().expr_ty(left1).kind()
+                && check_lit(right2, 1)
+                && check_lit(right, 0)
+            {
+                build_sugg(cx, expr, left1, &mut applicability);
+            }
+
+            // (a - 1) & a == 0;
+            if let ExprKind::Binary(op1, left1, right1) = left.kind
+                && op1.node == BinOpKind::BitAnd
+                && let ExprKind::Binary(op2, left2, right2) = left1.kind
+                && op2.node == BinOpKind::Sub
+                && check_eq_expr(cx, right1, left2)
+                && let &Uint(_) = cx.typeck_results().expr_ty(right1).kind()
+                && check_lit(right2, 1)
+                && check_lit(right, 0)
+            {
+                build_sugg(cx, expr, right1, &mut applicability);
+            }
+
+            // 0 == a & (a - 1);
+            if let ExprKind::Binary(op1, left1, right1) = right.kind
+                && op1.node == BinOpKind::BitAnd
+                && let ExprKind::Binary(op2, left2, right2) = right1.kind
+                && op2.node == BinOpKind::Sub
+                && check_eq_expr(cx, left1, left2)
+                && let &Uint(_) = cx.typeck_results().expr_ty(left1).kind()
+                && check_lit(right2, 1)
+                && check_lit(left, 0)
+            {
+                build_sugg(cx, expr, left1, &mut applicability);
+            }
+
+            // 0 == (a - 1) & a
+            if let ExprKind::Binary(op1, left1, right1) = right.kind
+                && op1.node == BinOpKind::BitAnd
+                && let ExprKind::Binary(op2, left2, right2) = left1.kind
+                && op2.node == BinOpKind::Sub
+                && check_eq_expr(cx, right1, left2)
+                && let &Uint(_) = cx.typeck_results().expr_ty(right1).kind()
+                && check_lit(right2, 1)
+                && check_lit(left, 0)
+            {
+                build_sugg(cx, expr, right1, &mut applicability);
+            }
         }
     }
 }
+
+fn build_sugg(cx: &LateContext<'_>, expr: &Expr<'_>, reciever: &Expr<'_>, applicability: &mut Applicability) {
+    let snippet = snippet_with_applicability(cx, reciever.span, "..", applicability);
+
+    span_lint_and_sugg(
+        cx,
+        MANUAL_IS_POWER_OF_TWO,
+        expr.span,
+        "manually reimplementing `is_power_of_two`",
+        "consider using `.is_power_of_two()`",
+        format!("{snippet}.is_power_of_two()"),
+        *applicability,
+    );
+}
+
+fn check_lit(expr: &Expr<'_>, expected_num: u128) -> bool {
+    if let ExprKind::Lit(lit) = expr.kind
+        && let LitKind::Int(Pu128(num), _) = lit.node
+        && num == expected_num
+    {
+        return true;
+    }
+    false
+}
+
+fn check_eq_expr(cx: &LateContext<'_>, lhs: &Expr<'_>, rhs: &Expr<'_>) -> bool {
+    SpanlessEq::new(cx).eq_expr(lhs, rhs)
+}
diff --git a/tests/ui/manual_is_power_of_two.fixed b/tests/ui/manual_is_power_of_two.fixed
index beee2eaf665a9..dda5fe0ec3e77 100644
--- a/tests/ui/manual_is_power_of_two.fixed
+++ b/tests/ui/manual_is_power_of_two.fixed
@@ -6,6 +6,12 @@ fn main() {
     let _ = a.is_power_of_two();
     let _ = a.is_power_of_two();
 
+    // Test different orders of expression
+    let _ = a.is_power_of_two();
+    let _ = a.is_power_of_two();
+    let _ = a.is_power_of_two();
+    let _ = a.is_power_of_two();
+
     let b = 4_i64;
 
     // is_power_of_two only works for unsigned integers
diff --git a/tests/ui/manual_is_power_of_two.rs b/tests/ui/manual_is_power_of_two.rs
index 0810b4c28da75..a1d3a95c4102b 100644
--- a/tests/ui/manual_is_power_of_two.rs
+++ b/tests/ui/manual_is_power_of_two.rs
@@ -6,6 +6,12 @@ fn main() {
     let _ = a.count_ones() == 1;
     let _ = a & (a - 1) == 0;
 
+    // Test different orders of expression
+    let _ = 1 == a.count_ones();
+    let _ = (a - 1) & a == 0;
+    let _ = 0 == a & (a - 1);
+    let _ = 0 == (a - 1) & a;
+
     let b = 4_i64;
 
     // is_power_of_two only works for unsigned integers
diff --git a/tests/ui/manual_is_power_of_two.stderr b/tests/ui/manual_is_power_of_two.stderr
index c7dfe6b11b99e..3cfc6297abf27 100644
--- a/tests/ui/manual_is_power_of_two.stderr
+++ b/tests/ui/manual_is_power_of_two.stderr
@@ -13,5 +13,29 @@ error: manually reimplementing `is_power_of_two`
 LL |     let _ = a & (a - 1) == 0;
    |             ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
 
-error: aborting due to 2 previous errors
+error: manually reimplementing `is_power_of_two`
+  --> tests/ui/manual_is_power_of_two.rs:10:13
+   |
+LL |     let _ = 1 == a.count_ones();
+   |             ^^^^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
+
+error: manually reimplementing `is_power_of_two`
+  --> tests/ui/manual_is_power_of_two.rs:11:13
+   |
+LL |     let _ = (a - 1) & a == 0;
+   |             ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
+
+error: manually reimplementing `is_power_of_two`
+  --> tests/ui/manual_is_power_of_two.rs:12:13
+   |
+LL |     let _ = 0 == a & (a - 1);
+   |             ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
+
+error: manually reimplementing `is_power_of_two`
+  --> tests/ui/manual_is_power_of_two.rs:13:13
+   |
+LL |     let _ = 0 == (a - 1) & a;
+   |             ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
+
+error: aborting due to 6 previous errors
 

From e3ca249e9647396b9a3849e147aa53e168cf4c73 Mon Sep 17 00:00:00 2001
From: WeiTheShinobi <weitheshinobi@gmail.com>
Date: Fri, 6 Sep 2024 23:10:42 +0800
Subject: [PATCH 045/114] fix `single_match` suggestion

---
 clippy_lints/src/matches/single_match.rs | 24 ++++++++++++++---
 tests/ui/single_match.fixed              | 10 +++++--
 tests/ui/single_match.rs                 | 15 +++++++++++
 tests/ui/single_match.stderr             | 33 +++++++++++++++++++++---
 tests/ui/single_match_else.fixed         |  2 +-
 tests/ui/single_match_else.stderr        |  2 +-
 6 files changed, 75 insertions(+), 11 deletions(-)

diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs
index 4bd46bced38e3..e7cef5bdbd767 100644
--- a/clippy_lints/src/matches/single_match.rs
+++ b/clippy_lints/src/matches/single_match.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{expr_block, snippet, SpanRangeExt};
+use clippy_utils::source::{expr_block, snippet, snippet_block_with_context, SpanRangeExt};
 use clippy_utils::ty::implements_trait;
 use clippy_utils::{
     is_lint_allowed, is_unit_expr, peel_blocks, peel_hir_pat_refs, peel_middle_ty_refs, peel_n_hir_expr_refs,
@@ -9,7 +9,7 @@ use rustc_arena::DroplessArena;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{walk_pat, Visitor};
-use rustc_hir::{Arm, Expr, ExprKind, HirId, Pat, PatKind, QPath};
+use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatKind, QPath, StmtKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, AdtDef, ParamEnv, TyCtxt, TypeckResults, VariantDef};
 use rustc_span::{sym, Span};
@@ -93,8 +93,24 @@ fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, exp
 
     if snippet(cx, ex.span, "..") == snippet(cx, arm.pat.span, "..") {
         let msg = "this pattern is irrefutable, `match` is useless";
-        let sugg = expr_block(cx, arm.body, ctxt, "..", Some(expr.span), &mut app);
-        span_lint_and_sugg(cx, lint, expr.span, msg, "try", sugg, app);
+        let (sugg, help) = if is_unit_expr(arm.body) {
+            (String::new(), "`match` expression can be removed")
+        } else {
+            let mut sugg = snippet_block_with_context(cx, arm.body.span, ctxt, "..", Some(expr.span), &mut app)
+                .0
+                .to_string();
+            if let Node::Stmt(stmt) = cx.tcx.parent_hir_node(expr.hir_id)
+                && let StmtKind::Expr(_) = stmt.kind
+                && match arm.body.kind {
+                    ExprKind::Block(block, _) => block.span.from_expansion(),
+                    _ => true,
+                }
+            {
+                sugg.push(';');
+            }
+            (sugg, "try")
+        };
+        span_lint_and_sugg(cx, lint, expr.span, msg, help, sugg.to_string(), app);
         return;
     }
 
diff --git a/tests/ui/single_match.fixed b/tests/ui/single_match.fixed
index 04129ec0f13b9..dcf5a1d33c2ac 100644
--- a/tests/ui/single_match.fixed
+++ b/tests/ui/single_match.fixed
@@ -304,13 +304,19 @@ const DATA: Data = Data([1, 2, 3, 4]);
 const CONST_I32: i32 = 1;
 
 fn irrefutable_match() {
-    { println!() }
+    println!();
 
-    { println!() }
+    println!();
 
     let i = 0;
     {
         let a = 1;
         let b = 2;
     }
+
+    
+
+    
+
+    println!()
 }
diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs
index 2d51cee3fd995..3ba5eebd01b71 100644
--- a/tests/ui/single_match.rs
+++ b/tests/ui/single_match.rs
@@ -386,4 +386,19 @@ fn irrefutable_match() {
         },
         _ => {},
     }
+
+    match i {
+        i => {},
+        _ => {},
+    }
+
+    match i {
+        i => (),
+        _ => (),
+    }
+
+    match CONST_I32 {
+        CONST_I32 => println!(),
+        _ => {},
+    }
 }
diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr
index 9578421d2cec5..9240b09c50a9f 100644
--- a/tests/ui/single_match.stderr
+++ b/tests/ui/single_match.stderr
@@ -223,7 +223,7 @@ LL | /     match DATA {
 LL | |         DATA => println!(),
 LL | |         _ => {},
 LL | |     }
-   | |_____^ help: try: `{ println!() }`
+   | |_____^ help: try: `println!();`
 
 error: this pattern is irrefutable, `match` is useless
   --> tests/ui/single_match.rs:376:5
@@ -232,7 +232,7 @@ LL | /     match CONST_I32 {
 LL | |         CONST_I32 => println!(),
 LL | |         _ => {},
 LL | |     }
-   | |_____^ help: try: `{ println!() }`
+   | |_____^ help: try: `println!();`
 
 error: this pattern is irrefutable, `match` is useless
   --> tests/ui/single_match.rs:382:5
@@ -254,5 +254,32 @@ LL +         let b = 2;
 LL +     }
    |
 
-error: aborting due to 23 previous errors
+error: this pattern is irrefutable, `match` is useless
+  --> tests/ui/single_match.rs:390:5
+   |
+LL | /     match i {
+LL | |         i => {},
+LL | |         _ => {},
+LL | |     }
+   | |_____^ help: `match` expression can be removed
+
+error: this pattern is irrefutable, `match` is useless
+  --> tests/ui/single_match.rs:395:5
+   |
+LL | /     match i {
+LL | |         i => (),
+LL | |         _ => (),
+LL | |     }
+   | |_____^ help: `match` expression can be removed
+
+error: this pattern is irrefutable, `match` is useless
+  --> tests/ui/single_match.rs:400:5
+   |
+LL | /     match CONST_I32 {
+LL | |         CONST_I32 => println!(),
+LL | |         _ => {},
+LL | |     }
+   | |_____^ help: try: `println!()`
+
+error: aborting due to 26 previous errors
 
diff --git a/tests/ui/single_match_else.fixed b/tests/ui/single_match_else.fixed
index fb57411aaa426..c2ca746976bd1 100644
--- a/tests/ui/single_match_else.fixed
+++ b/tests/ui/single_match_else.fixed
@@ -173,5 +173,5 @@ fn issue_10808(bar: Option<i32>) {
 }
 
 fn irrefutable_match() -> Option<&'static ExprNode> {
-    { Some(&NODE) }
+    Some(&NODE)
 }
diff --git a/tests/ui/single_match_else.stderr b/tests/ui/single_match_else.stderr
index 61209053fd0fc..a2801751a430a 100644
--- a/tests/ui/single_match_else.stderr
+++ b/tests/ui/single_match_else.stderr
@@ -207,7 +207,7 @@ LL | |             let x = 5;
 LL | |             None
 LL | |         },
 LL | |     }
-   | |_____^ help: try: `{ Some(&NODE) }`
+   | |_____^ help: try: `Some(&NODE)`
 
 error: aborting due to 10 previous errors
 

From 46f8d360de99afe38dacc1dd6e29133d856e9fd3 Mon Sep 17 00:00:00 2001
From: Samarth1696 <samarthrobo03@gmail.com>
Date: Fri, 26 Jul 2024 00:51:30 +0530
Subject: [PATCH 046/114] Lint ready

---
 CHANGELOG.md                             |   1 +
 clippy_lints/src/declared_lints.rs       |   1 +
 clippy_lints/src/lib.rs                  |   2 +
 clippy_lints/src/non_zero_suggestions.rs | 107 +++++++++++++++++++++++
 tests/ui/non_zero_suggestions.rs         |  52 +++++++++++
 5 files changed, 163 insertions(+)
 create mode 100644 clippy_lints/src/non_zero_suggestions.rs
 create mode 100644 tests/ui/non_zero_suggestions.rs

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f1de51c936ea0..0e5d1688e4a72 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5773,6 +5773,7 @@ Released 2018-09-13
 [`non_minimal_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_minimal_cfg
 [`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
 [`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty
+[`non_zero_suggestions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_zero_suggestions
 [`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool
 [`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonsensical_open_options
 [`nonstandard_macro_braces`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index 6f468f01b2fde..16c64830e70dd 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -557,6 +557,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::non_expressive_names::SIMILAR_NAMES_INFO,
     crate::non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS_INFO,
     crate::non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY_INFO,
+    crate::non_zero_suggestions::NON_ZERO_SUGGESTIONS_INFO,
     crate::nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES_INFO,
     crate::octal_escapes::OCTAL_ESCAPES_INFO,
     crate::only_used_in_recursion::ONLY_USED_IN_RECURSION_INFO,
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index bc16a3b0c014e..3604090b68ccc 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -273,6 +273,7 @@ mod non_copy_const;
 mod non_expressive_names;
 mod non_octal_unix_permissions;
 mod non_send_fields_in_send_ty;
+mod non_zero_suggestions;
 mod nonstandard_macro_braces;
 mod octal_escapes;
 mod only_used_in_recursion;
@@ -940,5 +941,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(pointers_in_nomem_asm_block::PointersInNomemAsmBlock));
     store.register_late_pass(move |_| Box::new(manual_div_ceil::ManualDivCeil::new(conf)));
     store.register_late_pass(|_| Box::new(manual_is_power_of_two::ManualIsPowerOfTwo));
+    store.register_late_pass(|_| Box::new(non_zero_suggestions::NonZeroSuggestions));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
diff --git a/clippy_lints/src/non_zero_suggestions.rs b/clippy_lints/src/non_zero_suggestions.rs
new file mode 100644
index 0000000000000..b9e7053db900f
--- /dev/null
+++ b/clippy_lints/src/non_zero_suggestions.rs
@@ -0,0 +1,107 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{self, Ty};
+use rustc_session::declare_lint_pass;
+use rustc_span::symbol::sym;
+
+declare_clippy_lint! {
+    /// ### What it does
+    ///
+    /// ### Why is this bad?
+    ///
+    /// ### Example
+    /// ```no_run
+    /// // example code where clippy issues a warning
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// // example code which does not raise clippy warning
+    /// ```
+    #[clippy::version = "1.81.0"]
+    pub NON_ZERO_SUGGESTIONS,
+    restriction,
+    "suggests using `NonZero#` from `u#` or `i#` for more efficient and type-safe conversions"
+}
+
+declare_lint_pass!(NonZeroSuggestions => [NON_ZERO_SUGGESTIONS]);
+
+impl<'tcx> LateLintPass<'tcx> for NonZeroSuggestions {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        if let ExprKind::Call(func, [arg]) = expr.kind {
+            if let ExprKind::Path(qpath) = &func.kind {
+                if let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id() {
+                    let fn_name = cx.tcx.item_name(def_id);
+                    let target_ty = cx.typeck_results().expr_ty(expr);
+
+                    if let ExprKind::MethodCall(rcv_path, receiver, _, _) = &arg.kind {
+                        let receiver_ty = cx.typeck_results().expr_ty(receiver);
+                        if let ty::Adt(adt_def, _) = receiver_ty.kind() {
+                            if adt_def.is_struct() && cx.tcx.get_diagnostic_name(adt_def.did()) == Some(sym::NonZero) {
+                                if let Some(target_non_zero_type) = get_target_non_zero_type(target_ty) {
+                                    let arg_snippet = get_arg_snippet(cx, arg, rcv_path);
+                                    suggest_non_zero_conversion(cx, expr, fn_name, target_non_zero_type, &arg_snippet);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+fn get_arg_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, rcv_path: &rustc_hir::PathSegment<'_>) -> String {
+    let arg_snippet = snippet(cx, arg.span, "..");
+    if let Some(index) = arg_snippet.rfind(&format!(".{}", rcv_path.ident.name)) {
+        arg_snippet[..index].trim().to_string()
+    } else {
+        arg_snippet.to_string()
+    }
+}
+
+fn suggest_non_zero_conversion(
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
+    fn_name: rustc_span::Symbol,
+    target_non_zero_type: &str,
+    arg_snippet: &str,
+) {
+    let suggestion = format!("{}::{}({})", target_non_zero_type, fn_name, arg_snippet);
+    span_lint_and_sugg(
+        cx,
+        NON_ZERO_SUGGESTIONS,
+        expr.span,
+        format!(
+            "Consider using `{}::{}()` for more efficient and type-safe conversion",
+            target_non_zero_type, fn_name
+        ),
+        "Replace with",
+        suggestion,
+        Applicability::MachineApplicable,
+    );
+}
+
+fn get_target_non_zero_type(ty: Ty<'_>) -> Option<&'static str> {
+    match ty.kind() {
+        ty::Uint(uint_ty) => Some(match uint_ty {
+            ty::UintTy::U8 => "NonZeroU8",
+            ty::UintTy::U16 => "NonZeroU16",
+            ty::UintTy::U32 => "NonZeroU32",
+            ty::UintTy::U64 => "NonZeroU64",
+            ty::UintTy::U128 => "NonZeroU128",
+            ty::UintTy::Usize => "NonZeroUsize",
+        }),
+        ty::Int(int_ty) => Some(match int_ty {
+            ty::IntTy::I8 => "NonZeroI8",
+            ty::IntTy::I16 => "NonZeroI16",
+            ty::IntTy::I32 => "NonZeroI32",
+            ty::IntTy::I64 => "NonZeroI64",
+            ty::IntTy::I128 => "NonZeroI128",
+            ty::IntTy::Isize => "NonZeroIsize",
+        }),
+        _ => None,
+    }
+}
diff --git a/tests/ui/non_zero_suggestions.rs b/tests/ui/non_zero_suggestions.rs
new file mode 100644
index 0000000000000..1a5ee40dc3da8
--- /dev/null
+++ b/tests/ui/non_zero_suggestions.rs
@@ -0,0 +1,52 @@
+#![warn(clippy::non_zero_suggestions)]
+
+use std::num::{
+    NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32,
+    NonZeroU64, NonZeroU8, NonZeroUsize,
+};
+
+fn main() {
+    // Basic cases
+    let _ = u8::try_from(NonZeroU8::new(5).unwrap().get());
+
+    let _ = u16::from(NonZeroU16::new(10).unwrap().get());
+
+    // Different integer types
+    let _ = u32::from(NonZeroU32::new(15).unwrap().get());
+
+    let _ = u64::from(NonZeroU64::new(20).unwrap().get());
+
+    let _ = u128::from(NonZeroU128::new(25).unwrap().get());
+
+    let _ = usize::from(NonZeroUsize::new(30).unwrap().get());
+
+    // Signed integer types
+    let _ = i8::try_from(NonZeroI8::new(-5).unwrap().get());
+
+    let _ = i16::from(NonZeroI16::new(-10).unwrap().get());
+
+    let _ = i32::from(NonZeroI32::new(-15).unwrap().get());
+
+    // Edge cases
+
+    // Complex expression
+    let _ = u8::from(NonZeroU8::new(5).unwrap().get() + 1);
+
+    // Function call
+    fn get_non_zero() -> NonZeroU8 {
+        NonZeroU8::new(42).unwrap()
+    }
+    let _ = u8::from(get_non_zero().get());
+
+    // Method chaining
+    let _ = u16::from(NonZeroU16::new(100).unwrap().get().checked_add(1).unwrap());
+    // This should not trigger the lint
+
+    // Different conversion methods
+    let _ = u32::try_from(NonZeroU32::new(200).unwrap().get()).unwrap();
+
+    // Cases that should not trigger the lint
+    let _ = u8::from(5);
+    let _ = u16::from(10u8);
+    let _ = i32::try_from(40u32).unwrap();
+}

From 73039f654e2efc3a7384462dcd46289851b80e62 Mon Sep 17 00:00:00 2001
From: Samarth1696 <samarthrobo03@gmail.com>
Date: Fri, 26 Jul 2024 17:11:51 +0530
Subject: [PATCH 047/114] test cases added including some edge cases

---
 clippy_lints/src/non_zero_suggestions.rs | 22 ++++++-
 tests/ui/non_zero_suggestions.fixed      | 69 ++++++++++++++++++++
 tests/ui/non_zero_suggestions.rs         | 83 ++++++++++++++----------
 tests/ui/non_zero_suggestions.stderr     | 59 +++++++++++++++++
 4 files changed, 198 insertions(+), 35 deletions(-)
 create mode 100644 tests/ui/non_zero_suggestions.fixed
 create mode 100644 tests/ui/non_zero_suggestions.stderr

diff --git a/clippy_lints/src/non_zero_suggestions.rs b/clippy_lints/src/non_zero_suggestions.rs
index b9e7053db900f..715d9eda6eeb3 100644
--- a/clippy_lints/src/non_zero_suggestions.rs
+++ b/clippy_lints/src/non_zero_suggestions.rs
@@ -9,16 +9,34 @@ use rustc_span::symbol::sym;
 
 declare_clippy_lint! {
     /// ### What it does
+    /// Checks for conversions from `NonZero` types to regular integer types,
+    /// and suggests using `NonZero` types for the target as well.
     ///
     /// ### Why is this bad?
+    /// Converting from `NonZero` types to regular integer types and then back to `NonZero`
+    /// types is less efficient and loses the type-safety guarantees provided by `NonZero` types.
+    /// Using `NonZero` types consistently can lead to more optimized code and prevent
+    /// certain classes of errors related to zero values.
     ///
     /// ### Example
     /// ```no_run
-    /// // example code where clippy issues a warning
+    /// use std::num::{NonZeroU32, NonZeroU64};
+    ///
+    /// fn example(x: u64, y: NonZeroU32) {
+    ///     // Bad: Converting NonZeroU32 to u64 unnecessarily
+    ///     let r1 = x / u64::from(y.get());
+    ///     let r2 = x % u64::from(y.get());
+    /// }
     /// ```
     /// Use instead:
     /// ```no_run
-    /// // example code which does not raise clippy warning
+    /// use std::num::{NonZeroU32, NonZeroU64};
+    ///
+    /// fn example(x: u64, y: NonZeroU32) {
+    ///     // Good: Preserving the NonZero property
+    ///     let r1 = x / NonZeroU64::from(y);
+    ///     let r2 = x % NonZeroU64::from(y);
+    /// }
     /// ```
     #[clippy::version = "1.81.0"]
     pub NON_ZERO_SUGGESTIONS,
diff --git a/tests/ui/non_zero_suggestions.fixed b/tests/ui/non_zero_suggestions.fixed
new file mode 100644
index 0000000000000..b33de1ef03f5d
--- /dev/null
+++ b/tests/ui/non_zero_suggestions.fixed
@@ -0,0 +1,69 @@
+#![warn(clippy::non_zero_suggestions)]
+
+use std::num::{NonZeroI16, NonZeroI8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
+
+fn main() {
+    // Positive test cases (lint should trigger)
+
+    // U32 -> U64
+    let x: u64 = 100;
+    let y = NonZeroU32::new(10).unwrap();
+    let r1 = x / NonZeroU64::from(y);
+    let r2 = x % NonZeroU64::from(y);
+
+    // U16 -> U32
+    let a: u32 = 50;
+    let b = NonZeroU16::new(5).unwrap();
+    let r3 = a / NonZeroU32::from(b);
+
+    // I8 -> I16
+    let c: i16 = 25;
+    let d = NonZeroI8::new(3).unwrap();
+    let r4 = NonZeroI16::from(d);
+
+    // Different operations
+    let m: u64 = 400;
+    let n = NonZeroU32::new(20).unwrap();
+    let r5 = m / NonZeroU64::from(n);
+
+    // Edge cases
+
+    // Using the max value of a type
+    let max_u32 = NonZeroU32::new(u32::MAX).unwrap();
+    let r6 = NonZeroU64::from(max_u32);
+
+    // Chained method calls
+    let _ = NonZeroU64::from(NonZeroU32::new(10).unwrap());
+
+    // Negative test cases (lint should not trigger)
+
+    // Same size types
+    let e: u32 = 200;
+    let f = NonZeroU32::new(20).unwrap();
+    let r10 = e / f.get();
+
+    // Smaller to larger, but not NonZero
+    let g: u64 = 1000;
+    let h: u32 = 50;
+    let r11 = g / u64::from(h);
+
+    // Using From correctly
+    let k: u64 = 300;
+    let l = NonZeroU32::new(15).unwrap();
+    let r12 = k / NonZeroU64::from(l);
+}
+
+// Additional function to test the lint in a different context
+fn divide_numbers(x: u64, y: NonZeroU32) -> u64 {
+    x / NonZeroU64::from(y)
+}
+
+struct Calculator {
+    value: u64,
+}
+
+impl Calculator {
+    fn divide(&self, divisor: NonZeroU32) -> u64 {
+        self.value / NonZeroU64::from(divisor)
+    }
+}
diff --git a/tests/ui/non_zero_suggestions.rs b/tests/ui/non_zero_suggestions.rs
index 1a5ee40dc3da8..27089eaf86ef5 100644
--- a/tests/ui/non_zero_suggestions.rs
+++ b/tests/ui/non_zero_suggestions.rs
@@ -1,52 +1,69 @@
 #![warn(clippy::non_zero_suggestions)]
 
-use std::num::{
-    NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32,
-    NonZeroU64, NonZeroU8, NonZeroUsize,
-};
+use std::num::{NonZeroI16, NonZeroI8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
 
 fn main() {
-    // Basic cases
-    let _ = u8::try_from(NonZeroU8::new(5).unwrap().get());
+    // Positive test cases (lint should trigger)
 
-    let _ = u16::from(NonZeroU16::new(10).unwrap().get());
+    // U32 -> U64
+    let x: u64 = 100;
+    let y = NonZeroU32::new(10).unwrap();
+    let r1 = x / u64::from(y.get());
+    let r2 = x % u64::from(y.get());
 
-    // Different integer types
-    let _ = u32::from(NonZeroU32::new(15).unwrap().get());
+    // U16 -> U32
+    let a: u32 = 50;
+    let b = NonZeroU16::new(5).unwrap();
+    let r3 = a / u32::from(b.get());
 
-    let _ = u64::from(NonZeroU64::new(20).unwrap().get());
+    // I8 -> I16
+    let c: i16 = 25;
+    let d = NonZeroI8::new(3).unwrap();
+    let r4 = i16::from(d.get());
 
-    let _ = u128::from(NonZeroU128::new(25).unwrap().get());
+    // Different operations
+    let m: u64 = 400;
+    let n = NonZeroU32::new(20).unwrap();
+    let r5 = m / u64::from(n.get());
 
-    let _ = usize::from(NonZeroUsize::new(30).unwrap().get());
+    // Edge cases
 
-    // Signed integer types
-    let _ = i8::try_from(NonZeroI8::new(-5).unwrap().get());
+    // Using the max value of a type
+    let max_u32 = NonZeroU32::new(u32::MAX).unwrap();
+    let r6 = u64::from(max_u32.get());
 
-    let _ = i16::from(NonZeroI16::new(-10).unwrap().get());
+    // Chained method calls
+    let _ = u64::from(NonZeroU32::new(10).unwrap().get());
 
-    let _ = i32::from(NonZeroI32::new(-15).unwrap().get());
+    // Negative test cases (lint should not trigger)
 
-    // Edge cases
+    // Same size types
+    let e: u32 = 200;
+    let f = NonZeroU32::new(20).unwrap();
+    let r10 = e / f.get();
 
-    // Complex expression
-    let _ = u8::from(NonZeroU8::new(5).unwrap().get() + 1);
+    // Smaller to larger, but not NonZero
+    let g: u64 = 1000;
+    let h: u32 = 50;
+    let r11 = g / u64::from(h);
 
-    // Function call
-    fn get_non_zero() -> NonZeroU8 {
-        NonZeroU8::new(42).unwrap()
-    }
-    let _ = u8::from(get_non_zero().get());
+    // Using From correctly
+    let k: u64 = 300;
+    let l = NonZeroU32::new(15).unwrap();
+    let r12 = k / NonZeroU64::from(l);
+}
 
-    // Method chaining
-    let _ = u16::from(NonZeroU16::new(100).unwrap().get().checked_add(1).unwrap());
-    // This should not trigger the lint
+// Additional function to test the lint in a different context
+fn divide_numbers(x: u64, y: NonZeroU32) -> u64 {
+    x / u64::from(y.get())
+}
 
-    // Different conversion methods
-    let _ = u32::try_from(NonZeroU32::new(200).unwrap().get()).unwrap();
+struct Calculator {
+    value: u64,
+}
 
-    // Cases that should not trigger the lint
-    let _ = u8::from(5);
-    let _ = u16::from(10u8);
-    let _ = i32::try_from(40u32).unwrap();
+impl Calculator {
+    fn divide(&self, divisor: NonZeroU32) -> u64 {
+        self.value / u64::from(divisor.get())
+    }
 }
diff --git a/tests/ui/non_zero_suggestions.stderr b/tests/ui/non_zero_suggestions.stderr
new file mode 100644
index 0000000000000..b30f9dd1e5ce2
--- /dev/null
+++ b/tests/ui/non_zero_suggestions.stderr
@@ -0,0 +1,59 @@
+error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+  --> tests/ui/non_zero_suggestions.rs:11:18
+   |
+LL |     let r1 = x / u64::from(y.get());
+   |                  ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(y)`
+   |
+   = note: `-D clippy::non-zero-suggestions` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::non_zero_suggestions)]`
+
+error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+  --> tests/ui/non_zero_suggestions.rs:12:18
+   |
+LL |     let r2 = x % u64::from(y.get());
+   |                  ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(y)`
+
+error: Consider using `NonZeroU32::from()` for more efficient and type-safe conversion
+  --> tests/ui/non_zero_suggestions.rs:17:18
+   |
+LL |     let r3 = a / u32::from(b.get());
+   |                  ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU32::from(b)`
+
+error: Consider using `NonZeroI16::from()` for more efficient and type-safe conversion
+  --> tests/ui/non_zero_suggestions.rs:22:14
+   |
+LL |     let r4 = i16::from(d.get());
+   |              ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroI16::from(d)`
+
+error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+  --> tests/ui/non_zero_suggestions.rs:27:18
+   |
+LL |     let r5 = m / u64::from(n.get());
+   |                  ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(n)`
+
+error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+  --> tests/ui/non_zero_suggestions.rs:33:14
+   |
+LL |     let r6 = u64::from(max_u32.get());
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(max_u32)`
+
+error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+  --> tests/ui/non_zero_suggestions.rs:36:13
+   |
+LL |     let _ = u64::from(NonZeroU32::new(10).unwrap().get());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(NonZeroU32::new(10).unwrap())`
+
+error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+  --> tests/ui/non_zero_suggestions.rs:58:9
+   |
+LL |     x / u64::from(y.get())
+   |         ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(y)`
+
+error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+  --> tests/ui/non_zero_suggestions.rs:67:22
+   |
+LL |         self.value / u64::from(divisor.get())
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(divisor)`
+
+error: aborting due to 9 previous errors
+

From 6f01273d5d2acec2a726f2115fbf557967c2336a Mon Sep 17 00:00:00 2001
From: Samarth1696 <samarthrobo03@gmail.com>
Date: Fri, 26 Jul 2024 17:46:41 +0530
Subject: [PATCH 048/114] dogfood test passed

---
 clippy_lints/src/non_zero_suggestions.rs | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/clippy_lints/src/non_zero_suggestions.rs b/clippy_lints/src/non_zero_suggestions.rs
index 715d9eda6eeb3..e652f6f510809 100644
--- a/clippy_lints/src/non_zero_suggestions.rs
+++ b/clippy_lints/src/non_zero_suggestions.rs
@@ -87,15 +87,12 @@ fn suggest_non_zero_conversion(
     target_non_zero_type: &str,
     arg_snippet: &str,
 ) {
-    let suggestion = format!("{}::{}({})", target_non_zero_type, fn_name, arg_snippet);
+    let suggestion = format!("{target_non_zero_type}::{fn_name}({arg_snippet})");
     span_lint_and_sugg(
         cx,
         NON_ZERO_SUGGESTIONS,
         expr.span,
-        format!(
-            "Consider using `{}::{}()` for more efficient and type-safe conversion",
-            target_non_zero_type, fn_name
-        ),
+        format!("Consider using `{target_non_zero_type}::{fn_name}()` for more efficient and type-safe conversion"),
         "Replace with",
         suggestion,
         Applicability::MachineApplicable,

From 0f99aa992ea19b0148767c137ff1a936d58b65e0 Mon Sep 17 00:00:00 2001
From: Samarth1696 <samarthrobo03@gmail.com>
Date: Fri, 26 Jul 2024 18:16:08 +0530
Subject: [PATCH 049/114] all tests passed

---
 clippy_lints/src/non_zero_suggestions.rs |  4 +--
 tests/ui/non_zero_suggestions.stderr     | 36 ++++++++++++------------
 2 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/clippy_lints/src/non_zero_suggestions.rs b/clippy_lints/src/non_zero_suggestions.rs
index e652f6f510809..fc2920868d492 100644
--- a/clippy_lints/src/non_zero_suggestions.rs
+++ b/clippy_lints/src/non_zero_suggestions.rs
@@ -92,8 +92,8 @@ fn suggest_non_zero_conversion(
         cx,
         NON_ZERO_SUGGESTIONS,
         expr.span,
-        format!("Consider using `{target_non_zero_type}::{fn_name}()` for more efficient and type-safe conversion"),
-        "Replace with",
+        format!("consider using `{target_non_zero_type}::{fn_name}()` for more efficient and type-safe conversion"),
+        "replace with",
         suggestion,
         Applicability::MachineApplicable,
     );
diff --git a/tests/ui/non_zero_suggestions.stderr b/tests/ui/non_zero_suggestions.stderr
index b30f9dd1e5ce2..4c86720c3086b 100644
--- a/tests/ui/non_zero_suggestions.stderr
+++ b/tests/ui/non_zero_suggestions.stderr
@@ -1,59 +1,59 @@
-error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
   --> tests/ui/non_zero_suggestions.rs:11:18
    |
 LL |     let r1 = x / u64::from(y.get());
-   |                  ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(y)`
+   |                  ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`
    |
    = note: `-D clippy::non-zero-suggestions` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::non_zero_suggestions)]`
 
-error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
   --> tests/ui/non_zero_suggestions.rs:12:18
    |
 LL |     let r2 = x % u64::from(y.get());
-   |                  ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(y)`
+   |                  ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`
 
-error: Consider using `NonZeroU32::from()` for more efficient and type-safe conversion
+error: consider using `NonZeroU32::from()` for more efficient and type-safe conversion
   --> tests/ui/non_zero_suggestions.rs:17:18
    |
 LL |     let r3 = a / u32::from(b.get());
-   |                  ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU32::from(b)`
+   |                  ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU32::from(b)`
 
-error: Consider using `NonZeroI16::from()` for more efficient and type-safe conversion
+error: consider using `NonZeroI16::from()` for more efficient and type-safe conversion
   --> tests/ui/non_zero_suggestions.rs:22:14
    |
 LL |     let r4 = i16::from(d.get());
-   |              ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroI16::from(d)`
+   |              ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroI16::from(d)`
 
-error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
   --> tests/ui/non_zero_suggestions.rs:27:18
    |
 LL |     let r5 = m / u64::from(n.get());
-   |                  ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(n)`
+   |                  ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(n)`
 
-error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
   --> tests/ui/non_zero_suggestions.rs:33:14
    |
 LL |     let r6 = u64::from(max_u32.get());
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(max_u32)`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(max_u32)`
 
-error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
   --> tests/ui/non_zero_suggestions.rs:36:13
    |
 LL |     let _ = u64::from(NonZeroU32::new(10).unwrap().get());
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(NonZeroU32::new(10).unwrap())`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(NonZeroU32::new(10).unwrap())`
 
-error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
   --> tests/ui/non_zero_suggestions.rs:58:9
    |
 LL |     x / u64::from(y.get())
-   |         ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(y)`
+   |         ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`
 
-error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
   --> tests/ui/non_zero_suggestions.rs:67:22
    |
 LL |         self.value / u64::from(divisor.get())
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(divisor)`
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(divisor)`
 
 error: aborting due to 9 previous errors
 

From bed44418eca84e81c7efa7a3ee45f450b8a834f4 Mon Sep 17 00:00:00 2001
From: Samarth1696 <samarthrobo03@gmail.com>
Date: Sat, 27 Jul 2024 02:35:16 +0530
Subject: [PATCH 050/114] refactored the code

---
 clippy_lints/src/non_zero_suggestions.rs | 31 ++++++++++++------------
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/clippy_lints/src/non_zero_suggestions.rs b/clippy_lints/src/non_zero_suggestions.rs
index fc2920868d492..1624c365ee948 100644
--- a/clippy_lints/src/non_zero_suggestions.rs
+++ b/clippy_lints/src/non_zero_suggestions.rs
@@ -48,23 +48,22 @@ declare_lint_pass!(NonZeroSuggestions => [NON_ZERO_SUGGESTIONS]);
 
 impl<'tcx> LateLintPass<'tcx> for NonZeroSuggestions {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if let ExprKind::Call(func, [arg]) = expr.kind {
-            if let ExprKind::Path(qpath) = &func.kind {
-                if let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id() {
-                    let fn_name = cx.tcx.item_name(def_id);
-                    let target_ty = cx.typeck_results().expr_ty(expr);
+        if let ExprKind::Call(func, [arg]) = expr.kind
+            && let ExprKind::Path(qpath) = &func.kind
+            && let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id()
+            && let ExprKind::MethodCall(rcv_path, receiver, _, _) = &arg.kind
+        {
+            let fn_name = cx.tcx.item_name(def_id);
+            let target_ty = cx.typeck_results().expr_ty(expr);
+            let receiver_ty = cx.typeck_results().expr_ty(receiver);
 
-                    if let ExprKind::MethodCall(rcv_path, receiver, _, _) = &arg.kind {
-                        let receiver_ty = cx.typeck_results().expr_ty(receiver);
-                        if let ty::Adt(adt_def, _) = receiver_ty.kind() {
-                            if adt_def.is_struct() && cx.tcx.get_diagnostic_name(adt_def.did()) == Some(sym::NonZero) {
-                                if let Some(target_non_zero_type) = get_target_non_zero_type(target_ty) {
-                                    let arg_snippet = get_arg_snippet(cx, arg, rcv_path);
-                                    suggest_non_zero_conversion(cx, expr, fn_name, target_non_zero_type, &arg_snippet);
-                                }
-                            }
-                        }
-                    }
+            if let ty::Adt(adt_def, _) = receiver_ty.kind()
+                && adt_def.is_struct()
+                && cx.tcx.get_diagnostic_name(adt_def.did()) == Some(sym::NonZero)
+            {
+                if let Some(target_non_zero_type) = get_target_non_zero_type(target_ty) {
+                    let arg_snippet = get_arg_snippet(cx, arg, rcv_path);
+                    suggest_non_zero_conversion(cx, expr, fn_name, target_non_zero_type, &arg_snippet);
                 }
             }
         }

From c6c74083a803f32ffe2447fdcd0afaafaa03179c Mon Sep 17 00:00:00 2001
From: Samarth1696 <samarthrobo03@gmail.com>
Date: Sat, 27 Jul 2024 03:15:40 +0530
Subject: [PATCH 051/114] error notations added

---
 tests/ui/non_zero_suggestions.fixed  | 25 +++++++++++++++++++------
 tests/ui/non_zero_suggestions.rs     | 25 +++++++++++++++++++------
 tests/ui/non_zero_suggestions.stderr | 26 ++++++++++++++++----------
 3 files changed, 54 insertions(+), 22 deletions(-)

diff --git a/tests/ui/non_zero_suggestions.fixed b/tests/ui/non_zero_suggestions.fixed
index b33de1ef03f5d..d7e6b19edc1f6 100644
--- a/tests/ui/non_zero_suggestions.fixed
+++ b/tests/ui/non_zero_suggestions.fixed
@@ -3,40 +3,45 @@
 use std::num::{NonZeroI16, NonZeroI8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
 
 fn main() {
-    // Positive test cases (lint should trigger)
-
+    /// Positive test cases (lint should trigger)
     // U32 -> U64
     let x: u64 = 100;
     let y = NonZeroU32::new(10).unwrap();
     let r1 = x / NonZeroU64::from(y);
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+
     let r2 = x % NonZeroU64::from(y);
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
 
     // U16 -> U32
     let a: u32 = 50;
     let b = NonZeroU16::new(5).unwrap();
     let r3 = a / NonZeroU32::from(b);
+    //~^ ERROR: consider using `NonZeroU32::from()` for more efficient and type-safe conversion
 
     // I8 -> I16
     let c: i16 = 25;
     let d = NonZeroI8::new(3).unwrap();
     let r4 = NonZeroI16::from(d);
+    //~^ ERROR: consider using `NonZeroI16::from()` for more efficient and type-safe conversion
 
     // Different operations
     let m: u64 = 400;
     let n = NonZeroU32::new(20).unwrap();
     let r5 = m / NonZeroU64::from(n);
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
 
-    // Edge cases
-
+    /// Edge cases
     // Using the max value of a type
     let max_u32 = NonZeroU32::new(u32::MAX).unwrap();
     let r6 = NonZeroU64::from(max_u32);
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
 
     // Chained method calls
     let _ = NonZeroU64::from(NonZeroU32::new(10).unwrap());
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
 
-    // Negative test cases (lint should not trigger)
-
+    /// Negative test cases (lint should not trigger)
     // Same size types
     let e: u32 = 200;
     let f = NonZeroU32::new(20).unwrap();
@@ -56,8 +61,16 @@ fn main() {
 // Additional function to test the lint in a different context
 fn divide_numbers(x: u64, y: NonZeroU32) -> u64 {
     x / NonZeroU64::from(y)
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
 }
 
+fn no_bin_exp(x: u64, y: NonZeroU32) -> u64 {
+    NonZeroU64::from(y)
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+}
+
+fn some_fn_that_only_takes_u64(_: u64) {}
+
 struct Calculator {
     value: u64,
 }
diff --git a/tests/ui/non_zero_suggestions.rs b/tests/ui/non_zero_suggestions.rs
index 27089eaf86ef5..8f256dabcb849 100644
--- a/tests/ui/non_zero_suggestions.rs
+++ b/tests/ui/non_zero_suggestions.rs
@@ -3,40 +3,45 @@
 use std::num::{NonZeroI16, NonZeroI8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
 
 fn main() {
-    // Positive test cases (lint should trigger)
-
+    /// Positive test cases (lint should trigger)
     // U32 -> U64
     let x: u64 = 100;
     let y = NonZeroU32::new(10).unwrap();
     let r1 = x / u64::from(y.get());
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+
     let r2 = x % u64::from(y.get());
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
 
     // U16 -> U32
     let a: u32 = 50;
     let b = NonZeroU16::new(5).unwrap();
     let r3 = a / u32::from(b.get());
+    //~^ ERROR: consider using `NonZeroU32::from()` for more efficient and type-safe conversion
 
     // I8 -> I16
     let c: i16 = 25;
     let d = NonZeroI8::new(3).unwrap();
     let r4 = i16::from(d.get());
+    //~^ ERROR: consider using `NonZeroI16::from()` for more efficient and type-safe conversion
 
     // Different operations
     let m: u64 = 400;
     let n = NonZeroU32::new(20).unwrap();
     let r5 = m / u64::from(n.get());
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
 
-    // Edge cases
-
+    /// Edge cases
     // Using the max value of a type
     let max_u32 = NonZeroU32::new(u32::MAX).unwrap();
     let r6 = u64::from(max_u32.get());
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
 
     // Chained method calls
     let _ = u64::from(NonZeroU32::new(10).unwrap().get());
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
 
-    // Negative test cases (lint should not trigger)
-
+    /// Negative test cases (lint should not trigger)
     // Same size types
     let e: u32 = 200;
     let f = NonZeroU32::new(20).unwrap();
@@ -56,8 +61,16 @@ fn main() {
 // Additional function to test the lint in a different context
 fn divide_numbers(x: u64, y: NonZeroU32) -> u64 {
     x / u64::from(y.get())
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
 }
 
+fn no_bin_exp(x: u64, y: NonZeroU32) -> u64 {
+    u64::from(y.get())
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+}
+
+fn some_fn_that_only_takes_u64(_: u64) {}
+
 struct Calculator {
     value: u64,
 }
diff --git a/tests/ui/non_zero_suggestions.stderr b/tests/ui/non_zero_suggestions.stderr
index 4c86720c3086b..b231c8d216ed5 100644
--- a/tests/ui/non_zero_suggestions.stderr
+++ b/tests/ui/non_zero_suggestions.stderr
@@ -1,5 +1,5 @@
 error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:11:18
+  --> tests/ui/non_zero_suggestions.rs:10:18
    |
 LL |     let r1 = x / u64::from(y.get());
    |                  ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`
@@ -8,52 +8,58 @@ LL |     let r1 = x / u64::from(y.get());
    = help: to override `-D warnings` add `#[allow(clippy::non_zero_suggestions)]`
 
 error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:12:18
+  --> tests/ui/non_zero_suggestions.rs:13:18
    |
 LL |     let r2 = x % u64::from(y.get());
    |                  ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`
 
 error: consider using `NonZeroU32::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:17:18
+  --> tests/ui/non_zero_suggestions.rs:19:18
    |
 LL |     let r3 = a / u32::from(b.get());
    |                  ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU32::from(b)`
 
 error: consider using `NonZeroI16::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:22:14
+  --> tests/ui/non_zero_suggestions.rs:25:14
    |
 LL |     let r4 = i16::from(d.get());
    |              ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroI16::from(d)`
 
 error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:27:18
+  --> tests/ui/non_zero_suggestions.rs:31:18
    |
 LL |     let r5 = m / u64::from(n.get());
    |                  ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(n)`
 
 error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:33:14
+  --> tests/ui/non_zero_suggestions.rs:37:14
    |
 LL |     let r6 = u64::from(max_u32.get());
    |              ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(max_u32)`
 
 error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:36:13
+  --> tests/ui/non_zero_suggestions.rs:41:13
    |
 LL |     let _ = u64::from(NonZeroU32::new(10).unwrap().get());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(NonZeroU32::new(10).unwrap())`
 
 error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:58:9
+  --> tests/ui/non_zero_suggestions.rs:63:9
    |
 LL |     x / u64::from(y.get())
    |         ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`
 
 error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:67:22
+  --> tests/ui/non_zero_suggestions.rs:68:5
+   |
+LL |     u64::from(y.get())
+   |     ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`
+
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+  --> tests/ui/non_zero_suggestions.rs:80:22
    |
 LL |         self.value / u64::from(divisor.get())
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(divisor)`
 
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
 

From d43acb803f1bdabfd3761e54bd9509f8b19fb16a Mon Sep 17 00:00:00 2001
From: Samarth1696 <samarthrobo03@gmail.com>
Date: Thu, 1 Aug 2024 17:29:07 +0530
Subject: [PATCH 052/114] Added checks for binary expr and added different test
 cases for unfixable cases

---
 clippy_lints/src/non_zero_suggestions.rs      | 53 +++++++++++++------
 tests/ui/non_zero_suggestions.fixed           | 43 +++++----------
 tests/ui/non_zero_suggestions.rs              | 43 +++++----------
 tests/ui/non_zero_suggestions.stderr          | 42 ++++-----------
 tests/ui/non_zero_suggestions_unfixable.rs    | 20 +++++++
 .../ui/non_zero_suggestions_unfixable.stderr  | 23 ++++++++
 6 files changed, 115 insertions(+), 109 deletions(-)
 create mode 100644 tests/ui/non_zero_suggestions_unfixable.rs
 create mode 100644 tests/ui/non_zero_suggestions_unfixable.stderr

diff --git a/clippy_lints/src/non_zero_suggestions.rs b/clippy_lints/src/non_zero_suggestions.rs
index 1624c365ee948..808de147d722e 100644
--- a/clippy_lints/src/non_zero_suggestions.rs
+++ b/clippy_lints/src/non_zero_suggestions.rs
@@ -1,5 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
+use rustc_ast::ast::BinOpKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -48,23 +49,42 @@ declare_lint_pass!(NonZeroSuggestions => [NON_ZERO_SUGGESTIONS]);
 
 impl<'tcx> LateLintPass<'tcx> for NonZeroSuggestions {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if let ExprKind::Call(func, [arg]) = expr.kind
-            && let ExprKind::Path(qpath) = &func.kind
-            && let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id()
-            && let ExprKind::MethodCall(rcv_path, receiver, _, _) = &arg.kind
+        if let ExprKind::Binary(op, _, rhs) = expr.kind
+            && matches!(op.node, BinOpKind::Div | BinOpKind::Rem)
         {
-            let fn_name = cx.tcx.item_name(def_id);
-            let target_ty = cx.typeck_results().expr_ty(expr);
-            let receiver_ty = cx.typeck_results().expr_ty(receiver);
+            check_non_zero_conversion(cx, rhs, Applicability::MachineApplicable);
+        } else {
+            // Check if the parent expression is a binary operation
+            let parent_is_binary = cx.tcx.hir().parent_iter(expr.hir_id).any(|(_, node)| {
+                matches!(node, rustc_hir::Node::Expr(parent_expr) if matches!(parent_expr.kind, ExprKind::Binary(..)))
+            });
 
-            if let ty::Adt(adt_def, _) = receiver_ty.kind()
-                && adt_def.is_struct()
-                && cx.tcx.get_diagnostic_name(adt_def.did()) == Some(sym::NonZero)
-            {
-                if let Some(target_non_zero_type) = get_target_non_zero_type(target_ty) {
-                    let arg_snippet = get_arg_snippet(cx, arg, rcv_path);
-                    suggest_non_zero_conversion(cx, expr, fn_name, target_non_zero_type, &arg_snippet);
-                }
+            if !parent_is_binary {
+                check_non_zero_conversion(cx, expr, Applicability::MaybeIncorrect);
+            }
+        }
+    }
+}
+
+fn check_non_zero_conversion(cx: &LateContext<'_>, expr: &Expr<'_>, applicability: Applicability) {
+    // Check if the expression is a function call with one argument
+    if let ExprKind::Call(func, [arg]) = expr.kind
+        && let ExprKind::Path(qpath) = &func.kind
+        && let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id()
+        && let ExprKind::MethodCall(rcv_path, receiver, _, _) = &arg.kind
+    {
+        let fn_name = cx.tcx.item_name(def_id);
+        let target_ty = cx.typeck_results().expr_ty(expr);
+        let receiver_ty = cx.typeck_results().expr_ty(receiver);
+
+        // Check if the receiver type is a NonZero type
+        if let ty::Adt(adt_def, _) = receiver_ty.kind()
+            && adt_def.is_struct()
+            && cx.tcx.get_diagnostic_name(adt_def.did()) == Some(sym::NonZero)
+        {
+            if let Some(target_non_zero_type) = get_target_non_zero_type(target_ty) {
+                let arg_snippet = get_arg_snippet(cx, arg, rcv_path);
+                suggest_non_zero_conversion(cx, expr, fn_name, target_non_zero_type, &arg_snippet, applicability);
             }
         }
     }
@@ -85,6 +105,7 @@ fn suggest_non_zero_conversion(
     fn_name: rustc_span::Symbol,
     target_non_zero_type: &str,
     arg_snippet: &str,
+    applicability: Applicability,
 ) {
     let suggestion = format!("{target_non_zero_type}::{fn_name}({arg_snippet})");
     span_lint_and_sugg(
@@ -94,7 +115,7 @@ fn suggest_non_zero_conversion(
         format!("consider using `{target_non_zero_type}::{fn_name}()` for more efficient and type-safe conversion"),
         "replace with",
         suggestion,
-        Applicability::MachineApplicable,
+        applicability,
     );
 }
 
diff --git a/tests/ui/non_zero_suggestions.fixed b/tests/ui/non_zero_suggestions.fixed
index d7e6b19edc1f6..9851063782e70 100644
--- a/tests/ui/non_zero_suggestions.fixed
+++ b/tests/ui/non_zero_suggestions.fixed
@@ -1,5 +1,4 @@
 #![warn(clippy::non_zero_suggestions)]
-
 use std::num::{NonZeroI16, NonZeroI8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
 
 fn main() {
@@ -19,43 +18,33 @@ fn main() {
     let r3 = a / NonZeroU32::from(b);
     //~^ ERROR: consider using `NonZeroU32::from()` for more efficient and type-safe conversion
 
-    // I8 -> I16
-    let c: i16 = 25;
-    let d = NonZeroI8::new(3).unwrap();
-    let r4 = NonZeroI16::from(d);
-    //~^ ERROR: consider using `NonZeroI16::from()` for more efficient and type-safe conversion
-
-    // Different operations
-    let m: u64 = 400;
-    let n = NonZeroU32::new(20).unwrap();
-    let r5 = m / NonZeroU64::from(n);
+    let x = NonZeroU64::from(NonZeroU32::new(5).unwrap());
     //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
 
-    /// Edge cases
-    // Using the max value of a type
-    let max_u32 = NonZeroU32::new(u32::MAX).unwrap();
-    let r6 = NonZeroU64::from(max_u32);
-    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+    /// Negative test cases (lint should not trigger)
+    // Left hand side expressions should not be triggered
+    let c: u32 = 50;
+    let d = NonZeroU16::new(5).unwrap();
+    let r4 = u32::from(b.get()) / a;
 
-    // Chained method calls
-    let _ = NonZeroU64::from(NonZeroU32::new(10).unwrap());
-    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+    // Should not trigger for any other operand other than `/` and `%`
+    let r5 = a + u32::from(b.get());
+    let r6 = a - u32::from(b.get());
 
-    /// Negative test cases (lint should not trigger)
     // Same size types
     let e: u32 = 200;
     let f = NonZeroU32::new(20).unwrap();
-    let r10 = e / f.get();
+    let r7 = e / f.get();
 
     // Smaller to larger, but not NonZero
     let g: u64 = 1000;
     let h: u32 = 50;
-    let r11 = g / u64::from(h);
+    let r8 = g / u64::from(h);
 
     // Using From correctly
     let k: u64 = 300;
     let l = NonZeroU32::new(15).unwrap();
-    let r12 = k / NonZeroU64::from(l);
+    let r9 = k / NonZeroU64::from(l);
 }
 
 // Additional function to test the lint in a different context
@@ -64,13 +53,6 @@ fn divide_numbers(x: u64, y: NonZeroU32) -> u64 {
     //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
 }
 
-fn no_bin_exp(x: u64, y: NonZeroU32) -> u64 {
-    NonZeroU64::from(y)
-    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-}
-
-fn some_fn_that_only_takes_u64(_: u64) {}
-
 struct Calculator {
     value: u64,
 }
@@ -78,5 +60,6 @@ struct Calculator {
 impl Calculator {
     fn divide(&self, divisor: NonZeroU32) -> u64 {
         self.value / NonZeroU64::from(divisor)
+        //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
     }
 }
diff --git a/tests/ui/non_zero_suggestions.rs b/tests/ui/non_zero_suggestions.rs
index 8f256dabcb849..1605c459248c2 100644
--- a/tests/ui/non_zero_suggestions.rs
+++ b/tests/ui/non_zero_suggestions.rs
@@ -1,5 +1,4 @@
 #![warn(clippy::non_zero_suggestions)]
-
 use std::num::{NonZeroI16, NonZeroI8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
 
 fn main() {
@@ -19,43 +18,33 @@ fn main() {
     let r3 = a / u32::from(b.get());
     //~^ ERROR: consider using `NonZeroU32::from()` for more efficient and type-safe conversion
 
-    // I8 -> I16
-    let c: i16 = 25;
-    let d = NonZeroI8::new(3).unwrap();
-    let r4 = i16::from(d.get());
-    //~^ ERROR: consider using `NonZeroI16::from()` for more efficient and type-safe conversion
-
-    // Different operations
-    let m: u64 = 400;
-    let n = NonZeroU32::new(20).unwrap();
-    let r5 = m / u64::from(n.get());
+    let x = u64::from(NonZeroU32::new(5).unwrap().get());
     //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
 
-    /// Edge cases
-    // Using the max value of a type
-    let max_u32 = NonZeroU32::new(u32::MAX).unwrap();
-    let r6 = u64::from(max_u32.get());
-    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+    /// Negative test cases (lint should not trigger)
+    // Left hand side expressions should not be triggered
+    let c: u32 = 50;
+    let d = NonZeroU16::new(5).unwrap();
+    let r4 = u32::from(b.get()) / a;
 
-    // Chained method calls
-    let _ = u64::from(NonZeroU32::new(10).unwrap().get());
-    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+    // Should not trigger for any other operand other than `/` and `%`
+    let r5 = a + u32::from(b.get());
+    let r6 = a - u32::from(b.get());
 
-    /// Negative test cases (lint should not trigger)
     // Same size types
     let e: u32 = 200;
     let f = NonZeroU32::new(20).unwrap();
-    let r10 = e / f.get();
+    let r7 = e / f.get();
 
     // Smaller to larger, but not NonZero
     let g: u64 = 1000;
     let h: u32 = 50;
-    let r11 = g / u64::from(h);
+    let r8 = g / u64::from(h);
 
     // Using From correctly
     let k: u64 = 300;
     let l = NonZeroU32::new(15).unwrap();
-    let r12 = k / NonZeroU64::from(l);
+    let r9 = k / NonZeroU64::from(l);
 }
 
 // Additional function to test the lint in a different context
@@ -64,13 +53,6 @@ fn divide_numbers(x: u64, y: NonZeroU32) -> u64 {
     //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
 }
 
-fn no_bin_exp(x: u64, y: NonZeroU32) -> u64 {
-    u64::from(y.get())
-    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-}
-
-fn some_fn_that_only_takes_u64(_: u64) {}
-
 struct Calculator {
     value: u64,
 }
@@ -78,5 +60,6 @@ struct Calculator {
 impl Calculator {
     fn divide(&self, divisor: NonZeroU32) -> u64 {
         self.value / u64::from(divisor.get())
+        //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
     }
 }
diff --git a/tests/ui/non_zero_suggestions.stderr b/tests/ui/non_zero_suggestions.stderr
index b231c8d216ed5..7a57f7983be74 100644
--- a/tests/ui/non_zero_suggestions.stderr
+++ b/tests/ui/non_zero_suggestions.stderr
@@ -1,5 +1,5 @@
 error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:10:18
+  --> tests/ui/non_zero_suggestions.rs:9:18
    |
 LL |     let r1 = x / u64::from(y.get());
    |                  ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`
@@ -8,58 +8,34 @@ LL |     let r1 = x / u64::from(y.get());
    = help: to override `-D warnings` add `#[allow(clippy::non_zero_suggestions)]`
 
 error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:13:18
+  --> tests/ui/non_zero_suggestions.rs:12:18
    |
 LL |     let r2 = x % u64::from(y.get());
    |                  ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`
 
 error: consider using `NonZeroU32::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:19:18
+  --> tests/ui/non_zero_suggestions.rs:18:18
    |
 LL |     let r3 = a / u32::from(b.get());
    |                  ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU32::from(b)`
 
-error: consider using `NonZeroI16::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:25:14
-   |
-LL |     let r4 = i16::from(d.get());
-   |              ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroI16::from(d)`
-
-error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:31:18
-   |
-LL |     let r5 = m / u64::from(n.get());
-   |                  ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(n)`
-
 error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:37:14
+  --> tests/ui/non_zero_suggestions.rs:21:13
    |
-LL |     let r6 = u64::from(max_u32.get());
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(max_u32)`
+LL |     let x = u64::from(NonZeroU32::new(5).unwrap().get());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(NonZeroU32::new(5).unwrap())`
 
 error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:41:13
-   |
-LL |     let _ = u64::from(NonZeroU32::new(10).unwrap().get());
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(NonZeroU32::new(10).unwrap())`
-
-error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:63:9
+  --> tests/ui/non_zero_suggestions.rs:52:9
    |
 LL |     x / u64::from(y.get())
    |         ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`
 
 error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:68:5
-   |
-LL |     u64::from(y.get())
-   |     ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`
-
-error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions.rs:80:22
+  --> tests/ui/non_zero_suggestions.rs:62:22
    |
 LL |         self.value / u64::from(divisor.get())
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(divisor)`
 
-error: aborting due to 10 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui/non_zero_suggestions_unfixable.rs b/tests/ui/non_zero_suggestions_unfixable.rs
new file mode 100644
index 0000000000000..71f5f94dcc7bc
--- /dev/null
+++ b/tests/ui/non_zero_suggestions_unfixable.rs
@@ -0,0 +1,20 @@
+#![warn(clippy::non_zero_suggestions)]
+//@no-rustfix
+use std::num::{NonZeroI16, NonZeroI8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
+
+fn main() {
+    let x: u64 = u64::from(NonZeroU32::new(5).unwrap().get());
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+
+    let n = NonZeroU32::new(20).unwrap();
+    let y = u64::from(n.get());
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+    some_fn_that_only_takes_u64(y);
+}
+
+fn return_non_zero(x: u64, y: NonZeroU32) -> u64 {
+    u64::from(y.get())
+    //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+}
+
+fn some_fn_that_only_takes_u64(_: u64) {}
diff --git a/tests/ui/non_zero_suggestions_unfixable.stderr b/tests/ui/non_zero_suggestions_unfixable.stderr
new file mode 100644
index 0000000000000..5e22fddbb1a4b
--- /dev/null
+++ b/tests/ui/non_zero_suggestions_unfixable.stderr
@@ -0,0 +1,23 @@
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+  --> tests/ui/non_zero_suggestions_unfixable.rs:6:18
+   |
+LL |     let x: u64 = u64::from(NonZeroU32::new(5).unwrap().get());
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(NonZeroU32::new(5).unwrap())`
+   |
+   = note: `-D clippy::non-zero-suggestions` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::non_zero_suggestions)]`
+
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+  --> tests/ui/non_zero_suggestions_unfixable.rs:10:13
+   |
+LL |     let y = u64::from(n.get());
+   |             ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(n)`
+
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+  --> tests/ui/non_zero_suggestions_unfixable.rs:16:5
+   |
+LL |     u64::from(y.get())
+   |     ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`
+
+error: aborting due to 3 previous errors
+

From af3346a85ffd0952f11581d83c6d6d3d57ae205b Mon Sep 17 00:00:00 2001
From: Samarth1696 <samarthrobo03@gmail.com>
Date: Sat, 31 Aug 2024 11:53:16 +0530
Subject: [PATCH 053/114] Check for get method and new test case in unfixable

---
 clippy_lints/src/non_zero_suggestions.rs       | 1 +
 tests/ui/non_zero_suggestions_unfixable.rs     | 3 +++
 tests/ui/non_zero_suggestions_unfixable.stderr | 2 +-
 3 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/clippy_lints/src/non_zero_suggestions.rs b/clippy_lints/src/non_zero_suggestions.rs
index 808de147d722e..90a9f2e994b81 100644
--- a/clippy_lints/src/non_zero_suggestions.rs
+++ b/clippy_lints/src/non_zero_suggestions.rs
@@ -72,6 +72,7 @@ fn check_non_zero_conversion(cx: &LateContext<'_>, expr: &Expr<'_>, applicabilit
         && let ExprKind::Path(qpath) = &func.kind
         && let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id()
         && let ExprKind::MethodCall(rcv_path, receiver, _, _) = &arg.kind
+        && rcv_path.ident.name.as_str() == "get"
     {
         let fn_name = cx.tcx.item_name(def_id);
         let target_ty = cx.typeck_results().expr_ty(expr);
diff --git a/tests/ui/non_zero_suggestions_unfixable.rs b/tests/ui/non_zero_suggestions_unfixable.rs
index 71f5f94dcc7bc..4eb22a8d4c717 100644
--- a/tests/ui/non_zero_suggestions_unfixable.rs
+++ b/tests/ui/non_zero_suggestions_unfixable.rs
@@ -10,6 +10,9 @@ fn main() {
     let y = u64::from(n.get());
     //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
     some_fn_that_only_takes_u64(y);
+
+    let m = NonZeroU32::try_from(1).unwrap();
+    let _z: NonZeroU64 = m.into();
 }
 
 fn return_non_zero(x: u64, y: NonZeroU32) -> u64 {
diff --git a/tests/ui/non_zero_suggestions_unfixable.stderr b/tests/ui/non_zero_suggestions_unfixable.stderr
index 5e22fddbb1a4b..787179f2a2d64 100644
--- a/tests/ui/non_zero_suggestions_unfixable.stderr
+++ b/tests/ui/non_zero_suggestions_unfixable.stderr
@@ -14,7 +14,7 @@ LL |     let y = u64::from(n.get());
    |             ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(n)`
 
 error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
-  --> tests/ui/non_zero_suggestions_unfixable.rs:16:5
+  --> tests/ui/non_zero_suggestions_unfixable.rs:19:5
    |
 LL |     u64::from(y.get())
    |     ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`

From ae5326b967d5a3d34d3c562882feeacd9839950c Mon Sep 17 00:00:00 2001
From: y21 <30553356+y21@users.noreply.github.com>
Date: Sat, 7 Sep 2024 17:06:32 +0200
Subject: [PATCH 054/114] visit struct fields in uninit fallback check

---
 clippy_utils/src/ty.rs     | 11 +++++++----
 tests/ui/uninit_vec.rs     | 32 ++++++++++++++++++++++++++++++++
 tests/ui/uninit_vec.stderr | 24 +++++++++++++++++++++++-
 3 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs
index f80981c11af65..5756e56c262e0 100644
--- a/clippy_utils/src/ty.rs
+++ b/clippy_utils/src/ty.rs
@@ -606,10 +606,13 @@ fn is_uninit_value_valid_for_ty_fallback<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t
         ty::Tuple(types) => types.iter().all(|ty| is_uninit_value_valid_for_ty(cx, ty)),
         // Unions are always fine right now.
         // This includes MaybeUninit, the main way people use uninitialized memory.
-        // For ADTs, we could look at all fields just like for tuples, but that's potentially
-        // exponential, so let's avoid doing that for now. Code doing that is sketchy enough to
-        // just use an `#[allow()]`.
-        ty::Adt(adt, _) => adt.is_union(),
+        ty::Adt(adt, _) if adt.is_union() => true,
+        // Types (e.g. `UnsafeCell<MaybeUninit<T>>`) that recursively contain only types that can be uninit
+        // can themselves be uninit too.
+        // This purposefully ignores enums as they may have a discriminant that can't be uninit.
+        ty::Adt(adt, args) if adt.is_struct() => adt
+            .all_fields()
+            .all(|field| is_uninit_value_valid_for_ty(cx, field.ty(cx.tcx, args))),
         // For the rest, conservatively assume that they cannot be uninit.
         _ => false,
     }
diff --git a/tests/ui/uninit_vec.rs b/tests/ui/uninit_vec.rs
index 0cc77a8775d57..464f88140bdba 100644
--- a/tests/ui/uninit_vec.rs
+++ b/tests/ui/uninit_vec.rs
@@ -150,4 +150,36 @@ fn main() {
             vec.set_len(10);
         }
     }
+
+    fn nested_union<T>() {
+        let mut vec: Vec<UnsafeCell<MaybeUninit<T>>> = Vec::with_capacity(1);
+        unsafe {
+            vec.set_len(1);
+        }
+    }
+
+    struct Recursive<T>(*const Recursive<T>, MaybeUninit<T>);
+    fn recursive_union<T>() {
+        // Make sure we don't stack overflow on recursive types.
+        // The pointer acts as the base case because it can't be uninit regardless of its pointee.
+
+        let mut vec: Vec<Recursive<T>> = Vec::with_capacity(1);
+        //~^ uninit_vec
+        unsafe {
+            vec.set_len(1);
+        }
+    }
+
+    #[repr(u8)]
+    enum Enum<T> {
+        Variant(T),
+    }
+    fn union_in_enum<T>() {
+        // Enums can have a discriminant that can't be uninit, so this should still warn
+        let mut vec: Vec<Enum<T>> = Vec::with_capacity(1);
+        //~^ uninit_vec
+        unsafe {
+            vec.set_len(1);
+        }
+    }
 }
diff --git a/tests/ui/uninit_vec.stderr b/tests/ui/uninit_vec.stderr
index e8b77d653f089..e7c81cf792f23 100644
--- a/tests/ui/uninit_vec.stderr
+++ b/tests/ui/uninit_vec.stderr
@@ -125,5 +125,27 @@ LL |             vec.set_len(10);
    |
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
-error: aborting due to 12 previous errors
+error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
+  --> tests/ui/uninit_vec.rs:166:9
+   |
+LL |         let mut vec: Vec<Recursive<T>> = Vec::with_capacity(1);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |             vec.set_len(1);
+   |             ^^^^^^^^^^^^^^
+   |
+   = help: initialize the buffer or wrap the content in `MaybeUninit`
+
+error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
+  --> tests/ui/uninit_vec.rs:179:9
+   |
+LL |         let mut vec: Vec<Enum<T>> = Vec::with_capacity(1);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |             vec.set_len(1);
+   |             ^^^^^^^^^^^^^^
+   |
+   = help: initialize the buffer or wrap the content in `MaybeUninit`
+
+error: aborting due to 14 previous errors
 

From 25efc04ea554301374ac8e6270dbc7f65fead347 Mon Sep 17 00:00:00 2001
From: Jake Herrmann <jtherrmann1@gmail.com>
Date: Sat, 7 Sep 2024 12:00:34 -0800
Subject: [PATCH 055/114] Fix typo

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

diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs
index 125f694996c1c..7d24d25dc2fa4 100644
--- a/clippy_lints/src/ptr.rs
+++ b/clippy_lints/src/ptr.rs
@@ -34,7 +34,7 @@ declare_clippy_lint! {
     /// with the appropriate `.to_owned()`/`to_string()` calls.
     ///
     /// ### Why is this bad?
-    /// Requiring the argument to be of the specific size
+    /// Requiring the argument to be of the specific type
     /// makes the function less useful for no benefit; slices in the form of `&[T]`
     /// or `&str` usually suffice and can be obtained from other types, too.
     ///

From 9e9526c6ab12fce8113d6c18d348572f4f98492b Mon Sep 17 00:00:00 2001
From: Samuel Tardieu <sam@rfc1149.net>
Date: Sat, 7 Sep 2024 16:18:45 +0200
Subject: [PATCH 056/114] Special-case suggestions for null pointers constness
 cast

---
 clippy_lints/src/casts/mod.rs                |  6 +-
 clippy_lints/src/casts/ptr_cast_constness.rs | 62 ++++++++++++++------
 tests/ui/ptr_cast_constness.fixed            | 13 ++++
 tests/ui/ptr_cast_constness.rs               | 13 ++++
 tests/ui/ptr_cast_constness.stderr           | 22 ++++++-
 5 files changed, 97 insertions(+), 19 deletions(-)

diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index c31716fbcee1d..fccddf558ed82 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -410,19 +410,23 @@ declare_clippy_lint! {
     /// ### Why is this bad?
     /// Though `as` casts between raw pointers are not terrible, `pointer::cast_mut` and
     /// `pointer::cast_const` are safer because they cannot accidentally cast the pointer to another
-    /// type.
+    /// type. Or, when null pointers are involved, `null()` and `null_mut()` can be used directly.
     ///
     /// ### Example
     /// ```no_run
     /// let ptr: *const u32 = &42_u32;
     /// let mut_ptr = ptr as *mut u32;
     /// let ptr = mut_ptr as *const u32;
+    /// let ptr1 = std::ptr::null::<u32>() as *mut u32;
+    /// let ptr2 = std::ptr::null_mut::<u32>() as *const u32;
     /// ```
     /// Use instead:
     /// ```no_run
     /// let ptr: *const u32 = &42_u32;
     /// let mut_ptr = ptr.cast_mut();
     /// let ptr = mut_ptr.cast_const();
+    /// let ptr1 = std::ptr::null_mut::<u32>();
+    /// let ptr2 = std::ptr::null::<u32>();
     /// ```
     #[clippy::version = "1.72.0"]
     pub PTR_CAST_CONSTNESS,
diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs
index 7513e18d408b1..98bc38ed134df 100644
--- a/clippy_lints/src/casts/ptr_cast_constness.rs
+++ b/clippy_lints/src/casts/ptr_cast_constness.rs
@@ -1,10 +1,12 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::std_or_core;
 use clippy_utils::sugg::Sugg;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, Mutability};
+use rustc_hir::{Expr, ExprKind, Mutability, QPath};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
+use rustc_span::sym;
 
 use super::PTR_CAST_CONSTNESS;
 
@@ -16,8 +18,7 @@ pub(super) fn check<'tcx>(
     cast_to: Ty<'tcx>,
     msrv: &Msrv,
 ) {
-    if msrv.meets(msrvs::POINTER_CAST_CONSTNESS)
-        && let ty::RawPtr(from_ty, from_mutbl) = cast_from.kind()
+    if let ty::RawPtr(from_ty, from_mutbl) = cast_from.kind()
         && let ty::RawPtr(to_ty, to_mutbl) = cast_to.kind()
         && matches!(
             (from_mutbl, to_mutbl),
@@ -26,20 +27,47 @@ pub(super) fn check<'tcx>(
         && from_ty == to_ty
         && !from_ty.has_erased_regions()
     {
-        let sugg = Sugg::hir(cx, cast_expr, "_");
-        let constness = match *to_mutbl {
-            Mutability::Not => "const",
-            Mutability::Mut => "mut",
-        };
+        if let ExprKind::Call(func, []) = cast_expr.kind
+            && let ExprKind::Path(QPath::Resolved(None, path)) = func.kind
+            && let Some(defid) = path.res.opt_def_id()
+            && let Some(prefix) = std_or_core(cx)
+            && let mut app = Applicability::MachineApplicable
+            && let sugg = format!("{}", Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app))
+            && let Some((_, after_lt)) = sugg.split_once("::<")
+            && let Some((source, target, target_func)) = match cx.tcx.get_diagnostic_name(defid) {
+                Some(sym::ptr_null) => Some(("const", "mutable", "null_mut")),
+                Some(sym::ptr_null_mut) => Some(("mutable", "const", "null")),
+                _ => None,
+            }
+        {
+            span_lint_and_sugg(
+                cx,
+                PTR_CAST_CONSTNESS,
+                expr.span,
+                format!("`as` casting to make a {source} null pointer into a {target} null pointer"),
+                format!("use `{target_func}()` directly instead"),
+                format!("{prefix}::ptr::{target_func}::<{after_lt}"),
+                app,
+            );
+            return;
+        }
 
-        span_lint_and_sugg(
-            cx,
-            PTR_CAST_CONSTNESS,
-            expr.span,
-            "`as` casting between raw pointers while changing only its constness",
-            format!("try `pointer::cast_{constness}`, a safer alternative"),
-            format!("{}.cast_{constness}()", sugg.maybe_par()),
-            Applicability::MachineApplicable,
-        );
+        if msrv.meets(msrvs::POINTER_CAST_CONSTNESS) {
+            let sugg = Sugg::hir(cx, cast_expr, "_");
+            let constness = match *to_mutbl {
+                Mutability::Not => "const",
+                Mutability::Mut => "mut",
+            };
+
+            span_lint_and_sugg(
+                cx,
+                PTR_CAST_CONSTNESS,
+                expr.span,
+                "`as` casting between raw pointers while changing only its constness",
+                format!("try `pointer::cast_{constness}`, a safer alternative"),
+                format!("{}.cast_{constness}()", sugg.maybe_par()),
+                Applicability::MachineApplicable,
+            );
+        }
     }
 }
diff --git a/tests/ui/ptr_cast_constness.fixed b/tests/ui/ptr_cast_constness.fixed
index 21ac42196e1bb..5bf9a30b01617 100644
--- a/tests/ui/ptr_cast_constness.fixed
+++ b/tests/ui/ptr_cast_constness.fixed
@@ -68,3 +68,16 @@ fn _msrv_1_65() {
     let _ = ptr.cast_mut();
     let _ = mut_ptr.cast_const();
 }
+
+#[inline_macros]
+fn null_pointers() {
+    use std::ptr;
+    let _ = std::ptr::null_mut::<String>();
+    let _ = std::ptr::null::<u32>();
+
+    // Make sure the lint is triggered inside a macro
+    let _ = inline!(std::ptr::null_mut::<u32>());
+
+    // Do not lint inside macros from external crates
+    let _ = external!(ptr::null::<u32>() as *mut u32);
+}
diff --git a/tests/ui/ptr_cast_constness.rs b/tests/ui/ptr_cast_constness.rs
index 5ce590b2b7e47..2575a5923e124 100644
--- a/tests/ui/ptr_cast_constness.rs
+++ b/tests/ui/ptr_cast_constness.rs
@@ -68,3 +68,16 @@ fn _msrv_1_65() {
     let _ = ptr as *mut u32;
     let _ = mut_ptr as *const u32;
 }
+
+#[inline_macros]
+fn null_pointers() {
+    use std::ptr;
+    let _ = ptr::null::<String>() as *mut String;
+    let _ = ptr::null_mut::<u32>() as *const u32;
+
+    // Make sure the lint is triggered inside a macro
+    let _ = inline!(ptr::null::<u32>() as *mut u32);
+
+    // Do not lint inside macros from external crates
+    let _ = external!(ptr::null::<u32>() as *mut u32);
+}
diff --git a/tests/ui/ptr_cast_constness.stderr b/tests/ui/ptr_cast_constness.stderr
index 2c52ebd3464d6..0806ca62806d1 100644
--- a/tests/ui/ptr_cast_constness.stderr
+++ b/tests/ui/ptr_cast_constness.stderr
@@ -43,5 +43,25 @@ error: `as` casting between raw pointers while changing only its constness
 LL |     let _ = mut_ptr as *const u32;
    |             ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()`
 
-error: aborting due to 7 previous errors
+error: `as` casting to make a const null pointer into a mutable null pointer
+  --> tests/ui/ptr_cast_constness.rs:75:13
+   |
+LL |     let _ = ptr::null::<String>() as *mut String;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<String>()`
+
+error: `as` casting to make a mutable null pointer into a const null pointer
+  --> tests/ui/ptr_cast_constness.rs:76:13
+   |
+LL |     let _ = ptr::null_mut::<u32>() as *const u32;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::<u32>()`
+
+error: `as` casting to make a const null pointer into a mutable null pointer
+  --> tests/ui/ptr_cast_constness.rs:79:21
+   |
+LL |     let _ = inline!(ptr::null::<u32>() as *mut u32);
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<u32>()`
+   |
+   = note: this error originates in the macro `__inline_mac_fn_null_pointers` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 10 previous errors
 

From 30608732c2f68c423e4a62e6c20cdf28f6d38559 Mon Sep 17 00:00:00 2001
From: Samuel Tardieu <sam@rfc1149.net>
Date: Sat, 7 Sep 2024 21:57:29 +0200
Subject: [PATCH 057/114] Handle null pointer constness cast through methods

This covers two cases:

- `core::ptr::null::<T>().cast_mut()` -> `core::ptr::null_mut::<T>()`
- `core::ptr::null_mut::<T>().cast_const()` -> `core::ptr::null::<T>()`
---
 clippy_lints/src/casts/mod.rs                |  5 ++++
 clippy_lints/src/casts/ptr_cast_constness.rs | 27 ++++++++++++++++++++
 tests/ui/ptr_cast_constness.fixed            |  4 +++
 tests/ui/ptr_cast_constness.rs               |  4 +++
 tests/ui/ptr_cast_constness.stderr           | 24 +++++++++++++++--
 5 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index fccddf558ed82..39f50a347c064 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -419,6 +419,8 @@ declare_clippy_lint! {
     /// let ptr = mut_ptr as *const u32;
     /// let ptr1 = std::ptr::null::<u32>() as *mut u32;
     /// let ptr2 = std::ptr::null_mut::<u32>() as *const u32;
+    /// let ptr3 = std::ptr::null::<u32>().cast_mut();
+    /// let ptr4 = std::ptr::null_mut::<u32>().cast_const();
     /// ```
     /// Use instead:
     /// ```no_run
@@ -427,6 +429,8 @@ declare_clippy_lint! {
     /// let ptr = mut_ptr.cast_const();
     /// let ptr1 = std::ptr::null_mut::<u32>();
     /// let ptr2 = std::ptr::null::<u32>();
+    /// let ptr3 = std::ptr::null_mut::<u32>();
+    /// let ptr4 = std::ptr::null::<u32>();
     /// ```
     #[clippy::version = "1.72.0"]
     pub PTR_CAST_CONSTNESS,
@@ -813,6 +817,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
         char_lit_as_u8::check(cx, expr);
         ptr_as_ptr::check(cx, expr, &self.msrv);
         cast_slice_different_sizes::check(cx, expr, &self.msrv);
+        ptr_cast_constness::check_null_ptr_cast_method(cx, expr);
     }
 
     extract_msrv_attr!(LateContext);
diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs
index 98bc38ed134df..7518dd2435aee 100644
--- a/clippy_lints/src/casts/ptr_cast_constness.rs
+++ b/clippy_lints/src/casts/ptr_cast_constness.rs
@@ -71,3 +71,30 @@ pub(super) fn check<'tcx>(
         }
     }
 }
+
+pub(super) fn check_null_ptr_cast_method(cx: &LateContext<'_>, expr: &Expr<'_>) {
+    if let ExprKind::MethodCall(method, cast_expr, [], _) = expr.kind
+        && let ExprKind::Call(func, []) = cast_expr.kind
+        && let ExprKind::Path(QPath::Resolved(None, path)) = func.kind
+        && let Some(defid) = path.res.opt_def_id()
+        && let method = match (cx.tcx.get_diagnostic_name(defid), method.ident.as_str()) {
+            (Some(sym::ptr_null), "cast_mut") => "null_mut",
+            (Some(sym::ptr_null_mut), "cast_const") => "null",
+            _ => return,
+        }
+        && let Some(prefix) = std_or_core(cx)
+        && let mut app = Applicability::MachineApplicable
+        && let sugg = format!("{}", Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app))
+        && let Some((_, after_lt)) = sugg.split_once("::<")
+    {
+        span_lint_and_sugg(
+            cx,
+            PTR_CAST_CONSTNESS,
+            expr.span,
+            "changing constness of a null pointer",
+            format!("use `{method}()` directly instead"),
+            format!("{prefix}::ptr::{method}::<{after_lt}"),
+            app,
+        );
+    }
+}
diff --git a/tests/ui/ptr_cast_constness.fixed b/tests/ui/ptr_cast_constness.fixed
index 5bf9a30b01617..9a5272c7adc36 100644
--- a/tests/ui/ptr_cast_constness.fixed
+++ b/tests/ui/ptr_cast_constness.fixed
@@ -74,10 +74,14 @@ fn null_pointers() {
     use std::ptr;
     let _ = std::ptr::null_mut::<String>();
     let _ = std::ptr::null::<u32>();
+    let _ = std::ptr::null_mut::<u32>();
+    let _ = std::ptr::null::<u32>();
 
     // Make sure the lint is triggered inside a macro
     let _ = inline!(std::ptr::null_mut::<u32>());
+    let _ = inline!(std::ptr::null_mut::<u32>());
 
     // Do not lint inside macros from external crates
     let _ = external!(ptr::null::<u32>() as *mut u32);
+    let _ = external!(ptr::null::<u32>().cast_mut());
 }
diff --git a/tests/ui/ptr_cast_constness.rs b/tests/ui/ptr_cast_constness.rs
index 2575a5923e124..43ab5f5ba7ccc 100644
--- a/tests/ui/ptr_cast_constness.rs
+++ b/tests/ui/ptr_cast_constness.rs
@@ -74,10 +74,14 @@ fn null_pointers() {
     use std::ptr;
     let _ = ptr::null::<String>() as *mut String;
     let _ = ptr::null_mut::<u32>() as *const u32;
+    let _ = ptr::null::<u32>().cast_mut();
+    let _ = ptr::null_mut::<u32>().cast_const();
 
     // Make sure the lint is triggered inside a macro
     let _ = inline!(ptr::null::<u32>() as *mut u32);
+    let _ = inline!(ptr::null::<u32>().cast_mut());
 
     // Do not lint inside macros from external crates
     let _ = external!(ptr::null::<u32>() as *mut u32);
+    let _ = external!(ptr::null::<u32>().cast_mut());
 }
diff --git a/tests/ui/ptr_cast_constness.stderr b/tests/ui/ptr_cast_constness.stderr
index 0806ca62806d1..a693793a4ae96 100644
--- a/tests/ui/ptr_cast_constness.stderr
+++ b/tests/ui/ptr_cast_constness.stderr
@@ -55,13 +55,33 @@ error: `as` casting to make a mutable null pointer into a const null pointer
 LL |     let _ = ptr::null_mut::<u32>() as *const u32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::<u32>()`
 
+error: changing constness of a null pointer
+  --> tests/ui/ptr_cast_constness.rs:77:13
+   |
+LL |     let _ = ptr::null::<u32>().cast_mut();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<u32>()`
+
+error: changing constness of a null pointer
+  --> tests/ui/ptr_cast_constness.rs:78:13
+   |
+LL |     let _ = ptr::null_mut::<u32>().cast_const();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::<u32>()`
+
 error: `as` casting to make a const null pointer into a mutable null pointer
-  --> tests/ui/ptr_cast_constness.rs:79:21
+  --> tests/ui/ptr_cast_constness.rs:81:21
    |
 LL |     let _ = inline!(ptr::null::<u32>() as *mut u32);
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<u32>()`
    |
    = note: this error originates in the macro `__inline_mac_fn_null_pointers` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 10 previous errors
+error: changing constness of a null pointer
+  --> tests/ui/ptr_cast_constness.rs:82:21
+   |
+LL |     let _ = inline!(ptr::null::<u32>().cast_mut());
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<u32>()`
+   |
+   = note: this error originates in the macro `__inline_mac_fn_null_pointers` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 13 previous errors
 

From b0db9c285dae65fc30a72d6862264df23feae430 Mon Sep 17 00:00:00 2001
From: cuishuang <imcusg@gmail.com>
Date: Mon, 9 Sep 2024 16:43:46 +0800
Subject: [PATCH 058/114] Remove unnecessary symbols and add missing symbols

Signed-off-by: cuishuang <imcusg@gmail.com>
---
 clippy_lints/src/methods/unnecessary_to_owned.rs | 2 +-
 tests/ui/crashes/ice-3969.rs                     | 4 ++--
 tests/ui/crashes/ice-6251.rs                     | 2 +-
 tests/ui/floating_point_arithmetic_nostd.rs      | 2 +-
 tests/ui/unsafe_removed_from_name.rs             | 2 +-
 5 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs
index 69c5bc57e2996..9e198c7e55cd7 100644
--- a/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -717,7 +717,7 @@ fn check_if_applicable_to_argument<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'tcx
 // check that:
 // 1. This is a method with only one argument that doesn't come from a trait.
 // 2. That it has `Borrow` in its generic predicates.
-// 3. `Self` is a std "map type" (ie `HashSet`, `HashMap`, BTreeSet`, `BTreeMap`).
+// 3. `Self` is a std "map type" (ie `HashSet`, `HashMap`, `BTreeSet`, `BTreeMap`).
 fn check_borrow_predicate<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
     if let ExprKind::MethodCall(_, caller, &[arg], _) = expr.kind
         && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
diff --git a/tests/ui/crashes/ice-3969.rs b/tests/ui/crashes/ice-3969.rs
index d5676cbd91d19..ac09ce08753af 100644
--- a/tests/ui/crashes/ice-3969.rs
+++ b/tests/ui/crashes/ice-3969.rs
@@ -1,7 +1,7 @@
 // https://github.com/rust-lang/rust-clippy/issues/3969
 // used to crash: error: internal compiler error:
 // src/librustc_traits/normalize_erasing_regions.rs:43: could not fully normalize `<i32 as
-// std::iter::Iterator>::Item test from rustc ./ui/trivial-bounds/trivial-bounds-inconsistent.rs
+// std::iter::Iterator>::Item` test from rustc ./ui/trivial-bounds/trivial-bounds-inconsistent.rs
 
 // Check that tautalogically false bounds are accepted, and are used
 // in type inference.
@@ -18,7 +18,7 @@ struct Dst<X: ?Sized> {
 struct TwoStrs(str, str)
 where
     str: Sized;
-//~^ ERROR: trait bound str: std::marker::Sized does not depend on any type or lifetim
+//~^ ERROR: trait bound str: std::marker::Sized does not depend on any type or lifetime
 //~| NOTE: `-D trivial-bounds` implied by `-D warnings`
 
 fn unsized_local()
diff --git a/tests/ui/crashes/ice-6251.rs b/tests/ui/crashes/ice-6251.rs
index a81137a646558..73e919b6dd2eb 100644
--- a/tests/ui/crashes/ice-6251.rs
+++ b/tests/ui/crashes/ice-6251.rs
@@ -1,5 +1,5 @@
 // originally from glacier/fixed/77329.rs
-// assertion failed: `(left == right) ; different DefIds
+// assertion failed: `(left == right)` ; different DefIds
 //@no-rustfix
 fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> {
     std::iter::empty()
diff --git a/tests/ui/floating_point_arithmetic_nostd.rs b/tests/ui/floating_point_arithmetic_nostd.rs
index 47c113d61c041..8ea75fae89b65 100644
--- a/tests/ui/floating_point_arithmetic_nostd.rs
+++ b/tests/ui/floating_point_arithmetic_nostd.rs
@@ -4,7 +4,7 @@
 #![no_std]
 
 // The following should not lint, as the suggested methods `{f16,f32,f64,f128}.mul_add()`
-// and ``{f16,f32,f64,f128}::abs()` are not available in no_std
+// and `{f16,f32,f64,f128}::abs()` are not available in no_std
 
 pub fn mul_add() {
     let a: f64 = 1234.567;
diff --git a/tests/ui/unsafe_removed_from_name.rs b/tests/ui/unsafe_removed_from_name.rs
index e0e0ded140fc0..e9e6c8312f5eb 100644
--- a/tests/ui/unsafe_removed_from_name.rs
+++ b/tests/ui/unsafe_removed_from_name.rs
@@ -7,7 +7,7 @@ use std::cell::UnsafeCell as TotallySafeCell;
 //~| NOTE: `-D clippy::unsafe-removed-from-name` implied by `-D warnings`
 
 use std::cell::UnsafeCell as TotallySafeCellAgain;
-//~^ ERROR: removed `unsafe` from the name of `UnsafeCell` in use as `TotallySafeCellAgain
+//~^ ERROR: removed `unsafe` from the name of `UnsafeCell` in use as `TotallySafeCellAgain`
 
 // Shouldn't error
 use std::cell::RefCell as ProbablyNotUnsafe;

From 1f1363335922b76e6940cf632a391f3315f564cf Mon Sep 17 00:00:00 2001
From: Oli Scherer <github@oli-obk.de>
Date: Sat, 17 Aug 2024 21:38:10 +0200
Subject: [PATCH 059/114] Bump ui_test

---
 Cargo.toml                                    |  2 +-
 tests/compile-test.rs                         | 10 ++-
 tests/ui/asm_syntax_not_x86.rs                |  3 +-
 tests/ui/asm_syntax_x86.rs                    |  4 +-
 tests/ui/asm_syntax_x86.stderr                | 70 +++++++++++++++++++
 tests/ui/crashes/ice-7410.rs                  |  3 +-
 .../entrypoint_recursion.rs                   |  2 +-
 .../no_std_main_recursion.rs                  |  2 +-
 tests/ui/def_id_nocore.rs                     |  2 +-
 tests/ui/empty_loop_no_std.rs                 |  2 +-
 tests/ui/enum_clike_unportable_variant.rs     |  2 +-
 tests/ui/macro_use_imports.fixed              |  2 +-
 tests/ui/macro_use_imports.rs                 |  2 +-
 tests/ui/macro_use_imports_expect.rs          |  2 +-
 tests/ui/mixed_attributes_style.rs            |  3 +-
 tests/ui/mixed_attributes_style.stderr        |  3 +-
 tests/ui/non_octal_unix_permissions.fixed     |  2 +-
 tests/ui/non_octal_unix_permissions.rs        |  2 +-
 tests/ui/result_large_err.rs                  |  2 +-
 tests/ui/single_call_fn.rs                    |  2 +-
 tests/ui/transmute_32bit.rs                   |  2 +-
 tests/ui/transmute_64bit.rs                   |  2 +-
 22 files changed, 96 insertions(+), 30 deletions(-)
 create mode 100644 tests/ui/asm_syntax_x86.stderr

diff --git a/Cargo.toml b/Cargo.toml
index 5b62e387ac631..cf810798d8cc1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -31,7 +31,7 @@ anstream = "0.6.0"
 
 [dev-dependencies]
 cargo_metadata = "0.18.1"
-ui_test = "0.25"
+ui_test = "0.26.4"
 regex = "1.5.5"
 serde = { version = "1.0.145", features = ["derive"] }
 serde_json = "1.0.122"
diff --git a/tests/compile-test.rs b/tests/compile-test.rs
index 9754254cdd0df..c7243348ce46f 100644
--- a/tests/compile-test.rs
+++ b/tests/compile-test.rs
@@ -13,7 +13,6 @@ use test_utils::IS_RUSTC_TEST_SUITE;
 use ui_test::custom_flags::rustfix::RustfixMode;
 use ui_test::custom_flags::Flag;
 use ui_test::spanned::Spanned;
-use ui_test::test_result::TestRun;
 use ui_test::{status_emitter, Args, CommandBuilder, Config, Match, OutputConflictHandling};
 
 use std::collections::{BTreeMap, HashMap};
@@ -469,15 +468,14 @@ fn applicability_ord(applicability: &Applicability) -> u8 {
 impl Flag for DiagnosticCollector {
     fn post_test_action(
         &self,
-        _config: &ui_test::per_test_config::TestConfig<'_>,
-        _cmd: &mut std::process::Command,
+        _config: &ui_test::per_test_config::TestConfig,
         output: &std::process::Output,
-        _build_manager: &ui_test::build_manager::BuildManager<'_>,
-    ) -> Result<Vec<TestRun>, ui_test::Errored> {
+        _build_manager: &ui_test::build_manager::BuildManager,
+    ) -> Result<(), ui_test::Errored> {
         if !output.stderr.is_empty() {
             self.sender.send(output.stderr.clone()).unwrap();
         }
-        Ok(Vec::new())
+        Ok(())
     }
 
     fn clone_inner(&self) -> Box<dyn Flag> {
diff --git a/tests/ui/asm_syntax_not_x86.rs b/tests/ui/asm_syntax_not_x86.rs
index 33cea4806814b..a7d29cc239e53 100644
--- a/tests/ui/asm_syntax_not_x86.rs
+++ b/tests/ui/asm_syntax_not_x86.rs
@@ -1,5 +1,4 @@
-//@ignore-target-i686
-//@ignore-target-x86
+//@ignore-target: i686 x86
 //@needs-asm-support
 
 #[warn(clippy::inline_asm_x86_intel_syntax)]
diff --git a/tests/ui/asm_syntax_x86.rs b/tests/ui/asm_syntax_x86.rs
index 835943b43894c..5ceaceb7527b3 100644
--- a/tests/ui/asm_syntax_x86.rs
+++ b/tests/ui/asm_syntax_x86.rs
@@ -1,6 +1,4 @@
-//@revisions: i686 x86_64
-//@[i686] only-target-i686
-//@[x86_64] only-target-x86_64
+//@only-target: i686 x86_64
 
 #[warn(clippy::inline_asm_x86_intel_syntax)]
 mod warn_intel {
diff --git a/tests/ui/asm_syntax_x86.stderr b/tests/ui/asm_syntax_x86.stderr
new file mode 100644
index 0000000000000..1911ef66e2391
--- /dev/null
+++ b/tests/ui/asm_syntax_x86.stderr
@@ -0,0 +1,70 @@
+error: Intel x86 assembly syntax used
+  --> tests/ui/asm_syntax_x86.rs:8:9
+   |
+LL |         asm!("");
+   |         ^^^^^^^^
+   |
+   = help: use AT&T x86 assembly syntax
+   = note: `-D clippy::inline-asm-x86-intel-syntax` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::inline_asm_x86_intel_syntax)]`
+
+error: Intel x86 assembly syntax used
+  --> tests/ui/asm_syntax_x86.rs:10:9
+   |
+LL |         asm!("", options());
+   |         ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use AT&T x86 assembly syntax
+
+error: Intel x86 assembly syntax used
+  --> tests/ui/asm_syntax_x86.rs:12:9
+   |
+LL |         asm!("", options(nostack));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use AT&T x86 assembly syntax
+
+error: Intel x86 assembly syntax used
+  --> tests/ui/asm_syntax_x86.rs:18:5
+   |
+LL |     global_asm!("");
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: use AT&T x86 assembly syntax
+
+error: Intel x86 assembly syntax used
+  --> tests/ui/asm_syntax_x86.rs:20:5
+   |
+LL |     global_asm!("", options());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use AT&T x86 assembly syntax
+
+error: AT&T x86 assembly syntax used
+  --> tests/ui/asm_syntax_x86.rs:33:9
+   |
+LL |         asm!("", options(att_syntax));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use Intel x86 assembly syntax
+   = note: `-D clippy::inline-asm-x86-att-syntax` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::inline_asm_x86_att_syntax)]`
+
+error: AT&T x86 assembly syntax used
+  --> tests/ui/asm_syntax_x86.rs:35:9
+   |
+LL |         asm!("", options(nostack, att_syntax));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use Intel x86 assembly syntax
+
+error: AT&T x86 assembly syntax used
+  --> tests/ui/asm_syntax_x86.rs:41:5
+   |
+LL |     global_asm!("", options(att_syntax));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use Intel x86 assembly syntax
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/crashes/ice-7410.rs b/tests/ui/crashes/ice-7410.rs
index a2683b3ce3402..ccf6d7ff94f23 100644
--- a/tests/ui/crashes/ice-7410.rs
+++ b/tests/ui/crashes/ice-7410.rs
@@ -1,6 +1,5 @@
 //@compile-flags: -Clink-arg=-nostartfiles
-//@ignore-target-apple
-//@ignore-target-windows
+//@ignore-target: apple windows
 
 #![feature(lang_items, start, libc)]
 #![no_std]
diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.rs b/tests/ui/crate_level_checks/entrypoint_recursion.rs
index aa76688d80101..5d853d97bc35b 100644
--- a/tests/ui/crate_level_checks/entrypoint_recursion.rs
+++ b/tests/ui/crate_level_checks/entrypoint_recursion.rs
@@ -1,4 +1,4 @@
-//@ignore-target-apple
+//@ignore-target: apple
 
 #![feature(rustc_attrs)]
 
diff --git a/tests/ui/crate_level_checks/no_std_main_recursion.rs b/tests/ui/crate_level_checks/no_std_main_recursion.rs
index 32eba9695920c..9e5b2a4890348 100644
--- a/tests/ui/crate_level_checks/no_std_main_recursion.rs
+++ b/tests/ui/crate_level_checks/no_std_main_recursion.rs
@@ -1,5 +1,5 @@
 //@compile-flags: -Clink-arg=-nostartfiles
-//@ignore-target-apple
+//@ignore-target: apple
 
 #![feature(lang_items, start, libc)]
 #![no_std]
diff --git a/tests/ui/def_id_nocore.rs b/tests/ui/def_id_nocore.rs
index 190d636ebf34a..c9650312db878 100644
--- a/tests/ui/def_id_nocore.rs
+++ b/tests/ui/def_id_nocore.rs
@@ -1,4 +1,4 @@
-//@ignore-target-apple
+//@ignore-target: apple
 
 #![feature(no_core, lang_items, start)]
 #![no_core]
diff --git a/tests/ui/empty_loop_no_std.rs b/tests/ui/empty_loop_no_std.rs
index 5fe32351ed450..1bb895bda75d7 100644
--- a/tests/ui/empty_loop_no_std.rs
+++ b/tests/ui/empty_loop_no_std.rs
@@ -1,5 +1,5 @@
 //@compile-flags: -Clink-arg=-nostartfiles
-//@ignore-target-apple
+//@ignore-target: apple
 
 #![warn(clippy::empty_loop)]
 #![feature(lang_items, start, libc)]
diff --git a/tests/ui/enum_clike_unportable_variant.rs b/tests/ui/enum_clike_unportable_variant.rs
index c50404c5047bb..37849179d6a0b 100644
--- a/tests/ui/enum_clike_unportable_variant.rs
+++ b/tests/ui/enum_clike_unportable_variant.rs
@@ -1,4 +1,4 @@
-//@ignore-32bit
+//@ignore-bitwidth: 32
 
 #![warn(clippy::enum_clike_unportable_variant)]
 #![allow(unused, non_upper_case_globals)]
diff --git a/tests/ui/macro_use_imports.fixed b/tests/ui/macro_use_imports.fixed
index 38ed5a957e73e..28844fab74793 100644
--- a/tests/ui/macro_use_imports.fixed
+++ b/tests/ui/macro_use_imports.fixed
@@ -2,7 +2,7 @@
 //@aux-build:macro_use_helper.rs
 //@aux-build:proc_macro_derive.rs
 
-//@ignore-32bit
+//@ignore-bitwidth: 32
 
 #![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)]
 #![allow(clippy::single_component_path_imports)]
diff --git a/tests/ui/macro_use_imports.rs b/tests/ui/macro_use_imports.rs
index ae6cc16ed2769..5381f29598987 100644
--- a/tests/ui/macro_use_imports.rs
+++ b/tests/ui/macro_use_imports.rs
@@ -2,7 +2,7 @@
 //@aux-build:macro_use_helper.rs
 //@aux-build:proc_macro_derive.rs
 
-//@ignore-32bit
+//@ignore-bitwidth: 32
 
 #![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)]
 #![allow(clippy::single_component_path_imports)]
diff --git a/tests/ui/macro_use_imports_expect.rs b/tests/ui/macro_use_imports_expect.rs
index df6d5b9fbabf2..60cce1d24a289 100644
--- a/tests/ui/macro_use_imports_expect.rs
+++ b/tests/ui/macro_use_imports_expect.rs
@@ -1,7 +1,7 @@
 //@aux-build:macro_rules.rs
 //@aux-build:macro_use_helper.rs
 //@aux-build:proc_macro_derive.rs
-//@ignore-32bit
+//@ignore-bitwidth: 32
 
 #![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)]
 #![allow(clippy::single_component_path_imports)]
diff --git a/tests/ui/mixed_attributes_style.rs b/tests/ui/mixed_attributes_style.rs
index 1a646c2652236..93ab9392cf8bd 100644
--- a/tests/ui/mixed_attributes_style.rs
+++ b/tests/ui/mixed_attributes_style.rs
@@ -82,7 +82,8 @@ mod issue_12530 {
             #![allow(dead_code)]
         }
     }
-    /// Nested mod //~ ERROR: item has both inner and outer attributes
+    /// Nested mod
+    //~^ ERROR: item has both inner and outer attributes
     #[allow(unused)]
     mod nest_mod_2 {
         #![allow(unused)]
diff --git a/tests/ui/mixed_attributes_style.stderr b/tests/ui/mixed_attributes_style.stderr
index a1d3fc430f6cf..abdc2df23cf12 100644
--- a/tests/ui/mixed_attributes_style.stderr
+++ b/tests/ui/mixed_attributes_style.stderr
@@ -46,13 +46,14 @@ error: item has both inner and outer attributes
   --> tests/ui/mixed_attributes_style.rs:85:5
    |
 LL | /     /// Nested mod
+LL | |
 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
+  --> tests/ui/mixed_attributes_style.rs:91:9
    |
 LL | /         #[allow(dead_code)]
 LL | |         mod inner_mod {
diff --git a/tests/ui/non_octal_unix_permissions.fixed b/tests/ui/non_octal_unix_permissions.fixed
index 237f5f5b97a4f..f68d5e30d27e7 100644
--- a/tests/ui/non_octal_unix_permissions.fixed
+++ b/tests/ui/non_octal_unix_permissions.fixed
@@ -1,4 +1,4 @@
-//@ignore-target-windows
+//@ignore-target: windows
 
 #![warn(clippy::non_octal_unix_permissions)]
 use std::fs::{DirBuilder, File, OpenOptions, Permissions};
diff --git a/tests/ui/non_octal_unix_permissions.rs b/tests/ui/non_octal_unix_permissions.rs
index c8da5dbcec282..647c3769d2c3f 100644
--- a/tests/ui/non_octal_unix_permissions.rs
+++ b/tests/ui/non_octal_unix_permissions.rs
@@ -1,4 +1,4 @@
-//@ignore-target-windows
+//@ignore-target: windows
 
 #![warn(clippy::non_octal_unix_permissions)]
 use std::fs::{DirBuilder, File, OpenOptions, Permissions};
diff --git a/tests/ui/result_large_err.rs b/tests/ui/result_large_err.rs
index b25348bf99617..9c39f023da2da 100644
--- a/tests/ui/result_large_err.rs
+++ b/tests/ui/result_large_err.rs
@@ -1,4 +1,4 @@
-//@ignore-32bit
+//@ignore-bitwidth: 32
 
 #![warn(clippy::result_large_err)]
 #![allow(clippy::large_enum_variant)]
diff --git a/tests/ui/single_call_fn.rs b/tests/ui/single_call_fn.rs
index 55e7508a9573a..a0597664da55c 100644
--- a/tests/ui/single_call_fn.rs
+++ b/tests/ui/single_call_fn.rs
@@ -1,4 +1,4 @@
-//@ignore-32bit
+//@ignore-bitwidth: 32
 //@aux-build:proc_macros.rs
 #![allow(clippy::redundant_closure_call, unused)]
 #![warn(clippy::single_call_fn)]
diff --git a/tests/ui/transmute_32bit.rs b/tests/ui/transmute_32bit.rs
index 8e1316ca39d4f..e162bbb2d9296 100644
--- a/tests/ui/transmute_32bit.rs
+++ b/tests/ui/transmute_32bit.rs
@@ -1,4 +1,4 @@
-//@ignore-64bit
+//@ignore-bitwidth: 64
 
 #[warn(clippy::wrong_transmute)]
 fn main() {
diff --git a/tests/ui/transmute_64bit.rs b/tests/ui/transmute_64bit.rs
index 767cc503a39df..fd0ad74bcfa0a 100644
--- a/tests/ui/transmute_64bit.rs
+++ b/tests/ui/transmute_64bit.rs
@@ -1,4 +1,4 @@
-//@ignore-32bit
+//@ignore-bitwidth: 32
 
 #[warn(clippy::wrong_transmute)]
 fn main() {

From 49a501856dd3dc390de7a7ef01ac9c48c13f209c Mon Sep 17 00:00:00 2001
From: Alexey Semenyuk <alexsemenyuk88@gmail.com>
Date: Wed, 11 Sep 2024 12:40:20 +0500
Subject: [PATCH 060/114] Fix WHILE_LET_LOOP doc

---
 clippy_lints/src/loops/mod.rs | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs
index 92ccc0cc0a15e..5155fd76b253e 100644
--- a/clippy_lints/src/loops/mod.rs
+++ b/clippy_lints/src/loops/mod.rs
@@ -188,22 +188,22 @@ declare_clippy_lint! {
     /// The `while let` loop is usually shorter and more
     /// readable.
     ///
-    /// ### Known problems
-    /// Sometimes the wrong binding is displayed ([#383](https://github.com/rust-lang/rust-clippy/issues/383)).
-    ///
     /// ### Example
     /// ```rust,no_run
-    /// # let y = Some(1);
+    /// let y = Some(1);
     /// loop {
     ///     let x = match y {
     ///         Some(x) => x,
     ///         None => break,
     ///     };
-    ///     // .. do something with x
+    ///     // ..
     /// }
-    /// // is easier written as
+    /// ```
+    /// Use instead:
+    /// ```rust,no_run
+    /// let y = Some(1);
     /// while let Some(x) = y {
-    ///     // .. do something with x
+    ///     // ..
     /// };
     /// ```
     #[clippy::version = "pre 1.29.0"]

From 2775dcdd24c2fa6a3596a071450f8863d0746d78 Mon Sep 17 00:00:00 2001
From: Alex Macleod <alex@macleod.io>
Date: Wed, 11 Sep 2024 13:45:03 +0000
Subject: [PATCH 061/114] Remove unused collect_metadata function

---
 tests/dogfood.rs | 49 +-----------------------------------------------
 1 file changed, 1 insertion(+), 48 deletions(-)

diff --git a/tests/dogfood.rs b/tests/dogfood.rs
index 8d10d5e7161a6..858be389a9e6e 100644
--- a/tests/dogfood.rs
+++ b/tests/dogfood.rs
@@ -6,11 +6,9 @@
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
 use itertools::Itertools;
-use std::fs::File;
 use std::io::{self, IsTerminal};
 use std::path::PathBuf;
 use std::process::Command;
-use std::time::SystemTime;
 use test_utils::IS_RUSTC_TEST_SUITE;
 use ui_test::Args;
 
@@ -28,11 +26,7 @@ fn main() {
             println!("dogfood: test");
         }
     } else if !args.skip.iter().any(|arg| arg == "dogfood") {
-        if args.filters.iter().any(|arg| arg == "collect_metadata") {
-            collect_metadata();
-        } else {
-            dogfood();
-        }
+        dogfood();
     }
 }
 
@@ -61,47 +55,6 @@ fn dogfood() {
     );
 }
 
-fn collect_metadata() {
-    assert!(cfg!(feature = "internal"));
-
-    // Setup for validation
-    let metadata_output_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("util/gh-pages/lints.json");
-    let start_time = SystemTime::now();
-
-    // Run collection as is
-    std::env::set_var("ENABLE_METADATA_COLLECTION", "1");
-    assert!(run_clippy_for_package(
-        "clippy_lints",
-        &["-A", "unfulfilled_lint_expectations"]
-    ));
-
-    // Check if cargo caching got in the way
-    if let Ok(file) = File::open(metadata_output_path) {
-        if let Ok(metadata) = file.metadata() {
-            if let Ok(last_modification) = metadata.modified() {
-                if last_modification > start_time {
-                    // The output file has been modified. Most likely by a hungry
-                    // metadata collection monster. So We'll return.
-                    return;
-                }
-            }
-        }
-    }
-
-    // Force cargo to invalidate the caches
-    filetime::set_file_mtime(
-        PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("clippy_lints/src/lib.rs"),
-        filetime::FileTime::now(),
-    )
-    .unwrap();
-
-    // Running the collection again
-    assert!(run_clippy_for_package(
-        "clippy_lints",
-        &["-A", "unfulfilled_lint_expectations"]
-    ));
-}
-
 #[must_use]
 fn run_clippy_for_package(project: &str, args: &[&str]) -> bool {
     let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));

From 0905a7786e44727b265cb11486d742f1c6681e7d Mon Sep 17 00:00:00 2001
From: Caio <c410.f3r@gmail.com>
Date: Wed, 11 Sep 2024 13:58:05 -0300
Subject: [PATCH 062/114] Fix #13381

---
 clippy_lints/src/panic_in_result_fn.rs | 12 +++++++-----
 tests/ui/panic_in_result_fn.rs         |  9 +++++++++
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/clippy_lints/src/panic_in_result_fn.rs b/clippy_lints/src/panic_in_result_fn.rs
index 381975199d285..fa15d5e4f9f5a 100644
--- a/clippy_lints/src/panic_in_result_fn.rs
+++ b/clippy_lints/src/panic_in_result_fn.rs
@@ -1,8 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::root_macro_call_first_node;
-use clippy_utils::return_ty;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::{is_inside_always_const_context, return_ty};
 use core::ops::ControlFlow;
 use rustc_hir as hir;
 use rustc_hir::intravisit::FnKind;
@@ -68,10 +68,12 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir
         let Some(macro_call) = root_macro_call_first_node(cx, e) else {
             return ControlFlow::Continue(Descend::Yes);
         };
-        if matches!(
-            cx.tcx.item_name(macro_call.def_id).as_str(),
-            "panic" | "assert" | "assert_eq" | "assert_ne"
-        ) {
+        if !is_inside_always_const_context(cx.tcx, e.hir_id)
+            && matches!(
+                cx.tcx.item_name(macro_call.def_id).as_str(),
+                "panic" | "assert" | "assert_eq" | "assert_ne"
+            )
+        {
             panics.push(macro_call.span);
             ControlFlow::Continue(Descend::No)
         } else {
diff --git a/tests/ui/panic_in_result_fn.rs b/tests/ui/panic_in_result_fn.rs
index aaaf9a109acbb..e2375aa996f7d 100644
--- a/tests/ui/panic_in_result_fn.rs
+++ b/tests/ui/panic_in_result_fn.rs
@@ -71,6 +71,15 @@ fn function_result_with_custom_todo() -> Result<bool, String> // should not emit
     Ok(true)
 }
 
+fn issue_13381<const N: usize>() -> Result<(), String> {
+    const {
+        if N == 0 {
+            panic!();
+        }
+    }
+    Ok(())
+}
+
 fn main() -> Result<(), String> {
     todo!("finish main method");
     Ok(())

From 1c2e9f8775f9911cb81ddf1b20a59ed2137b004a Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Wed, 11 Sep 2024 18:52:36 -0400
Subject: [PATCH 063/114] Remove unused functions from ast CoroutineKind

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

diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs
index 181bbdde8e5f1..de8bbb619f8e4 100644
--- a/clippy_utils/src/ast_utils.rs
+++ b/clippy_utils/src/ast_utils.rs
@@ -221,7 +221,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
         ) => {
             eq_closure_binder(lb, rb)
                 && lc == rc
-                && la.map_or(false, CoroutineKind::is_async) == ra.map_or(false, CoroutineKind::is_async)
+                && eq_coroutine_kind(*la, *ra)
                 && lm == rm
                 && eq_fn_decl(lf, rf)
                 && eq_expr(le, re)
@@ -241,6 +241,16 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
     }
 }
 
+fn eq_coroutine_kind(a: Option<CoroutineKind>, b: Option<CoroutineKind>) -> bool {
+    match (a, b) {
+        (Some(CoroutineKind::Async { .. }), Some(CoroutineKind::Async { .. }))
+        | (Some(CoroutineKind::Gen { .. }), Some(CoroutineKind::Gen { .. }))
+        | (Some(CoroutineKind::AsyncGen { .. }), Some(CoroutineKind::AsyncGen { .. }))
+        | (None, None) => true,
+        _ => false,
+    }
+}
+
 pub fn eq_field(l: &ExprField, r: &ExprField) -> bool {
     l.is_placeholder == r.is_placeholder
         && eq_id(l.ident, r.ident)

From 7097830a9b6c2d9c56d0b8cea7b0612dc8a53b50 Mon Sep 17 00:00:00 2001
From: Alexey Semenyuk <alexsemenyuk88@gmail.com>
Date: Thu, 12 Sep 2024 11:49:16 +0500
Subject: [PATCH 064/114] Not trigger duplicated_attributes on duplicate
 reasons

---
 clippy_lints/src/attrs/duplicated_attributes.rs | 2 +-
 tests/ui/duplicated_attributes.rs               | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/clippy_lints/src/attrs/duplicated_attributes.rs b/clippy_lints/src/attrs/duplicated_attributes.rs
index 40a1c4e288422..199e07565b0ea 100644
--- a/clippy_lints/src/attrs/duplicated_attributes.rs
+++ b/clippy_lints/src/attrs/duplicated_attributes.rs
@@ -36,7 +36,7 @@ fn check_duplicated_attr(
     }
     let Some(ident) = attr.ident() else { return };
     let name = ident.name;
-    if name == sym::doc || name == sym::cfg_attr || name == sym::rustc_on_unimplemented {
+    if name == sym::doc || name == sym::cfg_attr || name == sym::rustc_on_unimplemented || name == sym::reason {
         // FIXME: Would be nice to handle `cfg_attr` as well. Only problem is to check that cfg
         // conditions are the same.
         // `#[rustc_on_unimplemented]` contains duplicated subattributes, that's expected.
diff --git a/tests/ui/duplicated_attributes.rs b/tests/ui/duplicated_attributes.rs
index 97cf4a69682d7..874f5d22075c1 100644
--- a/tests/ui/duplicated_attributes.rs
+++ b/tests/ui/duplicated_attributes.rs
@@ -27,4 +27,8 @@ trait Abc {}
 #[proc_macro_attr::duplicated_attr()] // Should not warn!
 fn babar() {}
 
+#[allow(missing_docs, reason = "library for internal use only")]
+#[allow(exported_private_dependencies, reason = "library for internal use only")]
+fn duplicate_reason() {}
+
 fn main() {}

From 6371b308d86757a6328ad4b6ecb3bcdd2a1c6d7a Mon Sep 17 00:00:00 2001
From: Samuel Tardieu <sam@rfc1149.net>
Date: Thu, 12 Sep 2024 16:31:05 +0200
Subject: [PATCH 065/114] Make it clearer that the suggestion is an alternative
 one

`needless_pass_by_value` sometimes suggest marking the concerned type as
`Copy`. Adding a `or` before this suggestion makes it clearer that this
is not the second part of the original suggestion, but an alternative one.
---
 clippy_lints/src/needless_pass_by_value.rs                | 2 +-
 .../ui/crashes/needless_pass_by_value-w-late-bound.stderr | 2 +-
 tests/ui/needless_pass_by_value.stderr                    | 8 ++++----
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs
index 5bf390056f6c7..887070bcf9af5 100644
--- a/clippy_lints/src/needless_pass_by_value.rs
+++ b/clippy_lints/src/needless_pass_by_value.rs
@@ -208,7 +208,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                             )
                             .is_ok()
                             {
-                                diag.span_help(span, "consider marking this type as `Copy`");
+                                diag.span_help(span, "or consider marking this type as `Copy`");
                             }
                         }
                     }
diff --git a/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr b/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr
index 90076d4338a47..2847957000692 100644
--- a/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr
+++ b/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr
@@ -4,7 +4,7 @@ error: this argument is passed by value, but not consumed in the function body
 LL | fn test(x: Foo<'_>) {}
    |            ^^^^^^^ help: consider taking a reference instead: `&Foo<'_>`
    |
-help: consider marking this type as `Copy`
+help: or consider marking this type as `Copy`
   --> tests/ui/crashes/needless_pass_by_value-w-late-bound.rs:5:1
    |
 LL | struct Foo<'a>(&'a [(); 100]);
diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr
index dce28186ff85e..46ef8f3e8da43 100644
--- a/tests/ui/needless_pass_by_value.stderr
+++ b/tests/ui/needless_pass_by_value.stderr
@@ -121,7 +121,7 @@ error: this argument is passed by value, but not consumed in the function body
 LL | fn bar_copy(x: u32, y: CopyWrapper) {
    |                        ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper`
    |
-help: consider marking this type as `Copy`
+help: or consider marking this type as `Copy`
   --> tests/ui/needless_pass_by_value.rs:141:1
    |
 LL | struct CopyWrapper(u32);
@@ -133,7 +133,7 @@ error: this argument is passed by value, but not consumed in the function body
 LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) {
    |                             ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper`
    |
-help: consider marking this type as `Copy`
+help: or consider marking this type as `Copy`
   --> tests/ui/needless_pass_by_value.rs:141:1
    |
 LL | struct CopyWrapper(u32);
@@ -145,7 +145,7 @@ error: this argument is passed by value, but not consumed in the function body
 LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) {
    |                                             ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper`
    |
-help: consider marking this type as `Copy`
+help: or consider marking this type as `Copy`
   --> tests/ui/needless_pass_by_value.rs:141:1
    |
 LL | struct CopyWrapper(u32);
@@ -157,7 +157,7 @@ error: this argument is passed by value, but not consumed in the function body
 LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) {
    |                                                             ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper`
    |
-help: consider marking this type as `Copy`
+help: or consider marking this type as `Copy`
   --> tests/ui/needless_pass_by_value.rs:141:1
    |
 LL | struct CopyWrapper(u32);

From d66e9addd685c8fc2264e68590d745e869311242 Mon Sep 17 00:00:00 2001
From: VictorHugoPilled <echase3@gmail.com>
Date: Tue, 10 Sep 2024 21:38:59 +0000
Subject: [PATCH 066/114] fix: Fixed incorrect comment form suggestion

chore: Ran cargo dev fmt

chore: Fixed spacing

fix: Fixed spacing for comment suggestion

fix: Added new module level test to too_long_first_doc_paragraph

chore: Ran cargo uibless
---
 .../src/doc/too_long_first_doc_paragraph.rs   |  9 +++++-
 tests/ui/too_long_first_doc_paragraph.rs      | 10 +++++++
 tests/ui/too_long_first_doc_paragraph.stderr  | 28 +++++++++++++++----
 3 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/clippy_lints/src/doc/too_long_first_doc_paragraph.rs b/clippy_lints/src/doc/too_long_first_doc_paragraph.rs
index 7bb3bb12f2ca9..0165d24c7df27 100644
--- a/clippy_lints/src/doc/too_long_first_doc_paragraph.rs
+++ b/clippy_lints/src/doc/too_long_first_doc_paragraph.rs
@@ -79,10 +79,17 @@ pub(super) fn check(
                 && let new_span = first_span.with_hi(second_span.lo()).with_lo(first_span.hi())
                 && let Some(snippet) = snippet_opt(cx, new_span)
             {
+                let Some(first) = snippet_opt(cx, first_span) else {
+                    return;
+                };
+                let Some(comment_form) = first.get(..3) else {
+                    return;
+                };
+
                 diag.span_suggestion(
                     new_span,
                     "add an empty line",
-                    format!("{snippet}///\n"),
+                    format!("{snippet}{comment_form}{snippet}"),
                     Applicability::MachineApplicable,
                 );
             }
diff --git a/tests/ui/too_long_first_doc_paragraph.rs b/tests/ui/too_long_first_doc_paragraph.rs
index 1042249c5b7bd..7d0a37cde46db 100644
--- a/tests/ui/too_long_first_doc_paragraph.rs
+++ b/tests/ui/too_long_first_doc_paragraph.rs
@@ -2,6 +2,16 @@
 
 #![warn(clippy::too_long_first_doc_paragraph)]
 
+pub mod foo {
+
+    // in foo.rs
+    //! A very short summary.
+    //! A much longer explanation that goes into a lot more detail about
+    //! how the thing works, possibly with doclinks and so one,
+    //! and probably spanning a many rows. Blablabla, it needs to be over
+    //! 200 characters so I needed to write something longeeeeeeer.
+}
+
 /// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia
 /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero,
 /// gravida non lacinia at, rhoncus eu lacus.
diff --git a/tests/ui/too_long_first_doc_paragraph.stderr b/tests/ui/too_long_first_doc_paragraph.stderr
index 7f48e5cf884e6..39926647f5437 100644
--- a/tests/ui/too_long_first_doc_paragraph.stderr
+++ b/tests/ui/too_long_first_doc_paragraph.stderr
@@ -1,16 +1,32 @@
 error: first doc comment paragraph is too long
-  --> tests/ui/too_long_first_doc_paragraph.rs:5:1
+  --> tests/ui/too_long_first_doc_paragraph.rs:8:5
+   |
+LL | /     //! A very short summary.
+LL | |     //! A much longer explanation that goes into a lot more detail about
+LL | |     //! how the thing works, possibly with doclinks and so one,
+LL | |     //! and probably spanning a many rows. Blablabla, it needs to be over
+LL | |     //! 200 characters so I needed to write something longeeeeeeer.
+   | |____^
+   |
+   = note: `-D clippy::too-long-first-doc-paragraph` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::too_long_first_doc_paragraph)]`
+help: add an empty line
+   |
+LL ~     //! A very short summary.
+LL +     //!
+LL ~     //! A much longer explanation that goes into a lot more detail about
+   |
+
+error: first doc comment paragraph is too long
+  --> tests/ui/too_long_first_doc_paragraph.rs:15:1
    |
 LL | / /// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia
 LL | | /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero,
 LL | | /// gravida non lacinia at, rhoncus eu lacus.
    | |_
-   |
-   = note: `-D clippy::too-long-first-doc-paragraph` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::too_long_first_doc_paragraph)]`
 
 error: first doc comment paragraph is too long
-  --> tests/ui/too_long_first_doc_paragraph.rs:26:1
+  --> tests/ui/too_long_first_doc_paragraph.rs:36:1
    |
 LL | / /// Lorem
 LL | | /// ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia
@@ -18,5 +34,5 @@ LL | | /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris a
 LL | | /// gravida non lacinia at, rhoncus eu lacus.
    | |_
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 

From bc7d323bdff24e50acf3129a25c51bf77ab60ed0 Mon Sep 17 00:00:00 2001
From: Alexey Semenyuk <alexsemenyuk88@gmail.com>
Date: Thu, 12 Sep 2024 20:42:19 +0500
Subject: [PATCH 067/114] Clarify type_complexity

---
 clippy_lints/src/types/mod.rs | 55 +++++++++++++++++++++++++++++++++--
 1 file changed, 53 insertions(+), 2 deletions(-)

diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs
index 3a14927802b48..120d5ffbbd33f 100644
--- a/clippy_lints/src/types/mod.rs
+++ b/clippy_lints/src/types/mod.rs
@@ -261,8 +261,59 @@ declare_clippy_lint! {
     /// ### Example
     /// ```no_run
     /// # use std::rc::Rc;
-    /// struct Foo {
-    ///     inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>>,
+    /// struct PointMatrixContainer {
+    ///     matrix: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>>,
+    /// }
+    ///
+    /// fn main() {
+    ///     let point_matrix: Vec<Vec<Box<(u32, u32, u32, u32)>>> = vec![
+    ///         vec![
+    ///             Box::new((1, 2, 3, 4)),
+    ///             Box::new((5, 6, 7, 8)),
+    ///         ],
+    ///         vec![
+    ///             Box::new((9, 10, 11, 12)),
+    ///         ],
+    ///     ];
+    ///
+    ///     let shared_point_matrix: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>> = Rc::new(point_matrix);
+    ///
+    ///     let container = PointMatrixContainer {
+    ///         matrix: shared_point_matrix,
+    ///     };
+    ///
+    ///     // ...
+    /// }
+    /// ```
+    /// Use instead:
+    /// ### Example
+    /// ```no_run
+    /// # use std::rc::Rc;
+    /// type PointMatrix = Vec<Vec<Box<(u32, u32, u32, u32)>>>;
+    /// type SharedPointMatrix = Rc<PointMatrix>;
+    ///
+    /// struct PointMatrixContainer {
+    ///     matrix: SharedPointMatrix,
+    /// }
+    ///
+    /// fn main() {
+    ///     let point_matrix: PointMatrix = vec![
+    ///         vec![
+    ///             Box::new((1, 2, 3, 4)),
+    ///             Box::new((5, 6, 7, 8)),
+    ///         ],
+    ///         vec![
+    ///             Box::new((9, 10, 11, 12)),
+    ///         ],
+    ///     ];
+    ///
+    ///     let shared_point_matrix: SharedPointMatrix = Rc::new(point_matrix);
+    ///
+    ///     let container = PointMatrixContainer {
+    ///         matrix: shared_point_matrix,
+    ///     };
+    ///
+    ///     // ...
     /// }
     /// ```
     #[clippy::version = "pre 1.29.0"]

From cd99729478c0b50f11f2ae6badb2cf57e103cd92 Mon Sep 17 00:00:00 2001
From: Obei Sideg <obei.sideg@gmail.com>
Date: Sat, 24 Aug 2024 06:49:09 +0300
Subject: [PATCH 068/114] Update tests for hidden references to mutable static

---
 .../checked_unwrap/simple_conditionals.stderr | 13 +++-
 tests/ui/multiple_unsafe_ops_per_block.rs     |  1 +
 tests/ui/multiple_unsafe_ops_per_block.stderr | 58 +++++++--------
 tests/ui/must_use_candidates.fixed            |  7 +-
 tests/ui/must_use_candidates.rs               |  7 +-
 tests/ui/must_use_candidates.stderr           | 10 +--
 tests/ui/redundant_static_lifetimes.fixed     |  2 +
 tests/ui/redundant_static_lifetimes.rs        |  2 +
 tests/ui/redundant_static_lifetimes.stderr    | 36 ++++-----
 tests/ui/useless_conversion.fixed             |  2 +
 tests/ui/useless_conversion.rs                |  2 +
 tests/ui/useless_conversion.stderr            | 74 +++++++++----------
 12 files changed, 122 insertions(+), 92 deletions(-)

diff --git a/tests/ui/checked_unwrap/simple_conditionals.stderr b/tests/ui/checked_unwrap/simple_conditionals.stderr
index f7e338935a770..d92c03f488813 100644
--- a/tests/ui/checked_unwrap/simple_conditionals.stderr
+++ b/tests/ui/checked_unwrap/simple_conditionals.stderr
@@ -236,5 +236,16 @@ LL |     if result.is_ok() {
 LL |         result.as_mut().unwrap();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 25 previous errors
+error: creating a shared reference to mutable static is discouraged
+  --> tests/ui/checked_unwrap/simple_conditionals.rs:174:12
+   |
+LL |         if X.is_some() {
+   |            ^^^^^^^^^^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+   = note: `-D static-mut-refs` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(static_mut_refs)]`
+
+error: aborting due to 26 previous errors
 
diff --git a/tests/ui/multiple_unsafe_ops_per_block.rs b/tests/ui/multiple_unsafe_ops_per_block.rs
index 6b8a103d4a947..87d3517cd5f22 100644
--- a/tests/ui/multiple_unsafe_ops_per_block.rs
+++ b/tests/ui/multiple_unsafe_ops_per_block.rs
@@ -4,6 +4,7 @@
 #![allow(deref_nullptr)]
 #![allow(clippy::unnecessary_operation)]
 #![allow(dropping_copy_types)]
+#![allow(clippy::assign_op_pattern)]
 #![warn(clippy::multiple_unsafe_ops_per_block)]
 
 extern crate proc_macros;
diff --git a/tests/ui/multiple_unsafe_ops_per_block.stderr b/tests/ui/multiple_unsafe_ops_per_block.stderr
index e732bde0707e5..a9417a9ef91c7 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:37:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:38: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:38:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:39:9
    |
 LL |         STATIC += 1;
    |         ^^^^^^^^^^^
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:39:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:40: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:46:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:47: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:47:14
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:48:14
    |
 LL |         drop(u.u);
    |              ^^^
 note: raw pointer dereference occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:48:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:49:9
    |
 LL |         *raw_ptr();
    |         ^^^^^^^^^^
 
 error: this `unsafe` block contains 3 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:53:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:54:5
    |
 LL | /     unsafe {
 LL | |         asm!("nop");
@@ -51,23 +51,23 @@ LL | |     }
    | |_____^
    |
 note: inline assembly used here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:54:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:55:9
    |
 LL |         asm!("nop");
    |         ^^^^^^^^^^^
 note: unsafe method call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:55:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:56:9
    |
 LL |         sample.not_very_safe();
    |         ^^^^^^^^^^^^^^^^^^^^^^
 note: modification of a mutable static occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:56:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:57:9
    |
 LL |         STATIC = 0;
    |         ^^^^^^^^^^
 
 error: this `unsafe` block contains 6 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:62:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:63: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:63:14
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:64:14
    |
 LL |         drop(u.u);
    |              ^^^
 note: access of a mutable static occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:64:14
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:65:14
    |
 LL |         drop(STATIC);
    |              ^^^^^^
 note: unsafe method call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:65:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:66:9
    |
 LL |         sample.not_very_safe();
    |         ^^^^^^^^^^^^^^^^^^^^^^
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:66:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:67:9
    |
 LL |         not_very_safe();
    |         ^^^^^^^^^^^^^^^
 note: raw pointer dereference occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:67:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:68:9
    |
 LL |         *raw_ptr();
    |         ^^^^^^^^^^
 note: inline assembly used here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:68:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:69:9
    |
 LL |         asm!("nop");
    |         ^^^^^^^^^^^
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:106:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:107:5
    |
 LL |     unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:106:14
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:107:14
    |
 LL |     unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: raw pointer dereference occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:106:39
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:107: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:124:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:125:5
    |
 LL | /     unsafe {
 LL | |         x();
@@ -136,18 +136,18 @@ LL | |     }
    | |_____^
    |
 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();
    |         ^^^
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:126:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:127:9
    |
 LL |         x();
    |         ^^^
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:135:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:136: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:136:13
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:137:13
    |
 LL |             T::X();
    |             ^^^^^^
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:137:13
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:138:13
    |
 LL |             T::X();
    |             ^^^^^^
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:145:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:146: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:146:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:147:9
    |
 LL |         x.0();
    |         ^^^^^
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:147:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:148:9
    |
 LL |         x.0();
    |         ^^^^^
diff --git a/tests/ui/must_use_candidates.fixed b/tests/ui/must_use_candidates.fixed
index c057eba4aca16..adb266ffbc8dd 100644
--- a/tests/ui/must_use_candidates.fixed
+++ b/tests/ui/must_use_candidates.fixed
@@ -1,5 +1,10 @@
 #![feature(never_type)]
-#![allow(unused_mut, clippy::redundant_allocation, clippy::needless_pass_by_ref_mut)]
+#![allow(
+    unused_mut,
+    clippy::redundant_allocation,
+    clippy::needless_pass_by_ref_mut,
+    static_mut_refs
+)]
 #![warn(clippy::must_use_candidate)]
 use std::rc::Rc;
 use std::sync::atomic::{AtomicBool, Ordering};
diff --git a/tests/ui/must_use_candidates.rs b/tests/ui/must_use_candidates.rs
index 360196520062f..49bb16af788f1 100644
--- a/tests/ui/must_use_candidates.rs
+++ b/tests/ui/must_use_candidates.rs
@@ -1,5 +1,10 @@
 #![feature(never_type)]
-#![allow(unused_mut, clippy::redundant_allocation, clippy::needless_pass_by_ref_mut)]
+#![allow(
+    unused_mut,
+    clippy::redundant_allocation,
+    clippy::needless_pass_by_ref_mut,
+    static_mut_refs
+)]
 #![warn(clippy::must_use_candidate)]
 use std::rc::Rc;
 use std::sync::atomic::{AtomicBool, Ordering};
diff --git a/tests/ui/must_use_candidates.stderr b/tests/ui/must_use_candidates.stderr
index c64636ba44258..2117e37866e2d 100644
--- a/tests/ui/must_use_candidates.stderr
+++ b/tests/ui/must_use_candidates.stderr
@@ -1,5 +1,5 @@
 error: this function could have a `#[must_use]` attribute
-  --> tests/ui/must_use_candidates.rs:11:1
+  --> tests/ui/must_use_candidates.rs:16:1
    |
 LL | pub fn pure(i: u8) -> u8 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn pure(i: u8) -> u8`
@@ -8,25 +8,25 @@ LL | pub fn pure(i: u8) -> u8 {
    = help: to override `-D warnings` add `#[allow(clippy::must_use_candidate)]`
 
 error: this method could have a `#[must_use]` attribute
-  --> tests/ui/must_use_candidates.rs:16:5
+  --> tests/ui/must_use_candidates.rs:21:5
    |
 LL |     pub fn inherent_pure(&self) -> u8 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn inherent_pure(&self) -> u8`
 
 error: this function could have a `#[must_use]` attribute
-  --> tests/ui/must_use_candidates.rs:47:1
+  --> tests/ui/must_use_candidates.rs:52:1
    |
 LL | pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool`
 
 error: this function could have a `#[must_use]` attribute
-  --> tests/ui/must_use_candidates.rs:59:1
+  --> tests/ui/must_use_candidates.rs:64:1
    |
 LL | pub fn rcd(_x: Rc<u32>) -> bool {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn rcd(_x: Rc<u32>) -> bool`
 
 error: this function could have a `#[must_use]` attribute
-  --> tests/ui/must_use_candidates.rs:67:1
+  --> tests/ui/must_use_candidates.rs:72:1
    |
 LL | pub fn arcd(_x: Arc<u32>) -> bool {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn arcd(_x: Arc<u32>) -> bool`
diff --git a/tests/ui/redundant_static_lifetimes.fixed b/tests/ui/redundant_static_lifetimes.fixed
index 9787bb635e709..3d1c78bd12d9e 100644
--- a/tests/ui/redundant_static_lifetimes.fixed
+++ b/tests/ui/redundant_static_lifetimes.fixed
@@ -1,4 +1,6 @@
 #![allow(unused)]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 
 #[derive(Debug)]
 struct Foo;
diff --git a/tests/ui/redundant_static_lifetimes.rs b/tests/ui/redundant_static_lifetimes.rs
index b5a4827fa948e..5932f14b8d9a9 100644
--- a/tests/ui/redundant_static_lifetimes.rs
+++ b/tests/ui/redundant_static_lifetimes.rs
@@ -1,4 +1,6 @@
 #![allow(unused)]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 
 #[derive(Debug)]
 struct Foo;
diff --git a/tests/ui/redundant_static_lifetimes.stderr b/tests/ui/redundant_static_lifetimes.stderr
index 5c5e2f2a57360..48871eba2dc75 100644
--- a/tests/ui/redundant_static_lifetimes.stderr
+++ b/tests/ui/redundant_static_lifetimes.stderr
@@ -1,5 +1,5 @@
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:6:17
+  --> tests/ui/redundant_static_lifetimes.rs:8:17
    |
 LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR: Consider removing 'static.
    |                -^^^^^^^---- help: consider removing `'static`: `&str`
@@ -8,103 +8,103 @@ LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR: Consider removi
    = help: to override `-D warnings` add `#[allow(clippy::redundant_static_lifetimes)]`
 
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:10:21
+  --> tests/ui/redundant_static_lifetimes.rs:12:21
    |
 LL | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static
    |                    -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:12:32
+  --> tests/ui/redundant_static_lifetimes.rs:14:32
    |
 LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static
    |                               -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:12:47
+  --> tests/ui/redundant_static_lifetimes.rs:14:47
    |
 LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static
    |                                              -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:14:17
+  --> tests/ui/redundant_static_lifetimes.rs:16:17
    |
 LL | const VAR_SIX: &'static u8 = &5;
    |                -^^^^^^^--- help: consider removing `'static`: `&u8`
 
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:16:20
+  --> tests/ui/redundant_static_lifetimes.rs:18:20
    |
 LL | const VAR_HEIGHT: &'static Foo = &Foo {};
    |                   -^^^^^^^---- help: consider removing `'static`: `&Foo`
 
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:18:19
+  --> tests/ui/redundant_static_lifetimes.rs:20:19
    |
 LL | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR: Consider removing 'static.
    |                  -^^^^^^^----- help: consider removing `'static`: `&[u8]`
 
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:20:19
+  --> tests/ui/redundant_static_lifetimes.rs:22:19
    |
 LL | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static.
    |                  -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)`
 
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:22:19
+  --> tests/ui/redundant_static_lifetimes.rs:24:19
    |
 LL | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static.
    |                  -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:24:25
+  --> tests/ui/redundant_static_lifetimes.rs:26:25
    |
 LL | static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR: Consider removing 'static.
    |                        -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:28:29
+  --> tests/ui/redundant_static_lifetimes.rs:30:29
    |
 LL | static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static
    |                            -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:30:25
+  --> tests/ui/redundant_static_lifetimes.rs:32:25
    |
 LL | static STATIC_VAR_SIX: &'static u8 = &5;
    |                        -^^^^^^^--- help: consider removing `'static`: `&u8`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:32:28
+  --> tests/ui/redundant_static_lifetimes.rs:34:28
    |
 LL | static STATIC_VAR_HEIGHT: &'static Foo = &Foo {};
    |                           -^^^^^^^---- help: consider removing `'static`: `&Foo`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:34:27
+  --> tests/ui/redundant_static_lifetimes.rs:36:27
    |
 LL | static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR: Consider removing 'static.
    |                          -^^^^^^^----- help: consider removing `'static`: `&[u8]`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:36:27
+  --> tests/ui/redundant_static_lifetimes.rs:38:27
    |
 LL | static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static.
    |                          -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:38:27
+  --> tests/ui/redundant_static_lifetimes.rs:40:27
    |
 LL | static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static.
    |                          -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:40:31
+  --> tests/ui/redundant_static_lifetimes.rs:42:31
    |
 LL | static mut STATIC_MUT_SLICE: &'static mut [u32] = &mut [0];
    |                              -^^^^^^^---------- help: consider removing `'static`: `&mut [u32]`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:69:16
+  --> tests/ui/redundant_static_lifetimes.rs:71:16
    |
 LL |     static V: &'static u8 = &17;
    |               -^^^^^^^--- help: consider removing `'static`: `&u8`
diff --git a/tests/ui/useless_conversion.fixed b/tests/ui/useless_conversion.fixed
index ce00fde2f9930..eff617a801689 100644
--- a/tests/ui/useless_conversion.fixed
+++ b/tests/ui/useless_conversion.fixed
@@ -1,5 +1,7 @@
 #![deny(clippy::useless_conversion)]
 #![allow(clippy::needless_if, clippy::unnecessary_wraps)]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 
 fn test_generic<T: Copy>(val: T) -> T {
     let _ = val;
diff --git a/tests/ui/useless_conversion.rs b/tests/ui/useless_conversion.rs
index 399796195868d..64b0662078919 100644
--- a/tests/ui/useless_conversion.rs
+++ b/tests/ui/useless_conversion.rs
@@ -1,5 +1,7 @@
 #![deny(clippy::useless_conversion)]
 #![allow(clippy::needless_if, clippy::unnecessary_wraps)]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 
 fn test_generic<T: Copy>(val: T) -> T {
     let _ = T::from(val);
diff --git a/tests/ui/useless_conversion.stderr b/tests/ui/useless_conversion.stderr
index 82f945c5e89f6..b149357bcf4f4 100644
--- a/tests/ui/useless_conversion.stderr
+++ b/tests/ui/useless_conversion.stderr
@@ -1,5 +1,5 @@
 error: useless conversion to the same type: `T`
-  --> tests/ui/useless_conversion.rs:5:13
+  --> tests/ui/useless_conversion.rs:7:13
    |
 LL |     let _ = T::from(val);
    |             ^^^^^^^^^^^^ help: consider removing `T::from()`: `val`
@@ -11,217 +11,217 @@ LL | #![deny(clippy::useless_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: useless conversion to the same type: `T`
-  --> tests/ui/useless_conversion.rs:6:5
+  --> tests/ui/useless_conversion.rs:8:5
    |
 LL |     val.into()
    |     ^^^^^^^^^^ help: consider removing `.into()`: `val`
 
 error: useless conversion to the same type: `i32`
-  --> tests/ui/useless_conversion.rs:18:22
+  --> tests/ui/useless_conversion.rs:20:22
    |
 LL |         let _: i32 = 0i32.into();
    |                      ^^^^^^^^^^^ help: consider removing `.into()`: `0i32`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> tests/ui/useless_conversion.rs:48:22
+  --> tests/ui/useless_conversion.rs:50:22
    |
 LL |     if Some("ok") == lines.into_iter().next() {}
    |                      ^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `lines`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> tests/ui/useless_conversion.rs:53:21
+  --> tests/ui/useless_conversion.rs:55:21
    |
 LL |     let mut lines = text.lines().into_iter();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> tests/ui/useless_conversion.rs:59:22
+  --> tests/ui/useless_conversion.rs:61:22
    |
 LL |     if Some("ok") == text.lines().into_iter().next() {}
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()`
 
 error: useless conversion to the same type: `std::ops::Range<i32>`
-  --> tests/ui/useless_conversion.rs:65:13
+  --> tests/ui/useless_conversion.rs:67:13
    |
 LL |     let _ = NUMBERS.into_iter().next();
    |             ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS`
 
 error: useless conversion to the same type: `std::ops::Range<i32>`
-  --> tests/ui/useless_conversion.rs:70:17
+  --> tests/ui/useless_conversion.rs:72:17
    |
 LL |     let mut n = NUMBERS.into_iter();
    |                 ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion.rs:132:21
+  --> tests/ui/useless_conversion.rs:134:21
    |
 LL |     let _: String = "foo".to_string().into();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion.rs:133:21
+  --> tests/ui/useless_conversion.rs:135:21
    |
 LL |     let _: String = From::from("foo".to_string());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion.rs:134:13
+  --> tests/ui/useless_conversion.rs:136:13
    |
 LL |     let _ = String::from("foo".to_string());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion.rs:135:13
+  --> tests/ui/useless_conversion.rs:137:13
    |
 LL |     let _ = String::from(format!("A: {:04}", 123));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> tests/ui/useless_conversion.rs:136:13
+  --> tests/ui/useless_conversion.rs:138:13
    |
 LL |     let _ = "".lines().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()`
 
 error: useless conversion to the same type: `std::vec::IntoIter<i32>`
-  --> tests/ui/useless_conversion.rs:137:13
+  --> tests/ui/useless_conversion.rs:139:13
    |
 LL |     let _ = vec![1, 2, 3].into_iter().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion.rs:138:21
+  --> tests/ui/useless_conversion.rs:140:21
    |
 LL |     let _: String = format!("Hello {}", "world").into();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")`
 
 error: useless conversion to the same type: `i32`
-  --> tests/ui/useless_conversion.rs:143:13
+  --> tests/ui/useless_conversion.rs:145:13
    |
 LL |     let _ = i32::from(a + b) * 3;
    |             ^^^^^^^^^^^^^^^^ help: consider removing `i32::from()`: `(a + b)`
 
 error: useless conversion to the same type: `Foo<'a'>`
-  --> tests/ui/useless_conversion.rs:149:23
+  --> tests/ui/useless_conversion.rs:151:23
    |
 LL |     let _: Foo<'a'> = s2.into();
    |                       ^^^^^^^^^ help: consider removing `.into()`: `s2`
 
 error: useless conversion to the same type: `Foo<'a'>`
-  --> tests/ui/useless_conversion.rs:151:13
+  --> tests/ui/useless_conversion.rs:153:13
    |
 LL |     let _ = Foo::<'a'>::from(s3);
    |             ^^^^^^^^^^^^^^^^^^^^ help: consider removing `Foo::<'a'>::from()`: `s3`
 
 error: useless conversion to the same type: `std::vec::IntoIter<Foo<'a'>>`
-  --> tests/ui/useless_conversion.rs:153:13
+  --> tests/ui/useless_conversion.rs:155:13
    |
 LL |     let _ = vec![s4, s4, s4].into_iter().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()`
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:185:7
+  --> tests/ui/useless_conversion.rs:187:7
    |
 LL |     b(vec![1, 2].into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:175:13
+  --> tests/ui/useless_conversion.rs:177:13
    |
 LL |     fn b<T: IntoIterator<Item = i32>>(_: T) {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:186:7
+  --> tests/ui/useless_conversion.rs:188:7
    |
 LL |     c(vec![1, 2].into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:176:18
+  --> tests/ui/useless_conversion.rs:178:18
    |
 LL |     fn c(_: impl IntoIterator<Item = i32>) {}
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:187:7
+  --> tests/ui/useless_conversion.rs:189:7
    |
 LL |     d(vec![1, 2].into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:179:12
+  --> tests/ui/useless_conversion.rs:181:12
    |
 LL |         T: IntoIterator<Item = i32>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:190:7
+  --> tests/ui/useless_conversion.rs:192:7
    |
 LL |     b(vec![1, 2].into_iter().into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:175:13
+  --> tests/ui/useless_conversion.rs:177:13
    |
 LL |     fn b<T: IntoIterator<Item = i32>>(_: T) {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:191:7
+  --> tests/ui/useless_conversion.rs:193:7
    |
 LL |     b(vec![1, 2].into_iter().into_iter().into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:175:13
+  --> tests/ui/useless_conversion.rs:177:13
    |
 LL |     fn b<T: IntoIterator<Item = i32>>(_: T) {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:237:24
+  --> tests/ui/useless_conversion.rs:239:24
    |
 LL |         foo2::<i32, _>([1, 2, 3].into_iter());
    |                        ^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `[1, 2, 3]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:216:12
+  --> tests/ui/useless_conversion.rs:218:12
    |
 LL |         I: IntoIterator<Item = i32> + Helper<X>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:245:14
+  --> tests/ui/useless_conversion.rs:247:14
    |
 LL |         foo3([1, 2, 3].into_iter());
    |              ^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `[1, 2, 3]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:225:12
+  --> tests/ui/useless_conversion.rs:227:12
    |
 LL |         I: IntoIterator<Item = i32>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:254:16
+  --> tests/ui/useless_conversion.rs:256:16
    |
 LL |         S1.foo([1, 2].into_iter());
    |                ^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `[1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:251:27
+  --> tests/ui/useless_conversion.rs:253:27
    |
 LL |             pub fn foo<I: IntoIterator>(&self, _: I) {}
    |                           ^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:273:44
+  --> tests/ui/useless_conversion.rs:275:44
    |
 LL |         v0.into_iter().interleave_shortest(v1.into_iter());
    |                                            ^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `v1`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:260:20
+  --> tests/ui/useless_conversion.rs:262:20
    |
 LL |                 J: IntoIterator,
    |                    ^^^^^^^^^^^^

From 7fcdebf65860268b482edb38f76dc06e283504fb Mon Sep 17 00:00:00 2001
From: Trevor Spiteri <tspiteri@ieee.org>
Date: Fri, 13 Sep 2024 13:28:22 +0200
Subject: [PATCH 069/114] Revert "stabilize const_float_bits_conv" for
 src/tools/clippy/clippy_lints

This reverts the part of commit 19908ff7a37a9a431399bb6f2868efc22820f2b6 in
subdirectory src/tools/clippy/clippy_lints.
---
 clippy_lints/src/transmute/mod.rs                    | 6 +++---
 clippy_lints/src/transmute/transmute_float_to_int.rs | 3 ++-
 clippy_lints/src/transmute/transmute_int_to_float.rs | 3 ++-
 clippy_lints/src/transmute/transmute_num_to_bytes.rs | 6 ++++++
 4 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs
index a2ae36cc484ad..373bf61d8ff94 100644
--- a/clippy_lints/src/transmute/mod.rs
+++ b/clippy_lints/src/transmute/mod.rs
@@ -619,10 +619,10 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
                 | 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, &self.msrv)
                 | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg)
-                | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg)
+                | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context)
                 | transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg)
-                | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg)
-                | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg)
+                | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context)
+                | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context)
                 | (unsound_collection_transmute::check(cx, e, from_ty, to_ty)
                     || transmute_undefined_repr::check(cx, e, from_ty, to_ty))
                 | (eager_transmute::check(cx, e, arg, from_ty, to_ty));
diff --git a/clippy_lints/src/transmute/transmute_float_to_int.rs b/clippy_lints/src/transmute/transmute_float_to_int.rs
index cb46109c27e2f..ab3bb5e1062d3 100644
--- a/clippy_lints/src/transmute/transmute_float_to_int.rs
+++ b/clippy_lints/src/transmute/transmute_float_to_int.rs
@@ -15,9 +15,10 @@ pub(super) fn check<'tcx>(
     from_ty: Ty<'tcx>,
     to_ty: Ty<'tcx>,
     mut arg: &'tcx Expr<'_>,
+    const_context: bool,
 ) -> bool {
     match (&from_ty.kind(), &to_ty.kind()) {
-        (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) => {
+        (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) if !const_context => {
             span_lint_and_then(
                 cx,
                 TRANSMUTE_FLOAT_TO_INT,
diff --git a/clippy_lints/src/transmute/transmute_int_to_float.rs b/clippy_lints/src/transmute/transmute_int_to_float.rs
index e00fb90c3074e..d51888e30971b 100644
--- a/clippy_lints/src/transmute/transmute_int_to_float.rs
+++ b/clippy_lints/src/transmute/transmute_int_to_float.rs
@@ -14,9 +14,10 @@ pub(super) fn check<'tcx>(
     from_ty: Ty<'tcx>,
     to_ty: Ty<'tcx>,
     arg: &'tcx Expr<'_>,
+    const_context: bool,
 ) -> bool {
     match (&from_ty.kind(), &to_ty.kind()) {
-        (ty::Int(_) | ty::Uint(_), ty::Float(_)) => {
+        (ty::Int(_) | ty::Uint(_), ty::Float(_)) if !const_context => {
             span_lint_and_then(
                 cx,
                 TRANSMUTE_INT_TO_FLOAT,
diff --git a/clippy_lints/src/transmute/transmute_num_to_bytes.rs b/clippy_lints/src/transmute/transmute_num_to_bytes.rs
index 362f2bb6960a2..88b0ac5a36887 100644
--- a/clippy_lints/src/transmute/transmute_num_to_bytes.rs
+++ b/clippy_lints/src/transmute/transmute_num_to_bytes.rs
@@ -14,12 +14,18 @@ pub(super) fn check<'tcx>(
     from_ty: Ty<'tcx>,
     to_ty: Ty<'tcx>,
     arg: &'tcx Expr<'_>,
+    const_context: bool,
 ) -> bool {
     match (&from_ty.kind(), &to_ty.kind()) {
         (ty::Int(_) | ty::Uint(_) | ty::Float(_), ty::Array(arr_ty, _)) => {
             if !matches!(arr_ty.kind(), ty::Uint(UintTy::U8)) {
                 return false;
             }
+            if matches!(from_ty.kind(), ty::Float(_)) && const_context {
+                // TODO: Remove when const_float_bits_conv is stabilized
+                // rust#72447
+                return false;
+            }
 
             span_lint_and_then(
                 cx,

From 7cccef84cf2f5f9f94f77a09a193d414b3cff03d Mon Sep 17 00:00:00 2001
From: Trevor Spiteri <tspiteri@ieee.org>
Date: Fri, 13 Sep 2024 13:43:41 +0200
Subject: [PATCH 070/114] handle transmutes in const context if
 msrvs::CONST_FLOAT_BITS_CONV

---
 clippy_config/src/msrvs.rs                           | 3 ++-
 clippy_lints/src/transmute/mod.rs                    | 6 +++---
 clippy_lints/src/transmute/transmute_float_to_int.rs | 6 +++++-
 clippy_lints/src/transmute/transmute_int_to_float.rs | 4 +++-
 clippy_lints/src/transmute/transmute_num_to_bytes.rs | 6 +++---
 5 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs
index 0e8215aa8e3cd..e17458b3310fe 100644
--- a/clippy_config/src/msrvs.rs
+++ b/clippy_config/src/msrvs.rs
@@ -17,7 +17,8 @@ macro_rules! msrv_aliases {
 
 // names may refer to stabilized feature flags or library items
 msrv_aliases! {
-    1,81,0  { LINT_REASONS_STABILIZATION }
+    1,83,0 { CONST_FLOAT_BITS_CONV }
+    1,81,0 { LINT_REASONS_STABILIZATION }
     1,80,0 { BOX_INTO_ITER}
     1,77,0 { C_STR_LITERALS }
     1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT }
diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs
index 373bf61d8ff94..da7906b118353 100644
--- a/clippy_lints/src/transmute/mod.rs
+++ b/clippy_lints/src/transmute/mod.rs
@@ -619,10 +619,10 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
                 | 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, &self.msrv)
                 | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg)
-                | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context)
+                | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context, &self.msrv)
                 | transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg)
-                | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context)
-                | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context)
+                | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context, &self.msrv)
+                | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context, &self.msrv)
                 | (unsound_collection_transmute::check(cx, e, from_ty, to_ty)
                     || transmute_undefined_repr::check(cx, e, from_ty, to_ty))
                 | (eager_transmute::check(cx, e, arg, from_ty, to_ty));
diff --git a/clippy_lints/src/transmute/transmute_float_to_int.rs b/clippy_lints/src/transmute/transmute_float_to_int.rs
index ab3bb5e1062d3..3507eb9a12480 100644
--- a/clippy_lints/src/transmute/transmute_float_to_int.rs
+++ b/clippy_lints/src/transmute/transmute_float_to_int.rs
@@ -1,4 +1,5 @@
 use super::TRANSMUTE_FLOAT_TO_INT;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::sugg;
 use rustc_ast as ast;
@@ -16,9 +17,12 @@ pub(super) fn check<'tcx>(
     to_ty: Ty<'tcx>,
     mut arg: &'tcx Expr<'_>,
     const_context: bool,
+    msrv: &Msrv,
 ) -> bool {
     match (&from_ty.kind(), &to_ty.kind()) {
-        (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) if !const_context => {
+        (ty::Float(float_ty), ty::Int(_) | ty::Uint(_))
+            if !const_context || msrv.meets(msrvs::CONST_FLOAT_BITS_CONV) =>
+        {
             span_lint_and_then(
                 cx,
                 TRANSMUTE_FLOAT_TO_INT,
diff --git a/clippy_lints/src/transmute/transmute_int_to_float.rs b/clippy_lints/src/transmute/transmute_int_to_float.rs
index d51888e30971b..c5c7ed6d398b9 100644
--- a/clippy_lints/src/transmute/transmute_int_to_float.rs
+++ b/clippy_lints/src/transmute/transmute_int_to_float.rs
@@ -1,4 +1,5 @@
 use super::TRANSMUTE_INT_TO_FLOAT;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::sugg;
 use rustc_errors::Applicability;
@@ -15,9 +16,10 @@ pub(super) fn check<'tcx>(
     to_ty: Ty<'tcx>,
     arg: &'tcx Expr<'_>,
     const_context: bool,
+    msrv: &Msrv,
 ) -> bool {
     match (&from_ty.kind(), &to_ty.kind()) {
-        (ty::Int(_) | ty::Uint(_), ty::Float(_)) if !const_context => {
+        (ty::Int(_) | ty::Uint(_), ty::Float(_)) if !const_context || msrv.meets(msrvs::CONST_FLOAT_BITS_CONV) => {
             span_lint_and_then(
                 cx,
                 TRANSMUTE_INT_TO_FLOAT,
diff --git a/clippy_lints/src/transmute/transmute_num_to_bytes.rs b/clippy_lints/src/transmute/transmute_num_to_bytes.rs
index 88b0ac5a36887..a94cd27c7fd1d 100644
--- a/clippy_lints/src/transmute/transmute_num_to_bytes.rs
+++ b/clippy_lints/src/transmute/transmute_num_to_bytes.rs
@@ -1,4 +1,5 @@
 use super::TRANSMUTE_NUM_TO_BYTES;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::sugg;
 use rustc_errors::Applicability;
@@ -15,15 +16,14 @@ pub(super) fn check<'tcx>(
     to_ty: Ty<'tcx>,
     arg: &'tcx Expr<'_>,
     const_context: bool,
+    msrv: &Msrv,
 ) -> bool {
     match (&from_ty.kind(), &to_ty.kind()) {
         (ty::Int(_) | ty::Uint(_) | ty::Float(_), ty::Array(arr_ty, _)) => {
             if !matches!(arr_ty.kind(), ty::Uint(UintTy::U8)) {
                 return false;
             }
-            if matches!(from_ty.kind(), ty::Float(_)) && const_context {
-                // TODO: Remove when const_float_bits_conv is stabilized
-                // rust#72447
+            if matches!(from_ty.kind(), ty::Float(_)) && const_context && !msrv.meets(msrvs::CONST_FLOAT_BITS_CONV) {
                 return false;
             }
 

From 15495ebf42a2d9748ae25774a73f28c43e47fd0b Mon Sep 17 00:00:00 2001
From: y21 <30553356+y21@users.noreply.github.com>
Date: Mon, 26 Aug 2024 19:24:13 +0200
Subject: [PATCH 071/114] Look at adjusted types instead of fn signature types
 in `ptr_arg`

---
 clippy_lints/src/ptr.rs | 100 ++++++++++++++++------------------------
 tests/ui/ptr_arg.rs     |  22 +++++++++
 tests/ui/ptr_arg.stderr |  14 +++++-
 3 files changed, 75 insertions(+), 61 deletions(-)

diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs
index 7d24d25dc2fa4..cd8e921347cc3 100644
--- a/clippy_lints/src/ptr.rs
+++ b/clippy_lints/src/ptr.rs
@@ -1,11 +1,9 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then};
 use clippy_utils::source::SpanRangeExt;
-use clippy_utils::ty::expr_sig;
 use clippy_utils::visitors::contains_unsafe_block;
 use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local};
 use hir::LifetimeName;
 use rustc_errors::{Applicability, MultiSpan};
-use rustc_hir::def_id::DefId;
 use rustc_hir::hir_id::{HirId, HirIdMap};
 use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{
@@ -323,7 +321,6 @@ struct PtrArg<'tcx> {
     idx: usize,
     emission_id: HirId,
     span: Span,
-    ty_did: DefId,
     ty_name: Symbol,
     method_renames: &'static [(&'static str, &'static str)],
     ref_prefix: RefPrefix,
@@ -411,7 +408,6 @@ impl<'tcx> DerefTy<'tcx> {
     }
 }
 
-#[expect(clippy::too_many_lines)]
 fn check_fn_args<'cx, 'tcx: 'cx>(
     cx: &'cx LateContext<'tcx>,
     fn_sig: ty::FnSig<'tcx>,
@@ -514,7 +510,6 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
                     idx: i,
                     emission_id,
                     span: hir_ty.span,
-                    ty_did: adt.did(),
                     ty_name: name.ident.name,
                     method_renames,
                     ref_prefix: RefPrefix { lt: *lt, mutability },
@@ -610,65 +605,50 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &Body<'tcx>, args: &[
                         set_skip_flag();
                     }
                 },
-                Some((Node::Expr(e), child_id)) => match e.kind {
-                    ExprKind::Call(f, expr_args) => {
-                        let i = expr_args.iter().position(|arg| arg.hir_id == child_id).unwrap_or(0);
-                        if expr_sig(self.cx, f).and_then(|sig| sig.input(i)).map_or(true, |ty| {
-                            match *ty.skip_binder().peel_refs().kind() {
-                                ty::Dynamic(preds, _, _) => !matches_preds(self.cx, args.deref_ty.ty(self.cx), preds),
-                                ty::Param(_) => true,
-                                ty::Adt(def, _) => def.did() == args.ty_did,
-                                _ => false,
-                            }
-                        }) {
-                            // Passed to a function taking the non-dereferenced type.
-                            set_skip_flag();
-                        }
-                    },
-                    ExprKind::MethodCall(name, self_arg, expr_args, _) => {
-                        let i = iter::once(self_arg)
-                            .chain(expr_args.iter())
-                            .position(|arg| arg.hir_id == child_id)
-                            .unwrap_or(0);
-                        if i == 0 {
-                            // Check if the method can be renamed.
-                            let name = name.ident.as_str();
-                            if let Some((_, replacement)) = args.method_renames.iter().find(|&&(x, _)| x == name) {
-                                result.replacements.push(PtrArgReplacement {
-                                    expr_span: e.span,
-                                    self_span: self_arg.span,
-                                    replacement,
-                                });
-                                return;
-                            }
+                Some((Node::Expr(use_expr), child_id)) => {
+                    if let ExprKind::Index(e, ..) = use_expr.kind
+                        && e.hir_id == child_id
+                    {
+                        // Indexing works with both owned and its dereferenced type
+                        return;
+                    }
+
+                    if let ExprKind::MethodCall(name, receiver, ..) = use_expr.kind
+                        && receiver.hir_id == child_id
+                    {
+                        let name = name.ident.as_str();
+
+                        // Check if the method can be renamed.
+                        if let Some((_, replacement)) = args.method_renames.iter().find(|&&(x, _)| x == name) {
+                            result.replacements.push(PtrArgReplacement {
+                                expr_span: use_expr.span,
+                                self_span: receiver.span,
+                                replacement,
+                            });
+                            return;
                         }
 
-                        let Some(id) = self.cx.typeck_results().type_dependent_def_id(e.hir_id) else {
-                            set_skip_flag();
+                        // Some methods exist on both `[T]` and `Vec<T>`, such as `len`, where the receiver type
+                        // doesn't coerce to a slice and our adjusted type check below isn't enough,
+                        // but it would still be valid to call with a slice
+                        if is_allowed_vec_method(self.cx, use_expr) {
                             return;
-                        };
-
-                        match *self.cx.tcx.fn_sig(id).instantiate_identity().skip_binder().inputs()[i]
-                            .peel_refs()
-                            .kind()
-                        {
-                            ty::Dynamic(preds, _, _) if !matches_preds(self.cx, args.deref_ty.ty(self.cx), preds) => {
-                                set_skip_flag();
-                            },
-                            ty::Param(_) => {
-                                set_skip_flag();
-                            },
-                            // If the types match check for methods which exist on both types. e.g. `Vec::len` and
-                            // `slice::len`
-                            ty::Adt(def, _) if def.did() == args.ty_did && !is_allowed_vec_method(self.cx, e) => {
-                                set_skip_flag();
-                            },
-                            _ => (),
                         }
-                    },
-                    // Indexing is fine for currently supported types.
-                    ExprKind::Index(e, _, _) if e.hir_id == child_id => (),
-                    _ => set_skip_flag(),
+                    }
+
+                    let deref_ty = args.deref_ty.ty(self.cx);
+                    let adjusted_ty = self.cx.typeck_results().expr_ty_adjusted(e).peel_refs();
+                    if adjusted_ty == deref_ty {
+                        return;
+                    }
+
+                    if let ty::Dynamic(preds, ..) = adjusted_ty.kind()
+                        && matches_preds(self.cx, deref_ty, preds)
+                    {
+                        return;
+                    }
+
+                    set_skip_flag();
                 },
                 _ => set_skip_flag(),
             }
diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs
index e6ef626812128..e8b42d3b913b0 100644
--- a/tests/ui/ptr_arg.rs
+++ b/tests/ui/ptr_arg.rs
@@ -309,3 +309,25 @@ mod issue_11181 {
         extern "C" fn allowed(_v: &Vec<u32>) {}
     }
 }
+
+mod issue_13308 {
+    use std::ops::Deref;
+
+    fn repro(source: &str, destination: &mut String) {
+        source.clone_into(destination);
+    }
+    fn repro2(source: &str, destination: &mut String) {
+        ToOwned::clone_into(source, destination);
+    }
+
+    fn h1(_: &<String as Deref>::Target) {}
+    fn h2<T: Deref>(_: T, _: &T::Target) {}
+
+    // Other cases that are still ok to lint and ideally shouldn't regress
+    fn good(v1: &String, v2: &String) {
+        //~^ ERROR: writing `&String` instead of `&str`
+        //~^^ ERROR: writing `&String` instead of `&str`
+        h1(v1);
+        h2(String::new(), v2);
+    }
+}
diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr
index 4246453e64ca7..1a6b3aa1f8d41 100644
--- a/tests/ui/ptr_arg.stderr
+++ b/tests/ui/ptr_arg.stderr
@@ -221,5 +221,17 @@ error: using a reference to `Cow` is not recommended
 LL |     fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str {
    |                                        ^^^^^^^^^^^^^^^^ help: change this to: `&str`
 
-error: aborting due to 25 previous errors
+error: writing `&String` instead of `&str` involves a new object where a slice will do
+  --> tests/ui/ptr_arg.rs:327:17
+   |
+LL |     fn good(v1: &String, v2: &String) {
+   |                 ^^^^^^^ help: change this to: `&str`
+
+error: writing `&String` instead of `&str` involves a new object where a slice will do
+  --> tests/ui/ptr_arg.rs:327:30
+   |
+LL |     fn good(v1: &String, v2: &String) {
+   |                              ^^^^^^^ help: change this to: `&str`
+
+error: aborting due to 27 previous errors
 

From 9e697964dc82522ed56b5d2f73f54a8e88638e9a Mon Sep 17 00:00:00 2001
From: Gurinder Singh <frederick.the.fool@gmail.com>
Date: Sat, 14 Sep 2024 16:12:00 +0530
Subject: [PATCH 072/114] Fix lint levels not getting overridden by attrs on
 `Stmt` nodes

---
 tests/ui/expect_tool_lint_rfc_2383.stderr | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/tests/ui/expect_tool_lint_rfc_2383.stderr b/tests/ui/expect_tool_lint_rfc_2383.stderr
index f70d3408aa4d9..028e22ca724e4 100644
--- a/tests/ui/expect_tool_lint_rfc_2383.stderr
+++ b/tests/ui/expect_tool_lint_rfc_2383.stderr
@@ -13,6 +13,14 @@ error: this lint expectation is unfulfilled
 LL |         #[expect(invalid_nan_comparisons)]
    |                  ^^^^^^^^^^^^^^^^^^^^^^^
 
+error: this lint expectation is unfulfilled
+  --> tests/ui/expect_tool_lint_rfc_2383.rs:36:18
+   |
+LL |         #[expect(invalid_nan_comparisons)]
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error: this lint expectation is unfulfilled
   --> tests/ui/expect_tool_lint_rfc_2383.rs:107:14
    |
@@ -37,5 +45,5 @@ error: this lint expectation is unfulfilled
 LL |     #[expect(clippy::overly_complex_bool_expr)]
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
 

From b5ea5c23b34129f5af82ccf5b9e5babd9bbc9285 Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert@folkertdev.nl>
Date: Thu, 29 Aug 2024 15:33:34 +0200
Subject: [PATCH 073/114] stabilize `const_extern_fn`

---
 clippy_config/src/msrvs.rs                    |  3 +-
 clippy_lints/src/missing_const_for_fn.rs      | 10 +-
 .../ui/missing_const_for_fn/cant_be_const.rs  |  6 --
 .../missing_const_for_fn/could_be_const.fixed | 14 +++
 .../ui/missing_const_for_fn/could_be_const.rs | 14 +++
 .../could_be_const.stderr                     | 99 ++++++++++++++-----
 .../could_be_const_with_const_extern_fn.fixed | 14 ---
 .../could_be_const_with_const_extern_fn.rs    | 14 ---
 ...could_be_const_with_const_extern_fn.stderr | 59 -----------
 9 files changed, 111 insertions(+), 122 deletions(-)
 delete mode 100644 tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.fixed
 delete mode 100644 tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs
 delete mode 100644 tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.stderr

diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs
index e17458b3310fe..a2b4b6e256fa7 100644
--- a/clippy_config/src/msrvs.rs
+++ b/clippy_config/src/msrvs.rs
@@ -17,6 +17,7 @@ macro_rules! msrv_aliases {
 
 // names may refer to stabilized feature flags or library items
 msrv_aliases! {
+    1,83,0 { CONST_EXTERN_FN }
     1,83,0 { CONST_FLOAT_BITS_CONV }
     1,81,0 { LINT_REASONS_STABILIZATION }
     1,80,0 { BOX_INTO_ITER}
@@ -27,7 +28,7 @@ msrv_aliases! {
     1,68,0 { PATH_MAIN_SEPARATOR_STR }
     1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS }
     1,63,0 { CLONE_INTO }
-    1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE, CONST_EXTERN_FN }
+    1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE, CONST_EXTERN_C_FN }
     1,59,0 { THREAD_LOCAL_CONST_INIT }
     1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY, CONST_RAW_PTR_DEREF }
     1,56,0 { CONST_FN_UNION }
diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs
index 052d738b2e79e..859afe1b9636e 100644
--- a/clippy_lints/src/missing_const_for_fn.rs
+++ b/clippy_lints/src/missing_const_for_fn.rs
@@ -119,9 +119,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
                     .iter()
                     .any(|param| matches!(param.kind, GenericParamKind::Const { .. }));
 
-                if already_const(header)
-                    || has_const_generic_params
-                    || !could_be_const_with_abi(cx, &self.msrv, header.abi)
+                if already_const(header) || has_const_generic_params || !could_be_const_with_abi(&self.msrv, header.abi)
                 {
                     return;
                 }
@@ -183,13 +181,13 @@ fn already_const(header: hir::FnHeader) -> bool {
     header.constness == Constness::Const
 }
 
-fn could_be_const_with_abi(cx: &LateContext<'_>, msrv: &Msrv, abi: Abi) -> bool {
+fn could_be_const_with_abi(msrv: &Msrv, abi: Abi) -> bool {
     match abi {
         Abi::Rust => true,
         // `const extern "C"` was stabilized after 1.62.0
-        Abi::C { unwind: false } => msrv.meets(msrvs::CONST_EXTERN_FN),
+        Abi::C { unwind: false } => msrv.meets(msrvs::CONST_EXTERN_C_FN),
         // Rest ABIs are still unstable and need the `const_extern_fn` feature enabled.
-        _ => cx.tcx.features().const_extern_fn,
+        _ => msrv.meets(msrvs::CONST_EXTERN_FN),
     }
 }
 
diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs
index 2c6e1e92da025..ca323dcf17336 100644
--- a/tests/ui/missing_const_for_fn/cant_be_const.rs
+++ b/tests/ui/missing_const_for_fn/cant_be_const.rs
@@ -186,12 +186,6 @@ mod msrv {
     extern "C" fn c() {}
 }
 
-mod with_extern {
-    extern "C-unwind" fn c_unwind() {}
-    extern "system" fn system() {}
-    extern "system-unwind" fn system_unwind() {}
-}
-
 mod with_ty_alias {
     type Foo = impl std::fmt::Debug;
 
diff --git a/tests/ui/missing_const_for_fn/could_be_const.fixed b/tests/ui/missing_const_for_fn/could_be_const.fixed
index f54503ada9759..0aef4d31fd9cb 100644
--- a/tests/ui/missing_const_for_fn/could_be_const.fixed
+++ b/tests/ui/missing_const_for_fn/could_be_const.fixed
@@ -1,5 +1,6 @@
 #![warn(clippy::missing_const_for_fn)]
 #![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)]
+#![allow(unsupported_calling_conventions)]
 #![feature(const_mut_refs)]
 #![feature(const_trait_impl)]
 
@@ -204,3 +205,16 @@ mod with_ty_alias {
     // in this test.
     const fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
 }
+
+mod extern_fn {
+    const extern "C-unwind" fn c_unwind() {}
+    //~^ ERROR: this could be a `const fn`
+    const extern "system" fn system() {}
+    //~^ ERROR: this could be a `const fn`
+    const extern "system-unwind" fn system_unwind() {}
+    //~^ ERROR: this could be a `const fn`
+    pub const extern "stdcall" fn std_call() {}
+    //~^ ERROR: this could be a `const fn`
+    pub const extern "stdcall-unwind" fn std_call_unwind() {}
+    //~^ ERROR: this could be a `const fn`
+}
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 2c229068e4dda..4246494fe7219 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,6 @@
 #![warn(clippy::missing_const_for_fn)]
 #![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)]
+#![allow(unsupported_calling_conventions)]
 #![feature(const_mut_refs)]
 #![feature(const_trait_impl)]
 
@@ -204,3 +205,16 @@ mod with_ty_alias {
     // in this test.
     fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
 }
+
+mod extern_fn {
+    extern "C-unwind" fn c_unwind() {}
+    //~^ ERROR: this could be a `const fn`
+    extern "system" fn system() {}
+    //~^ ERROR: this could be a `const fn`
+    extern "system-unwind" fn system_unwind() {}
+    //~^ ERROR: this could be a `const fn`
+    pub extern "stdcall" fn std_call() {}
+    //~^ ERROR: this could be a `const fn`
+    pub extern "stdcall-unwind" fn std_call_unwind() {}
+    //~^ ERROR: this could be a `const fn`
+}
diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr
index fb4db70310316..6bc71e29840d2 100644
--- a/tests/ui/missing_const_for_fn/could_be_const.stderr
+++ b/tests/ui/missing_const_for_fn/could_be_const.stderr
@@ -1,5 +1,5 @@
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:14:5
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:15:5
    |
 LL | /     pub fn new() -> Self {
 LL | |
@@ -16,7 +16,7 @@ LL |     pub const fn new() -> Self {
    |         +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:20:5
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:21:5
    |
 LL | /     fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] {
 LL | |
@@ -30,7 +30,7 @@ LL |     const fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T;
    |     +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:27:1
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:28:1
    |
 LL | / fn one() -> i32 {
 LL | |
@@ -44,7 +44,7 @@ LL | const fn one() -> i32 {
    | +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:33:1
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:34:1
    |
 LL | / fn two() -> i32 {
 LL | |
@@ -59,7 +59,7 @@ LL | const fn two() -> i32 {
    | +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:40:1
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:41:1
    |
 LL | / fn string() -> String {
 LL | |
@@ -73,7 +73,7 @@ LL | const fn string() -> String {
    | +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:46:1
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:47:1
    |
 LL | / unsafe fn four() -> i32 {
 LL | |
@@ -87,7 +87,7 @@ LL | const unsafe fn four() -> i32 {
    | +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:52:1
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:53:1
    |
 LL | / fn generic<T>(t: T) -> T {
 LL | |
@@ -101,7 +101,7 @@ LL | const fn generic<T>(t: T) -> T {
    | +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:61:1
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:62:1
    |
 LL | / fn generic_arr<T: Copy>(t: [T; 1]) -> T {
 LL | |
@@ -115,7 +115,7 @@ LL | const fn generic_arr<T: Copy>(t: [T; 1]) -> T {
    | +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:75:9
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:76:9
    |
 LL | /         pub fn b(self, a: &A) -> B {
 LL | |
@@ -129,7 +129,7 @@ LL |         pub const fn b(self, a: &A) -> B {
    |             +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:85:5
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:86:5
    |
 LL | /     fn const_fn_stabilized_before_msrv(byte: u8) {
 LL | |
@@ -143,7 +143,7 @@ LL |     const fn const_fn_stabilized_before_msrv(byte: u8) {
    |     +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:97:1
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:98:1
    |
 LL | / fn msrv_1_46() -> i32 {
 LL | |
@@ -157,7 +157,7 @@ LL | const fn msrv_1_46() -> i32 {
    | +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:117:1
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:118:1
    |
 LL | fn d(this: D) {}
    | ^^^^^^^^^^^^^^^^
@@ -168,7 +168,7 @@ LL | const fn d(this: D) {}
    | +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:125:9
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:126:9
    |
 LL | /         fn deref_ptr_can_be_const(self) -> usize {
 LL | |
@@ -182,7 +182,7 @@ LL |         const fn deref_ptr_can_be_const(self) -> usize {
    |         +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:130:9
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:131:9
    |
 LL | /         fn deref_copied_val(self) -> usize {
 LL | |
@@ -196,7 +196,7 @@ LL |         const fn deref_copied_val(self) -> usize {
    |         +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:141:5
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:142:5
    |
 LL | /     fn union_access_can_be_const() {
 LL | |
@@ -211,7 +211,7 @@ LL |     const fn union_access_can_be_const() {
    |     +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:149:9
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:150:9
    |
 LL |         extern "C" fn c() {}
    |         ^^^^^^^^^^^^^^^^^^^^
@@ -222,7 +222,7 @@ LL |         const extern "C" fn c() {}
    |         +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:153:9
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:154:9
    |
 LL |         extern fn implicit_c() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -233,7 +233,7 @@ LL |         const extern fn implicit_c() {}
    |         +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:170:9
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:171:9
    |
 LL | /         pub fn new(strings: Vec<String>) -> Self {
 LL | |             Self { strings }
@@ -246,7 +246,7 @@ LL |         pub const fn new(strings: Vec<String>) -> Self {
    |             +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:175:9
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:176:9
    |
 LL | /         pub fn empty() -> Self {
 LL | |             Self { strings: Vec::new() }
@@ -259,7 +259,7 @@ LL |         pub const fn empty() -> Self {
    |             +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:186:9
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:187:9
    |
 LL | /         pub fn new(text: String) -> Self {
 LL | |             let vec = Vec::new();
@@ -273,7 +273,7 @@ LL |         pub const fn new(text: String) -> Self {
    |             +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:205:5
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:206:5
    |
 LL |     fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -283,5 +283,60 @@ help: make the function `const`
 LL |     const fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
    |     +++++
 
-error: aborting due to 21 previous errors
+error: this could be a `const fn`
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:210:5
+   |
+LL |     extern "C-unwind" fn c_unwind() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function `const`
+   |
+LL |     const extern "C-unwind" fn c_unwind() {}
+   |     +++++
+
+error: this could be a `const fn`
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:212:5
+   |
+LL |     extern "system" fn system() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function `const`
+   |
+LL |     const extern "system" fn system() {}
+   |     +++++
+
+error: this could be a `const fn`
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:214:5
+   |
+LL |     extern "system-unwind" fn system_unwind() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function `const`
+   |
+LL |     const extern "system-unwind" fn system_unwind() {}
+   |     +++++
+
+error: this could be a `const fn`
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:216:5
+   |
+LL |     pub extern "stdcall" fn std_call() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function `const`
+   |
+LL |     pub const extern "stdcall" fn std_call() {}
+   |         +++++
+
+error: this could be a `const fn`
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:218:5
+   |
+LL |     pub extern "stdcall-unwind" fn std_call_unwind() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: make the function `const`
+   |
+LL |     pub const extern "stdcall-unwind" fn std_call_unwind() {}
+   |         +++++
+
+error: aborting due to 26 previous errors
 
diff --git a/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.fixed b/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.fixed
deleted file mode 100644
index c103db536ab50..0000000000000
--- a/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.fixed
+++ /dev/null
@@ -1,14 +0,0 @@
-#![warn(clippy::missing_const_for_fn)]
-#![allow(unsupported_calling_conventions)]
-#![feature(const_extern_fn)]
-
-const extern "C-unwind" fn c_unwind() {}
-//~^ ERROR: this could be a `const fn`
-const extern "system" fn system() {}
-//~^ ERROR: this could be a `const fn`
-const extern "system-unwind" fn system_unwind() {}
-//~^ ERROR: this could be a `const fn`
-pub const extern "stdcall" fn std_call() {}
-//~^ ERROR: this could be a `const fn`
-pub const extern "stdcall-unwind" fn std_call_unwind() {}
-//~^ ERROR: this could be a `const fn`
diff --git a/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs b/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs
deleted file mode 100644
index 0f7020ae559a9..0000000000000
--- a/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-#![warn(clippy::missing_const_for_fn)]
-#![allow(unsupported_calling_conventions)]
-#![feature(const_extern_fn)]
-
-extern "C-unwind" fn c_unwind() {}
-//~^ ERROR: this could be a `const fn`
-extern "system" fn system() {}
-//~^ ERROR: this could be a `const fn`
-extern "system-unwind" fn system_unwind() {}
-//~^ ERROR: this could be a `const fn`
-pub extern "stdcall" fn std_call() {}
-//~^ ERROR: this could be a `const fn`
-pub extern "stdcall-unwind" fn std_call_unwind() {}
-//~^ ERROR: this could be a `const fn`
diff --git a/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.stderr b/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.stderr
deleted file mode 100644
index 036094a367b22..0000000000000
--- a/tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.stderr
+++ /dev/null
@@ -1,59 +0,0 @@
-error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:5:1
-   |
-LL | extern "C-unwind" fn c_unwind() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `-D clippy::missing-const-for-fn` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::missing_const_for_fn)]`
-help: make the function `const`
-   |
-LL | const extern "C-unwind" fn c_unwind() {}
-   | +++++
-
-error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:7:1
-   |
-LL | extern "system" fn system() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: make the function `const`
-   |
-LL | const extern "system" fn system() {}
-   | +++++
-
-error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:9:1
-   |
-LL | extern "system-unwind" fn system_unwind() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: make the function `const`
-   |
-LL | const extern "system-unwind" fn system_unwind() {}
-   | +++++
-
-error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:11:1
-   |
-LL | pub extern "stdcall" fn std_call() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: make the function `const`
-   |
-LL | pub const extern "stdcall" fn std_call() {}
-   |     +++++
-
-error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:13:1
-   |
-LL | pub extern "stdcall-unwind" fn std_call_unwind() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: make the function `const`
-   |
-LL | pub const extern "stdcall-unwind" fn std_call_unwind() {}
-   |     +++++
-
-error: aborting due to 5 previous errors
-

From 976131f89663f565da9ab2b26bb8c33674d70460 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sat, 17 Aug 2024 14:19:34 +0200
Subject: [PATCH 074/114] stabilize const_mut_refs

---
 tests/ui/arithmetic_side_effects.rs           |  6 +--
 .../missing_const_for_fn/could_be_const.fixed |  1 -
 .../ui/missing_const_for_fn/could_be_const.rs |  1 -
 .../could_be_const.stderr                     | 52 +++++++++----------
 4 files changed, 29 insertions(+), 31 deletions(-)

diff --git a/tests/ui/arithmetic_side_effects.rs b/tests/ui/arithmetic_side_effects.rs
index 9d06e14e88c52..0838d064a5fa1 100644
--- a/tests/ui/arithmetic_side_effects.rs
+++ b/tests/ui/arithmetic_side_effects.rs
@@ -1,5 +1,8 @@
 //@aux-build:proc_macro_derive.rs
 
+#![feature(f128)]
+#![feature(f16)]
+
 #![allow(
     clippy::assign_op_pattern,
     clippy::erasing_op,
@@ -10,9 +13,6 @@
     arithmetic_overflow,
     unconditional_panic
 )]
-#![feature(const_mut_refs)]
-#![feature(f128)]
-#![feature(f16)]
 #![warn(clippy::arithmetic_side_effects)]
 
 extern crate proc_macro_derive;
diff --git a/tests/ui/missing_const_for_fn/could_be_const.fixed b/tests/ui/missing_const_for_fn/could_be_const.fixed
index 0aef4d31fd9cb..41b424a8e5d53 100644
--- a/tests/ui/missing_const_for_fn/could_be_const.fixed
+++ b/tests/ui/missing_const_for_fn/could_be_const.fixed
@@ -1,7 +1,6 @@
 #![warn(clippy::missing_const_for_fn)]
 #![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)]
 #![allow(unsupported_calling_conventions)]
-#![feature(const_mut_refs)]
 #![feature(const_trait_impl)]
 
 use std::mem::transmute;
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 4246494fe7219..27593575a013f 100644
--- a/tests/ui/missing_const_for_fn/could_be_const.rs
+++ b/tests/ui/missing_const_for_fn/could_be_const.rs
@@ -1,7 +1,6 @@
 #![warn(clippy::missing_const_for_fn)]
 #![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)]
 #![allow(unsupported_calling_conventions)]
-#![feature(const_mut_refs)]
 #![feature(const_trait_impl)]
 
 use std::mem::transmute;
diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr
index 6bc71e29840d2..12d97b1711911 100644
--- a/tests/ui/missing_const_for_fn/could_be_const.stderr
+++ b/tests/ui/missing_const_for_fn/could_be_const.stderr
@@ -1,5 +1,5 @@
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:15:5
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:14:5
    |
 LL | /     pub fn new() -> Self {
 LL | |
@@ -16,7 +16,7 @@ LL |     pub const fn new() -> Self {
    |         +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:21:5
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:20:5
    |
 LL | /     fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] {
 LL | |
@@ -30,7 +30,7 @@ LL |     const fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T;
    |     +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:28:1
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:27:1
    |
 LL | / fn one() -> i32 {
 LL | |
@@ -44,7 +44,7 @@ LL | const fn one() -> i32 {
    | +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:34:1
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:33:1
    |
 LL | / fn two() -> i32 {
 LL | |
@@ -59,7 +59,7 @@ LL | const fn two() -> i32 {
    | +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:41:1
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:40:1
    |
 LL | / fn string() -> String {
 LL | |
@@ -73,7 +73,7 @@ LL | const fn string() -> String {
    | +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:47:1
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:46:1
    |
 LL | / unsafe fn four() -> i32 {
 LL | |
@@ -87,7 +87,7 @@ LL | const unsafe fn four() -> i32 {
    | +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:53:1
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:52:1
    |
 LL | / fn generic<T>(t: T) -> T {
 LL | |
@@ -101,7 +101,7 @@ LL | const fn generic<T>(t: T) -> T {
    | +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:62:1
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:61:1
    |
 LL | / fn generic_arr<T: Copy>(t: [T; 1]) -> T {
 LL | |
@@ -115,7 +115,7 @@ LL | const fn generic_arr<T: Copy>(t: [T; 1]) -> T {
    | +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:76:9
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:75:9
    |
 LL | /         pub fn b(self, a: &A) -> B {
 LL | |
@@ -129,7 +129,7 @@ LL |         pub const fn b(self, a: &A) -> B {
    |             +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:86:5
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:85:5
    |
 LL | /     fn const_fn_stabilized_before_msrv(byte: u8) {
 LL | |
@@ -143,7 +143,7 @@ LL |     const fn const_fn_stabilized_before_msrv(byte: u8) {
    |     +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:98:1
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:97:1
    |
 LL | / fn msrv_1_46() -> i32 {
 LL | |
@@ -157,7 +157,7 @@ LL | const fn msrv_1_46() -> i32 {
    | +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:118:1
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:117:1
    |
 LL | fn d(this: D) {}
    | ^^^^^^^^^^^^^^^^
@@ -168,7 +168,7 @@ LL | const fn d(this: D) {}
    | +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:126:9
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:125:9
    |
 LL | /         fn deref_ptr_can_be_const(self) -> usize {
 LL | |
@@ -182,7 +182,7 @@ LL |         const fn deref_ptr_can_be_const(self) -> usize {
    |         +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:131:9
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:130:9
    |
 LL | /         fn deref_copied_val(self) -> usize {
 LL | |
@@ -196,7 +196,7 @@ LL |         const fn deref_copied_val(self) -> usize {
    |         +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:142:5
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:141:5
    |
 LL | /     fn union_access_can_be_const() {
 LL | |
@@ -211,7 +211,7 @@ LL |     const fn union_access_can_be_const() {
    |     +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:150:9
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:149:9
    |
 LL |         extern "C" fn c() {}
    |         ^^^^^^^^^^^^^^^^^^^^
@@ -222,7 +222,7 @@ LL |         const extern "C" fn c() {}
    |         +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:154:9
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:153:9
    |
 LL |         extern fn implicit_c() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -233,7 +233,7 @@ LL |         const extern fn implicit_c() {}
    |         +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:171:9
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:170:9
    |
 LL | /         pub fn new(strings: Vec<String>) -> Self {
 LL | |             Self { strings }
@@ -246,7 +246,7 @@ LL |         pub const fn new(strings: Vec<String>) -> Self {
    |             +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:176:9
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:175:9
    |
 LL | /         pub fn empty() -> Self {
 LL | |             Self { strings: Vec::new() }
@@ -259,7 +259,7 @@ LL |         pub const fn empty() -> Self {
    |             +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:187:9
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:186:9
    |
 LL | /         pub fn new(text: String) -> Self {
 LL | |             let vec = Vec::new();
@@ -273,7 +273,7 @@ LL |         pub const fn new(text: String) -> Self {
    |             +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:206:5
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:205:5
    |
 LL |     fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -284,7 +284,7 @@ LL |     const fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
    |     +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:210:5
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:209:5
    |
 LL |     extern "C-unwind" fn c_unwind() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -295,7 +295,7 @@ LL |     const extern "C-unwind" fn c_unwind() {}
    |     +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:212:5
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:211:5
    |
 LL |     extern "system" fn system() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -306,7 +306,7 @@ LL |     const extern "system" fn system() {}
    |     +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:214:5
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:213:5
    |
 LL |     extern "system-unwind" fn system_unwind() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -317,7 +317,7 @@ LL |     const extern "system-unwind" fn system_unwind() {}
    |     +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:216:5
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:215:5
    |
 LL |     pub extern "stdcall" fn std_call() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -328,7 +328,7 @@ LL |     pub const extern "stdcall" fn std_call() {}
    |         +++++
 
 error: this could be a `const fn`
-  --> tests/ui/missing_const_for_fn/could_be_const.rs:218:5
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:217:5
    |
 LL |     pub extern "stdcall-unwind" fn std_call_unwind() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

From c3d58cd5fabf6f09aefed4a8971ca0b65ad47e23 Mon Sep 17 00:00:00 2001
From: Lukas Lueg <lukas.lueg@gmail.com>
Date: Tue, 17 Sep 2024 23:19:29 +0200
Subject: [PATCH 075/114] Fix `if_then_some_else_none` sugg missing closure
 intro

Fixes #13407
---
 clippy_lints/src/if_then_some_else_none.rs | 2 ++
 tests/ui/if_then_some_else_none.fixed      | 4 ++++
 tests/ui/if_then_some_else_none.rs         | 4 ++++
 tests/ui/if_then_some_else_none.stderr     | 8 +++++++-
 4 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/clippy_lints/src/if_then_some_else_none.rs b/clippy_lints/src/if_then_some_else_none.rs
index 0bca53c1536de..55f9625709b3c 100644
--- a/clippy_lints/src/if_then_some_else_none.rs
+++ b/clippy_lints/src/if_then_some_else_none.rs
@@ -105,6 +105,8 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
                             snippet_with_context(cx, first_stmt.span.until(then_arg.span), ctxt, "..", &mut app);
                         let closure = if method_name == "then" { "|| " } else { "" };
                         format!("{closure} {{ {block_snippet}; {arg_snip} }}")
+                    } else if method_name == "then" {
+                        (std::borrow::Cow::Borrowed("|| ") + arg_snip).into_owned()
                     } else {
                         arg_snip.into_owned()
                     };
diff --git a/tests/ui/if_then_some_else_none.fixed b/tests/ui/if_then_some_else_none.fixed
index ad13372a68b7e..1f47dddcbc40a 100644
--- a/tests/ui/if_then_some_else_none.fixed
+++ b/tests/ui/if_then_some_else_none.fixed
@@ -113,6 +113,10 @@ fn issue11394(b: bool, v: Result<(), ()>) -> Result<(), ()> {
     Ok(())
 }
 
+fn issue13407(s: &str) -> Option<bool> {
+    (s == "1").then(|| true)
+}
+
 const fn issue12103(x: u32) -> Option<u32> {
     // Should not issue an error in `const` context
     if x > 42 { Some(150) } else { None }
diff --git a/tests/ui/if_then_some_else_none.rs b/tests/ui/if_then_some_else_none.rs
index 73edbb7da2a87..499f008fb876d 100644
--- a/tests/ui/if_then_some_else_none.rs
+++ b/tests/ui/if_then_some_else_none.rs
@@ -131,6 +131,10 @@ fn issue11394(b: bool, v: Result<(), ()>) -> Result<(), ()> {
     Ok(())
 }
 
+fn issue13407(s: &str) -> Option<bool> {
+    if s == "1" { Some(true) } else { None }
+}
+
 const fn issue12103(x: u32) -> Option<u32> {
     // Should not issue an error in `const` context
     if x > 42 { Some(150) } else { None }
diff --git a/tests/ui/if_then_some_else_none.stderr b/tests/ui/if_then_some_else_none.stderr
index aed01e026cbe7..e7bc66b3ee881 100644
--- a/tests/ui/if_then_some_else_none.stderr
+++ b/tests/ui/if_then_some_else_none.stderr
@@ -52,5 +52,11 @@ LL | |         None
 LL | |     };
    | |_____^ help: try: `foo().then(||  { println!("true!"); 150 })`
 
-error: aborting due to 5 previous errors
+error: this could be simplified with `bool::then`
+  --> tests/ui/if_then_some_else_none.rs:135:5
+   |
+LL |     if s == "1" { Some(true) } else { None }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(s == "1").then(|| true)`
+
+error: aborting due to 6 previous errors
 

From 431f7d6709908618b3c9291b7ef5317660bb9919 Mon Sep 17 00:00:00 2001
From: y21 <30553356+y21@users.noreply.github.com>
Date: Tue, 17 Sep 2024 21:38:37 +0200
Subject: [PATCH 076/114] build quine-mc_cluskey with O3 in dev builds

---
 Cargo.toml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Cargo.toml b/Cargo.toml
index cf810798d8cc1..ddc27179ef2f2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -67,3 +67,10 @@ harness = false
 [[test]]
 name = "dogfood"
 harness = false
+
+# quine-mc_cluskey makes up a significant part of the runtime in dogfood
+# due to the number of conditions in the clippy_lints crate
+# and enabling optimizations for that specific dependency helps a bit
+# without increasing total build times.
+[profile.dev.package.quine-mc_cluskey]
+opt-level = 3

From 978582be7421b3e5f447181c8b20f6d4ded13a52 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 16:59:57 +0100
Subject: [PATCH 077/114] [Clippy] Swap `manual_retain` to use diagnostic items
 instead of paths

---
 clippy_lints/src/manual_retain.rs | 34 +++++++++++++++----------------
 clippy_utils/src/paths.rs         |  9 --------
 2 files changed, 17 insertions(+), 26 deletions(-)

diff --git a/clippy_lints/src/manual_retain.rs b/clippy_lints/src/manual_retain.rs
index d4e53f8f74bd6..a35b0f914e058 100644
--- a/clippy_lints/src/manual_retain.rs
+++ b/clippy_lints/src/manual_retain.rs
@@ -3,22 +3,22 @@ use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item};
-use clippy_utils::{match_def_path, paths, SpanlessEq};
+use clippy_utils::SpanlessEq;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::ExprKind::Assign;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
-use rustc_span::symbol::sym;
+use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 
-const ACCEPTABLE_METHODS: [&[&str]; 5] = [
-    &paths::BINARYHEAP_ITER,
-    &paths::HASHSET_ITER,
-    &paths::BTREESET_ITER,
-    &paths::SLICE_INTO,
-    &paths::VEC_DEQUE_ITER,
+const ACCEPTABLE_METHODS: [Symbol; 5] = [
+    sym::binaryheap_iter,
+    sym::hashset_iter,
+    sym::btreeset_iter,
+    sym::slice_iter,
+    sym::vecdeque_iter,
 ];
 
 declare_clippy_lint! {
@@ -84,7 +84,7 @@ fn check_into_iter(
 ) {
     if let hir::ExprKind::MethodCall(_, into_iter_expr, [_], _) = &target_expr.kind
         && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
-        && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
+        && cx.tcx.is_diagnostic_item(sym::iter_filter, filter_def_id)
         && let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &into_iter_expr.kind
         && let Some(into_iter_def_id) = cx.typeck_results().type_dependent_def_id(into_iter_expr.hir_id)
         && Some(into_iter_def_id) == cx.tcx.lang_items().into_iter_fn()
@@ -127,14 +127,14 @@ fn check_iter(
 ) {
     if let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind
         && let Some(copied_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
-        && (match_def_path(cx, copied_def_id, &paths::CORE_ITER_COPIED)
-            || match_def_path(cx, copied_def_id, &paths::CORE_ITER_CLONED))
+        && (cx.tcx.is_diagnostic_item(sym::iter_copied, copied_def_id)
+            || cx.tcx.is_diagnostic_item(sym::iter_cloned, copied_def_id))
         && let hir::ExprKind::MethodCall(_, iter_expr, [_], _) = &filter_expr.kind
         && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(filter_expr.hir_id)
-        && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
+        && cx.tcx.is_diagnostic_item(sym::iter_filter, filter_def_id)
         && let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &iter_expr.kind
         && let Some(iter_expr_def_id) = cx.typeck_results().type_dependent_def_id(iter_expr.hir_id)
-        && match_acceptable_def_path(cx, iter_expr_def_id)
+        && match_acceptable_sym(cx, iter_expr_def_id)
         && match_acceptable_type(cx, left_expr, msrv)
         && SpanlessEq::new(cx).eq_expr(left_expr, struct_expr)
         && let hir::ExprKind::MethodCall(_, _, [closure_expr], _) = filter_expr.kind
@@ -189,10 +189,10 @@ fn check_to_owned(
         && cx.tcx.is_diagnostic_item(sym::to_owned_method, to_owned_def_id)
         && let hir::ExprKind::MethodCall(_, chars_expr, [_], _) = &filter_expr.kind
         && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(filter_expr.hir_id)
-        && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
+        && cx.tcx.is_diagnostic_item(sym::iter_filter, filter_def_id)
         && let hir::ExprKind::MethodCall(_, str_expr, [], _) = &chars_expr.kind
         && let Some(chars_expr_def_id) = cx.typeck_results().type_dependent_def_id(chars_expr.hir_id)
-        && match_def_path(cx, chars_expr_def_id, &paths::STR_CHARS)
+        && cx.tcx.is_diagnostic_item(sym::str_chars, chars_expr_def_id)
         && let ty = cx.typeck_results().expr_ty(str_expr).peel_refs()
         && is_type_lang_item(cx, ty, hir::LangItem::String)
         && SpanlessEq::new(cx).eq_expr(left_expr, str_expr)
@@ -247,10 +247,10 @@ fn make_sugg(
     }
 }
 
-fn match_acceptable_def_path(cx: &LateContext<'_>, collect_def_id: DefId) -> bool {
+fn match_acceptable_sym(cx: &LateContext<'_>, collect_def_id: DefId) -> bool {
     ACCEPTABLE_METHODS
         .iter()
-        .any(|&method| match_def_path(cx, collect_def_id, method))
+        .any(|&method| cx.tcx.is_diagnostic_item(method, collect_def_id))
 }
 
 fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: &Msrv) -> bool {
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 684c645c19964..fd28ca12d50fe 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -12,13 +12,8 @@ pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
     ["rustc_lint_defs", "Applicability", "MachineApplicable"],
 ];
 pub const DIAG: [&str; 2] = ["rustc_errors", "Diag"];
-pub const BINARYHEAP_ITER: [&str; 5] = ["alloc", "collections", "binary_heap", "BinaryHeap", "iter"];
 pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"];
 pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"];
-pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "BTreeSet", "iter"];
-pub const CORE_ITER_CLONED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "cloned"];
-pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "copied"];
-pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"];
 pub const CORE_RESULT_OK_METHOD: [&str; 4] = ["core", "result", "Result", "ok"];
 pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"];
 pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
@@ -39,7 +34,6 @@ pub const HASHMAP_VALUES: [&str; 5] = ["std", "collections", "hash", "map", "Val
 pub const HASHMAP_DRAIN: [&str; 5] = ["std", "collections", "hash", "map", "Drain"];
 pub const HASHMAP_VALUES_MUT: [&str; 5] = ["std", "collections", "hash", "map", "ValuesMut"];
 pub const HASHSET_ITER_TY: [&str; 5] = ["std", "collections", "hash", "set", "Iter"];
-pub const HASHSET_ITER: [&str; 6] = ["std", "collections", "hash", "set", "HashSet", "iter"];
 pub const HASHSET_DRAIN: [&str; 5] = ["std", "collections", "hash", "set", "Drain"];
 pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"];
 pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"];
@@ -71,13 +65,11 @@ pub const REGEX_SET_NEW: [&str; 3] = ["regex", "RegexSet", "new"];
 pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
 pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
 pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"];
-pub const SLICE_INTO: [&str; 4] = ["core", "slice", "<impl [T]>", "iter"];
 pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
 pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
 pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"];
 pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"];
 pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"];
-pub const STR_CHARS: [&str; 4] = ["core", "str", "<impl str>", "chars"];
 pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"];
 pub const STR_LEN: [&str; 4] = ["core", "str", "<impl str>", "len"];
 pub const STR_STARTS_WITH: [&str; 4] = ["core", "str", "<impl str>", "starts_with"];
@@ -100,7 +92,6 @@ pub const TOKIO_IO_OPEN_OPTIONS: [&str; 4] = ["tokio", "fs", "open_options", "Op
 pub const TOKIO_IO_OPEN_OPTIONS_NEW: [&str; 5] = ["tokio", "fs", "open_options", "OpenOptions", "new"];
 pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"];
 pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"];
-pub const VEC_DEQUE_ITER: [&str; 5] = ["alloc", "collections", "vec_deque", "VecDeque", "iter"];
 pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"];
 pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"];
 pub const VEC_WITH_CAPACITY: [&str; 4] = ["alloc", "vec", "Vec", "with_capacity"];

From 106a9af4cead1956bd27c8643672c891bcb38904 Mon Sep 17 00:00:00 2001
From: Philipp Krones <hello@philkrones.com>
Date: Wed, 18 Sep 2024 19:29:05 +0200
Subject: [PATCH 078/114] End my vacation

---
 triagebot.toml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/triagebot.toml b/triagebot.toml
index 99b3560a06427..dcf00e4e384b0 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -20,7 +20,6 @@ new_pr = true
 [assign]
 contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md"
 users_on_vacation = [
-    "flip1995",
     "matthiaskrgr",
     "giraffate",
 ]

From d2305ff634ddad950ef3a54103bc59e0309e9a17 Mon Sep 17 00:00:00 2001
From: Alex Macleod <alex@macleod.io>
Date: Wed, 18 Sep 2024 17:17:16 +0000
Subject: [PATCH 079/114] Generate versions HTML directly

---
 .github/deploy.sh           |   9 +--
 util/gh-pages/versions.html | 121 +++++++++++++++++++-----------------
 util/versions.py            |  41 ++++++------
 3 files changed, 87 insertions(+), 84 deletions(-)

diff --git a/.github/deploy.sh b/.github/deploy.sh
index d937661c0f828..5b4b4be4e36b5 100644
--- a/.github/deploy.sh
+++ b/.github/deploy.sh
@@ -25,16 +25,15 @@ if [[ $BETA = "true" ]]; then
 fi
 
 # Generate version index that is shown as root index page
-cp util/gh-pages/versions.html out/index.html
-
-echo "Making the versions.json file"
-python3 ./util/versions.py out
+python3 ./util/versions.py ./util/gh-pages/versions.html out
 
 # Now let's go have some fun with the cloned repo
 cd out
 git config user.name "GHA CI"
 git config user.email "gha@ci.invalid"
 
+git status
+
 if [[ -n $TAG_NAME ]]; then
   # track files, so that the following check works
   git add --intent-to-add "$TAG_NAME"
@@ -46,8 +45,6 @@ if [[ -n $TAG_NAME ]]; then
   git add "$TAG_NAME"
   # Update the symlink
   git add stable
-  # Update versions file
-  git add versions.json
   git commit -m "Add documentation for ${TAG_NAME} release: ${SHA}"
 elif [[ $BETA = "true" ]]; then
   if git diff --exit-code --quiet -- beta/; then
diff --git a/util/gh-pages/versions.html b/util/gh-pages/versions.html
index 31ce881932952..d38fe39a46403 100644
--- a/util/gh-pages/versions.html
+++ b/util/gh-pages/versions.html
@@ -1,4 +1,5 @@
 <!DOCTYPE html>
+<!-- Expanded by util/versions.py into the HTML file seen at https://rust-lang.github.io/rust-clippy/ -->
 <html lang="en">
 <head>
     <meta charset="UTF-8"/>
@@ -7,26 +8,15 @@
     <title>Clippy lints documentation</title>
 
     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css"/>
-    <style>
-        [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { display: none !important; }
-    </style>
 </head>
 <body>
-    <div class="container" ng-app="clippy" ng-controller="docVersions">
+    <div class="container">
         <div class="page-header">
             <h1>Clippy lints documentation</h1>
         </div>
 
-        <div ng-cloak>
-            <div class="alert alert-info" role="alert" ng-if="loading">
-                Loading&#x2026;
-            </div>
-            <div class="alert alert-danger" role="alert" ng-if="error">
-                Error loading versions!<br/>
-                You can always try to get <a href="master/index.html">the master branch docs</a>.
-            </div>
-
-            <article class="panel panel-default" ng-show="data">
+        <div>
+            <article class="panel panel-default">
                 <div class="panel-heading">
                     <h3 class="panel-title">
                         Available versions
@@ -34,55 +24,70 @@ <h3 class="panel-title">
                 </div>
 
                 <ul class="list-group">
-                    <a class="list-group-item" ng-repeat="version in data | orderBy:versionOrder:true"
-                       href="./{{version}}/index.html">
-                        {{version}}
-                    </a>
+                    $list
                 </ul>
             </article>
         </div>
     </div>
 
-    <a href="https://github.com/rust-lang/rust-clippy">
-        <img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"/>
-    </a>
-
-
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.12/angular.min.js"></script>
-    <script>
-        angular.module('clippy', [])
-        .controller('docVersions', function ($scope, $http) {
-            $scope.loading = true;
-
-            $scope.normalizeVersion = function(v) {
-                return v.replace(/^rust-/, '');
-            };
-
-            $scope.versionOrder = function(v) {
-                if (v === 'master') { return Infinity; }
-                if (v === 'stable') { return Number.MAX_VALUE; }
-                if (v === 'beta') { return Number.MAX_VALUE - 1; }
-                if (v === 'pre-1.29.0') { return Number.MIN_VALUE; }
-
-                return $scope.normalizeVersion(v)
-                    .split('.')
-                    .reverse()
-                    .reduce(function(acc, val, index) {
-                        return acc + (val * Math.pow(100, index));
-                    }, 0);
+    <a
+        aria-label="View source on GitHub"
+        class="github-corner"
+        href="https://github.com/rust-lang/rust-clippy"
+        rel="noopener noreferrer"
+        target="_blank"
+    >
+        <svg
+            width="80"
+            height="80"
+            viewBox="0 0 250 250"
+            style="position: absolute; top: 0; border: 0; right: 0"
+            aria-hidden="true"
+        >
+            <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z" fill="var(--theme-color)"></path>
+            <path
+                d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
+                fill="currentColor"
+                style="transform-origin: 130px 106px"
+                class="octo-arm"
+            ></path>
+            <path
+                d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
+                fill="currentColor"
+                class="octo-body"
+            ></path>
+        </svg>
+        <style>
+            .github-corner svg {
+                fill: black;
+                color: white;
             }
-
-            $http.get('./versions.json')
-            .success(function (data) {
-                $scope.data = data;
-                $scope.loading = false;
-            })
-            .error(function (data) {
-                $scope.error = data;
-                $scope.loading = false;
-            });
-        })
-        ;
-    </script>
+            .github-corner:hover .octo-arm {
+                animation: octocat-wave 560ms ease-in-out;
+            }
+            @keyframes octocat-wave {
+                0%,
+                100% {
+                    transform: rotate(0);
+                }
+                20%,
+                60% {
+                    transform: rotate(-25deg);
+                }
+                40%,
+                80% {
+                    transform: rotate(10deg);
+                }
+            }
+            @media (max-width: 500px) {
+                .github-corner:hover .octo-arm {
+                    animation: none;
+                }
+                .github-corner .octo-arm {
+                    animation: octocat-wave 560ms ease-in-out;
+                }
+            }
+        </style>
+    </a>
 </body>
 </html>
diff --git a/util/versions.py b/util/versions.py
index c041fc606a8f3..7a21a840a6d9a 100755
--- a/util/versions.py
+++ b/util/versions.py
@@ -1,22 +1,22 @@
 #!/usr/bin/env python
 
+from string import Template
+import argparse
 import json
-import logging as log
 import os
 import sys
 
-log.basicConfig(level=log.INFO, format="%(levelname)s: %(message)s")
-
-
 def key(v):
     if v == "master":
-        return float("inf")
-    if v == "stable":
         return sys.maxsize
-    if v == "beta":
+    if v == "stable":
         return sys.maxsize - 1
+    if v == "beta":
+        return sys.maxsize - 2
     if v == "pre-1.29.0":
         return -1
+    if not v.startswith("rust-"):
+        return None
 
     v = v.replace("rust-", "")
 
@@ -26,26 +26,27 @@ def key(v):
 
     return s
 
-
 def main():
-    if len(sys.argv) < 2:
-        log.error("specify output directory")
-        return
+    parser = argparse.ArgumentParser()
+    parser.add_argument("input", help="path to the versions.html template", type=argparse.FileType("r"))
+    parser.add_argument("outdir", help="path to write the output HTML")
+    args = parser.parse_args()
 
-    outdir = sys.argv[1]
     versions = [
         dir
-        for dir in os.listdir(outdir)
-        if not dir.startswith(".")
-        and not dir.startswith("v")
-        and os.path.isdir(os.path.join(outdir, dir))
+        for dir in os.listdir(args.outdir)
+        if key(dir) is not None
     ]
-    versions.sort(key=key)
+    versions.sort(key=key, reverse=True)
+    links = [f'<a class="list-group-item" href="./{version}/index.html">{version}</a>' for version in versions]
 
-    with open(os.path.join(outdir, "versions.json"), "w") as fp:
-        json.dump(versions, fp, indent=2)
-        log.info("wrote JSON for great justice")
+    template = Template(args.input.read())
+    html = template.substitute(list="\n".join(links))
 
+    path = os.path.join(args.outdir, "index.html")
+    with open(path, "w") as out:
+        out.write(html)
+        print(f"wrote HTML to {path}")
 
 if __name__ == "__main__":
     main()

From 5a13a93d41b34b869e3813c1dff4d8b81ed4b777 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 17:58:18 +0100
Subject: [PATCH 080/114] [Clippy] Swap `map_entry` to use diagnostic items
 instead of paths

---
 clippy_lints/src/entry.rs | 12 ++++++------
 clippy_utils/src/paths.rs |  4 ----
 2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs
index b7c9d3d03852f..9c5100a8c1af8 100644
--- a/clippy_lints/src/entry.rs
+++ b/clippy_lints/src/entry.rs
@@ -1,8 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{reindent_multiline, snippet_indent, snippet_with_applicability, snippet_with_context};
 use clippy_utils::{
-    can_move_expr_to_closure_no_visit, higher, is_expr_final_block_expr, is_expr_used_or_unified, match_def_path,
-    paths, peel_hir_expr_while, SpanlessEq,
+    can_move_expr_to_closure_no_visit, higher, is_expr_final_block_expr, is_expr_used_or_unified,
+    peel_hir_expr_while, SpanlessEq,
 };
 use core::fmt::{self, Write};
 use rustc_errors::Applicability;
@@ -11,7 +11,7 @@ use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{Block, Expr, ExprKind, HirId, Pat, Stmt, StmtKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::{Span, SyntaxContext, DUMMY_SP};
+use rustc_span::{sym, Span, SyntaxContext, DUMMY_SP};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -269,9 +269,9 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio
                 key,
                 call_ctxt: expr.span.ctxt(),
             };
-            if match_def_path(cx, id, &paths::BTREEMAP_CONTAINS_KEY) {
+            if cx.tcx.is_diagnostic_item(sym::btreemap_contains_key, id) {
                 Some((MapType::BTree, expr))
-            } else if match_def_path(cx, id, &paths::HASHMAP_CONTAINS_KEY) {
+            } else if cx.tcx.is_diagnostic_item(sym::hashmap_contains_key, id) {
                 Some((MapType::Hash, expr))
             } else {
                 None
@@ -306,7 +306,7 @@ struct InsertExpr<'tcx> {
 fn try_parse_insert<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<InsertExpr<'tcx>> {
     if let ExprKind::MethodCall(_, map, [key, value], _) = expr.kind {
         let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
-        if match_def_path(cx, id, &paths::BTREEMAP_INSERT) || match_def_path(cx, id, &paths::HASHMAP_INSERT) {
+        if cx.tcx.is_diagnostic_item(sym::btreemap_insert, id) || cx.tcx.is_diagnostic_item(sym::hashmap_insert, id) {
             Some(InsertExpr { map, key, value })
         } else {
             None
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index fd28ca12d50fe..59105383093da 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -12,8 +12,6 @@ pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
     ["rustc_lint_defs", "Applicability", "MachineApplicable"],
 ];
 pub const DIAG: [&str; 2] = ["rustc_errors", "Diag"];
-pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"];
-pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"];
 pub const CORE_RESULT_OK_METHOD: [&str; 4] = ["core", "result", "Result", "ok"];
 pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"];
 pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
@@ -25,8 +23,6 @@ pub const FILE_OPTIONS: [&str; 4] = ["std", "fs", "File", "options"];
 pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const FUTURES_IO_ASYNCWRITEEXT: [&str; 3] = ["futures_util", "io", "AsyncWriteExt"];
-pub const HASHMAP_CONTAINS_KEY: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "contains_key"];
-pub const HASHMAP_INSERT: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "insert"];
 pub const HASHMAP_ITER: [&str; 5] = ["std", "collections", "hash", "map", "Iter"];
 pub const HASHMAP_ITER_MUT: [&str; 5] = ["std", "collections", "hash", "map", "IterMut"];
 pub const HASHMAP_KEYS: [&str; 5] = ["std", "collections", "hash", "map", "Keys"];

From 71dbfd55a110cbd1673346db768fb6a06016abdd Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 19:36:12 +0100
Subject: [PATCH 081/114] [Clippy] Swap `lines_filter_map_ok` to use a
 diagnostic item instead of path

---
 clippy_lints/src/lines_filter_map_ok.rs | 4 ++--
 clippy_utils/src/paths.rs               | 1 -
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/clippy_lints/src/lines_filter_map_ok.rs b/clippy_lints/src/lines_filter_map_ok.rs
index 3d1c666dfea06..8206c75927b71 100644
--- a/clippy_lints/src/lines_filter_map_ok.rs
+++ b/clippy_lints/src/lines_filter_map_ok.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_diag_item_method, is_trait_method, match_def_path, path_to_local_id, paths};
+use clippy_utils::{is_diag_item_method, is_trait_method, path_to_local_id};
 use rustc_errors::Applicability;
 use rustc_hir::{Body, Closure, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -96,7 +96,7 @@ fn should_lint(cx: &LateContext<'_>, args: &[Expr<'_>], method_str: &str) -> boo
                 ExprKind::Path(qpath) => cx
                     .qpath_res(qpath, fm_arg.hir_id)
                     .opt_def_id()
-                    .is_some_and(|did| match_def_path(cx, did, &paths::CORE_RESULT_OK_METHOD)),
+                    .is_some_and(|did| cx.tcx.is_diagnostic_item(sym::result_ok_method, did)),
                 // Detect `|x| x.ok()`
                 ExprKind::Closure(Closure { body, .. }) => {
                     if let Body {
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 59105383093da..0d1d438287502 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -12,7 +12,6 @@ pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
     ["rustc_lint_defs", "Applicability", "MachineApplicable"],
 ];
 pub const DIAG: [&str; 2] = ["rustc_errors", "Diag"];
-pub const CORE_RESULT_OK_METHOD: [&str; 4] = ["core", "result", "Result", "ok"];
 pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"];
 pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
 pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"];

From 7ffd485be0fb0dc0a96ec0f1a56d108cc70e5584 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 21:09:06 +0100
Subject: [PATCH 082/114] [Clippy] Swap `option_as_ref_deref` to use diagnostic
 items instead of paths

---
 .../src/methods/option_as_ref_deref.rs        | 24 +++++++++----------
 clippy_utils/src/paths.rs                     |  7 ------
 2 files changed, 12 insertions(+), 19 deletions(-)

diff --git a/clippy_lints/src/methods/option_as_ref_deref.rs b/clippy_lints/src/methods/option_as_ref_deref.rs
index cb57689b0c41c..9a18d8a14219f 100644
--- a/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -2,12 +2,12 @@ use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{match_def_path, path_to_local_id, paths, peel_blocks};
+use clippy_utils::{path_to_local_id, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::sym;
+use rustc_span::{sym, Symbol};
 
 use super::OPTION_AS_REF_DEREF;
 
@@ -31,14 +31,14 @@ pub(super) fn check(
         return;
     }
 
-    let deref_aliases: [&[&str]; 7] = [
-        &paths::CSTRING_AS_C_STR,
-        &paths::OS_STRING_AS_OS_STR,
-        &paths::PATH_BUF_AS_PATH,
-        &paths::STRING_AS_STR,
-        &paths::STRING_AS_MUT_STR,
-        &paths::VEC_AS_SLICE,
-        &paths::VEC_AS_MUT_SLICE,
+    let deref_aliases: [Symbol; 7] = [
+        sym::cstring_as_c_str,
+        sym::os_string_as_os_str,
+        sym::pathbuf_as_path,
+        sym::string_as_str,
+        sym::string_as_mut_str,
+        sym::vec_as_slice,
+        sym::vec_as_mut_slice,
     ];
 
     let is_deref = match map_arg.kind {
@@ -48,7 +48,7 @@ pub(super) fn check(
                 .map_or(false, |fun_def_id| {
                     cx.tcx.is_diagnostic_item(sym::deref_method, fun_def_id)
                         || cx.tcx.is_diagnostic_item(sym::deref_mut_method, fun_def_id)
-                        || deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path))
+                        || deref_aliases.iter().any(|&sym| cx.tcx.is_diagnostic_item(sym, fun_def_id))
                 })
         },
         hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
@@ -69,7 +69,7 @@ pub(super) fn check(
                         let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap();
                         cx.tcx.is_diagnostic_item(sym::deref_method, method_did)
                             || cx.tcx.is_diagnostic_item(sym::deref_mut_method, method_did)
-                            || deref_aliases.iter().any(|path| match_def_path(cx, method_did, path))
+                            || deref_aliases.iter().any(|&sym| cx.tcx.is_diagnostic_item(sym, method_did))
                     } else {
                         false
                     }
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 0d1d438287502..e0fa814d30b14 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -12,7 +12,6 @@ pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
     ["rustc_lint_defs", "Applicability", "MachineApplicable"],
 ];
 pub const DIAG: [&str; 2] = ["rustc_errors", "Diag"];
-pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"];
 pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
 pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"];
 pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"];
@@ -40,12 +39,10 @@ pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"];
 pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
 pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"];
 pub const OPEN_OPTIONS_NEW: [&str; 4] = ["std", "fs", "OpenOptions", "new"];
-pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"];
 pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"];
 pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
 pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockReadGuard"];
 pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockWriteGuard"];
-pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"];
 pub const PATH_MAIN_SEPARATOR: [&str; 3] = ["std", "path", "MAIN_SEPARATOR"];
 pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
 #[cfg_attr(not(unix), allow(clippy::invalid_paths))]
@@ -62,8 +59,6 @@ pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
 pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"];
 pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
 pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
-pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"];
-pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"];
 pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"];
 pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"];
 pub const STR_LEN: [&str; 4] = ["core", "str", "<impl str>", "len"];
@@ -85,8 +80,6 @@ pub const TOKIO_IO_ASYNCWRITEEXT: [&str; 5] = ["tokio", "io", "util", "async_wri
 pub const TOKIO_IO_OPEN_OPTIONS: [&str; 4] = ["tokio", "fs", "open_options", "OpenOptions"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const TOKIO_IO_OPEN_OPTIONS_NEW: [&str; 5] = ["tokio", "fs", "open_options", "OpenOptions", "new"];
-pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"];
-pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"];
 pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"];
 pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"];
 pub const VEC_WITH_CAPACITY: [&str; 4] = ["alloc", "vec", "Vec", "with_capacity"];

From 8fc9e67cf516fe3fe48ea6ddb85d95c76062f98c Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 21:15:03 +0100
Subject: [PATCH 083/114] [Clippy] Swap `float_equality_without_abs` to use
 diagnostic items instead of paths

---
 clippy_lints/src/operators/float_equality_without_abs.rs | 6 +++---
 clippy_utils/src/paths.rs                                | 2 --
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/clippy_lints/src/operators/float_equality_without_abs.rs b/clippy_lints/src/operators/float_equality_without_abs.rs
index cace85a245139..be97ad389bf60 100644
--- a/clippy_lints/src/operators/float_equality_without_abs.rs
+++ b/clippy_lints/src/operators/float_equality_without_abs.rs
@@ -1,12 +1,12 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::{match_def_path, paths, sugg};
+use clippy_utils::sugg;
 use rustc_ast::util::parser::AssocOp;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::source_map::Spanned;
+use rustc_span::{sym, source_map::Spanned};
 
 use super::FLOAT_EQUALITY_WITHOUT_ABS;
 
@@ -36,7 +36,7 @@ pub(crate) fn check<'tcx>(
         // right hand side matches either f32::EPSILON or f64::EPSILON
         && let ExprKind::Path(ref epsilon_path) = rhs.kind
         && let Res::Def(DefKind::AssocConst, def_id) = cx.qpath_res(epsilon_path, rhs.hir_id)
-        && (match_def_path(cx, def_id, &paths::F32_EPSILON) || match_def_path(cx, def_id, &paths::F64_EPSILON))
+        && ([sym::f32_epsilon, sym::f64_epsilon].into_iter().any(|sym| cx.tcx.is_diagnostic_item(sym, def_id)))
 
         // values of the subtractions on the left hand side are of the type float
         && let t_val_l = cx.typeck_results().expr_ty(val_l)
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index e0fa814d30b14..ea7c19dec6d0d 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -14,8 +14,6 @@ pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
 pub const DIAG: [&str; 2] = ["rustc_errors", "Diag"];
 pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
 pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"];
-pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"];
-pub const F64_EPSILON: [&str; 4] = ["core", "f64", "<impl f64>", "EPSILON"];
 pub const FILE_OPTIONS: [&str; 4] = ["std", "fs", "File", "options"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];

From 1922a99bc677da7c758ee20dfb02929fe7008095 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 21:21:17 +0100
Subject: [PATCH 084/114] [Clippy] Swap `redundant_clone` to use diagnostic
 items instead of paths

---
 clippy_lints/src/redundant_clone.rs | 6 +++---
 clippy_utils/src/paths.rs           | 2 --
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs
index bfdc1cbeed7e1..4e24ddad83a56 100644
--- a/clippy_lints/src/redundant_clone.rs
+++ b/clippy_lints/src/redundant_clone.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
 use clippy_utils::mir::{visit_local_usage, LocalUsage, PossibleBorrowerMap};
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, is_type_lang_item, walk_ptrs_ty_depth};
-use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths};
+use clippy_utils::fn_has_unsatisfiable_preds;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{def_id, Body, FnDecl, LangItem};
@@ -102,8 +102,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
                     && is_type_lang_item(cx, arg_ty, LangItem::String));
 
             let from_deref = !from_borrow
-                && (match_def_path(cx, fn_def_id, &paths::PATH_TO_PATH_BUF)
-                    || match_def_path(cx, fn_def_id, &paths::OS_STR_TO_OS_STRING));
+                && (cx.tcx.is_diagnostic_item(sym::path_to_pathbuf, fn_def_id)
+                    || cx.tcx.is_diagnostic_item(sym::os_str_to_os_string, fn_def_id));
 
             if !from_borrow && !from_deref {
                 continue;
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index ea7c19dec6d0d..0a36d9a666494 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -37,12 +37,10 @@ pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"];
 pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
 pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"];
 pub const OPEN_OPTIONS_NEW: [&str; 4] = ["std", "fs", "OpenOptions", "new"];
-pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"];
 pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
 pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockReadGuard"];
 pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockWriteGuard"];
 pub const PATH_MAIN_SEPARATOR: [&str; 3] = ["std", "path", "MAIN_SEPARATOR"];
-pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
 #[cfg_attr(not(unix), allow(clippy::invalid_paths))]
 pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"];
 pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"];

From 959f7a2bbb481a5f8c7fb410f4017debea27e798 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 21:24:42 +0100
Subject: [PATCH 085/114] [Clippy] Swap `manual_main_separator_str` to use
 diagnostic item instead of path

---
 clippy_lints/src/manual_main_separator_str.rs | 4 ++--
 clippy_utils/src/paths.rs                     | 1 -
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/clippy_lints/src/manual_main_separator_str.rs b/clippy_lints/src/manual_main_separator_str.rs
index db491a8c8f692..5198d7838a281 100644
--- a/clippy_lints/src/manual_main_separator_str.rs
+++ b/clippy_lints/src/manual_main_separator_str.rs
@@ -1,7 +1,7 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::{is_trait_method, match_def_path, paths, peel_hir_expr_refs};
+use clippy_utils::{is_trait_method, peel_hir_expr_refs};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Expr, ExprKind, Mutability, QPath};
@@ -56,7 +56,7 @@ impl LateLintPass<'_> for ManualMainSeparatorStr {
             && let Res::Def(DefKind::Const, receiver_def_id) = path.res
             && is_trait_method(cx, target, sym::ToString)
             && self.msrv.meets(msrvs::PATH_MAIN_SEPARATOR_STR)
-            && match_def_path(cx, receiver_def_id, &paths::PATH_MAIN_SEPARATOR)
+            && cx.tcx.is_diagnostic_item(sym::path_main_separator, receiver_def_id)
             && let ty::Ref(_, ty, Mutability::Not) = cx.typeck_results().expr_ty_adjusted(expr).kind()
             && ty.is_str()
         {
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 0a36d9a666494..5e8157ac0c302 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -40,7 +40,6 @@ pub const OPEN_OPTIONS_NEW: [&str; 4] = ["std", "fs", "OpenOptions", "new"];
 pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
 pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockReadGuard"];
 pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockWriteGuard"];
-pub const PATH_MAIN_SEPARATOR: [&str; 3] = ["std", "path", "MAIN_SEPARATOR"];
 #[cfg_attr(not(unix), allow(clippy::invalid_paths))]
 pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"];
 pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"];

From f66915e8f82fd273ee9601c17b3eb2470774801a Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 21:37:12 +0100
Subject: [PATCH 086/114] [Clippy] Swap
 `single_char_add_str`/`format_push_string` to use diagnostic items instead of
 paths

---
 clippy_lints/src/format_push_string.rs          | 4 ++--
 clippy_lints/src/methods/single_char_add_str.rs | 6 +++---
 clippy_utils/src/paths.rs                       | 2 --
 3 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/clippy_lints/src/format_push_string.rs b/clippy_lints/src/format_push_string.rs
index d05c5a01f41ce..c6f03c3a7cf9a 100644
--- a/clippy_lints/src/format_push_string.rs
+++ b/clippy_lints/src/format_push_string.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::is_type_lang_item;
-use clippy_utils::{higher, match_def_path, paths};
+use clippy_utils::higher;
 use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem, MatchSource};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
@@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatPushString {
         let arg = match expr.kind {
             ExprKind::MethodCall(_, _, [arg], _) => {
                 if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
-                    && match_def_path(cx, fn_def_id, &paths::PUSH_STR)
+                    && cx.tcx.is_diagnostic_item(sym::string_push_str, fn_def_id)
                 {
                     arg
                 } else {
diff --git a/clippy_lints/src/methods/single_char_add_str.rs b/clippy_lints/src/methods/single_char_add_str.rs
index 81450fd8c6c3c..ccdf5529d537a 100644
--- a/clippy_lints/src/methods/single_char_add_str.rs
+++ b/clippy_lints/src/methods/single_char_add_str.rs
@@ -1,13 +1,13 @@
 use crate::methods::{single_char_insert_string, single_char_push_string};
-use clippy_utils::{match_def_path, paths};
 use rustc_hir as hir;
 use rustc_lint::LateContext;
+use rustc_span::sym;
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
     if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
-        if match_def_path(cx, fn_def_id, &paths::PUSH_STR) {
+        if cx.tcx.is_diagnostic_item(sym::string_push_str, fn_def_id) {
             single_char_push_string::check(cx, expr, receiver, args);
-        } else if match_def_path(cx, fn_def_id, &paths::INSERT_STR) {
+        } else if cx.tcx.is_diagnostic_item(sym::string_insert_str, fn_def_id) {
             single_char_insert_string::check(cx, expr, receiver, args);
         }
     }
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 5e8157ac0c302..64540637cdbfb 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -29,7 +29,6 @@ pub const HASHSET_ITER_TY: [&str; 5] = ["std", "collections", "hash", "set", "It
 pub const HASHSET_DRAIN: [&str; 5] = ["std", "collections", "hash", "set", "Drain"];
 pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"];
 pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"];
-pub const INSERT_STR: [&str; 4] = ["alloc", "string", "String", "insert_str"];
 pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
 pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"];
 pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"];
@@ -42,7 +41,6 @@ pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwL
 pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockWriteGuard"];
 #[cfg_attr(not(unix), allow(clippy::invalid_paths))]
 pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"];
-pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"];
 pub const REGEX_BUILDER_NEW: [&str; 3] = ["regex", "RegexBuilder", "new"];
 pub const REGEX_BYTES_BUILDER_NEW: [&str; 4] = ["regex", "bytes", "RegexBuilder", "new"];
 pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "bytes", "Regex", "new"];

From 545967955a52e2a2790def258a9c8a57dea3d379 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 21:42:38 +0100
Subject: [PATCH 087/114] [Clippy] Swap `VecArgs::hir` to use diagnostic items
 instead of paths

---
 clippy_lints/src/slow_vector_initialization.rs | 2 +-
 clippy_utils/src/higher.rs                     | 8 ++++----
 clippy_utils/src/paths.rs                      | 3 ---
 3 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs
index b0e25c02265b7..6c0b0e11c9e90 100644
--- a/clippy_lints/src/slow_vector_initialization.rs
+++ b/clippy_lints/src/slow_vector_initialization.rs
@@ -153,7 +153,7 @@ impl SlowVectorInit {
             && is_expr_path_def_path(cx, func, &paths::VEC_WITH_CAPACITY)
         {
             Some(InitializedSize::Initialized(len_expr))
-        } else if matches!(expr.kind, ExprKind::Call(func, _) if is_expr_path_def_path(cx, func, &paths::VEC_NEW)) {
+        } else if matches!(expr.kind, ExprKind::Call(func, _) if is_path_diagnostic_item(cx, func, sym::vec_new)) {
             Some(InitializedSize::Uninitialized)
         } else {
             None
diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs
index 8970b4d122984..e09cc9edf3ac3 100644
--- a/clippy_utils/src/higher.rs
+++ b/clippy_utils/src/higher.rs
@@ -4,7 +4,7 @@
 
 use crate::consts::{ConstEvalCtxt, Constant};
 use crate::ty::is_type_diagnostic_item;
-use crate::{is_expn_of, match_def_path, paths};
+use crate::is_expn_of;
 
 use rustc_ast::ast;
 use rustc_hir as hir;
@@ -297,10 +297,10 @@ impl<'a> VecArgs<'a> {
             && is_expn_of(fun.span, "vec").is_some()
             && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id()
         {
-            return if match_def_path(cx, fun_def_id, &paths::VEC_FROM_ELEM) && args.len() == 2 {
+            return if cx.tcx.is_diagnostic_item(sym::vec_from_elem, fun_def_id) && args.len() == 2 {
                 // `vec![elem; size]` case
                 Some(VecArgs::Repeat(&args[0], &args[1]))
-            } else if match_def_path(cx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 {
+            } else if cx.tcx.is_diagnostic_item(sym::slice_into_vec, fun_def_id) && args.len() == 1 {
                 // `vec![a, b, c]` case
                 if let ExprKind::Call(_, [arg]) = &args[0].kind
                     && let ExprKind::Array(args) = arg.kind
@@ -309,7 +309,7 @@ impl<'a> VecArgs<'a> {
                 } else {
                     None
                 }
-            } else if match_def_path(cx, fun_def_id, &paths::VEC_NEW) && args.is_empty() {
+            } else if cx.tcx.is_diagnostic_item(sym::vec_new, fun_def_id) && args.is_empty() {
                 Some(VecArgs::Vec(&[]))
             } else {
                 None
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 64540637cdbfb..1d5a22949789a 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -49,7 +49,6 @@ pub const REGEX_NEW: [&str; 3] = ["regex", "Regex", "new"];
 pub const REGEX_SET_NEW: [&str; 3] = ["regex", "RegexSet", "new"];
 pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
 pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
-pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"];
 pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
 pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
 pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"];
@@ -73,8 +72,6 @@ pub const TOKIO_IO_ASYNCWRITEEXT: [&str; 5] = ["tokio", "io", "util", "async_wri
 pub const TOKIO_IO_OPEN_OPTIONS: [&str; 4] = ["tokio", "fs", "open_options", "OpenOptions"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const TOKIO_IO_OPEN_OPTIONS_NEW: [&str; 5] = ["tokio", "fs", "open_options", "OpenOptions", "new"];
-pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"];
-pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"];
 pub const VEC_WITH_CAPACITY: [&str; 4] = ["alloc", "vec", "Vec", "with_capacity"];
 pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"];
 pub const VEC_IS_EMPTY: [&str; 4] = ["alloc", "vec", "Vec", "is_empty"];

From 984bd6fed6fafb1b6e33c7419ae4485402d76c62 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 21:53:28 +0100
Subject: [PATCH 088/114] [Clippy] Swap `repeat_vec_with_capacity` to use
 diagnostic item instead of path

---
 clippy_lints/src/repeat_vec_with_capacity.rs   | 6 +++---
 clippy_lints/src/slow_vector_initialization.rs | 6 +++---
 clippy_utils/src/paths.rs                      | 1 -
 3 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/clippy_lints/src/repeat_vec_with_capacity.rs b/clippy_lints/src/repeat_vec_with_capacity.rs
index 678681ea4252d..08de10f69b059 100644
--- a/clippy_lints/src/repeat_vec_with_capacity.rs
+++ b/clippy_lints/src/repeat_vec_with_capacity.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::VecArgs;
 use clippy_utils::macros::matching_root_macro_call;
 use clippy_utils::source::snippet;
-use clippy_utils::{expr_or_init, fn_def_id, match_def_path, paths};
+use clippy_utils::{expr_or_init, fn_def_id};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -67,7 +67,7 @@ fn emit_lint(cx: &LateContext<'_>, span: Span, kind: &str, note: &'static str, s
 fn check_vec_macro(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if matching_root_macro_call(cx, expr.span, sym::vec_macro).is_some()
         && let Some(VecArgs::Repeat(repeat_expr, len_expr)) = VecArgs::hir(cx, expr)
-        && fn_def_id(cx, repeat_expr).is_some_and(|did| match_def_path(cx, did, &paths::VEC_WITH_CAPACITY))
+        && fn_def_id(cx, repeat_expr).is_some_and(|did| cx.tcx.is_diagnostic_item(sym::vec_with_capacity, did))
         && !len_expr.span.from_expansion()
         && let Some(Constant::Int(2..)) = ConstEvalCtxt::new(cx).eval(expr_or_init(cx, len_expr))
     {
@@ -91,7 +91,7 @@ fn check_repeat_fn(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if !expr.span.from_expansion()
         && fn_def_id(cx, expr).is_some_and(|did| cx.tcx.is_diagnostic_item(sym::iter_repeat, did))
         && let ExprKind::Call(_, [repeat_expr]) = expr.kind
-        && fn_def_id(cx, repeat_expr).is_some_and(|did| match_def_path(cx, did, &paths::VEC_WITH_CAPACITY))
+        && fn_def_id(cx, repeat_expr).is_some_and(|did| cx.tcx.is_diagnostic_item(sym::vec_with_capacity, did))
         && !repeat_expr.span.from_expansion()
     {
         emit_lint(
diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs
index 6c0b0e11c9e90..04c16281ec4be 100644
--- a/clippy_lints/src/slow_vector_initialization.rs
+++ b/clippy_lints/src/slow_vector_initialization.rs
@@ -2,8 +2,8 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::matching_root_macro_call;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
-    get_enclosing_block, is_expr_path_def_path, is_integer_literal, is_path_diagnostic_item, path_to_local,
-    path_to_local_id, paths, SpanlessEq,
+    get_enclosing_block, is_integer_literal, is_path_diagnostic_item, path_to_local,
+    path_to_local_id, SpanlessEq,
 };
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, Visitor};
@@ -150,7 +150,7 @@ impl SlowVectorInit {
         }
 
         if let ExprKind::Call(func, [len_expr]) = expr.kind
-            && is_expr_path_def_path(cx, func, &paths::VEC_WITH_CAPACITY)
+            && is_path_diagnostic_item(cx, func, sym::vec_with_capacity)
         {
             Some(InitializedSize::Initialized(len_expr))
         } else if matches!(expr.kind, ExprKind::Call(func, _) if is_path_diagnostic_item(cx, func, sym::vec_new)) {
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 1d5a22949789a..0a0749aa005fd 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -72,7 +72,6 @@ pub const TOKIO_IO_ASYNCWRITEEXT: [&str; 5] = ["tokio", "io", "util", "async_wri
 pub const TOKIO_IO_OPEN_OPTIONS: [&str; 4] = ["tokio", "fs", "open_options", "OpenOptions"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const TOKIO_IO_OPEN_OPTIONS_NEW: [&str; 5] = ["tokio", "fs", "open_options", "OpenOptions", "new"];
-pub const VEC_WITH_CAPACITY: [&str; 4] = ["alloc", "vec", "Vec", "with_capacity"];
 pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"];
 pub const VEC_IS_EMPTY: [&str; 4] = ["alloc", "vec", "Vec", "is_empty"];
 pub const VEC_POP: [&str; 4] = ["alloc", "vec", "Vec", "pop"];

From b0152909d659b30879965b84bcf4a69ec4e82746 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 21:59:31 +0100
Subject: [PATCH 089/114] [Clippy] Swap `manual_while_let_some` to use
 diagnostic items instead of paths

---
 clippy_lints/src/loops/manual_while_let_some.rs | 14 +++++++-------
 clippy_utils/src/paths.rs                       |  4 ----
 2 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/clippy_lints/src/loops/manual_while_let_some.rs b/clippy_lints/src/loops/manual_while_let_some.rs
index 57434f3554443..55d1b9ee67671 100644
--- a/clippy_lints/src/loops/manual_while_let_some.rs
+++ b/clippy_lints/src/loops/manual_while_let_some.rs
@@ -1,10 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
-use clippy_utils::{match_def_path, paths, SpanlessEq};
+use clippy_utils::SpanlessEq;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Pat, Stmt, StmtKind, UnOp};
 use rustc_lint::LateContext;
-use rustc_span::Span;
+use rustc_span::{sym, Symbol, Span};
 use std::borrow::Cow;
 
 use super::MANUAL_WHILE_LET_SOME;
@@ -47,20 +47,20 @@ fn report_lint(cx: &LateContext<'_>, pop_span: Span, pop_stmt_kind: PopStmt<'_>,
     );
 }
 
-fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: &[&str]) -> bool {
+fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: Symbol) -> bool {
     if let ExprKind::MethodCall(..) = expr.kind
         && let Some(id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
     {
-        match_def_path(cx, id, method)
+        cx.tcx.is_diagnostic_item(method, id)
     } else {
         false
     }
 }
 
 fn is_vec_pop_unwrap(cx: &LateContext<'_>, expr: &Expr<'_>, is_empty_recv: &Expr<'_>) -> bool {
-    if (match_method_call(cx, expr, &paths::OPTION_UNWRAP) || match_method_call(cx, expr, &paths::OPTION_EXPECT))
+    if (match_method_call(cx, expr, sym::option_unwrap) || match_method_call(cx, expr, sym::option_expect))
         && let ExprKind::MethodCall(_, unwrap_recv, ..) = expr.kind
-        && match_method_call(cx, unwrap_recv, &paths::VEC_POP)
+        && match_method_call(cx, unwrap_recv, sym::vec_pop)
         && let ExprKind::MethodCall(_, pop_recv, ..) = unwrap_recv.kind
     {
         // make sure they're the same `Vec`
@@ -96,7 +96,7 @@ fn check_call_arguments(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &E
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, full_cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>, loop_span: Span) {
     if let ExprKind::Unary(UnOp::Not, cond) = full_cond.kind
         && let ExprKind::MethodCall(_, is_empty_recv, _, _) = cond.kind
-        && match_method_call(cx, cond, &paths::VEC_IS_EMPTY)
+        && match_method_call(cx, cond, sym::vec_is_empty)
         && let ExprKind::Block(body, _) = body.kind
         && let Some(stmt) = body.stmts.first()
     {
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 0a0749aa005fd..4a93939d0ccea 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -73,9 +73,5 @@ pub const TOKIO_IO_OPEN_OPTIONS: [&str; 4] = ["tokio", "fs", "open_options", "Op
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const TOKIO_IO_OPEN_OPTIONS_NEW: [&str; 5] = ["tokio", "fs", "open_options", "OpenOptions", "new"];
 pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"];
-pub const VEC_IS_EMPTY: [&str; 4] = ["alloc", "vec", "Vec", "is_empty"];
-pub const VEC_POP: [&str; 4] = ["alloc", "vec", "Vec", "pop"];
 pub const WAKER: [&str; 4] = ["core", "task", "wake", "Waker"];
-pub const OPTION_UNWRAP: [&str; 4] = ["core", "option", "Option", "unwrap"];
-pub const OPTION_EXPECT: [&str; 4] = ["core", "option", "Option", "expect"];
 pub const BOOL_THEN: [&str; 4] = ["core", "bool", "<impl bool>", "then"];

From 45c1700e13f5226a6a61d8f1136a319d6a4868bc Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 22:01:52 +0100
Subject: [PATCH 090/114] [Clippy] Swap `filter_map_bool_then` to use
 diagnostic item instead of path

---
 clippy_lints/src/methods/filter_map_bool_then.rs | 5 ++---
 clippy_utils/src/paths.rs                        | 1 -
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/clippy_lints/src/methods/filter_map_bool_then.rs b/clippy_lints/src/methods/filter_map_bool_then.rs
index 4fbf661727daa..77a62fbb4fb92 100644
--- a/clippy_lints/src/methods/filter_map_bool_then.rs
+++ b/clippy_lints/src/methods/filter_map_bool_then.rs
@@ -1,9 +1,8 @@
 use super::FILTER_MAP_BOOL_THEN;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::paths::BOOL_THEN;
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::is_copy;
-use clippy_utils::{is_from_proc_macro, is_trait_method, match_def_path, peel_blocks};
+use clippy_utils::{is_from_proc_macro, is_trait_method, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LintContext};
@@ -35,7 +34,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &
         && let ExprKind::Closure(then_closure) = then_arg.kind
         && let then_body = peel_blocks(cx.tcx.hir().body(then_closure.body).value)
         && let Some(def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id)
-        && match_def_path(cx, def_id, &BOOL_THEN)
+        && cx.tcx.is_diagnostic_item(sym::bool_then, def_id)
         && !is_from_proc_macro(cx, expr)
         // Count the number of derefs needed to get to the bool because we need those in the suggestion
         && let needed_derefs = cx.typeck_results().expr_adjustments(recv)
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 4a93939d0ccea..cb0330d004618 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -74,4 +74,3 @@ pub const TOKIO_IO_OPEN_OPTIONS: [&str; 4] = ["tokio", "fs", "open_options", "Op
 pub const TOKIO_IO_OPEN_OPTIONS_NEW: [&str; 5] = ["tokio", "fs", "open_options", "OpenOptions", "new"];
 pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"];
 pub const WAKER: [&str; 4] = ["core", "task", "wake", "Waker"];
-pub const BOOL_THEN: [&str; 4] = ["core", "bool", "<impl bool>", "then"];

From d63e35ba22ae0122e570fdabdb9e8875ef2bbef3 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 22:05:02 +0100
Subject: [PATCH 091/114] [Clippy] Swap `waker_clone_wake` to use diagnostic
 item instead of path

---
 clippy_lints/src/methods/waker_clone_wake.rs | 4 ++--
 clippy_utils/src/paths.rs                    | 1 -
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/clippy_lints/src/methods/waker_clone_wake.rs b/clippy_lints/src/methods/waker_clone_wake.rs
index da66632d55f5e..9b64cc7589ccc 100644
--- a/clippy_lints/src/methods/waker_clone_wake.rs
+++ b/clippy_lints/src/methods/waker_clone_wake.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_trait_method, match_def_path, paths};
+use clippy_utils::is_trait_method;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
@@ -12,7 +12,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'
     let ty = cx.typeck_results().expr_ty(recv);
 
     if let Some(did) = ty.ty_adt_def()
-        && match_def_path(cx, did.did(), &paths::WAKER)
+        && cx.tcx.is_diagnostic_item(sym::Waker, did.did())
         && let ExprKind::MethodCall(_, waker_ref, &[], _) = recv.kind
         && is_trait_method(cx, recv, sym::Clone)
     {
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index cb0330d004618..89c1bd8a8a03f 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -73,4 +73,3 @@ pub const TOKIO_IO_OPEN_OPTIONS: [&str; 4] = ["tokio", "fs", "open_options", "Op
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const TOKIO_IO_OPEN_OPTIONS_NEW: [&str; 5] = ["tokio", "fs", "open_options", "OpenOptions", "new"];
 pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"];
-pub const WAKER: [&str; 4] = ["core", "task", "wake", "Waker"];

From 98dc68e85e350a00dd65b76251b598f276d5a7c5 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 22:08:04 +0100
Subject: [PATCH 092/114] [Clippy] Swap `instant_subtraction` to use diagnostic
 item instead of path

---
 clippy_lints/src/instant_subtraction.rs | 2 +-
 clippy_utils/src/paths.rs               | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/clippy_lints/src/instant_subtraction.rs b/clippy_lints/src/instant_subtraction.rs
index f41fdf3203c99..6d6820311b679 100644
--- a/clippy_lints/src/instant_subtraction.rs
+++ b/clippy_lints/src/instant_subtraction.rs
@@ -112,7 +112,7 @@ impl LateLintPass<'_> for InstantSubtraction {
 fn is_instant_now_call(cx: &LateContext<'_>, expr_block: &'_ Expr<'_>) -> bool {
     if let ExprKind::Call(fn_expr, []) = expr_block.kind
         && let Some(fn_id) = clippy_utils::path_def_id(cx, fn_expr)
-        && clippy_utils::match_def_path(cx, fn_id, &clippy_utils::paths::INSTANT_NOW)
+        && cx.tcx.is_diagnostic_item(sym::instant_now, fn_id)
     {
         true
     } else {
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 89c1bd8a8a03f..26f680e2666a1 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -72,4 +72,3 @@ pub const TOKIO_IO_ASYNCWRITEEXT: [&str; 5] = ["tokio", "io", "util", "async_wri
 pub const TOKIO_IO_OPEN_OPTIONS: [&str; 4] = ["tokio", "fs", "open_options", "OpenOptions"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const TOKIO_IO_OPEN_OPTIONS_NEW: [&str; 5] = ["tokio", "fs", "open_options", "OpenOptions", "new"];
-pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"];

From acb6748f800f2581834bf7abc744d71e9bfc73d9 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 22:10:05 +0100
Subject: [PATCH 093/114] [Clippy] Swap `unnecessary_to_owned` to use
 diagnostic item instead of path

---
 clippy_lints/src/methods/unnecessary_to_owned.rs | 4 ++--
 clippy_utils/src/paths.rs                        | 1 -
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs
index 69c5bc57e2996..bf7555a29e220 100644
--- a/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -6,7 +6,7 @@ use clippy_utils::source::{snippet, SpanRangeExt};
 use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item};
 use clippy_utils::visitors::find_all_ret_expressions;
 use clippy_utils::{
-    fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, match_def_path, paths, peel_middle_ty_refs,
+    fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, peel_middle_ty_refs,
     return_ty,
 };
 use rustc_errors::Applicability;
@@ -250,7 +250,7 @@ fn check_string_from_utf8<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>,
     if let Some((call, arg)) = skip_addr_of_ancestors(cx, expr)
         && !arg.span.from_expansion()
         && let ExprKind::Call(callee, _) = call.kind
-        && fn_def_id(cx, call).is_some_and(|did| match_def_path(cx, did, &paths::STRING_FROM_UTF8))
+        && fn_def_id(cx, call).is_some_and(|did| cx.tcx.is_diagnostic_item(sym::string_from_utf8, did))
         && let Some(unwrap_call) = get_parent_expr(cx, call)
         && let ExprKind::MethodCall(unwrap_method_name, ..) = unwrap_call.kind
         && matches!(unwrap_method_name.ident.name, sym::unwrap | sym::expect)
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 26f680e2666a1..646c7bc5df85b 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -61,7 +61,6 @@ pub const SYMBOL_INTERN: [&str; 4] = ["rustc_span", "symbol", "Symbol", "intern"
 pub const SYMBOL_TO_IDENT_STRING: [&str; 4] = ["rustc_span", "symbol", "Symbol", "to_ident_string"];
 pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
 pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
-pub const STRING_FROM_UTF8: [&str; 4] = ["alloc", "string", "String", "from_utf8"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const TOKIO_FILE_OPTIONS: [&str; 5] = ["tokio", "fs", "file", "File", "options"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates

From 1b76ae683c2283c73ed2e84a29c2d023bb0f3974 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 22:13:50 +0100
Subject: [PATCH 094/114] [Clippy] Swap `manual_strip` to use diagnostic items
 instead of paths

---
 clippy_lints/src/manual_strip.rs | 10 +++++-----
 clippy_utils/src/paths.rs        |  3 ---
 2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs
index 85cabd2800a65..02d433ecc5aaa 100644
--- a/clippy_lints/src/manual_strip.rs
+++ b/clippy_lints/src/manual_strip.rs
@@ -4,7 +4,7 @@ use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use clippy_utils::usage::mutated_variables;
-use clippy_utils::{eq_expr_value, higher, match_def_path, paths};
+use clippy_utils::{eq_expr_value, higher};
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
@@ -14,7 +14,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
 use rustc_span::source_map::Spanned;
-use rustc_span::Span;
+use rustc_span::{sym, Span};
 use std::iter;
 
 declare_clippy_lint! {
@@ -76,9 +76,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
             && self.msrv.meets(msrvs::STR_STRIP_PREFIX)
             && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(cond.hir_id)
         {
-            let strip_kind = if match_def_path(cx, method_def_id, &paths::STR_STARTS_WITH) {
+            let strip_kind = if cx.tcx.is_diagnostic_item(sym::str_starts_with, method_def_id) {
                 StripKind::Prefix
-            } else if match_def_path(cx, method_def_id, &paths::STR_ENDS_WITH) {
+            } else if cx.tcx.is_diagnostic_item(sym::str_ends_with, method_def_id) {
                 StripKind::Suffix
             } else {
                 return;
@@ -137,7 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
 fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     if let ExprKind::MethodCall(_, arg, [], _) = expr.kind
         && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
-        && match_def_path(cx, method_def_id, &paths::STR_LEN)
+        && cx.tcx.is_diagnostic_item(sym::str_len, method_def_id)
     {
         Some(arg)
     } else {
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 646c7bc5df85b..986adddc6aecc 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -52,9 +52,6 @@ pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
 pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
 pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
 pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"];
-pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"];
-pub const STR_LEN: [&str; 4] = ["core", "str", "<impl str>", "len"];
-pub const STR_STARTS_WITH: [&str; 4] = ["core", "str", "<impl str>", "starts_with"];
 pub const SYMBOL: [&str; 3] = ["rustc_span", "symbol", "Symbol"];
 pub const SYMBOL_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Symbol", "as_str"];
 pub const SYMBOL_INTERN: [&str; 4] = ["rustc_span", "symbol", "Symbol", "intern"];

From f1fc9c07c4db8e1327558ad1088f074434213f42 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 22:38:27 +0100
Subject: [PATCH 095/114] [Clippy] Swap `unnecessary_owned_empty_strings` to
 use diagnostic item instead of path

---
 clippy_lints/src/unnecessary_owned_empty_strings.rs | 3 +--
 clippy_utils/src/paths.rs                           | 1 -
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/clippy_lints/src/unnecessary_owned_empty_strings.rs b/clippy_lints/src/unnecessary_owned_empty_strings.rs
index 6b5e6c6ab2095..f01cb457af896 100644
--- a/clippy_lints/src/unnecessary_owned_empty_strings.rs
+++ b/clippy_lints/src/unnecessary_owned_empty_strings.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::ty::is_type_lang_item;
-use clippy_utils::{match_def_path, paths};
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
@@ -42,7 +41,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryOwnedEmptyStrings {
             && let ty::Ref(_, inner_str, _) = cx.typeck_results().expr_ty_adjusted(expr).kind()
             && inner_str.is_str()
         {
-            if match_def_path(cx, fun_def_id, &paths::STRING_NEW) {
+            if cx.tcx.is_diagnostic_item(sym::string_new, fun_def_id) {
                 span_lint_and_sugg(
                     cx,
                     UNNECESSARY_OWNED_EMPTY_STRINGS,
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 986adddc6aecc..dd304e7aae876 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -51,7 +51,6 @@ pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
 pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
 pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
 pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
-pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"];
 pub const SYMBOL: [&str; 3] = ["rustc_span", "symbol", "Symbol"];
 pub const SYMBOL_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Symbol", "as_str"];
 pub const SYMBOL_INTERN: [&str; 4] = ["rustc_span", "symbol", "Symbol", "intern"];

From 37e38320b449dcb8bc11a537fd7914c8759c2e0c Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 23:01:37 +0100
Subject: [PATCH 096/114] [Clippy] Swap `non_octal_unix_permissions` to use
 diagnostic item instead of path

---
 clippy_lints/src/non_octal_unix_permissions.rs | 3 +--
 clippy_utils/src/paths.rs                      | 2 --
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/clippy_lints/src/non_octal_unix_permissions.rs b/clippy_lints/src/non_octal_unix_permissions.rs
index b915df527629e..cfc15d9271583 100644
--- a/clippy_lints/src/non_octal_unix_permissions.rs
+++ b/clippy_lints/src/non_octal_unix_permissions.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{snippet_with_applicability, SpanRangeExt};
-use clippy_utils::{match_def_path, paths};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -63,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
             ExprKind::Call(func, [param]) => {
                 if let ExprKind::Path(ref path) = func.kind
                     && let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
-                    && match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE)
+                    && cx.tcx.is_diagnostic_item(sym::permissions_from_mode, def_id)
                     && let ExprKind::Lit(_) = param.kind
                     && param.span.eq_ctxt(expr.span)
                     && param
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index dd304e7aae876..c7b1c01de1d88 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -39,8 +39,6 @@ pub const OPEN_OPTIONS_NEW: [&str; 4] = ["std", "fs", "OpenOptions", "new"];
 pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
 pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockReadGuard"];
 pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockWriteGuard"];
-#[cfg_attr(not(unix), allow(clippy::invalid_paths))]
-pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"];
 pub const REGEX_BUILDER_NEW: [&str; 3] = ["regex", "RegexBuilder", "new"];
 pub const REGEX_BYTES_BUILDER_NEW: [&str; 4] = ["regex", "bytes", "RegexBuilder", "new"];
 pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "bytes", "Regex", "new"];

From 917775fff17fba253a93d05b39b3c151deb6e106 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Wed, 18 Sep 2024 23:21:35 +0100
Subject: [PATCH 097/114] [Clippy] Swap `iter_over_hash_type` to use diagnostic
 items instead of paths

---
 clippy_lints/src/iter_over_hash_type.rs | 38 +++++++++----------------
 clippy_utils/src/paths.rs               |  8 ------
 2 files changed, 14 insertions(+), 32 deletions(-)

diff --git a/clippy_lints/src/iter_over_hash_type.rs b/clippy_lints/src/iter_over_hash_type.rs
index fb29d98241797..f162948bb4457 100644
--- a/clippy_lints/src/iter_over_hash_type.rs
+++ b/clippy_lints/src/iter_over_hash_type.rs
@@ -1,10 +1,5 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::higher::ForLoop;
-use clippy_utils::match_any_def_paths;
-use clippy_utils::paths::{
-    HASHMAP_DRAIN, HASHMAP_ITER, HASHMAP_ITER_MUT, HASHMAP_KEYS, HASHMAP_VALUES, HASHMAP_VALUES_MUT, HASHSET_DRAIN,
-    HASHSET_ITER_TY,
-};
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
@@ -44,28 +39,23 @@ declare_lint_pass!(IterOverHashType => [ITER_OVER_HASH_TYPE]);
 
 impl LateLintPass<'_> for IterOverHashType {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ rustc_hir::Expr<'_>) {
+        let hash_iter_tys = [
+            sym::HashMap,
+            sym::HashSet,
+            sym::hashmap_keys_ty,
+            sym::hashmap_values_ty,
+            sym::hashmap_values_mut_ty,
+            sym::hashmap_iter_ty,
+            sym::hashmap_iter_mut_ty,
+            sym::hashmap_drain_ty,
+            sym::hashset_iter_ty,
+            sym::hashset_drain_ty,
+        ];
+
         if let Some(for_loop) = ForLoop::hir(expr)
             && !for_loop.body.span.from_expansion()
             && let ty = cx.typeck_results().expr_ty(for_loop.arg).peel_refs()
-            && let Some(adt) = ty.ty_adt_def()
-            && let did = adt.did()
-            && (match_any_def_paths(
-                cx,
-                did,
-                &[
-                    &HASHMAP_KEYS,
-                    &HASHMAP_VALUES,
-                    &HASHMAP_VALUES_MUT,
-                    &HASHMAP_ITER,
-                    &HASHMAP_ITER_MUT,
-                    &HASHMAP_DRAIN,
-                    &HASHSET_ITER_TY,
-                    &HASHSET_DRAIN,
-                ],
-            )
-            .is_some()
-                || is_type_diagnostic_item(cx, ty, sym::HashMap)
-                || is_type_diagnostic_item(cx, ty, sym::HashSet))
+            && hash_iter_tys.into_iter().any(|sym| is_type_diagnostic_item(cx, ty, sym))
         {
             span_lint(
                 cx,
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index c7b1c01de1d88..ccaed3057f4d2 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -19,14 +19,6 @@ pub const FILE_OPTIONS: [&str; 4] = ["std", "fs", "File", "options"];
 pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const FUTURES_IO_ASYNCWRITEEXT: [&str; 3] = ["futures_util", "io", "AsyncWriteExt"];
-pub const HASHMAP_ITER: [&str; 5] = ["std", "collections", "hash", "map", "Iter"];
-pub const HASHMAP_ITER_MUT: [&str; 5] = ["std", "collections", "hash", "map", "IterMut"];
-pub const HASHMAP_KEYS: [&str; 5] = ["std", "collections", "hash", "map", "Keys"];
-pub const HASHMAP_VALUES: [&str; 5] = ["std", "collections", "hash", "map", "Values"];
-pub const HASHMAP_DRAIN: [&str; 5] = ["std", "collections", "hash", "map", "Drain"];
-pub const HASHMAP_VALUES_MUT: [&str; 5] = ["std", "collections", "hash", "map", "ValuesMut"];
-pub const HASHSET_ITER_TY: [&str; 5] = ["std", "collections", "hash", "set", "Iter"];
-pub const HASHSET_DRAIN: [&str; 5] = ["std", "collections", "hash", "set", "Drain"];
 pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"];
 pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"];
 pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];

From c7453b42801cc4cd9d7b7abaef6456bbb8d0de0b Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Thu, 19 Sep 2024 12:19:48 +0100
Subject: [PATCH 098/114] [Clippy] Swap `open_options` to use diagnostic items
 instead of paths

---
 clippy_lints/src/methods/open_options.rs | 23 ++++++++++++-----------
 clippy_utils/src/paths.rs                |  2 --
 2 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/clippy_lints/src/methods/open_options.rs b/clippy_lints/src/methods/open_options.rs
index cbeb48b6cc376..f1a3c81cebbdb 100644
--- a/clippy_lints/src/methods/open_options.rs
+++ b/clippy_lints/src/methods/open_options.rs
@@ -126,17 +126,18 @@ fn get_open_options(
         && let ExprKind::Path(path) = callee.kind
         && let Some(did) = cx.qpath_res(&path, callee.hir_id).opt_def_id()
     {
-        match_any_def_paths(
-            cx,
-            did,
-            &[
-                &paths::TOKIO_IO_OPEN_OPTIONS_NEW,
-                &paths::OPEN_OPTIONS_NEW,
-                &paths::FILE_OPTIONS,
-                &paths::TOKIO_FILE_OPTIONS,
-            ],
-        )
-        .is_some()
+        let std_file_options = [
+            sym::file_options,
+            sym::open_options_new,
+        ];
+
+        let tokio_file_options: &[&[&str]] = &[
+            &paths::TOKIO_IO_OPEN_OPTIONS_NEW,
+            &paths::TOKIO_FILE_OPTIONS,
+        ];
+
+        let is_std_options = std_file_options.into_iter().any(|sym| cx.tcx.is_diagnostic_item(sym, did));
+        is_std_options || match_any_def_paths(cx, did, tokio_file_options).is_some()
     } else {
         false
     }
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index ccaed3057f4d2..103a331a0a790 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -14,7 +14,6 @@ pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
 pub const DIAG: [&str; 2] = ["rustc_errors", "Diag"];
 pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
 pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"];
-pub const FILE_OPTIONS: [&str; 4] = ["std", "fs", "File", "options"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
@@ -27,7 +26,6 @@ pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"];
 pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"];
 pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
 pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"];
-pub const OPEN_OPTIONS_NEW: [&str; 4] = ["std", "fs", "OpenOptions", "new"];
 pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
 pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockReadGuard"];
 pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockWriteGuard"];

From 07b6e0713e37242037136b169d440d58c4500a3c Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Thu, 19 Sep 2024 13:09:25 +0100
Subject: [PATCH 099/114] Categorise paths in `clippy_utils::paths`

---
 clippy_utils/src/paths.rs | 33 ++++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 103a331a0a790..c8b59fca52418 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -4,6 +4,7 @@
 //! Whenever possible, please consider diagnostic items over hardcoded paths.
 //! See <https://github.com/rust-lang/rust-clippy/issues/5393> for more information.
 
+// Paths inside rustc
 pub const APPLICABILITY: [&str; 2] = ["rustc_lint_defs", "Applicability"];
 pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
     ["rustc_lint_defs", "Applicability", "Unspecified"],
@@ -14,18 +15,32 @@ pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
 pub const DIAG: [&str; 2] = ["rustc_errors", "Diag"];
 pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
 pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"];
-#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
-pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];
-#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
-pub const FUTURES_IO_ASYNCWRITEEXT: [&str; 3] = ["futures_util", "io", "AsyncWriteExt"];
 pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"];
 pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"];
-pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
 pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"];
 pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"];
 pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"];
 pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
+pub const SYMBOL: [&str; 3] = ["rustc_span", "symbol", "Symbol"];
+pub const SYMBOL_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Symbol", "as_str"];
+pub const SYMBOL_INTERN: [&str; 4] = ["rustc_span", "symbol", "Symbol", "intern"];
+pub const SYMBOL_TO_IDENT_STRING: [&str; 4] = ["rustc_span", "symbol", "Symbol", "to_ident_string"];
+pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
+pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
+
+// Paths in `core`/`alloc`/`std`. This should be avoided and cleaned up by adding diagnostic items.
+pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
+pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
+
+// Paths in clippy itself
 pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"];
+
+// Paths in external crates
+#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
+pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];
+#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
+pub const FUTURES_IO_ASYNCWRITEEXT: [&str; 3] = ["futures_util", "io", "AsyncWriteExt"];
+pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
 pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
 pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockReadGuard"];
 pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockWriteGuard"];
@@ -37,14 +52,6 @@ pub const REGEX_NEW: [&str; 3] = ["regex", "Regex", "new"];
 pub const REGEX_SET_NEW: [&str; 3] = ["regex", "RegexSet", "new"];
 pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
 pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
-pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
-pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
-pub const SYMBOL: [&str; 3] = ["rustc_span", "symbol", "Symbol"];
-pub const SYMBOL_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Symbol", "as_str"];
-pub const SYMBOL_INTERN: [&str; 4] = ["rustc_span", "symbol", "Symbol", "intern"];
-pub const SYMBOL_TO_IDENT_STRING: [&str; 4] = ["rustc_span", "symbol", "Symbol", "to_ident_string"];
-pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
-pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const TOKIO_FILE_OPTIONS: [&str; 5] = ["tokio", "fs", "file", "File", "options"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates

From 290a01e448e9e17710e03fc28c73de19f5889e5a Mon Sep 17 00:00:00 2001
From: Lukas Lueg <lukas.lueg@gmail.com>
Date: Thu, 19 Sep 2024 21:27:39 +0200
Subject: [PATCH 100/114] Initial impl of `unnecessary_first_then_check`

Fixes #11212
---
 CHANGELOG.md                                  |  1 +
 clippy_lints/src/declared_lints.rs            |  1 +
 clippy_lints/src/methods/mod.rs               | 33 +++++++++++
 .../methods/unnecessary_first_then_check.rs   | 56 +++++++++++++++++++
 tests/ui/unnecessary_first_then_check.fixed   | 22 ++++++++
 tests/ui/unnecessary_first_then_check.rs      | 22 ++++++++
 tests/ui/unnecessary_first_then_check.stderr  | 47 ++++++++++++++++
 7 files changed, 182 insertions(+)
 create mode 100644 clippy_lints/src/methods/unnecessary_first_then_check.rs
 create mode 100644 tests/ui/unnecessary_first_then_check.fixed
 create mode 100644 tests/ui/unnecessary_first_then_check.rs
 create mode 100644 tests/ui/unnecessary_first_then_check.stderr

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0e5d1688e4a72..6e0aaa25a7c8d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6021,6 +6021,7 @@ Released 2018-09-13
 [`unnecessary_fallible_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fallible_conversions
 [`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map
 [`unnecessary_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_find_map
+[`unnecessary_first_then_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_first_then_check
 [`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold
 [`unnecessary_get_then_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_get_then_check
 [`unnecessary_join`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_join
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index 16c64830e70dd..824f57cece93c 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -467,6 +467,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::methods::UNNECESSARY_FALLIBLE_CONVERSIONS_INFO,
     crate::methods::UNNECESSARY_FILTER_MAP_INFO,
     crate::methods::UNNECESSARY_FIND_MAP_INFO,
+    crate::methods::UNNECESSARY_FIRST_THEN_CHECK_INFO,
     crate::methods::UNNECESSARY_FOLD_INFO,
     crate::methods::UNNECESSARY_GET_THEN_CHECK_INFO,
     crate::methods::UNNECESSARY_JOIN_INFO,
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 9b7cba9dafba1..d8812dfd90cf2 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -111,6 +111,7 @@ mod uninit_assumed_init;
 mod unit_hash;
 mod unnecessary_fallible_conversions;
 mod unnecessary_filter_map;
+mod unnecessary_first_then_check;
 mod unnecessary_fold;
 mod unnecessary_get_then_check;
 mod unnecessary_iter_cloned;
@@ -4137,6 +4138,34 @@ declare_clippy_lint! {
     "use of `map` returning the original item"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks the usage of `.first().is_some()` or `.first().is_none()` to check if a slice is
+    /// empty.
+    ///
+    /// ### Why is this bad?
+    /// Using `.is_empty()` is shorter and better communicates the intention.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// let v = vec![1, 2, 3];
+    /// if v.first().is_none() {
+    ///     // The vector is empty...
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// let v = vec![1, 2, 3];
+    /// if v.is_empty() {
+    ///     // The vector is empty...
+    /// }
+    /// ```
+    #[clippy::version = "1.83.0"]
+    pub UNNECESSARY_FIRST_THEN_CHECK,
+    complexity,
+    "calling `.first().is_some()` or `.first().is_none()` instead of `.is_empty()`"
+}
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Msrv,
@@ -4294,6 +4323,7 @@ impl_lint_pass!(Methods => [
     UNNECESSARY_RESULT_MAP_OR_ELSE,
     MANUAL_C_STR_LITERALS,
     UNNECESSARY_GET_THEN_CHECK,
+    UNNECESSARY_FIRST_THEN_CHECK,
     NEEDLESS_CHARACTER_ITERATION,
     MANUAL_INSPECT,
     UNNECESSARY_MIN_OR_MAX,
@@ -5066,6 +5096,9 @@ fn check_is_some_is_none(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>,
         Some(("get", f_recv, [arg], _, _)) => {
             unnecessary_get_then_check::check(cx, call_span, recv, f_recv, arg, is_some);
         },
+        Some(("first", f_recv, [], _, _)) => {
+            unnecessary_first_then_check::check(cx, call_span, recv, f_recv, is_some);
+        },
         _ => {},
     }
 }
diff --git a/clippy_lints/src/methods/unnecessary_first_then_check.rs b/clippy_lints/src/methods/unnecessary_first_then_check.rs
new file mode 100644
index 0000000000000..7ae1bb54e6098
--- /dev/null
+++ b/clippy_lints/src/methods/unnecessary_first_then_check.rs
@@ -0,0 +1,56 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::SpanRangeExt;
+
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::LateContext;
+use rustc_span::Span;
+
+use super::UNNECESSARY_FIRST_THEN_CHECK;
+
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    call_span: Span,
+    first_call: &Expr<'_>,
+    first_caller: &Expr<'_>,
+    is_some: bool,
+) {
+    if !cx
+        .typeck_results()
+        .expr_ty_adjusted(first_caller)
+        .peel_refs()
+        .is_slice()
+    {
+        return;
+    }
+
+    let ExprKind::MethodCall(_, _, _, first_call_span) = first_call.kind else {
+        return;
+    };
+
+    let both_calls_span = first_call_span.with_hi(call_span.hi());
+    if let Some(both_calls_snippet) = both_calls_span.get_source_text(cx)
+        && let Some(first_caller_snippet) = first_caller.span.get_source_text(cx)
+    {
+        let (sugg_span, suggestion) = if is_some {
+            (
+                first_caller.span.with_hi(call_span.hi()),
+                format!("!{first_caller_snippet}.is_empty()"),
+            )
+        } else {
+            (both_calls_span, "is_empty()".to_owned())
+        };
+        span_lint_and_sugg(
+            cx,
+            UNNECESSARY_FIRST_THEN_CHECK,
+            sugg_span,
+            format!(
+                "unnecessary use of `{both_calls_snippet}` to check if slice {}",
+                if is_some { "is not empty" } else { "is empty" }
+            ),
+            "replace this with",
+            suggestion,
+            Applicability::MaybeIncorrect,
+        );
+    }
+}
diff --git a/tests/ui/unnecessary_first_then_check.fixed b/tests/ui/unnecessary_first_then_check.fixed
new file mode 100644
index 0000000000000..7202e1bbd179c
--- /dev/null
+++ b/tests/ui/unnecessary_first_then_check.fixed
@@ -0,0 +1,22 @@
+#![warn(clippy::unnecessary_first_then_check)]
+#![allow(clippy::useless_vec, clippy::const_is_empty)]
+
+fn main() {
+    let s = [1, 2, 3];
+    let _: bool = !s.is_empty();
+    let _: bool = s.is_empty();
+
+    let v = vec![1, 2, 3];
+    let _: bool = !v.is_empty();
+
+    let n = [[1, 2, 3], [4, 5, 6]];
+    let _: bool = !n[0].is_empty();
+    let _: bool = n[0].is_empty();
+
+    struct Foo {
+        bar: &'static [i32],
+    }
+    let f = [Foo { bar: &[] }];
+    let _: bool = !f[0].bar.is_empty();
+    let _: bool = f[0].bar.is_empty();
+}
diff --git a/tests/ui/unnecessary_first_then_check.rs b/tests/ui/unnecessary_first_then_check.rs
new file mode 100644
index 0000000000000..762b959992883
--- /dev/null
+++ b/tests/ui/unnecessary_first_then_check.rs
@@ -0,0 +1,22 @@
+#![warn(clippy::unnecessary_first_then_check)]
+#![allow(clippy::useless_vec, clippy::const_is_empty)]
+
+fn main() {
+    let s = [1, 2, 3];
+    let _: bool = s.first().is_some();
+    let _: bool = s.first().is_none();
+
+    let v = vec![1, 2, 3];
+    let _: bool = v.first().is_some();
+
+    let n = [[1, 2, 3], [4, 5, 6]];
+    let _: bool = n[0].first().is_some();
+    let _: bool = n[0].first().is_none();
+
+    struct Foo {
+        bar: &'static [i32],
+    }
+    let f = [Foo { bar: &[] }];
+    let _: bool = f[0].bar.first().is_some();
+    let _: bool = f[0].bar.first().is_none();
+}
diff --git a/tests/ui/unnecessary_first_then_check.stderr b/tests/ui/unnecessary_first_then_check.stderr
new file mode 100644
index 0000000000000..bbaf7e68edabb
--- /dev/null
+++ b/tests/ui/unnecessary_first_then_check.stderr
@@ -0,0 +1,47 @@
+error: unnecessary use of `first().is_some()` to check if slice is not empty
+  --> tests/ui/unnecessary_first_then_check.rs:6:19
+   |
+LL |     let _: bool = s.first().is_some();
+   |                   ^^^^^^^^^^^^^^^^^^^ help: replace this with: `!s.is_empty()`
+   |
+   = note: `-D clippy::unnecessary-first-then-check` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::unnecessary_first_then_check)]`
+
+error: unnecessary use of `first().is_none()` to check if slice is empty
+  --> tests/ui/unnecessary_first_then_check.rs:7:21
+   |
+LL |     let _: bool = s.first().is_none();
+   |                     ^^^^^^^^^^^^^^^^^ help: replace this with: `is_empty()`
+
+error: unnecessary use of `first().is_some()` to check if slice is not empty
+  --> tests/ui/unnecessary_first_then_check.rs:10:19
+   |
+LL |     let _: bool = v.first().is_some();
+   |                   ^^^^^^^^^^^^^^^^^^^ help: replace this with: `!v.is_empty()`
+
+error: unnecessary use of `first().is_some()` to check if slice is not empty
+  --> tests/ui/unnecessary_first_then_check.rs:13:19
+   |
+LL |     let _: bool = n[0].first().is_some();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `!n[0].is_empty()`
+
+error: unnecessary use of `first().is_none()` to check if slice is empty
+  --> tests/ui/unnecessary_first_then_check.rs:14:24
+   |
+LL |     let _: bool = n[0].first().is_none();
+   |                        ^^^^^^^^^^^^^^^^^ help: replace this with: `is_empty()`
+
+error: unnecessary use of `first().is_some()` to check if slice is not empty
+  --> tests/ui/unnecessary_first_then_check.rs:20:19
+   |
+LL |     let _: bool = f[0].bar.first().is_some();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `!f[0].bar.is_empty()`
+
+error: unnecessary use of `first().is_none()` to check if slice is empty
+  --> tests/ui/unnecessary_first_then_check.rs:21:28
+   |
+LL |     let _: bool = f[0].bar.first().is_none();
+   |                            ^^^^^^^^^^^^^^^^^ help: replace this with: `is_empty()`
+
+error: aborting due to 7 previous errors
+

From 4f319002cd961ce417820b7f7159b28c840a6ef0 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Thu, 19 Sep 2024 14:30:22 +0100
Subject: [PATCH 101/114] [Clippy] Remove final std paths for diagnostic item

---
 clippy_lints/src/methods/seek_from_current.rs |  6 ++--
 .../seek_to_start_instead_of_rewind.rs        |  6 ++--
 clippy_utils/src/lib.rs                       | 28 ++++++++-----------
 clippy_utils/src/paths.rs                     |  3 +-
 4 files changed, 18 insertions(+), 25 deletions(-)

diff --git a/clippy_lints/src/methods/seek_from_current.rs b/clippy_lints/src/methods/seek_from_current.rs
index e45c7962f13f4..8bc535ac47a84 100644
--- a/clippy_lints/src/methods/seek_from_current.rs
+++ b/clippy_lints/src/methods/seek_from_current.rs
@@ -8,7 +8,7 @@ use rustc_span::sym;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{match_def_path, paths};
+use clippy_utils::is_enum_variant_ctor;
 
 use super::SEEK_FROM_CURRENT;
 
@@ -36,8 +36,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'
 fn arg_is_seek_from_current<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
     if let ExprKind::Call(f, args) = expr.kind
         && let ExprKind::Path(ref path) = f.kind
-        && let Some(def_id) = cx.qpath_res(path, f.hir_id).opt_def_id()
-        && match_def_path(cx, def_id, &paths::STD_IO_SEEK_FROM_CURRENT)
+        && let Some(ctor_call_id) = cx.qpath_res(path, f.hir_id).opt_def_id()
+        && is_enum_variant_ctor(cx, sym::SeekFrom, sym!(Current), ctor_call_id)
     {
         // check if argument of `SeekFrom::Current` is `0`
         if args.len() == 1
diff --git a/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs b/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
index cc4cb47e35c63..7c09cc252e13a 100644
--- a/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
+++ b/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{is_expr_used_or_unified, match_def_path, paths};
+use clippy_utils::{is_expr_used_or_unified, is_enum_variant_ctor};
 use rustc_ast::ast::{LitIntType, LitKind};
 use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
@@ -28,8 +28,8 @@ pub(super) fn check<'tcx>(
         && implements_trait(cx, ty, seek_trait_id, &[])
         && let ExprKind::Call(func, args1) = arg.kind
         && let ExprKind::Path(ref path) = func.kind
-        && let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
-        && match_def_path(cx, def_id, &paths::STD_IO_SEEKFROM_START)
+        && let Some(ctor_call_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
+        && is_enum_variant_ctor(cx, sym::SeekFrom, sym!(Start), ctor_call_id)
         && args1.len() == 1
         && let ExprKind::Lit(lit) = args1[0].kind
         && let LitKind::Int(Pu128(0), LitIntType::Unsuffixed) = lit.node
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 5db14872c36b0..0d0d6219c5e05 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -263,24 +263,18 @@ pub fn is_res_lang_ctor(cx: &LateContext<'_>, res: Res, lang_item: LangItem) ->
     }
 }
 
-pub fn is_res_diagnostic_ctor(cx: &LateContext<'_>, res: Res, diag_item: Symbol) -> bool {
-    if let Res::Def(DefKind::Ctor(..), id) = res
-        && let Some(id) = cx.tcx.opt_parent(id)
-    {
-        cx.tcx.is_diagnostic_item(diag_item, id)
-    } else {
-        false
-    }
-}
 
-/// Checks if a `QPath` resolves to a constructor of a diagnostic item.
-pub fn is_diagnostic_ctor(cx: &LateContext<'_>, qpath: &QPath<'_>, diagnostic_item: Symbol) -> bool {
-    if let QPath::Resolved(_, path) = qpath {
-        if let Res::Def(DefKind::Ctor(..), ctor_id) = path.res {
-            return cx.tcx.is_diagnostic_item(diagnostic_item, cx.tcx.parent(ctor_id));
-        }
-    }
-    false
+/// Checks if `{ctor_call_id}(...)` is `{enum_item}::{variant_name}(...)`.
+pub fn is_enum_variant_ctor(cx: &LateContext<'_>, enum_item: Symbol, variant_name: Symbol, ctor_call_id: DefId) -> bool {
+    let Some(enum_def_id) = cx.tcx.get_diagnostic_item(enum_item) else {
+        return false;
+    };
+
+    let variants = cx.tcx.adt_def(enum_def_id).variants().iter();
+    variants
+        .filter(|variant| variant.name == variant_name)
+        .filter_map(|variant| variant.ctor.as_ref())
+        .any(|(_, ctor_def_id)| *ctor_def_id == ctor_call_id)
 }
 
 /// Checks if the `DefId` matches the given diagnostic item or it's constructor.
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index c8b59fca52418..a30edc48fff26 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -29,8 +29,7 @@ pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
 pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
 
 // Paths in `core`/`alloc`/`std`. This should be avoided and cleaned up by adding diagnostic items.
-pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
-pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
+// ... none currently!
 
 // Paths in clippy itself
 pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"];

From 05ebce8e1a973907db7d3e89e4738a095c250371 Mon Sep 17 00:00:00 2001
From: Ruairidh Williamson <williamsonruairidh@gmail.com>
Date: Sat, 21 Sep 2024 00:54:20 +0100
Subject: [PATCH 102/114] Add lint unused_trait_names

---
 CHANGELOG.md                           |  1 +
 book/src/lint_configuration.md         |  1 +
 clippy_config/src/conf.rs              |  1 +
 clippy_config/src/msrvs.rs             |  1 +
 clippy_lints/src/declared_lints.rs     |  1 +
 clippy_lints/src/lib.rs                |  2 +
 clippy_lints/src/unused_trait_names.rs | 94 ++++++++++++++++++++++++++
 7 files changed, 101 insertions(+)
 create mode 100644 clippy_lints/src/unused_trait_names.rs

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6e0aaa25a7c8d..41a86e8ce5102 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6063,6 +6063,7 @@ Released 2018-09-13
 [`unused_result_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_result_ok
 [`unused_rounding`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_rounding
 [`unused_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_self
+[`unused_trait_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_trait_names
 [`unused_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit
 [`unusual_byte_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unusual_byte_groupings
 [`unwrap_in_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_in_result
diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md
index 78348797588a6..91159bc79c511 100644
--- a/book/src/lint_configuration.md
+++ b/book/src/lint_configuration.md
@@ -727,6 +727,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
 * [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args)
 * [`unnecessary_lazy_evaluations`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations)
 * [`unnested_or_patterns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns)
+* [`unused_trait_names`](https://rust-lang.github.io/rust-clippy/master/index.html#unused_trait_names)
 * [`use_self`](https://rust-lang.github.io/rust-clippy/master/index.html#use_self)
 
 
diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs
index 6c1dd232593a1..1765cf87d4885 100644
--- a/clippy_config/src/conf.rs
+++ b/clippy_config/src/conf.rs
@@ -563,6 +563,7 @@ define_Conf! {
         uninlined_format_args,
         unnecessary_lazy_evaluations,
         unnested_or_patterns,
+        unused_trait_names,
         use_self,
     )]
     msrv: Msrv = Msrv::empty(),
diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs
index a70effd637699..a6cba84992214 100644
--- a/clippy_config/src/msrvs.rs
+++ b/clippy_config/src/msrvs.rs
@@ -49,6 +49,7 @@ msrv_aliases! {
     1,36,0 { ITERATOR_COPIED }
     1,35,0 { OPTION_COPIED, RANGE_CONTAINS }
     1,34,0 { TRY_FROM }
+    1,33,0 { UNDERSCORE_IMPORTS }
     1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES }
     1,29,0 { ITER_FLATTEN }
     1,28,0 { FROM_BOOL }
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index 824f57cece93c..2b229d2fe6ac5 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -748,6 +748,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::unused_result_ok::UNUSED_RESULT_OK_INFO,
     crate::unused_rounding::UNUSED_ROUNDING_INFO,
     crate::unused_self::UNUSED_SELF_INFO,
+    crate::unused_trait_names::UNUSED_TRAIT_NAMES_INFO,
     crate::unused_unit::UNUSED_UNIT_INFO,
     crate::unwrap::PANICKING_UNWRAP_INFO,
     crate::unwrap::UNNECESSARY_UNWRAP_INFO,
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 3604090b68ccc..b21d3f8d09eca 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -376,6 +376,7 @@ mod unused_peekable;
 mod unused_result_ok;
 mod unused_rounding;
 mod unused_self;
+mod unused_trait_names;
 mod unused_unit;
 mod unwrap;
 mod unwrap_in_result;
@@ -942,5 +943,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(move |_| Box::new(manual_div_ceil::ManualDivCeil::new(conf)));
     store.register_late_pass(|_| Box::new(manual_is_power_of_two::ManualIsPowerOfTwo));
     store.register_late_pass(|_| Box::new(non_zero_suggestions::NonZeroSuggestions));
+    store.register_late_pass(move |_| Box::new(unused_trait_names::UnusedTraitNames::new(conf)));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
diff --git a/clippy_lints/src/unused_trait_names.rs b/clippy_lints/src/unused_trait_names.rs
new file mode 100644
index 0000000000000..c1cf58dcfce3d
--- /dev/null
+++ b/clippy_lints/src/unused_trait_names.rs
@@ -0,0 +1,94 @@
+use clippy_config::msrvs::{self, Msrv};
+use clippy_config::Conf;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_from_proc_macro;
+use clippy_utils::source::snippet_opt;
+use rustc_errors::Applicability;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::{Item, ItemKind, UseKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext as _};
+use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty::Visibility;
+use rustc_session::impl_lint_pass;
+use rustc_span::symbol::kw;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `use Trait` where the Trait is only used for its methods and not referenced by a path directly.
+    ///
+    /// ### Why is this bad?
+    /// Traits imported that aren't used directly can be imported anonymously with `use Trait as _`.
+    /// It is more explicit, avoids polluting the current scope with unused names and can be useful to show which imports are required for traits.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// use std::fmt::Write;
+    ///
+    /// fn main() {
+    ///     let mut s = String::new();
+    ///     let _ = write!(s, "hello, world!");
+    ///     println!("{s}");
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// use std::fmt::Write as _;
+    ///
+    /// fn main() {
+    ///     let mut s = String::new();
+    ///     let _ = write!(s, "hello, world!");
+    ///     println!("{s}");
+    /// }
+    /// ```
+    #[clippy::version = "1.83.0"]
+    pub UNUSED_TRAIT_NAMES,
+    restriction,
+    "use items that import a trait but only use it anonymously"
+}
+
+pub struct UnusedTraitNames {
+    msrv: Msrv,
+}
+
+impl UnusedTraitNames {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
+    }
+}
+
+impl_lint_pass!(UnusedTraitNames => [UNUSED_TRAIT_NAMES]);
+
+impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+        if self.msrv.meets(msrvs::UNDERSCORE_IMPORTS)
+            && !in_external_macro(cx.sess(), item.span)
+            && let ItemKind::Use(path, UseKind::Single) = item.kind
+            // Ignore imports that already use Underscore
+            && item.ident.name != kw::Underscore
+            // Only check traits
+            && let Some(Res::Def(DefKind::Trait, _)) = path.res.first()
+            && cx.tcx.maybe_unused_trait_imports(()).contains(&item.owner_id.def_id)
+            // Only check this import if it is visible to its module only (no pub, pub(crate), ...)
+            && let module = cx.tcx.parent_module_from_def_id(item.owner_id.def_id)
+            && cx.tcx.visibility(item.owner_id.def_id) == Visibility::Restricted(module.to_def_id())
+            && let Some(last_segment) = path.segments.last()
+            && let Some(snip) = snippet_opt(cx, last_segment.ident.span)
+            && !is_from_proc_macro(cx, &last_segment.ident)
+        {
+            let complete_span = last_segment.ident.span.to(item.ident.span);
+            span_lint_and_sugg(
+                cx,
+                UNUSED_TRAIT_NAMES,
+                complete_span,
+                "importing trait that is only used anonymously",
+                "use",
+                format!("{snip} as _"),
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+
+    extract_msrv_attr!(LateContext);
+}

From 739ef7bf0d5686ef10e7700f34e34995936e00ff Mon Sep 17 00:00:00 2001
From: Ruairidh Williamson <williamsonruairidh@gmail.com>
Date: Sat, 21 Sep 2024 00:54:56 +0100
Subject: [PATCH 103/114] Add unused_trait_names tests

---
 clippy_lints/src/attrs/useless_attribute.rs |   1 +
 tests/ui/unused_trait_names.fixed           | 286 ++++++++++++++++++++
 tests/ui/unused_trait_names.rs              | 286 ++++++++++++++++++++
 tests/ui/unused_trait_names.stderr          |  73 +++++
 4 files changed, 646 insertions(+)
 create mode 100644 tests/ui/unused_trait_names.fixed
 create mode 100644 tests/ui/unused_trait_names.rs
 create mode 100644 tests/ui/unused_trait_names.stderr

diff --git a/clippy_lints/src/attrs/useless_attribute.rs b/clippy_lints/src/attrs/useless_attribute.rs
index 67ba605a59fa5..1296b59f2e1a0 100644
--- a/clippy_lints/src/attrs/useless_attribute.rs
+++ b/clippy_lints/src/attrs/useless_attribute.rs
@@ -51,6 +51,7 @@ pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute])
                                         | "module_name_repetitions"
                                         | "single_component_path_imports"
                                         | "disallowed_types"
+                                        | "unused_trait_names"
                                 )
                             }) {
                                 return;
diff --git a/tests/ui/unused_trait_names.fixed b/tests/ui/unused_trait_names.fixed
new file mode 100644
index 0000000000000..7dfd0db65aa1b
--- /dev/null
+++ b/tests/ui/unused_trait_names.fixed
@@ -0,0 +1,286 @@
+//@aux-build:proc_macros.rs
+
+#![allow(unused)]
+#![warn(clippy::unused_trait_names)]
+#![feature(decl_macro)]
+
+extern crate proc_macros;
+
+fn main() {}
+
+fn bad() {
+    use std::any::Any as _;
+
+    println!("{:?}", "foo".type_id());
+}
+
+fn good() {
+    use std::any::Any as _;
+
+    println!("{:?}", "foo".type_id());
+}
+
+fn used_good() {
+    use std::any::Any;
+
+    println!("{:?}", Any::type_id("foo"));
+    println!("{:?}", "foo".type_id());
+}
+
+fn multi_bad() {
+    use std::any::{self, Any as _, TypeId};
+
+    println!("{:?}", "foo".type_id());
+}
+
+fn multi_good() {
+    use std::any::{self, Any as _, TypeId};
+
+    println!("{:?}", "foo".type_id());
+}
+
+fn renamed_bad() {
+    use std::any::Any as _;
+
+    println!("{:?}", "foo".type_id());
+}
+
+fn multi_renamed_bad() {
+    use std::any::{Any as _, TypeId as MyTypeId};
+
+    println!("{:?}", "foo".type_id());
+}
+
+mod pub_good {
+    pub use std::any::Any;
+
+    fn foo() {
+        println!("{:?}", "foo".type_id());
+    }
+}
+
+mod used_mod_good {
+    use std::any::Any;
+
+    fn foo() {
+        println!("{:?}", Any::type_id("foo"));
+    }
+}
+
+mod mod_import_bad {
+    fn mod_import_bad() {
+        use std::any::Any as _;
+
+        println!("{:?}", "foo".type_id());
+    }
+}
+
+mod nested_mod_used_good1 {
+    use std::any::Any;
+
+    mod foo {
+        fn foo() {
+            super::Any::type_id("foo");
+        }
+    }
+}
+
+mod nested_mod_used_good2 {
+    use std::any::Any;
+
+    mod foo {
+        use super::Any;
+
+        fn foo() {
+            Any::type_id("foo");
+        }
+    }
+}
+
+mod nested_mod_used_good3 {
+    use std::any::Any;
+
+    mod foo {
+        use crate::nested_mod_used_good3::Any;
+
+        fn foo() {
+            println!("{:?}", Any::type_id("foo"));
+        }
+    }
+}
+
+mod nested_mod_used_bad {
+    use std::any::Any as _;
+
+    fn bar() {
+        println!("{:?}", "foo".type_id());
+    }
+
+    mod foo {
+        use std::any::Any;
+
+        fn foo() {
+            println!("{:?}", Any::type_id("foo"));
+        }
+    }
+}
+
+// More complex example where `use std::any::Any;` should be anonymised but `use std::any::Any as
+// MyAny;` should not as it is used by a sub module. Even though if you removed `use std::any::Any;`
+// the code would still compile.
+mod nested_mod_used_bad1 {
+    use std::any::Any as _;
+
+    use std::any::Any as MyAny;
+
+    fn baz() {
+        println!("{:?}", "baz".type_id());
+    }
+
+    mod foo {
+        use crate::nested_mod_used_bad1::MyAny;
+
+        fn foo() {
+            println!("{:?}", MyAny::type_id("foo"));
+        }
+    }
+}
+
+// Example of nested import with an unused import to try and trick it
+mod nested_mod_used_good5 {
+    use std::any::Any;
+
+    mod foo {
+        use std::any::Any;
+
+        fn baz() {
+            println!("{:?}", "baz".type_id());
+        }
+
+        mod bar {
+            use crate::nested_mod_used_good5::foo::Any;
+
+            fn foo() {
+                println!("{:?}", Any::type_id("foo"));
+            }
+        }
+    }
+}
+
+mod simple_trait {
+    pub trait MyTrait {
+        fn do_things(&self);
+    }
+
+    pub struct MyStruct;
+
+    impl MyTrait for MyStruct {
+        fn do_things(&self) {}
+    }
+}
+
+// Underscore imports were stabilized in 1.33
+#[clippy::msrv = "1.32"]
+fn msrv_1_32() {
+    use simple_trait::{MyStruct, MyTrait};
+    MyStruct.do_things();
+}
+
+#[clippy::msrv = "1.33"]
+fn msrv_1_33() {
+    use simple_trait::{MyStruct, MyTrait as _};
+    MyStruct.do_things();
+}
+
+mod lint_inside_macro_expansion_bad {
+    macro_rules! foo {
+        () => {
+            use std::any::Any as _;
+            fn bar() {
+                "bar".type_id();
+            }
+        };
+    }
+
+    foo!();
+}
+
+mod macro_and_trait_same_name {
+    pub macro Foo() {}
+    pub trait Foo {
+        fn bar(&self);
+    }
+    impl Foo for () {
+        fn bar(&self) {}
+    }
+}
+
+fn call_macro_and_trait_good() {
+    // importing trait and macro but only using macro by path won't allow us to change this to
+    // `use macro_and_trait_same_name::Foo as _;`
+    use macro_and_trait_same_name::Foo;
+    Foo!();
+    ().bar();
+}
+
+proc_macros::external!(
+    fn ignore_inside_external_proc_macro() {
+        use std::any::Any;
+        "foo".type_id();
+    }
+);
+
+proc_macros::with_span!(
+    span
+
+    fn ignore_inside_with_span_proc_macro() {
+        use std::any::Any;
+        "foo".type_id();
+    }
+);
+
+// This should warn the import is unused but should not trigger unused_trait_names
+#[warn(unused)]
+mod unused_import {
+    
+}
+
+#[allow(clippy::unused_trait_names)]
+fn allow_lint_fn() {
+    use std::any::Any;
+
+    "foo".type_id();
+}
+
+#[allow(clippy::unused_trait_names)]
+mod allow_lint_mod {
+    use std::any::Any;
+
+    fn foo() {
+        "foo".type_id();
+    }
+}
+
+mod allow_lint_import {
+    #[allow(clippy::unused_trait_names)]
+    use std::any::Any;
+
+    fn foo() {
+        "foo".type_id();
+    }
+}
+
+// Limitation: Suggests `use std::any::Any as _::{self};` which looks weird
+// fn use_trait_self_good() {
+//     use std::any::Any::{self};
+//     "foo".type_id();
+// }
+
+// Limitation: Suggests `use std::any::{Any as _, Any as _};`
+// mod repeated_renamed {
+//     use std::any::{Any, Any as MyAny};
+
+//     fn foo() {
+//         "foo".type_id();
+//     }
+// }
diff --git a/tests/ui/unused_trait_names.rs b/tests/ui/unused_trait_names.rs
new file mode 100644
index 0000000000000..ce44eedbc79c2
--- /dev/null
+++ b/tests/ui/unused_trait_names.rs
@@ -0,0 +1,286 @@
+//@aux-build:proc_macros.rs
+
+#![allow(unused)]
+#![warn(clippy::unused_trait_names)]
+#![feature(decl_macro)]
+
+extern crate proc_macros;
+
+fn main() {}
+
+fn bad() {
+    use std::any::Any;
+
+    println!("{:?}", "foo".type_id());
+}
+
+fn good() {
+    use std::any::Any as _;
+
+    println!("{:?}", "foo".type_id());
+}
+
+fn used_good() {
+    use std::any::Any;
+
+    println!("{:?}", Any::type_id("foo"));
+    println!("{:?}", "foo".type_id());
+}
+
+fn multi_bad() {
+    use std::any::{self, Any, TypeId};
+
+    println!("{:?}", "foo".type_id());
+}
+
+fn multi_good() {
+    use std::any::{self, Any as _, TypeId};
+
+    println!("{:?}", "foo".type_id());
+}
+
+fn renamed_bad() {
+    use std::any::Any as MyAny;
+
+    println!("{:?}", "foo".type_id());
+}
+
+fn multi_renamed_bad() {
+    use std::any::{Any as MyAny, TypeId as MyTypeId};
+
+    println!("{:?}", "foo".type_id());
+}
+
+mod pub_good {
+    pub use std::any::Any;
+
+    fn foo() {
+        println!("{:?}", "foo".type_id());
+    }
+}
+
+mod used_mod_good {
+    use std::any::Any;
+
+    fn foo() {
+        println!("{:?}", Any::type_id("foo"));
+    }
+}
+
+mod mod_import_bad {
+    fn mod_import_bad() {
+        use std::any::Any;
+
+        println!("{:?}", "foo".type_id());
+    }
+}
+
+mod nested_mod_used_good1 {
+    use std::any::Any;
+
+    mod foo {
+        fn foo() {
+            super::Any::type_id("foo");
+        }
+    }
+}
+
+mod nested_mod_used_good2 {
+    use std::any::Any;
+
+    mod foo {
+        use super::Any;
+
+        fn foo() {
+            Any::type_id("foo");
+        }
+    }
+}
+
+mod nested_mod_used_good3 {
+    use std::any::Any;
+
+    mod foo {
+        use crate::nested_mod_used_good3::Any;
+
+        fn foo() {
+            println!("{:?}", Any::type_id("foo"));
+        }
+    }
+}
+
+mod nested_mod_used_bad {
+    use std::any::Any;
+
+    fn bar() {
+        println!("{:?}", "foo".type_id());
+    }
+
+    mod foo {
+        use std::any::Any;
+
+        fn foo() {
+            println!("{:?}", Any::type_id("foo"));
+        }
+    }
+}
+
+// More complex example where `use std::any::Any;` should be anonymised but `use std::any::Any as
+// MyAny;` should not as it is used by a sub module. Even though if you removed `use std::any::Any;`
+// the code would still compile.
+mod nested_mod_used_bad1 {
+    use std::any::Any;
+
+    use std::any::Any as MyAny;
+
+    fn baz() {
+        println!("{:?}", "baz".type_id());
+    }
+
+    mod foo {
+        use crate::nested_mod_used_bad1::MyAny;
+
+        fn foo() {
+            println!("{:?}", MyAny::type_id("foo"));
+        }
+    }
+}
+
+// Example of nested import with an unused import to try and trick it
+mod nested_mod_used_good5 {
+    use std::any::Any;
+
+    mod foo {
+        use std::any::Any;
+
+        fn baz() {
+            println!("{:?}", "baz".type_id());
+        }
+
+        mod bar {
+            use crate::nested_mod_used_good5::foo::Any;
+
+            fn foo() {
+                println!("{:?}", Any::type_id("foo"));
+            }
+        }
+    }
+}
+
+mod simple_trait {
+    pub trait MyTrait {
+        fn do_things(&self);
+    }
+
+    pub struct MyStruct;
+
+    impl MyTrait for MyStruct {
+        fn do_things(&self) {}
+    }
+}
+
+// Underscore imports were stabilized in 1.33
+#[clippy::msrv = "1.32"]
+fn msrv_1_32() {
+    use simple_trait::{MyStruct, MyTrait};
+    MyStruct.do_things();
+}
+
+#[clippy::msrv = "1.33"]
+fn msrv_1_33() {
+    use simple_trait::{MyStruct, MyTrait};
+    MyStruct.do_things();
+}
+
+mod lint_inside_macro_expansion_bad {
+    macro_rules! foo {
+        () => {
+            use std::any::Any;
+            fn bar() {
+                "bar".type_id();
+            }
+        };
+    }
+
+    foo!();
+}
+
+mod macro_and_trait_same_name {
+    pub macro Foo() {}
+    pub trait Foo {
+        fn bar(&self);
+    }
+    impl Foo for () {
+        fn bar(&self) {}
+    }
+}
+
+fn call_macro_and_trait_good() {
+    // importing trait and macro but only using macro by path won't allow us to change this to
+    // `use macro_and_trait_same_name::Foo as _;`
+    use macro_and_trait_same_name::Foo;
+    Foo!();
+    ().bar();
+}
+
+proc_macros::external!(
+    fn ignore_inside_external_proc_macro() {
+        use std::any::Any;
+        "foo".type_id();
+    }
+);
+
+proc_macros::with_span!(
+    span
+
+    fn ignore_inside_with_span_proc_macro() {
+        use std::any::Any;
+        "foo".type_id();
+    }
+);
+
+// This should warn the import is unused but should not trigger unused_trait_names
+#[warn(unused)]
+mod unused_import {
+    use std::any::Any;
+}
+
+#[allow(clippy::unused_trait_names)]
+fn allow_lint_fn() {
+    use std::any::Any;
+
+    "foo".type_id();
+}
+
+#[allow(clippy::unused_trait_names)]
+mod allow_lint_mod {
+    use std::any::Any;
+
+    fn foo() {
+        "foo".type_id();
+    }
+}
+
+mod allow_lint_import {
+    #[allow(clippy::unused_trait_names)]
+    use std::any::Any;
+
+    fn foo() {
+        "foo".type_id();
+    }
+}
+
+// Limitation: Suggests `use std::any::Any as _::{self};` which looks weird
+// fn use_trait_self_good() {
+//     use std::any::Any::{self};
+//     "foo".type_id();
+// }
+
+// Limitation: Suggests `use std::any::{Any as _, Any as _};`
+// mod repeated_renamed {
+//     use std::any::{Any, Any as MyAny};
+
+//     fn foo() {
+//         "foo".type_id();
+//     }
+// }
diff --git a/tests/ui/unused_trait_names.stderr b/tests/ui/unused_trait_names.stderr
new file mode 100644
index 0000000000000..f59d8f58a170a
--- /dev/null
+++ b/tests/ui/unused_trait_names.stderr
@@ -0,0 +1,73 @@
+error: unused import: `std::any::Any`
+  --> tests/ui/unused_trait_names.rs:245:9
+   |
+LL |     use std::any::Any;
+   |         ^^^^^^^^^^^^^
+   |
+   = note: `-D unused-imports` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(unused_imports)]`
+
+error: importing trait that is only used anonymously
+  --> tests/ui/unused_trait_names.rs:12:19
+   |
+LL |     use std::any::Any;
+   |                   ^^^ help: use: `Any as _`
+   |
+   = note: `-D clippy::unused-trait-names` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::unused_trait_names)]`
+
+error: importing trait that is only used anonymously
+  --> tests/ui/unused_trait_names.rs:31:26
+   |
+LL |     use std::any::{self, Any, TypeId};
+   |                          ^^^ help: use: `Any as _`
+
+error: importing trait that is only used anonymously
+  --> tests/ui/unused_trait_names.rs:43:19
+   |
+LL |     use std::any::Any as MyAny;
+   |                   ^^^^^^^^^^^^ help: use: `Any as _`
+
+error: importing trait that is only used anonymously
+  --> tests/ui/unused_trait_names.rs:49:20
+   |
+LL |     use std::any::{Any as MyAny, TypeId as MyTypeId};
+   |                    ^^^^^^^^^^^^ help: use: `Any as _`
+
+error: importing trait that is only used anonymously
+  --> tests/ui/unused_trait_names.rs:72:23
+   |
+LL |         use std::any::Any;
+   |                       ^^^ help: use: `Any as _`
+
+error: importing trait that is only used anonymously
+  --> tests/ui/unused_trait_names.rs:113:19
+   |
+LL |     use std::any::Any;
+   |                   ^^^ help: use: `Any as _`
+
+error: importing trait that is only used anonymously
+  --> tests/ui/unused_trait_names.rs:132:19
+   |
+LL |     use std::any::Any;
+   |                   ^^^ help: use: `Any as _`
+
+error: importing trait that is only used anonymously
+  --> tests/ui/unused_trait_names.rs:191:34
+   |
+LL |     use simple_trait::{MyStruct, MyTrait};
+   |                                  ^^^^^^^ help: use: `MyTrait as _`
+
+error: importing trait that is only used anonymously
+  --> tests/ui/unused_trait_names.rs:198:27
+   |
+LL |             use std::any::Any;
+   |                           ^^^ help: use: `Any as _`
+...
+LL |     foo!();
+   |     ------ in this macro invocation
+   |
+   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 10 previous errors
+

From 249210e8d86a4de347def1be559dfa79d346cb9f Mon Sep 17 00:00:00 2001
From: Ben Kimock <kimockb@gmail.com>
Date: Thu, 19 Sep 2024 22:56:04 -0400
Subject: [PATCH 104/114] Fix clippy

---
 clippy_utils/src/mir/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clippy_utils/src/mir/mod.rs b/clippy_utils/src/mir/mod.rs
index e4966690d8c5c..654fb564848e2 100644
--- a/clippy_utils/src/mir/mod.rs
+++ b/clippy_utils/src/mir/mod.rs
@@ -30,7 +30,7 @@ pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) -
         locals.len()
     ];
 
-    traversal::Postorder::new(&mir.basic_blocks, location.block)
+    traversal::Postorder::new(&mir.basic_blocks, location.block, ())
         .collect::<Vec<_>>()
         .into_iter()
         .rev()

From 3ab1da8bab0779888975b62c934160da6b8aa6e7 Mon Sep 17 00:00:00 2001
From: Philipp Krones <hello@philkrones.com>
Date: Sun, 22 Sep 2024 20:42:10 +0200
Subject: [PATCH 105/114] Formatting

---
 clippy_config/src/conf.rs                     |   2 +-
 clippy_config/src/lib.rs                      |   2 +-
 clippy_config/src/msrvs.rs                    |   2 +-
 clippy_config/src/types.rs                    |   2 +-
 clippy_dev/src/fmt.rs                         |   2 +-
 clippy_dev/src/new_lint.rs                    |   2 +-
 clippy_dev/src/update_lints.rs                |  30 +--
 clippy_lints/src/absolute_paths.rs            |   4 +-
 clippy_lints/src/almost_complete_range.rs     |   2 +-
 clippy_lints/src/approx_const.rs              |   4 +-
 clippy_lints/src/arc_with_non_send_sync.rs    |   2 +-
 clippy_lints/src/assertions_on_constants.rs   |   2 +-
 .../src/assertions_on_result_states.rs        |   2 +-
 clippy_lints/src/assigning_clones.rs          |   4 +-
 .../attrs/allow_attributes_without_reason.rs  |   2 +-
 .../attrs/blanket_clippy_restriction_lints.rs |   4 +-
 clippy_lints/src/attrs/deprecated_cfg_attr.rs |   2 +-
 .../src/attrs/duplicated_attributes.rs        |   2 +-
 clippy_lints/src/attrs/inline_always.rs       |   4 +-
 clippy_lints/src/attrs/mod.rs                 |   2 +-
 clippy_lints/src/attrs/useless_attribute.rs   |   2 +-
 clippy_lints/src/await_holding_invalid.rs     |   2 +-
 clippy_lints/src/booleans.rs                  |   4 +-
 clippy_lints/src/box_default.rs               |   2 +-
 .../src/cargo/lint_groups_priority.rs         |   2 +-
 clippy_lints/src/casts/cast_lossless.rs       |   2 +-
 .../src/casts/cast_possible_truncation.rs     |   2 +-
 clippy_lints/src/casts/cast_possible_wrap.rs  |   2 +-
 clippy_lints/src/casts/cast_precision_loss.rs |   2 +-
 clippy_lints/src/casts/cast_sign_loss.rs      |   2 +-
 clippy_lints/src/casts/fn_to_numeric_cast.rs  |   2 +-
 .../fn_to_numeric_cast_with_truncation.rs     |   2 +-
 clippy_lints/src/casts/mod.rs                 |   2 +-
 clippy_lints/src/casts/ref_as_ptr.rs          |   2 +-
 clippy_lints/src/casts/unnecessary_cast.rs    |   4 +-
 clippy_lints/src/casts/utils.rs               |   2 +-
 clippy_lints/src/checked_conversions.rs       |   4 +-
 clippy_lints/src/cognitive_complexity.rs      |   4 +-
 clippy_lints/src/collection_is_never_read.rs  |   2 +-
 clippy_lints/src/comparison_chain.rs          |   2 +-
 clippy_lints/src/copies.rs                    |  11 +-
 clippy_lints/src/crate_in_macro_def.rs        |   2 +-
 clippy_lints/src/dbg_macro.rs                 |   4 +-
 clippy_lints/src/default.rs                   |   2 +-
 .../src/default_constructed_unit_structs.rs   |   2 +-
 .../src/default_instead_of_iter_empty.rs      |   4 +-
 clippy_lints/src/default_numeric_fallback.rs  |   2 +-
 clippy_lints/src/dereference.rs               |  73 +++---
 clippy_lints/src/derivable_impls.rs           |   2 +-
 clippy_lints/src/derive.rs                    |   4 +-
 clippy_lints/src/doc/empty_line_after.rs      |  13 +-
 clippy_lints/src/doc/link_with_quotes.rs      |   2 +-
 clippy_lints/src/doc/missing_headers.rs       |   2 +-
 clippy_lints/src/doc/mod.rs                   |   6 +-
 clippy_lints/src/doc/needless_doctest_main.rs |   2 +-
 clippy_lints/src/entry.rs                     |   8 +-
 clippy_lints/src/enum_clike.rs                |   2 +-
 clippy_lints/src/escape.rs                    |   4 +-
 clippy_lints/src/excessive_bools.rs           |   2 +-
 clippy_lints/src/excessive_nesting.rs         |   2 +-
 clippy_lints/src/explicit_write.rs            |   4 +-
 .../src/extra_unused_type_parameters.rs       |   4 +-
 clippy_lints/src/fallible_impl_from.rs        |   2 +-
 clippy_lints/src/floating_point_arithmetic.rs |   2 +-
 clippy_lints/src/format.rs                    |   6 +-
 clippy_lints/src/format_args.rs               |  11 +-
 clippy_lints/src/format_impl.rs               |   4 +-
 clippy_lints/src/format_push_string.rs        |   2 +-
 clippy_lints/src/from_over_into.rs            |   4 +-
 clippy_lints/src/from_str_radix_10.rs         |   2 +-
 clippy_lints/src/functions/mod.rs             |   2 +-
 clippy_lints/src/functions/must_use.rs        |   2 +-
 .../src/functions/not_unsafe_ptr_arg_deref.rs |   2 +-
 .../src/functions/renamed_function_params.rs  |   2 +-
 clippy_lints/src/functions/result.rs          |   4 +-
 clippy_lints/src/future_not_send.rs           |   2 +-
 clippy_lints/src/if_then_some_else_none.rs    |   2 +-
 clippy_lints/src/implicit_hasher.rs           |   6 +-
 clippy_lints/src/implicit_saturating_sub.rs   |   4 +-
 clippy_lints/src/incompatible_msrv.rs         |   4 +-
 clippy_lints/src/index_refutable_slice.rs     |   6 +-
 clippy_lints/src/ineffective_open_options.rs  |   2 +-
 clippy_lints/src/instant_subtraction.rs       |   2 +-
 clippy_lints/src/item_name_repetitions.rs     |   2 +-
 clippy_lints/src/items_after_test_module.rs   |   2 +-
 .../src/iter_not_returning_iterator.rs        |   2 +-
 clippy_lints/src/iter_over_hash_type.rs       |   4 +-
 clippy_lints/src/large_enum_variant.rs        |   2 +-
 clippy_lints/src/large_stack_arrays.rs        |   2 +-
 clippy_lints/src/legacy_numeric_constants.rs  |   4 +-
 clippy_lints/src/len_zero.rs                  |   4 +-
 clippy_lints/src/lib.rs                       |   2 +-
 clippy_lints/src/lifetimes.rs                 |  16 +-
 .../src/loops/explicit_counter_loop.rs        |   2 +-
 clippy_lints/src/loops/infinite_loop.rs       |   2 +-
 clippy_lints/src/loops/manual_find.rs         |   2 +-
 clippy_lints/src/loops/manual_flatten.rs      |   2 +-
 .../src/loops/manual_while_let_some.rs        |   4 +-
 clippy_lints/src/loops/mod.rs                 |   4 +-
 clippy_lints/src/loops/needless_range_loop.rs |   6 +-
 clippy_lints/src/loops/never_loop.rs          |   4 +-
 clippy_lints/src/loops/same_item_push.rs      |   4 +-
 clippy_lints/src/loops/single_element_loop.rs |   4 +-
 clippy_lints/src/loops/utils.rs               |   4 +-
 .../src/loops/while_immutable_condition.rs    |   2 +-
 .../src/loops/while_let_on_iterator.rs        |   4 +-
 clippy_lints/src/macro_metavars_in_unsafe.rs  |   6 +-
 clippy_lints/src/macro_use.rs                 |   2 +-
 clippy_lints/src/manual_async_fn.rs           |   4 +-
 clippy_lints/src/manual_bits.rs               |   2 +-
 clippy_lints/src/manual_clamp.rs              |   8 +-
 clippy_lints/src/manual_div_ceil.rs           |   2 +-
 clippy_lints/src/manual_hash_one.rs           |   2 +-
 clippy_lints/src/manual_is_ascii_check.rs     |   6 +-
 clippy_lints/src/manual_is_power_of_two.rs    |   2 +-
 clippy_lints/src/manual_let_else.rs           |   4 +-
 clippy_lints/src/manual_main_separator_str.rs |   2 +-
 clippy_lints/src/manual_non_exhaustive.rs     |   4 +-
 clippy_lints/src/manual_range_patterns.rs     |   2 +-
 clippy_lints/src/manual_rem_euclid.rs         |   2 +-
 clippy_lints/src/manual_retain.rs             |   8 +-
 clippy_lints/src/manual_string_new.rs         |   2 +-
 clippy_lints/src/manual_strip.rs              |   6 +-
 clippy_lints/src/map_unit_fn.rs               |   2 +-
 clippy_lints/src/matches/collapsible_match.rs |   4 +-
 clippy_lints/src/matches/manual_filter.rs     |   4 +-
 clippy_lints/src/matches/manual_map.rs        |   2 +-
 clippy_lints/src/matches/manual_unwrap_or.rs  |   4 +-
 clippy_lints/src/matches/manual_utils.rs      |   8 +-
 clippy_lints/src/matches/match_same_arms.rs   |   2 +-
 .../src/matches/match_str_case_mismatch.rs    |   4 +-
 clippy_lints/src/matches/mod.rs               |   2 +-
 clippy_lints/src/matches/overlapping_arms.rs  |   2 +-
 clippy_lints/src/matches/redundant_guards.rs  |   4 +-
 .../src/matches/redundant_pattern_match.rs    |   6 +-
 .../matches/significant_drop_in_scrutinee.rs  |   2 +-
 clippy_lints/src/matches/single_match.rs      |   6 +-
 clippy_lints/src/mem_replace.rs               |   4 +-
 .../src/methods/bind_instead_of_map.rs        |   2 +-
 ...se_sensitive_file_extension_comparisons.rs |   4 +-
 clippy_lints/src/methods/clear_with_drain.rs  |   2 +-
 clippy_lints/src/methods/clone_on_copy.rs     |   2 +-
 clippy_lints/src/methods/clone_on_ref_ptr.rs  |   2 +-
 .../src/methods/cloned_instead_of_copied.rs   |   2 +-
 .../src/methods/collapsible_str_replace.rs    |   2 +-
 clippy_lints/src/methods/drain_collect.rs     |   2 +-
 clippy_lints/src/methods/err_expect.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        |   4 +-
 .../src/methods/filter_map_bool_then.rs       |   4 +-
 .../src/methods/filter_map_identity.rs        |   2 +-
 clippy_lints/src/methods/flat_map_identity.rs |   2 +-
 clippy_lints/src/methods/flat_map_option.rs   |   2 +-
 clippy_lints/src/methods/get_last_with_len.rs |   2 +-
 .../src/methods/inefficient_to_string.rs      |   2 +-
 clippy_lints/src/methods/inspect_for_each.rs  |   2 +-
 clippy_lints/src/methods/into_iter_on_ref.rs  |   2 +-
 clippy_lints/src/methods/iter_filter.rs       |   2 +-
 clippy_lints/src/methods/iter_nth.rs          |   2 +-
 .../iter_on_single_or_empty_collections.rs    |   2 +-
 clippy_lints/src/methods/iter_with_drain.rs   |   2 +-
 .../src/methods/join_absolute_paths.rs        |   2 +-
 .../src/methods/manual_c_str_literals.rs      |   2 +-
 clippy_lints/src/methods/manual_inspect.rs    |   4 +-
 .../src/methods/manual_is_variant_and.rs      |   2 +-
 clippy_lints/src/methods/manual_ok_or.rs      |   2 +-
 clippy_lints/src/methods/manual_try_fold.rs   |   2 +-
 clippy_lints/src/methods/map_clone.rs         |   2 +-
 clippy_lints/src/methods/map_flatten.rs       |   2 +-
 clippy_lints/src/methods/map_identity.rs      |   2 +-
 clippy_lints/src/methods/mod.rs               |  13 +-
 clippy_lints/src/methods/mut_mutex_lock.rs    |   2 +-
 .../methods/needless_character_iteration.rs   |   2 +-
 clippy_lints/src/methods/needless_collect.rs  |   8 +-
 .../src/methods/needless_option_as_deref.rs   |   2 +-
 clippy_lints/src/methods/no_effect_replace.rs |   2 +-
 clippy_lints/src/methods/open_options.rs      |  16 +-
 .../src/methods/option_as_ref_cloned.rs       |   4 +-
 .../src/methods/option_as_ref_deref.rs        |  10 +-
 .../src/methods/option_map_unwrap_or.rs       |   4 +-
 clippy_lints/src/methods/or_fun_call.rs       |   2 +-
 clippy_lints/src/methods/or_then_unwrap.rs    |   2 +-
 .../src/methods/range_zip_with_len.rs         |   2 +-
 clippy_lints/src/methods/search_is_some.rs    |   2 +-
 clippy_lints/src/methods/seek_from_current.rs |   2 +-
 .../seek_to_start_instead_of_rewind.rs        |   4 +-
 clippy_lints/src/methods/str_splitn.rs        |   4 +-
 .../methods/suspicious_command_arg_space.rs   |   2 +-
 clippy_lints/src/methods/type_id_on_box.rs    |   2 +-
 .../unnecessary_fallible_conversions.rs       |   2 +-
 .../src/methods/unnecessary_filter_map.rs     |   2 +-
 clippy_lints/src/methods/unnecessary_fold.rs  |  70 ++---
 .../src/methods/unnecessary_get_then_check.rs |   2 +-
 .../src/methods/unnecessary_iter_cloned.rs    |   2 +-
 .../src/methods/unnecessary_literal_unwrap.rs |   2 +-
 .../src/methods/unnecessary_min_or_max.rs     |   2 +-
 .../methods/unnecessary_result_map_or_else.rs |   2 +-
 .../src/methods/unnecessary_to_owned.rs       |   7 +-
 .../src/methods/unused_enumerate_index.rs     |   4 +-
 clippy_lints/src/methods/useless_asref.rs     |   2 +-
 clippy_lints/src/methods/utils.rs             |   4 +-
 .../src/methods/vec_resize_to_zero.rs         |   2 +-
 clippy_lints/src/methods/waker_clone_wake.rs  |   2 +-
 clippy_lints/src/min_ident_chars.rs           |   2 +-
 clippy_lints/src/misc.rs                      |   6 +-
 clippy_lints/src/missing_assert_message.rs    |   2 +-
 .../src/missing_asserts_for_indexing.rs       |   4 +-
 clippy_lints/src/missing_const_for_fn.rs      |   4 +-
 .../src/missing_const_for_thread_local.rs     |   4 +-
 clippy_lints/src/missing_doc.rs               |   2 +-
 clippy_lints/src/missing_fields_in_debug.rs   |   4 +-
 clippy_lints/src/missing_inline.rs            |   2 +-
 .../src/mixed_read_write_in_expression.rs     |   2 +-
 .../src/multiple_unsafe_ops_per_block.rs      |  25 +-
 clippy_lints/src/mut_key.rs                   |   2 +-
 clippy_lints/src/mutable_debug_assertion.rs   |   2 +-
 .../src/needless_arbitrary_self_type.rs       |   2 +-
 clippy_lints/src/needless_bool.rs             |   6 +-
 .../src/needless_borrows_for_generic_args.rs  |   6 +-
 clippy_lints/src/needless_for_each.rs         |   4 +-
 clippy_lints/src/needless_pass_by_ref_mut.rs  |   2 +-
 clippy_lints/src/needless_pass_by_value.rs    |  15 +-
 clippy_lints/src/no_effect.rs                 |   4 +-
 clippy_lints/src/non_copy_const.rs            |   4 +-
 clippy_lints/src/non_expressive_names.rs      |   4 +-
 .../src/non_octal_unix_permissions.rs         |   2 +-
 clippy_lints/src/nonstandard_macro_braces.rs  |   4 +-
 clippy_lints/src/only_used_in_recursion.rs    |   2 +-
 .../operators/absurd_extreme_comparisons.rs   |   2 +-
 .../src/operators/const_comparisons.rs        |   4 +-
 .../operators/float_equality_without_abs.rs   |   3 +-
 clippy_lints/src/option_if_let_else.rs        |   6 +-
 clippy_lints/src/panic_in_result_fn.rs        |   4 +-
 clippy_lints/src/pass_by_ref_or_value.rs      |   2 +-
 clippy_lints/src/pathbuf_init_then_push.rs    |   4 +-
 clippy_lints/src/pattern_type_mismatch.rs     |   4 +-
 clippy_lints/src/ptr.rs                       |   4 +-
 clippy_lints/src/pub_underscore_fields.rs     |   2 +-
 clippy_lints/src/question_mark.rs             |   4 +-
 clippy_lints/src/ranges.rs                    |   6 +-
 clippy_lints/src/rc_clone_in_vec_init.rs      |   2 +-
 clippy_lints/src/read_zero_byte_vec.rs        |   4 +-
 clippy_lints/src/redundant_clone.rs           |  20 +-
 clippy_lints/src/redundant_closure_call.rs    |   2 +-
 clippy_lints/src/redundant_else.rs            |   2 +-
 clippy_lints/src/redundant_field_names.rs     |   2 +-
 clippy_lints/src/redundant_locals.rs          |   2 +-
 .../src/redundant_static_lifetimes.rs         |   2 +-
 clippy_lints/src/reference.rs                 |   2 +-
 clippy_lints/src/repeat_vec_with_capacity.rs  |   2 +-
 .../src/reserve_after_initialization.rs       |   2 +-
 clippy_lints/src/return_self_not_must_use.rs  |   2 +-
 clippy_lints/src/returns.rs                   |   8 +-
 clippy_lints/src/same_name_method.rs          |  13 +-
 clippy_lints/src/set_contains_or_insert.rs    |   4 +-
 .../src/significant_drop_tightening.rs        |   4 +-
 .../src/single_component_path_imports.rs      |   2 +-
 .../src/slow_vector_initialization.rs         |   5 +-
 clippy_lints/src/std_instead_of_core.rs       |   4 +-
 clippy_lints/src/string_patterns.rs           |   6 +-
 clippy_lints/src/strings.rs                   |   4 +-
 .../src/suspicious_operation_groupings.rs     |   4 +-
 clippy_lints/src/suspicious_trait_impl.rs     |   2 +-
 clippy_lints/src/swap.rs                      |   4 +-
 clippy_lints/src/swap_ptr_to_ref.rs           |   2 +-
 clippy_lints/src/tests_outside_test_module.rs |   2 +-
 clippy_lints/src/to_digit_is_some.rs          |  12 +-
 clippy_lints/src/trait_bounds.rs              |   6 +-
 clippy_lints/src/transmute/mod.rs             |   2 +-
 .../transmutes_expressible_as_ptr_casts.rs    |   2 +-
 .../transmute/unsound_collection_transmute.rs |   2 +-
 clippy_lints/src/tuple_array_conversions.rs   |   2 +-
 clippy_lints/src/types/box_collection.rs      |   2 +-
 clippy_lints/src/types/mod.rs                 |  66 ++---
 .../src/types/redundant_allocation.rs         |   2 +-
 clippy_lints/src/types/type_complexity.rs     |   2 +-
 clippy_lints/src/types/vec_box.rs             |   2 +-
 clippy_lints/src/unconditional_recursion.rs   |  17 +-
 .../src/undocumented_unsafe_blocks.rs         |   4 +-
 clippy_lints/src/uninhabited_references.rs    |   2 +-
 clippy_lints/src/uninit_vec.rs                |   6 +-
 clippy_lints/src/unit_return_expecting_ord.rs |   2 +-
 clippy_lints/src/unit_types/let_unit_value.rs |   2 +-
 clippy_lints/src/unit_types/unit_arg.rs       |   4 +-
 clippy_lints/src/unnecessary_wraps.rs         |   4 +-
 clippy_lints/src/unnested_or_patterns.rs      |   8 +-
 clippy_lints/src/unsafe_removed_from_name.rs  |   2 +-
 clippy_lints/src/unused_async.rs              |   4 +-
 clippy_lints/src/unused_io_amount.rs          |   2 +-
 clippy_lints/src/unused_peekable.rs           |   2 +-
 clippy_lints/src/unused_trait_names.rs        |   2 +-
 clippy_lints/src/unused_unit.rs               |   4 +-
 clippy_lints/src/unwrap.rs                    |   4 +-
 clippy_lints/src/unwrap_in_result.rs          |   2 +-
 clippy_lints/src/use_self.rs                  |   4 +-
 clippy_lints/src/useless_conversion.rs        |   2 +-
 clippy_lints/src/utils/author.rs              |   2 +-
 .../src/utils/format_args_collector.rs        |   4 +-
 .../utils/internal_lints/collapsible_calls.rs |   2 +-
 .../src/utils/internal_lints/invalid_paths.rs |   4 +-
 .../internal_lints/lint_without_lint_pass.rs  |   2 +-
 .../internal_lints/unnecessary_def_path.rs    |   4 +-
 clippy_lints/src/vec.rs                       |   4 +-
 clippy_lints/src/vec_init_then_push.rs        |   2 +-
 clippy_lints/src/visibility.rs                |   2 +-
 clippy_lints/src/wildcard_imports.rs          |   2 +-
 clippy_lints/src/write.rs                     |   6 +-
 clippy_lints/src/zombie_processes.rs          |   4 +-
 clippy_utils/src/ast_utils/ident_iter.rs      |   2 +-
 clippy_utils/src/attrs.rs                     |   2 +-
 clippy_utils/src/check_proc_macro.rs          |   4 +-
 clippy_utils/src/consts.rs                    |  10 +-
 clippy_utils/src/eager_or_lazy.rs             |   4 +-
 clippy_utils/src/higher.rs                    |   4 +-
 clippy_utils/src/hir_utils.rs                 |   8 +-
 clippy_utils/src/lib.rs                       |  34 +--
 clippy_utils/src/macros.rs                    |   4 +-
 clippy_utils/src/mir/mod.rs                   |  14 +-
 clippy_utils/src/ptr.rs                       |   2 +-
 clippy_utils/src/qualify_min_const_fn.rs      |   2 +-
 clippy_utils/src/source.rs                    |  21 +-
 clippy_utils/src/str_utils.rs                 |  10 +-
 clippy_utils/src/ty.rs                        |   4 +-
 clippy_utils/src/ty/type_certainty/mod.rs     |   4 +-
 clippy_utils/src/usage.rs                     |   2 +-
 clippy_utils/src/visitors.rs                  |   4 +-
 declare_clippy_lint/src/lib.rs                |  17 +-
 lintcheck/src/driver.rs                       |   2 +-
 lintcheck/src/recursive.rs                    |   2 +-
 src/driver.rs                                 |   2 +-
 tests/compile-test.rs                         |  10 +-
 tests/config-metadata.rs                      |   2 +-
 tests/ui-internal/unnecessary_def_path.fixed  |   2 +-
 tests/ui-internal/unnecessary_def_path.rs     |   2 +-
 .../conf_missing_enforced_import_rename.fixed |   2 +-
 .../conf_missing_enforced_import_rename.rs    |   2 +-
 ...conf_missing_enforced_import_rename.stderr |   6 +-
 tests/ui/arithmetic_side_effects.rs           |   1 -
 tests/ui/arithmetic_side_effects.stderr       | 246 +++++++++---------
 tests/ui/auxiliary/proc_macro_attr.rs         |   4 +-
 tests/ui/auxiliary/proc_macro_derive.rs       |   2 +-
 .../proc_macro_suspicious_else_formatting.rs  |   2 +-
 tests/ui/auxiliary/proc_macros.rs             |   2 +-
 .../borrow_interior_mutable_const/others.rs   |   2 +-
 .../declare_interior_mutable_const/others.rs  |   2 +-
 tests/ui/field_reassign_with_default.rs       |   2 +-
 tests/ui/format_args.fixed                    |   2 +-
 tests/ui/format_args.rs                       |   2 +-
 tests/ui/format_args_unfixable.rs             |   2 +-
 tests/ui/ignored_unit_patterns.fixed          |  15 +-
 tests/ui/ignored_unit_patterns.rs             |  15 +-
 tests/ui/ignored_unit_patterns.stderr         |  18 +-
 tests/ui/incompatible_msrv.rs                 |   2 +-
 tests/ui/legacy_numeric_constants.fixed       |   4 +-
 tests/ui/legacy_numeric_constants.rs          |   4 +-
 tests/ui/manual_saturating_arithmetic.fixed   |   2 +-
 tests/ui/manual_saturating_arithmetic.rs      |   2 +-
 tests/ui/must_use_candidates.fixed            |   2 +-
 tests/ui/must_use_candidates.rs               |   2 +-
 tests/ui/mut_key.rs                           |   2 +-
 tests/ui/non_zero_suggestions.fixed           |   2 +-
 tests/ui/non_zero_suggestions.rs              |   2 +-
 tests/ui/non_zero_suggestions_unfixable.rs    |   2 +-
 tests/ui/single_match.fixed                   |   2 +-
 tests/ui/single_match.rs                      |   2 +-
 tests/ui/suspicious_to_owned.rs               |   2 +-
 tests/ui/transmute_collection.rs              |   2 +-
 tests/ui/transmute_undefined_repr.rs          |   2 +-
 369 files changed, 874 insertions(+), 973 deletions(-)

diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs
index 1765cf87d4885..757620341ccc1 100644
--- a/clippy_config/src/conf.rs
+++ b/clippy_config/src/conf.rs
@@ -1,6 +1,6 @@
+use crate::ClippyConfiguration;
 use crate::msrvs::Msrv;
 use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename};
-use crate::ClippyConfiguration;
 use rustc_errors::Applicability;
 use rustc_session::Session;
 use rustc_span::edit_distance::edit_distance;
diff --git a/clippy_config/src/lib.rs b/clippy_config/src/lib.rs
index ac838cc81d2f0..c63d98a0a13f9 100644
--- a/clippy_config/src/lib.rs
+++ b/clippy_config/src/lib.rs
@@ -26,5 +26,5 @@ mod metadata;
 pub mod msrvs;
 pub mod types;
 
-pub use conf::{get_configuration_metadata, lookup_conf_file, Conf};
+pub use conf::{Conf, get_configuration_metadata, lookup_conf_file};
 pub use metadata::ClippyConfiguration;
diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs
index 5f163cbe8e17b..e30df3d32341a 100644
--- a/clippy_config/src/msrvs.rs
+++ b/clippy_config/src/msrvs.rs
@@ -1,7 +1,7 @@
 use rustc_ast::Attribute;
 use rustc_attr::parse_version;
 use rustc_session::{RustcVersion, Session};
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
 use serde::Deserialize;
 use std::fmt;
 
diff --git a/clippy_config/src/types.rs b/clippy_config/src/types.rs
index d47e34bb5bce5..bab63911182d1 100644
--- a/clippy_config/src/types.rs
+++ b/clippy_config/src/types.rs
@@ -1,5 +1,5 @@
 use serde::de::{self, Deserializer, Visitor};
-use serde::{ser, Deserialize, Serialize};
+use serde::{Deserialize, Serialize, ser};
 use std::fmt;
 
 #[derive(Debug, Deserialize)]
diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs
index 5fc4365c6e785..8c61c35533cf8 100644
--- a/clippy_dev/src/fmt.rs
+++ b/clippy_dev/src/fmt.rs
@@ -1,6 +1,6 @@
 use crate::clippy_project_root;
 use itertools::Itertools;
-use rustc_lexer::{tokenize, TokenKind};
+use rustc_lexer::{TokenKind, tokenize};
 use shell_escape::escape;
 use std::ffi::{OsStr, OsString};
 use std::ops::ControlFlow;
diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs
index de91233d196c8..c4d9c52a1cc25 100644
--- a/clippy_dev/src/new_lint.rs
+++ b/clippy_dev/src/new_lint.rs
@@ -441,7 +441,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
 
 #[allow(clippy::too_many_lines)]
 fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str> {
-    use super::update_lints::{match_tokens, LintDeclSearchResult};
+    use super::update_lints::{LintDeclSearchResult, match_tokens};
     use rustc_lexer::TokenKind;
 
     let lint_name_upper = lint.name.to_uppercase();
diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs
index 8dbda1c634c28..d6ed36d52f4e0 100644
--- a/clippy_dev/src/update_lints.rs
+++ b/clippy_dev/src/update_lints.rs
@@ -1,7 +1,7 @@
 use crate::clippy_project_root;
 use aho_corasick::AhoCorasickBuilder;
 use itertools::Itertools;
-use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
+use rustc_lexer::{LiteralKind, TokenKind, tokenize, unescape};
 use std::collections::{HashMap, HashSet};
 use std::ffi::OsStr;
 use std::fmt::{self, Write};
@@ -1048,23 +1048,17 @@ mod tests {
             Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
         ];
         let mut expected: HashMap<String, Vec<Lint>> = HashMap::new();
-        expected.insert(
-            "group1".to_string(),
-            vec![
-                Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
-                Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
-            ],
-        );
-        expected.insert(
-            "group2".to_string(),
-            vec![Lint::new(
-                "should_assert_eq2",
-                "group2",
-                "\"abc\"",
-                "module_name",
-                Range::default(),
-            )],
-        );
+        expected.insert("group1".to_string(), vec![
+            Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
+            Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
+        ]);
+        expected.insert("group2".to_string(), vec![Lint::new(
+            "should_assert_eq2",
+            "group2",
+            "\"abc\"",
+            "module_name",
+            Range::default(),
+        )]);
         assert_eq!(expected, Lint::by_lint_group(lints.into_iter()));
     }
 }
diff --git a/clippy_lints/src/absolute_paths.rs b/clippy_lints/src/absolute_paths.rs
index c72b3f1318c86..1af6d448a93c7 100644
--- a/clippy_lints/src/absolute_paths.rs
+++ b/clippy_lints/src/absolute_paths.rs
@@ -3,12 +3,12 @@ use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_from_proc_macro;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CRATE_DEF_INDEX, DefId};
 use rustc_hir::{HirId, ItemKind, Node, Path};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
-use rustc_span::symbol::kw;
 use rustc_span::Symbol;
+use rustc_span::symbol::kw;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/almost_complete_range.rs b/clippy_lints/src/almost_complete_range.rs
index 451bae959874f..370f0c482fd54 100644
--- a/clippy_lints/src/almost_complete_range.rs
+++ b/clippy_lints/src/almost_complete_range.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::{trim_span, walk_span_to_context};
 use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs
index 56f5e903dc3e2..4f8f091a09569 100644
--- a/clippy_lints/src/approx_const.rs
+++ b/clippy_lints/src/approx_const.rs
@@ -1,10 +1,10 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{impl_lint_pass, RustcVersion};
+use rustc_session::{RustcVersion, impl_lint_pass};
 use rustc_span::symbol;
 use std::f64::consts as f64;
 
diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs
index 4eafa330fafab..2643f850879cc 100644
--- a/clippy_lints/src/arc_with_non_send_sync.rs
+++ b/clippy_lints/src/arc_with_non_send_sync.rs
@@ -4,8 +4,8 @@ use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
-use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_middle::ty::GenericArgKind;
+use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_session::declare_lint_pass;
 use rustc_span::symbol::sym;
 
diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs
index 7eaac80f969f7..b6684825835a9 100644
--- a/clippy_lints/src/assertions_on_constants.rs
+++ b/clippy_lints/src/assertions_on_constants.rs
@@ -1,7 +1,7 @@
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::is_inside_always_const_context;
-use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn};
+use clippy_utils::macros::{PanicExpn, find_assert_args, root_macro_call_first_node};
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
diff --git a/clippy_lints/src/assertions_on_result_states.rs b/clippy_lints/src/assertions_on_result_states.rs
index f1cb4a05af86c..c073dee855e20 100644
--- a/clippy_lints/src/assertions_on_result_states.rs
+++ b/clippy_lints/src/assertions_on_result_states.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn};
+use clippy_utils::macros::{PanicExpn, find_assert_args, root_macro_call_first_node};
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::{has_debug_impl, is_copy, is_type_diagnostic_item};
 use clippy_utils::usage::local_used_after_expr;
diff --git a/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs
index 55645d04eef36..0b82c0cd04c12 100644
--- a/clippy_lints/src/assigning_clones.rs
+++ b/clippy_lints/src/assigning_clones.rs
@@ -1,7 +1,7 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::mir::{enclosing_mir, PossibleBorrowerMap};
+use clippy_utils::mir::{PossibleBorrowerMap, enclosing_mir};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{is_diag_trait_item, is_in_test, last_path_segment, local_is_initialized, path_to_local};
 use rustc_errors::Applicability;
diff --git a/clippy_lints/src/attrs/allow_attributes_without_reason.rs b/clippy_lints/src/attrs/allow_attributes_without_reason.rs
index 4c7e07478c129..40959eccd3a9f 100644
--- a/clippy_lints/src/attrs/allow_attributes_without_reason.rs
+++ b/clippy_lints/src/attrs/allow_attributes_without_reason.rs
@@ -1,4 +1,4 @@
-use super::{Attribute, ALLOW_ATTRIBUTES_WITHOUT_REASON};
+use super::{ALLOW_ATTRIBUTES_WITHOUT_REASON, Attribute};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_from_proc_macro;
 use rustc_ast::{MetaItemKind, NestedMetaItem};
diff --git a/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs b/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs
index 9b08fd6d654a5..508963a20ea71 100644
--- a/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs
+++ b/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs
@@ -1,10 +1,10 @@
-use super::utils::extract_clippy_lint;
 use super::BLANKET_CLIPPY_RESTRICTION_LINTS;
+use super::utils::extract_clippy_lint;
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
 use rustc_ast::NestedMetaItem;
 use rustc_lint::{LateContext, Level, LintContext};
 use rustc_span::symbol::Symbol;
-use rustc_span::{sym, DUMMY_SP};
+use rustc_span::{DUMMY_SP, sym};
 
 pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem]) {
     for lint in items {
diff --git a/clippy_lints/src/attrs/deprecated_cfg_attr.rs b/clippy_lints/src/attrs/deprecated_cfg_attr.rs
index e872ab6b4b5f5..abf924f7542e2 100644
--- a/clippy_lints/src/attrs/deprecated_cfg_attr.rs
+++ b/clippy_lints/src/attrs/deprecated_cfg_attr.rs
@@ -1,4 +1,4 @@
-use super::{unnecessary_clippy_cfg, Attribute, DEPRECATED_CFG_ATTR, DEPRECATED_CLIPPY_CFG_ATTR};
+use super::{Attribute, DEPRECATED_CFG_ATTR, DEPRECATED_CLIPPY_CFG_ATTR, unnecessary_clippy_cfg};
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use rustc_ast::AttrStyle;
diff --git a/clippy_lints/src/attrs/duplicated_attributes.rs b/clippy_lints/src/attrs/duplicated_attributes.rs
index 199e07565b0ea..55f8e1072db74 100644
--- a/clippy_lints/src/attrs/duplicated_attributes.rs
+++ b/clippy_lints/src/attrs/duplicated_attributes.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_ast::{Attribute, MetaItem};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 use std::collections::hash_map::Entry;
 
 fn emit_if_duplicated(
diff --git a/clippy_lints/src/attrs/inline_always.rs b/clippy_lints/src/attrs/inline_always.rs
index 3b5b80ffefaf2..d41bb580c6cd9 100644
--- a/clippy_lints/src/attrs/inline_always.rs
+++ b/clippy_lints/src/attrs/inline_always.rs
@@ -1,10 +1,10 @@
-use super::utils::is_word;
 use super::INLINE_ALWAYS;
+use super::utils::is_word;
 use clippy_utils::diagnostics::span_lint;
 use rustc_ast::Attribute;
 use rustc_lint::LateContext;
 use rustc_span::symbol::Symbol;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 pub(super) fn check(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Attribute]) {
     if span.from_expansion() {
diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs
index c8fea25c9f285..888f28fa2258c 100644
--- a/clippy_lints/src/attrs/mod.rs
+++ b/clippy_lints/src/attrs/mod.rs
@@ -12,8 +12,8 @@ mod unnecessary_clippy_cfg;
 mod useless_attribute;
 mod utils;
 
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use rustc_ast::{Attribute, MetaItemKind, NestedMetaItem};
 use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
 use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
diff --git a/clippy_lints/src/attrs/useless_attribute.rs b/clippy_lints/src/attrs/useless_attribute.rs
index 1296b59f2e1a0..12668c616c13e 100644
--- a/clippy_lints/src/attrs/useless_attribute.rs
+++ b/clippy_lints/src/attrs/useless_attribute.rs
@@ -1,7 +1,7 @@
 use super::utils::{extract_clippy_lint, is_lint_level, is_word};
 use super::{Attribute, USELESS_ATTRIBUTE};
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::{first_line_of_span, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, first_line_of_span};
 use rustc_ast::NestedMetaItem;
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
diff --git a/clippy_lints/src/await_holding_invalid.rs b/clippy_lints/src/await_holding_invalid.rs
index d5f017b26509b..9952d0af99e54 100644
--- a/clippy_lints/src/await_holding_invalid.rs
+++ b/clippy_lints/src/await_holding_invalid.rs
@@ -7,7 +7,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::CoroutineLayout;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs
index e933fdf1d6e6e..3c2af72624f60 100644
--- a/clippy_lints/src/booleans.rs
+++ b/clippy_lints/src/booleans.rs
@@ -4,12 +4,12 @@ use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
+use rustc_hir::intravisit::{FnKind, Visitor, walk_expr};
 use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, UnOp};
 use rustc_lint::{LateContext, LateLintPass, Level};
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/box_default.rs b/clippy_lints/src/box_default.rs
index 8459f051d3d9a..8261c65354fd5 100644
--- a/clippy_lints/src/box_default.rs
+++ b/clippy_lints/src/box_default.rs
@@ -4,7 +4,7 @@ use clippy_utils::ty::expr_sig;
 use clippy_utils::{is_default_equivalent, path_def_id};
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
-use rustc_hir::intravisit::{walk_ty, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_ty};
 use rustc_hir::{Block, Expr, ExprKind, LetStmt, Node, QPath, Ty, TyKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
diff --git a/clippy_lints/src/cargo/lint_groups_priority.rs b/clippy_lints/src/cargo/lint_groups_priority.rs
index e924542fea2aa..ffd6c520c9ae8 100644
--- a/clippy_lints/src/cargo/lint_groups_priority.rs
+++ b/clippy_lints/src/cargo/lint_groups_priority.rs
@@ -2,7 +2,7 @@ use super::LINT_GROUPS_PRIORITY;
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_lint::{unerased_lint_store, LateContext};
+use rustc_lint::{LateContext, unerased_lint_store};
 use rustc_span::{BytePos, Pos, SourceFile, Span, SyntaxContext};
 use serde::{Deserialize, Serialize};
 use std::collections::BTreeMap;
diff --git a/clippy_lints/src/casts/cast_lossless.rs b/clippy_lints/src/casts/cast_lossless.rs
index 346aed7e9f117..84a44b14dde5b 100644
--- a/clippy_lints/src/casts/cast_lossless.rs
+++ b/clippy_lints/src/casts/cast_lossless.rs
@@ -10,7 +10,7 @@ use rustc_lint::LateContext;
 use rustc_middle::ty::{self, FloatTy, Ty};
 use rustc_span::hygiene;
 
-use super::{utils, CAST_LOSSLESS};
+use super::{CAST_LOSSLESS, utils};
 
 pub(super) fn check(
     cx: &LateContext<'_>,
diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs
index 5708aae3f3eca..40a1a9d1ce8fb 100644
--- a/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -12,7 +12,7 @@ use rustc_middle::ty::{self, FloatTy, Ty};
 use rustc_span::Span;
 use rustc_target::abi::IntegerType;
 
-use super::{utils, CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION};
+use super::{CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION, utils};
 
 fn constant_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
     if let Some(Constant::Int(c)) = ConstEvalCtxt::new(cx).eval(expr) {
diff --git a/clippy_lints/src/casts/cast_possible_wrap.rs b/clippy_lints/src/casts/cast_possible_wrap.rs
index 11274383595a8..3cf4a43b0d4c7 100644
--- a/clippy_lints/src/casts/cast_possible_wrap.rs
+++ b/clippy_lints/src/casts/cast_possible_wrap.rs
@@ -3,7 +3,7 @@ use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty::Ty;
 
-use super::{utils, CAST_POSSIBLE_WRAP};
+use super::{CAST_POSSIBLE_WRAP, utils};
 
 // this should be kept in sync with the allowed bit widths of `usize` and `isize`
 const ALLOWED_POINTER_SIZES: [u64; 3] = [16, 32, 64];
diff --git a/clippy_lints/src/casts/cast_precision_loss.rs b/clippy_lints/src/casts/cast_precision_loss.rs
index 035666e4d4c92..1eb115ce6bdc0 100644
--- a/clippy_lints/src/casts/cast_precision_loss.rs
+++ b/clippy_lints/src/casts/cast_precision_loss.rs
@@ -4,7 +4,7 @@ use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, FloatTy, Ty};
 
-use super::{utils, CAST_PRECISION_LOSS};
+use super::{CAST_PRECISION_LOSS, utils};
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
     if !cast_from.is_integral() || cast_to.is_integral() {
diff --git a/clippy_lints/src/casts/cast_sign_loss.rs b/clippy_lints/src/casts/cast_sign_loss.rs
index 9daf237344a4b..4be53ace6871e 100644
--- a/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/clippy_lints/src/casts/cast_sign_loss.rs
@@ -3,7 +3,7 @@ use std::ops::ControlFlow;
 
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::visitors::{for_each_expr_without_closures, Descend};
+use clippy_utils::visitors::{Descend, for_each_expr_without_closures};
 use clippy_utils::{method_chain_args, sext};
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
diff --git a/clippy_lints/src/casts/fn_to_numeric_cast.rs b/clippy_lints/src/casts/fn_to_numeric_cast.rs
index dbe03e4ae8095..ac1a355c8d962 100644
--- a/clippy_lints/src/casts/fn_to_numeric_cast.rs
+++ b/clippy_lints/src/casts/fn_to_numeric_cast.rs
@@ -5,7 +5,7 @@ use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty, UintTy};
 
-use super::{utils, FN_TO_NUMERIC_CAST};
+use super::{FN_TO_NUMERIC_CAST, utils};
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
     // We only want to check casts to `ty::Uint` or `ty::Int`
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 dfbae1618ac62..18e7798452ead 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
@@ -5,7 +5,7 @@ use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
 
-use super::{utils, FN_TO_NUMERIC_CAST_WITH_TRUNCATION};
+use super::{FN_TO_NUMERIC_CAST_WITH_TRUNCATION, utils};
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
     // We only want to check casts to `ty::Uint` or `ty::Int`
diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index 39f50a347c064..3acd4eca420e0 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -23,8 +23,8 @@ mod unnecessary_cast;
 mod utils;
 mod zero_ptr;
 
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::is_hir_ty_cfg_dependant;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
diff --git a/clippy_lints/src/casts/ref_as_ptr.rs b/clippy_lints/src/casts/ref_as_ptr.rs
index 5f48b8bd2063e..dfa240ccec623 100644
--- a/clippy_lints/src/casts/ref_as_ptr.rs
+++ b/clippy_lints/src/casts/ref_as_ptr.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
-use clippy_utils::{expr_use_ctxt, is_no_std_crate, ExprUseNode};
+use clippy_utils::{ExprUseNode, expr_use_ctxt, is_no_std_crate};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, Mutability, Ty, TyKind};
 use rustc_lint::LateContext;
diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs
index 566adc83d6903..811d33c8bde2f 100644
--- a/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/clippy_lints/src/casts/unnecessary_cast.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::numeric_literal::NumericLiteral;
-use clippy_utils::source::{snippet_opt, SpanRangeExt};
-use clippy_utils::visitors::{for_each_expr_without_closures, Visitable};
+use clippy_utils::source::{SpanRangeExt, snippet_opt};
+use clippy_utils::visitors::{Visitable, for_each_expr_without_closures};
 use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local};
 use rustc_ast::{LitFloatType, LitIntType, LitKind};
 use rustc_errors::Applicability;
diff --git a/clippy_lints/src/casts/utils.rs b/clippy_lints/src/casts/utils.rs
index 5a4f20f099060..5ccba92a0afe8 100644
--- a/clippy_lints/src/casts/utils.rs
+++ b/clippy_lints/src/casts/utils.rs
@@ -1,4 +1,4 @@
-use clippy_utils::ty::{read_explicit_enum_value, EnumValue};
+use clippy_utils::ty::{EnumValue, read_explicit_enum_value};
 use rustc_middle::ty::{self, AdtDef, IntTy, Ty, TyCtxt, UintTy, VariantDiscr};
 
 /// Returns the size in bits of an integral type.
diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs
index dd7c34d1e4687..d3aa2fd1ea12c 100644
--- a/clippy_lints/src/checked_conversions.rs
+++ b/clippy_lints/src/checked_conversions.rs
@@ -1,8 +1,8 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_in_const_context, is_integer_literal, SpanlessEq};
+use clippy_utils::{SpanlessEq, is_in_const_context, is_integer_literal};
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, QPath, TyKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs
index 0099eefbc8dc1..495d8ce3fa701 100644
--- a/clippy_lints/src/cognitive_complexity.rs
+++ b/clippy_lints/src/cognitive_complexity.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::source::{IntoSpan, SpanRangeExt};
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::for_each_expr_without_closures;
-use clippy_utils::{get_async_fn_body, is_async_fn, LimitStack};
+use clippy_utils::{LimitStack, get_async_fn_body, is_async_fn};
 use core::ops::ControlFlow;
 use rustc_ast::ast::Attribute;
 use rustc_hir::intravisit::FnKind;
@@ -11,7 +11,7 @@ use rustc_hir::{Body, Expr, ExprKind, FnDecl};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/collection_is_never_read.rs b/clippy_lints/src/collection_is_never_read.rs
index c6847411c75ab..8276e53648c0e 100644
--- a/clippy_lints/src/collection_is_never_read.rs
+++ b/clippy_lints/src/collection_is_never_read.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item};
-use clippy_utils::visitors::{for_each_expr, Visitable};
+use clippy_utils::visitors::{Visitable, for_each_expr};
 use clippy_utils::{get_enclosing_block, path_to_local_id};
 use core::ops::ControlFlow;
 use rustc_hir::{Body, ExprKind, HirId, LangItem, LetStmt, Node, PatKind};
diff --git a/clippy_lints/src/comparison_chain.rs b/clippy_lints/src/comparison_chain.rs
index 5d78744e9b5e2..b9baf9af248ed 100644
--- a/clippy_lints/src/comparison_chain.rs
+++ b/clippy_lints/src/comparison_chain.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{if_sequence, is_else_clause, is_in_const_context, SpanlessEq};
+use clippy_utils::{SpanlessEq, if_sequence, is_else_clause, is_in_const_context};
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs
index 86e0368c4e423..d90a22bb62a60 100644
--- a/clippy_lints/src/copies.rs
+++ b/clippy_lints/src/copies.rs
@@ -1,16 +1,17 @@
 use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_then};
-use clippy_utils::source::{first_line_of_span, indent_of, reindent_multiline, snippet, IntoSpan, SpanRangeExt};
-use clippy_utils::ty::{needs_ordered_drop, InteriorMut};
+use clippy_utils::source::{IntoSpan, SpanRangeExt, first_line_of_span, indent_of, reindent_multiline, snippet};
+use clippy_utils::ty::{InteriorMut, needs_ordered_drop};
 use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{
-    capture_local_usage, eq_expr_value, find_binding_init, get_enclosing_block, hash_expr, hash_stmt, if_sequence,
-    is_else_clause, is_lint_allowed, path_to_local, search_same, ContainsName, HirEqInterExpr, SpanlessEq,
+    ContainsName, HirEqInterExpr, SpanlessEq, capture_local_usage, eq_expr_value, find_binding_init,
+    get_enclosing_block, hash_expr, hash_stmt, if_sequence, is_else_clause, is_lint_allowed, path_to_local,
+    search_same,
 };
 use core::iter;
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
-use rustc_hir::{intravisit, BinOpKind, Block, Expr, ExprKind, HirId, HirIdSet, Stmt, StmtKind};
+use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, HirIdSet, Stmt, StmtKind, intravisit};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::impl_lint_pass;
diff --git a/clippy_lints/src/crate_in_macro_def.rs b/clippy_lints/src/crate_in_macro_def.rs
index 678bdbc0ffb8a..c8f814137289c 100644
--- a/clippy_lints/src/crate_in_macro_def.rs
+++ b/clippy_lints/src/crate_in_macro_def.rs
@@ -5,8 +5,8 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_span::symbol::sym;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs
index 93c8fff05e9ed..a96c86f076574 100644
--- a/clippy_lints/src/dbg_macro.rs
+++ b/clippy_lints/src/dbg_macro.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_in_test;
-use clippy_utils::macros::{macro_backtrace, MacroCall};
+use clippy_utils::macros::{MacroCall, macro_backtrace};
 use clippy_utils::source::snippet_with_applicability;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
@@ -9,7 +9,7 @@ use rustc_hir::{Expr, ExprKind, Node};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span, SyntaxContext};
+use rustc_span::{Span, SyntaxContext, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/default.rs b/clippy_lints/src/default.rs
index 0b7279f2b360d..dc10b64698b4f 100644
--- a/clippy_lints/src/default.rs
+++ b/clippy_lints/src/default.rs
@@ -11,7 +11,7 @@ use rustc_middle::ty;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_session::impl_lint_pass;
 use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs
index 137781754966a..33a97222b8f8f 100644
--- a/clippy_lints/src/default_constructed_unit_structs.rs
+++ b/clippy_lints/src/default_constructed_unit_structs.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_ty_alias;
-use hir::def::Res;
 use hir::ExprKind;
+use hir::def::Res;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/clippy_lints/src/default_instead_of_iter_empty.rs b/clippy_lints/src/default_instead_of_iter_empty.rs
index ac49e6f1a482a..056e39c02af90 100644
--- a/clippy_lints/src/default_instead_of_iter_empty.rs
+++ b/clippy_lints/src/default_instead_of_iter_empty.rs
@@ -2,10 +2,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::{last_path_segment, std_or_core};
 use rustc_errors::Applicability;
-use rustc_hir::{def, Expr, ExprKind, GenericArg, QPath, TyKind};
+use rustc_hir::{Expr, ExprKind, GenericArg, QPath, TyKind, def};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, SyntaxContext};
+use rustc_span::{SyntaxContext, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/default_numeric_fallback.rs b/clippy_lints/src/default_numeric_fallback.rs
index 05c3cd3c81407..a065dc2cf7e52 100644
--- a/clippy_lints/src/default_numeric_fallback.rs
+++ b/clippy_lints/src/default_numeric_fallback.rs
@@ -3,7 +3,7 @@ use clippy_utils::numeric_literal;
 use clippy_utils::source::snippet_opt;
 use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, walk_stmt, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr, walk_stmt};
 use rustc_hir::{Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs
index 0e55d3db469ae..f34f5e056064d 100644
--- a/clippy_lints/src/dereference.rs
+++ b/clippy_lints/src/dereference.rs
@@ -3,14 +3,14 @@ use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
 use clippy_utils::sugg::has_enclosing_paren;
 use clippy_utils::ty::{implements_trait, is_manually_drop};
 use clippy_utils::{
-    expr_use_ctxt, get_parent_expr, is_block_like, is_lint_allowed, path_to_local, peel_middle_ty_refs, DefinedTy,
-    ExprUseNode,
+    DefinedTy, ExprUseNode, expr_use_ctxt, get_parent_expr, is_block_like, is_lint_allowed, path_to_local,
+    peel_middle_ty_refs,
 };
 use core::mem;
 use rustc_ast::util::parser::{PREC_PREFIX, PREC_UNAMBIGUOUS};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_ty, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_ty};
 use rustc_hir::{
     self as hir, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, Pat,
     PatKind, Path, QPath, TyKind, UnOp,
@@ -290,13 +290,10 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                             && let Some(ty) = use_node.defined_ty(cx)
                             && TyCoercionStability::for_defined_ty(cx, ty, use_node.is_return()).is_deref_stable()
                         {
-                            self.state = Some((
-                                State::ExplicitDeref { mutability: None },
-                                StateData {
-                                    first_expr: expr,
-                                    adjusted_ty,
-                                },
-                            ));
+                            self.state = Some((State::ExplicitDeref { mutability: None }, StateData {
+                                first_expr: expr,
+                                adjusted_ty,
+                            }));
                         }
                     },
                     RefOp::Method { mutbl, is_ufcs }
@@ -458,13 +455,10 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                             && next_adjust.map_or(true, |a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_)))
                             && iter.all(|a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_)))
                         {
-                            self.state = Some((
-                                State::Borrow { mutability },
-                                StateData {
-                                    first_expr: expr,
-                                    adjusted_ty,
-                                },
-                            ));
+                            self.state = Some((State::Borrow { mutability }, StateData {
+                                first_expr: expr,
+                                adjusted_ty,
+                            }));
                         }
                     },
                     _ => {},
@@ -508,13 +502,10 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                 let stability = state.stability;
                 report(cx, expr, State::DerefedBorrow(state), data, typeck);
                 if stability.is_deref_stable() {
-                    self.state = Some((
-                        State::Borrow { mutability },
-                        StateData {
-                            first_expr: expr,
-                            adjusted_ty,
-                        },
-                    ));
+                    self.state = Some((State::Borrow { mutability }, StateData {
+                        first_expr: expr,
+                        adjusted_ty,
+                    }));
                 }
             },
             (Some((State::DerefedBorrow(state), data)), RefOp::Deref) => {
@@ -539,13 +530,10 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                 } else if stability.is_deref_stable()
                     && let Some(parent) = get_parent_expr(cx, expr)
                 {
-                    self.state = Some((
-                        State::ExplicitDeref { mutability: None },
-                        StateData {
-                            first_expr: parent,
-                            adjusted_ty,
-                        },
-                    ));
+                    self.state = Some((State::ExplicitDeref { mutability: None }, StateData {
+                        first_expr: parent,
+                        adjusted_ty,
+                    }));
                 }
             },
 
@@ -1138,20 +1126,17 @@ impl<'tcx> Dereferencing<'tcx> {
         if let Some(outer_pat) = self.ref_locals.get_mut(&local) {
             if let Some(pat) = outer_pat {
                 // Check for auto-deref
-                if !matches!(
-                    cx.typeck_results().expr_adjustments(e),
-                    [
-                        Adjustment {
-                            kind: Adjust::Deref(_),
-                            ..
-                        },
-                        Adjustment {
-                            kind: Adjust::Deref(_),
-                            ..
-                        },
+                if !matches!(cx.typeck_results().expr_adjustments(e), [
+                    Adjustment {
+                        kind: Adjust::Deref(_),
+                        ..
+                    },
+                    Adjustment {
+                        kind: Adjust::Deref(_),
                         ..
-                    ]
-                ) {
+                    },
+                    ..
+                ]) {
                     match get_parent_expr(cx, e) {
                         // Field accesses are the same no matter the number of references.
                         Some(Expr {
diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs
index f27f68e2cbc5f..2920bbb4c81e8 100644
--- a/clippy_lints/src/derivable_impls.rs
+++ b/clippy_lints/src/derivable_impls.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::indent_of;
 use clippy_utils::{is_default_equivalent, peel_blocks};
diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs
index 636698e96f6d1..61c151d4f9d68 100644
--- a/clippy_lints/src/derive.rs
+++ b/clippy_lints/src/derive.rs
@@ -3,7 +3,7 @@ use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy};
 use clippy_utils::{has_non_exhaustive_attr, is_lint_allowed, match_def_path, paths};
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
-use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor};
+use rustc_hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn, walk_item};
 use rustc_hir::{
     self as hir, BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, Impl, Item, ItemKind, Safety, UnsafeSource,
 };
@@ -15,7 +15,7 @@ use rustc_middle::ty::{
 };
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/doc/empty_line_after.rs b/clippy_lints/src/doc/empty_line_after.rs
index 289debe0a6a94..125b907706146 100644
--- a/clippy_lints/src/doc/empty_line_after.rs
+++ b/clippy_lints/src/doc/empty_line_after.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::{snippet_indent, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet_indent};
 use clippy_utils::tokenize_with_text;
 use itertools::Itertools;
 use rustc_ast::token::CommentKind;
@@ -219,13 +219,10 @@ fn check_gaps(cx: &LateContext<'_>, gaps: &[Gap<'_>]) -> bool {
             if let Some(owner) = cx.last_node_with_lint_attrs.as_owner() {
                 let def_id = owner.to_def_id();
                 let def_descr = cx.tcx.def_descr(def_id);
-                diag.span_label(
-                    cx.tcx.def_span(def_id),
-                    match kind {
-                        StopKind::Attr => format!("the attribute applies to this {def_descr}"),
-                        StopKind::Doc(_) => format!("the comment documents this {def_descr}"),
-                    },
-                );
+                diag.span_label(cx.tcx.def_span(def_id), match kind {
+                    StopKind::Attr => format!("the attribute applies to this {def_descr}"),
+                    StopKind::Doc(_) => format!("the comment documents this {def_descr}"),
+                });
             }
 
             diag.multipart_suggestion_with_style(
diff --git a/clippy_lints/src/doc/link_with_quotes.rs b/clippy_lints/src/doc/link_with_quotes.rs
index 01191e811b003..1d4345e4541d7 100644
--- a/clippy_lints/src/doc/link_with_quotes.rs
+++ b/clippy_lints/src/doc/link_with_quotes.rs
@@ -3,7 +3,7 @@ use std::ops::Range;
 use clippy_utils::diagnostics::span_lint;
 use rustc_lint::LateContext;
 
-use super::{Fragments, DOC_LINK_WITH_QUOTES};
+use super::{DOC_LINK_WITH_QUOTES, Fragments};
 
 pub fn check(cx: &LateContext<'_>, trimmed_text: &str, range: Range<usize>, fragments: Fragments<'_>) {
     if ((trimmed_text.starts_with('\'') && trimmed_text.ends_with('\''))
diff --git a/clippy_lints/src/doc/missing_headers.rs b/clippy_lints/src/doc/missing_headers.rs
index e3d7484072612..c9173030a55e1 100644
--- a/clippy_lints/src/doc/missing_headers.rs
+++ b/clippy_lints/src/doc/missing_headers.rs
@@ -5,7 +5,7 @@ use clippy_utils::{is_doc_hidden, return_ty};
 use rustc_hir::{BodyId, FnSig, OwnerId, Safety};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 pub fn check(
     cx: &LateContext<'_>,
diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs
index f2c87f0fd70b3..0ae1fad569213 100644
--- a/clippy_lints/src/doc/mod.rs
+++ b/clippy_lints/src/doc/mod.rs
@@ -23,12 +23,12 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
 use rustc_resolve::rustdoc::{
-    add_doc_fragment, attrs_to_doc_fragments, main_body_opts, source_span_for_markdown_range, span_of_fragments,
-    DocFragment,
+    DocFragment, add_doc_fragment, attrs_to_doc_fragments, main_body_opts, source_span_for_markdown_range,
+    span_of_fragments,
 };
 use rustc_session::impl_lint_pass;
 use rustc_span::edition::Edition;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 use std::ops::Range;
 use url::Url;
 
diff --git a/clippy_lints/src/doc/needless_doctest_main.rs b/clippy_lints/src/doc/needless_doctest_main.rs
index c3e3c0431e6b7..9ba2723157ad9 100644
--- a/clippy_lints/src/doc/needless_doctest_main.rs
+++ b/clippy_lints/src/doc/needless_doctest_main.rs
@@ -13,7 +13,7 @@ use rustc_parse::parser::ForceCollect;
 use rustc_session::parse::ParseSess;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::{FilePathMapping, SourceMap};
-use rustc_span::{sym, FileName, Pos};
+use rustc_span::{FileName, Pos, sym};
 
 use super::Fragments;
 
diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs
index 9c5100a8c1af8..70524e458c78b 100644
--- a/clippy_lints/src/entry.rs
+++ b/clippy_lints/src/entry.rs
@@ -1,17 +1,17 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{reindent_multiline, snippet_indent, snippet_with_applicability, snippet_with_context};
 use clippy_utils::{
-    can_move_expr_to_closure_no_visit, higher, is_expr_final_block_expr, is_expr_used_or_unified,
-    peel_hir_expr_while, SpanlessEq,
+    SpanlessEq, can_move_expr_to_closure_no_visit, higher, is_expr_final_block_expr, is_expr_used_or_unified,
+    peel_hir_expr_while,
 };
 use core::fmt::{self, Write};
 use rustc_errors::Applicability;
 use rustc_hir::hir_id::HirIdSet;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 use rustc_hir::{Block, Expr, ExprKind, HirId, Pat, Stmt, StmtKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span, SyntaxContext, DUMMY_SP};
+use rustc_span::{DUMMY_SP, Span, SyntaxContext, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs
index 4755cefe784c5..e9e9d00907ea0 100644
--- a/clippy_lints/src/enum_clike.rs
+++ b/clippy_lints/src/enum_clike.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{mir_to_const, Constant};
+use clippy_utils::consts::{Constant, mir_to_const};
 use clippy_utils::diagnostics::span_lint;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs
index 803606979410b..5588124e791ea 100644
--- a/clippy_lints/src/escape.rs
+++ b/clippy_lints/src/escape.rs
@@ -1,15 +1,15 @@
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_hir;
-use rustc_hir::{intravisit, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind};
+use rustc_hir::{AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind, intravisit};
 use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt};
 use rustc_session::impl_lint_pass;
+use rustc_span::Span;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::kw;
-use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
 pub struct BoxedLocal {
diff --git a/clippy_lints/src/excessive_bools.rs b/clippy_lints/src/excessive_bools.rs
index 8f469efb1b502..c88fb50b5afc8 100644
--- a/clippy_lints/src/excessive_bools.rs
+++ b/clippy_lints/src/excessive_bools.rs
@@ -5,8 +5,8 @@ use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, FnDecl, Item, ItemKind, TraitFn, TraitItem, TraitItemKind, Ty};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
-use rustc_span::def_id::LocalDefId;
 use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
 use rustc_target::spec::abi::Abi;
 
 declare_clippy_lint! {
diff --git a/clippy_lints/src/excessive_nesting.rs b/clippy_lints/src/excessive_nesting.rs
index 5154edd4399b2..ce0e0faa01489 100644
--- a/clippy_lints/src/excessive_nesting.rs
+++ b/clippy_lints/src/excessive_nesting.rs
@@ -2,7 +2,7 @@ use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::source::snippet;
 use rustc_ast::node_id::NodeSet;
-use rustc_ast::visit::{walk_block, walk_item, Visitor};
+use rustc_ast::visit::{Visitor, walk_block, walk_item};
 use rustc_ast::{Block, Crate, Inline, Item, ItemKind, ModKind, NodeId};
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs
index 3c4a043a732b7..5b423a96918f6 100644
--- a/clippy_lints/src/explicit_write.rs
+++ b/clippy_lints/src/explicit_write.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::{format_args_inputs_span, FormatArgsStorage};
+use clippy_utils::macros::{FormatArgsStorage, format_args_inputs_span};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{is_expn_of, path_def_id};
 use rustc_errors::Applicability;
@@ -7,7 +7,7 @@ use rustc_hir::def::Res;
 use rustc_hir::{BindingMode, Block, BlockCheckMode, Expr, ExprKind, Node, PatKind, QPath, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, ExpnId};
+use rustc_span::{ExpnId, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/extra_unused_type_parameters.rs b/clippy_lints/src/extra_unused_type_parameters.rs
index bfe4e253ae47f..bf9388b4a70fd 100644
--- a/clippy_lints/src/extra_unused_type_parameters.rs
+++ b/clippy_lints/src/extra_unused_type_parameters.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
 use clippy_utils::{is_from_proc_macro, trait_ref_of_method};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_impl_item, walk_item, walk_param_bound, walk_ty, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_impl_item, walk_item, walk_param_bound, walk_ty};
 use rustc_hir::{
     BodyId, ExprKind, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind,
     PredicateOrigin, Ty, TyKind, WherePredicate,
@@ -12,8 +12,8 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::lint::in_external_macro;
 use rustc_session::impl_lint_pass;
-use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::Span;
+use rustc_span::def_id::{DefId, LocalDefId};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs
index 0446943321aa9..747ea9a434464 100644
--- a/clippy_lints/src/fallible_impl_from.rs
+++ b/clippy_lints/src/fallible_impl_from.rs
@@ -6,7 +6,7 @@ use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs
index bf4bcabfe8911..8da6623f34de9 100644
--- a/clippy_lints/src/floating_point_arithmetic.rs
+++ b/clippy_lints/src/floating_point_arithmetic.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::Constant::{Int, F32, F64};
+use clippy_utils::consts::Constant::{F32, F64, Int};
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::{
diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs
index 4dedff69b9abd..5e3f6b6a13707 100644
--- a/clippy_lints/src/format.rs
+++ b/clippy_lints/src/format.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::{find_format_arg_expr, root_macro_call_first_node, FormatArgsStorage};
-use clippy_utils::source::{snippet_with_context, SpanRangeExt};
+use clippy_utils::macros::{FormatArgsStorage, find_format_arg_expr, root_macro_call_first_node};
+use clippy_utils::source::{SpanRangeExt, snippet_with_context};
 use clippy_utils::sugg::Sugg;
 use rustc_ast::{FormatArgsPiece, FormatOptions, FormatTrait};
 use rustc_errors::Applicability;
@@ -8,7 +8,7 @@ use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs
index 020c0c5440d93..83ab9f6557bdd 100644
--- a/clippy_lints/src/format_args.rs
+++ b/clippy_lints/src/format_args.rs
@@ -1,11 +1,12 @@
 use arrayvec::ArrayVec;
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::is_diag_trait_item;
 use clippy_utils::macros::{
-    find_format_arg_expr, format_arg_removal_span, format_placeholder_format_span, is_assert_macro, is_format_macro,
-    is_panic, matching_root_macro_call, root_macro_call_first_node, FormatArgsStorage, FormatParamUsage, MacroCall,
+    FormatArgsStorage, FormatParamUsage, MacroCall, find_format_arg_expr, format_arg_removal_span,
+    format_placeholder_format_span, is_assert_macro, is_format_macro, is_panic, matching_root_macro_call,
+    root_macro_call_first_node,
 };
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::{implements_trait, is_type_lang_item};
@@ -18,11 +19,11 @@ use rustc_errors::Applicability;
 use rustc_errors::SuggestionStyle::{CompletelyHidden, ShowCode};
 use rustc_hir::{Expr, ExprKind, LangItem};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::ty::adjustment::{Adjust, Adjustment};
 use rustc_middle::ty::Ty;
+use rustc_middle::ty::adjustment::{Adjust, Adjustment};
 use rustc_session::impl_lint_pass;
 use rustc_span::edition::Edition::Edition2021;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{Span, Symbol, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/format_impl.rs b/clippy_lints/src/format_impl.rs
index 7cd12ac7db852..c196f404ce677 100644
--- a/clippy_lints/src/format_impl.rs
+++ b/clippy_lints/src/format_impl.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
-use clippy_utils::macros::{find_format_arg_expr, is_format_macro, root_macro_call_first_node, FormatArgsStorage};
+use clippy_utils::macros::{FormatArgsStorage, find_format_arg_expr, is_format_macro, root_macro_call_first_node};
 use clippy_utils::{get_parent_as_impl, is_diag_trait_item, path_to_local, peel_ref_operators};
 use rustc_ast::{FormatArgsPiece, FormatTrait};
 use rustc_errors::Applicability;
@@ -7,7 +7,7 @@ use rustc_hir::{Expr, ExprKind, Impl, ImplItem, ImplItemKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
 use rustc_span::symbol::kw;
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/format_push_string.rs b/clippy_lints/src/format_push_string.rs
index c6f03c3a7cf9a..8b1f86cbb9139 100644
--- a/clippy_lints/src/format_push_string.rs
+++ b/clippy_lints/src/format_push_string.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::ty::is_type_lang_item;
 use clippy_utils::higher;
+use clippy_utils::ty::is_type_lang_item;
 use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem, MatchSource};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs
index 5e9098474dc02..d716a624cc672 100644
--- a/clippy_lints/src/from_over_into.rs
+++ b/clippy_lints/src/from_over_into.rs
@@ -1,11 +1,11 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::span_is_local;
 use clippy_utils::path_def_id;
 use clippy_utils::source::SpanRangeExt;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_path, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_path};
 use rustc_hir::{
     FnRetTy, GenericArg, GenericArgs, HirId, Impl, ImplItemKind, ImplItemRef, Item, ItemKind, PatKind, Path,
     PathSegment, Ty, TyKind,
diff --git a/clippy_lints/src/from_str_radix_10.rs b/clippy_lints/src/from_str_radix_10.rs
index e5fa67d696427..7361546153c27 100644
--- a/clippy_lints/src/from_str_radix_10.rs
+++ b/clippy_lints/src/from_str_radix_10.rs
@@ -3,7 +3,7 @@ use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
 use clippy_utils::{is_in_const_context, is_integer_literal};
 use rustc_errors::Applicability;
-use rustc_hir::{def, Expr, ExprKind, LangItem, PrimTy, QPath, TyKind};
+use rustc_hir::{Expr, ExprKind, LangItem, PrimTy, QPath, TyKind, def};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::Ty;
 use rustc_session::declare_lint_pass;
diff --git a/clippy_lints/src/functions/mod.rs b/clippy_lints/src/functions/mod.rs
index 0f48941783b26..ba8a459c917e6 100644
--- a/clippy_lints/src/functions/mod.rs
+++ b/clippy_lints/src/functions/mod.rs
@@ -14,8 +14,8 @@ use rustc_hir::intravisit;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::impl_lint_pass;
-use rustc_span::def_id::{DefIdSet, LocalDefId};
 use rustc_span::Span;
+use rustc_span::def_id::{DefIdSet, LocalDefId};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs
index 9382812104706..cfd11e9339fb7 100644
--- a/clippy_lints/src/functions/must_use.rs
+++ b/clippy_lints/src/functions/must_use.rs
@@ -8,7 +8,7 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, Ty};
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use clippy_utils::attrs::is_proc_macro;
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
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 1aeefe73cf68f..c2b40ae01d4cc 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, HirId, HirIdSet};
+use rustc_hir::{self as hir, HirId, HirIdSet, intravisit};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_span::def_id::LocalDefId;
diff --git a/clippy_lints/src/functions/renamed_function_params.rs b/clippy_lints/src/functions/renamed_function_params.rs
index c7de0385c021b..ac2e866e4ff7e 100644
--- a/clippy_lints/src/functions/renamed_function_params.rs
+++ b/clippy_lints/src/functions/renamed_function_params.rs
@@ -4,8 +4,8 @@ use rustc_hir::def_id::{DefId, DefIdSet};
 use rustc_hir::hir_id::OwnerId;
 use rustc_hir::{Impl, ImplItem, ImplItemKind, ImplItemRef, ItemKind, Node, TraitRef};
 use rustc_lint::LateContext;
-use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::Span;
+use rustc_span::symbol::{Ident, Symbol, kw};
 
 use super::RENAMED_FUNCTION_PARAMS;
 
diff --git a/clippy_lints/src/functions/result.rs b/clippy_lints/src/functions/result.rs
index c3a0b40a677aa..d4eaa1663208c 100644
--- a/clippy_lints/src/functions/result.rs
+++ b/clippy_lints/src/functions/result.rs
@@ -3,11 +3,11 @@ use rustc_hir as hir;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, Ty};
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
 use clippy_utils::trait_ref_of_method;
-use clippy_utils::ty::{approx_ty_size, is_type_diagnostic_item, AdtVariantInfo};
+use clippy_utils::ty::{AdtVariantInfo, approx_ty_size, is_type_diagnostic_item};
 
 use super::{RESULT_LARGE_ERR, RESULT_UNIT_ERR};
 
diff --git a/clippy_lints/src/future_not_send.rs b/clippy_lints/src/future_not_send.rs
index 9488ba7568656..a4dbe134f3650 100644
--- a/clippy_lints/src/future_not_send.rs
+++ b/clippy_lints/src/future_not_send.rs
@@ -8,7 +8,7 @@ use rustc_middle::ty::print::PrintTraitRefExt;
 use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind};
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt};
 
diff --git a/clippy_lints/src/if_then_some_else_none.rs b/clippy_lints/src/if_then_some_else_none.rs
index 55f9625709b3c..d63c18c0edaab 100644
--- a/clippy_lints/src/if_then_some_else_none.rs
+++ b/clippy_lints/src/if_then_some_else_none.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::eager_or_lazy::switch_to_eager_eval;
 use clippy_utils::source::snippet_with_context;
diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs
index e56f33f8dcfe2..f683925145a28 100644
--- a/clippy_lints/src/implicit_hasher.rs
+++ b/clippy_lints/src/implicit_hasher.rs
@@ -3,18 +3,18 @@ use std::collections::BTreeMap;
 
 use rustc_errors::{Applicability, Diag};
 use rustc_hir as hir;
-use rustc_hir::intravisit::{walk_body, walk_expr, walk_inf, walk_ty, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_body, walk_expr, walk_inf, walk_ty};
 use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind};
 use rustc_hir_analysis::lower_ty;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{Ty, TypeckResults};
 use rustc_session::declare_lint_pass;
-use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_span::symbol::sym;
 
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::{snippet, IntoSpan, SpanRangeExt};
+use clippy_utils::source::{IntoSpan, SpanRangeExt, snippet};
 use clippy_utils::ty::is_type_diagnostic_item;
 
 declare_clippy_lint! {
diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs
index 3536309d83ca0..f4a64f5c20b44 100644
--- a/clippy_lints/src/implicit_saturating_sub.rs
+++ b/clippy_lints/src/implicit_saturating_sub.rs
@@ -1,9 +1,9 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet_opt;
 use clippy_utils::{
-    higher, is_in_const_context, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt, SpanlessEq,
+    SpanlessEq, higher, is_in_const_context, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt,
 };
 use rustc_ast::ast::LitKind;
 use rustc_data_structures::packed::Pu128;
diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs
index 2ad045e12686c..0b3a6ee1beaeb 100644
--- a/clippy_lints/src/incompatible_msrv.rs
+++ b/clippy_lints/src/incompatible_msrv.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::Msrv;
 use clippy_config::Conf;
+use clippy_config::msrvs::Msrv;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_in_test;
 use rustc_attr::{StabilityLevel, StableSince};
@@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::{Expr, ExprKind, HirId};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::TyCtxt;
-use rustc_session::{impl_lint_pass, RustcVersion};
+use rustc_session::{RustcVersion, impl_lint_pass};
 use rustc_span::def_id::DefId;
 use rustc_span::{ExpnKind, Span};
 
diff --git a/clippy_lints/src/index_refutable_slice.rs b/clippy_lints/src/index_refutable_slice.rs
index 2f9661c9ea385..39afb6810b8e2 100644
--- a/clippy_lints/src/index_refutable_slice.rs
+++ b/clippy_lints/src/index_refutable_slice.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::IfLet;
@@ -8,14 +8,14 @@ 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::intravisit::{self, Visitor};
 use rustc_hir::HirId;
+use rustc_hir::intravisit::{self, Visitor};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
-use rustc_span::symbol::Ident;
 use rustc_span::Span;
+use rustc_span::symbol::Ident;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/ineffective_open_options.rs b/clippy_lints/src/ineffective_open_options.rs
index af5b1f9573991..3a28553b55e25 100644
--- a/clippy_lints/src/ineffective_open_options.rs
+++ b/clippy_lints/src/ineffective_open_options.rs
@@ -7,7 +7,7 @@ use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, BytePos, Span};
+use rustc_span::{BytePos, Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/instant_subtraction.rs b/clippy_lints/src/instant_subtraction.rs
index 6d6820311b679..66931a7f98c36 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_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::sugg::Sugg;
diff --git a/clippy_lints/src/item_name_repetitions.rs b/clippy_lints/src/item_name_repetitions.rs
index 74bf82f58bdcf..66a8a3167a4f2 100644
--- a/clippy_lints/src/item_name_repetitions.rs
+++ b/clippy_lints/src/item_name_repetitions.rs
@@ -8,8 +8,8 @@ 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;
-use rustc_span::symbol::Symbol;
 use rustc_span::Span;
+use rustc_span::symbol::Symbol;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/items_after_test_module.rs b/clippy_lints/src/items_after_test_module.rs
index 8caa484bb9934..1ac549b74ac66 100644
--- a/clippy_lints/src/items_after_test_module.rs
+++ b/clippy_lints/src/items_after_test_module.rs
@@ -6,7 +6,7 @@ use rustc_hir::{HirId, Item, ItemKind, Mod};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 use rustc_span::hygiene::AstPass;
-use rustc_span::{sym, ExpnKind};
+use rustc_span::{ExpnKind, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/iter_not_returning_iterator.rs b/clippy_lints/src/iter_not_returning_iterator.rs
index ba0cd5d6eb359..b19b348c7430d 100644
--- a/clippy_lints/src/iter_not_returning_iterator.rs
+++ b/clippy_lints/src/iter_not_returning_iterator.rs
@@ -4,7 +4,7 @@ use rustc_hir::def_id::LocalDefId;
 use rustc_hir::{FnSig, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/iter_over_hash_type.rs b/clippy_lints/src/iter_over_hash_type.rs
index f162948bb4457..5131f5b7269b6 100644
--- a/clippy_lints/src/iter_over_hash_type.rs
+++ b/clippy_lints/src/iter_over_hash_type.rs
@@ -55,7 +55,9 @@ impl LateLintPass<'_> for IterOverHashType {
         if let Some(for_loop) = ForLoop::hir(expr)
             && !for_loop.body.span.from_expansion()
             && let ty = cx.typeck_results().expr_ty(for_loop.arg).peel_refs()
-            && hash_iter_tys.into_iter().any(|sym| is_type_diagnostic_item(cx, ty, sym))
+            && hash_iter_tys
+                .into_iter()
+                .any(|sym| is_type_diagnostic_item(cx, ty, sym))
         {
             span_lint(
                 cx,
diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs
index 2f027c1170728..923089c722322 100644
--- a/clippy_lints/src/large_enum_variant.rs
+++ b/clippy_lints/src/large_enum_variant.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::ty::{approx_ty_size, is_copy, AdtVariantInfo};
+use clippy_utils::ty::{AdtVariantInfo, approx_ty_size, is_copy};
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/clippy_lints/src/large_stack_arrays.rs b/clippy_lints/src/large_stack_arrays.rs
index 15a75b0608965..0f061d6de504f 100644
--- a/clippy_lints/src/large_stack_arrays.rs
+++ b/clippy_lints/src/large_stack_arrays.rs
@@ -8,7 +8,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, ConstKind};
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/legacy_numeric_constants.rs b/clippy_lints/src/legacy_numeric_constants.rs
index ccab1e27d3b0c..e17d6213679a6 100644
--- a/clippy_lints/src/legacy_numeric_constants.rs
+++ b/clippy_lints/src/legacy_numeric_constants.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{Msrv, NUMERIC_ASSOCIATED_CONSTANTS};
 use clippy_config::Conf;
+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;
@@ -10,7 +10,7 @@ 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};
+use rustc_span::{Symbol, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs
index 0bc7fc2dd9d1e..c1ba66de57e5a 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, SpanRangeExt};
-use clippy_utils::sugg::{has_enclosing_paren, Sugg};
+use clippy_utils::source::{SpanRangeExt, snippet_with_context};
+use clippy_utils::sugg::{Sugg, has_enclosing_paren};
 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;
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index b21d3f8d09eca..1d41f568f3785 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -394,7 +394,7 @@ mod zero_sized_map_values;
 mod zombie_processes;
 // end lints modules, do not remove this comment, it’s used in `update_lints`
 
-use clippy_config::{get_configuration_metadata, Conf};
+use clippy_config::{Conf, get_configuration_metadata};
 use clippy_utils::macros::FormatArgsStorage;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_lint::{Lint, LintId};
diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs
index ba34af9c100ea..755afe959b37a 100644
--- a/clippy_lints/src/lifetimes.rs
+++ b/clippy_lints/src/lifetimes.rs
@@ -3,25 +3,25 @@ use clippy_utils::trait_ref_of_method;
 use itertools::Itertools;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
+use rustc_hir::FnRetTy::Return;
 use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter};
 use rustc_hir::intravisit::{
-    walk_fn_decl, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
-    walk_poly_trait_ref, walk_trait_ref, walk_ty, Visitor,
+    Visitor, walk_fn_decl, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
+    walk_poly_trait_ref, walk_trait_ref, walk_ty,
 };
-use rustc_hir::FnRetTy::Return;
 use rustc_hir::{
-    lang_items, BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics,
-    Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
-    PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
+    BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl,
+    ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
+    PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate, lang_items,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter as middle_nested_filter;
 use rustc_middle::lint::in_external_macro;
 use rustc_session::declare_lint_pass;
-use rustc_span::def_id::LocalDefId;
-use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
+use rustc_span::symbol::{Ident, Symbol, kw};
 use std::ops::ControlFlow;
 
 declare_clippy_lint! {
diff --git a/clippy_lints/src/loops/explicit_counter_loop.rs b/clippy_lints/src/loops/explicit_counter_loop.rs
index 73a23615c2dc7..9aa4d2f0adc2c 100644
--- a/clippy_lints/src/loops/explicit_counter_loop.rs
+++ b/clippy_lints/src/loops/explicit_counter_loop.rs
@@ -1,4 +1,4 @@
-use super::{make_iterator_snippet, IncrementVisitor, InitializeVisitor, EXPLICIT_COUNTER_LOOP};
+use super::{EXPLICIT_COUNTER_LOOP, IncrementVisitor, InitializeVisitor, make_iterator_snippet};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{get_enclosing_block, is_integer_const};
diff --git a/clippy_lints/src/loops/infinite_loop.rs b/clippy_lints/src/loops/infinite_loop.rs
index 5b5bb88c17908..858e3be5093ef 100644
--- a/clippy_lints/src/loops/infinite_loop.rs
+++ b/clippy_lints/src/loops/infinite_loop.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::{fn_def_id, is_from_proc_macro, is_lint_allowed};
-use hir::intravisit::{walk_expr, Visitor};
+use hir::intravisit::{Visitor, walk_expr};
 use hir::{Expr, ExprKind, FnRetTy, FnSig, Node};
 use rustc_ast::Label;
 use rustc_errors::Applicability;
diff --git a/clippy_lints/src/loops/manual_find.rs b/clippy_lints/src/loops/manual_find.rs
index b27528c11d488..bfe2e68b5d1fa 100644
--- a/clippy_lints/src/loops/manual_find.rs
+++ b/clippy_lints/src/loops/manual_find.rs
@@ -1,5 +1,5 @@
-use super::utils::make_iterator_snippet;
 use super::MANUAL_FIND;
+use super::utils::make_iterator_snippet;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::implements_trait;
diff --git a/clippy_lints/src/loops/manual_flatten.rs b/clippy_lints/src/loops/manual_flatten.rs
index dbc094a6d73fc..366c310592f57 100644
--- a/clippy_lints/src/loops/manual_flatten.rs
+++ b/clippy_lints/src/loops/manual_flatten.rs
@@ -1,5 +1,5 @@
-use super::utils::make_iterator_snippet;
 use super::MANUAL_FLATTEN;
+use super::utils::make_iterator_snippet;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::visitors::is_local_used;
 use clippy_utils::{higher, path_to_local_id, peel_blocks_with_stmt};
diff --git a/clippy_lints/src/loops/manual_while_let_some.rs b/clippy_lints/src/loops/manual_while_let_some.rs
index 55d1b9ee67671..7476a87267f3b 100644
--- a/clippy_lints/src/loops/manual_while_let_some.rs
+++ b/clippy_lints/src/loops/manual_while_let_some.rs
@@ -1,10 +1,10 @@
+use clippy_utils::SpanlessEq;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
-use clippy_utils::SpanlessEq;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Pat, Stmt, StmtKind, UnOp};
 use rustc_lint::LateContext;
-use rustc_span::{sym, Symbol, Span};
+use rustc_span::{Span, Symbol, sym};
 use std::borrow::Cow;
 
 use super::MANUAL_WHILE_LET_SOME;
diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs
index 5155fd76b253e..17215621d2aa1 100644
--- a/clippy_lints/src/loops/mod.rs
+++ b/clippy_lints/src/loops/mod.rs
@@ -22,15 +22,15 @@ mod while_immutable_condition;
 mod while_let_loop;
 mod while_let_on_iterator;
 
-use clippy_config::msrvs::Msrv;
 use clippy_config::Conf;
+use clippy_config::msrvs::Msrv;
 use clippy_utils::higher;
 use rustc_ast::Label;
 use rustc_hir::{Expr, ExprKind, LoopSource, Pat};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
 use rustc_span::Span;
-use utils::{make_iterator_snippet, IncrementVisitor, InitializeVisitor};
+use utils::{IncrementVisitor, InitializeVisitor, make_iterator_snippet};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs
index e18e4374667de..20dd5a311dca0 100644
--- a/clippy_lints/src/loops/needless_range_loop.rs
+++ b/clippy_lints/src/loops/needless_range_loop.rs
@@ -3,17 +3,17 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::has_iter_method;
 use clippy_utils::visitors::is_local_used;
-use clippy_utils::{contains_name, higher, is_integer_const, sugg, SpanlessEq};
+use clippy_utils::{SpanlessEq, contains_name, higher, is_integer_const, sugg};
 use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 use rustc_hir::{BinOpKind, BorrowKind, Closure, Expr, ExprKind, HirId, Mutability, Pat, PatKind, QPath};
 use rustc_lint::LateContext;
 use rustc_middle::middle::region;
 use rustc_middle::ty::{self, Ty};
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{Symbol, sym};
 use std::{iter, mem};
 
 /// Checks for looping over a range and then indexing a sequence with it.
diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs
index 313a5bfefbc8d..1c55e3e22e8c1 100644
--- a/clippy_lints/src/loops/never_loop.rs
+++ b/clippy_lints/src/loops/never_loop.rs
@@ -1,5 +1,5 @@
-use super::utils::make_iterator_snippet;
 use super::NEVER_LOOP;
+use super::utils::make_iterator_snippet;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::ForLoop;
 use clippy_utils::macros::root_macro_call_first_node;
@@ -7,7 +7,7 @@ use clippy_utils::source::snippet;
 use rustc_errors::Applicability;
 use rustc_hir::{Block, Destination, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind};
 use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 use std::iter::once;
 
 pub(super) fn check<'tcx>(
diff --git a/clippy_lints/src/loops/same_item_push.rs b/clippy_lints/src/loops/same_item_push.rs
index 9185cf1f8b2ee..5662d3013e15b 100644
--- a/clippy_lints/src/loops/same_item_push.rs
+++ b/clippy_lints/src/loops/same_item_push.rs
@@ -6,11 +6,11 @@ use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 use rustc_hir::{BindingMode, Block, Expr, ExprKind, HirId, Mutability, Node, Pat, PatKind, Stmt, StmtKind};
 use rustc_lint::LateContext;
-use rustc_span::symbol::sym;
 use rustc_span::SyntaxContext;
+use rustc_span::symbol::sym;
 
 /// Detects for loop pushing the same item into a Vec
 pub(super) fn check<'tcx>(
diff --git a/clippy_lints/src/loops/single_element_loop.rs b/clippy_lints/src/loops/single_element_loop.rs
index 2b41911e8ec79..70f76ced09a43 100644
--- a/clippy_lints/src/loops/single_element_loop.rs
+++ b/clippy_lints/src/loops/single_element_loop.rs
@@ -2,10 +2,10 @@ use super::SINGLE_ELEMENT_LOOP;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{indent_of, snippet, snippet_with_applicability};
 use clippy_utils::visitors::contains_break_or_continue;
-use rustc_ast::util::parser::PREC_PREFIX;
 use rustc_ast::Mutability;
+use rustc_ast::util::parser::PREC_PREFIX;
 use rustc_errors::Applicability;
-use rustc_hir::{is_range_literal, BorrowKind, Expr, ExprKind, Pat, PatKind};
+use rustc_hir::{BorrowKind, Expr, ExprKind, Pat, PatKind, is_range_literal};
 use rustc_lint::LateContext;
 use rustc_span::edition::Edition;
 use rustc_span::sym;
diff --git a/clippy_lints/src/loops/utils.rs b/clippy_lints/src/loops/utils.rs
index 7b45cc95431c2..9a89a41d2b395 100644
--- a/clippy_lints/src/loops/utils.rs
+++ b/clippy_lints/src/loops/utils.rs
@@ -2,13 +2,13 @@ use clippy_utils::ty::{has_iter_method, implements_trait};
 use clippy_utils::{get_parent_expr, is_integer_const, path_to_local, path_to_local_id, sugg};
 use rustc_ast::ast::{LitIntType, LitKind};
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, walk_local, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr, walk_local};
 use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, HirIdMap, LetStmt, Mutability, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::source_map::Spanned;
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{Symbol, sym};
 
 #[derive(Debug, PartialEq, Eq)]
 enum IncrementVisitorVarState {
diff --git a/clippy_lints/src/loops/while_immutable_condition.rs b/clippy_lints/src/loops/while_immutable_condition.rs
index cc1bd5929d0fc..eab096e9a227d 100644
--- a/clippy_lints/src/loops/while_immutable_condition.rs
+++ b/clippy_lints/src/loops/while_immutable_condition.rs
@@ -4,7 +4,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::usage::mutated_variables;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefIdMap;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 use rustc_hir::{Expr, ExprKind, HirIdSet, QPath};
 use rustc_lint::LateContext;
 use std::ops::ControlFlow;
diff --git a/clippy_lints/src/loops/while_let_on_iterator.rs b/clippy_lints/src/loops/while_let_on_iterator.rs
index c171fa1c622af..7d9fbaf3ceabf 100644
--- a/clippy_lints/src/loops/while_let_on_iterator.rs
+++ b/clippy_lints/src/loops/while_let_on_iterator.rs
@@ -5,13 +5,13 @@ use clippy_utils::visitors::is_res_used;
 use clippy_utils::{get_enclosing_loop_or_multi_call_closure, higher, is_refutable, is_res_lang_ctor, is_trait_method};
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 use rustc_hir::{Closure, Expr, ExprKind, HirId, LangItem, LetStmt, Mutability, PatKind, UnOp};
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter::OnlyBodies;
 use rustc_middle::ty::adjustment::Adjust;
-use rustc_span::symbol::sym;
 use rustc_span::Symbol;
+use rustc_span::symbol::sym;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
     if let Some(higher::WhileLet { if_then, let_pat, let_expr, label, .. }) = higher::WhileLet::hir(expr)
diff --git a/clippy_lints/src/macro_metavars_in_unsafe.rs b/clippy_lints/src/macro_metavars_in_unsafe.rs
index e215097142be9..ccc554042d685 100644
--- a/clippy_lints/src/macro_metavars_in_unsafe.rs
+++ b/clippy_lints/src/macro_metavars_in_unsafe.rs
@@ -3,13 +3,13 @@ use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::is_lint_allowed;
 use itertools::Itertools;
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_stmt};
 use rustc_hir::{BlockCheckMode, Expr, ExprKind, HirId, Stmt, UnsafeSource};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span, SyntaxContext};
-use std::collections::btree_map::Entry;
+use rustc_span::{Span, SyntaxContext, sym};
 use std::collections::BTreeMap;
+use std::collections::btree_map::Entry;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs
index 067384b09015a..bd6b3f1a47b16 100644
--- a/clippy_lints/src/macro_use.rs
+++ b/clippy_lints/src/macro_use.rs
@@ -8,7 +8,7 @@ use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::impl_lint_pass;
 use rustc_span::edition::Edition;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 use std::collections::BTreeMap;
 
 declare_clippy_lint! {
diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs
index 61723aec59049..fc3bba9e51232 100644
--- a/clippy_lints/src/manual_async_fn.rs
+++ b/clippy_lints/src/manual_async_fn.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::{position_before_rarrow, snippet_block, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, position_before_rarrow, snippet_block};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
@@ -9,7 +9,7 @@ use rustc_hir::{
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/manual_bits.rs b/clippy_lints/src/manual_bits.rs
index 5cbdc7f864a75..c0e87e8a1faed 100644
--- a/clippy_lints/src/manual_bits.rs
+++ b/clippy_lints/src/manual_bits.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::get_parent_expr;
 use clippy_utils::source::snippet_with_context;
diff --git a/clippy_lints/src/manual_clamp.rs b/clippy_lints/src/manual_clamp.rs
index 4123c933660bc..788649fd4f90e 100644
--- a/clippy_lints/src/manual_clamp.rs
+++ b/clippy_lints/src/manual_clamp.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
 use clippy_utils::higher::If;
@@ -7,8 +7,8 @@ use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::visitors::is_const_evaluatable;
 use clippy_utils::{
-    eq_expr_value, is_diag_trait_item, is_in_const_context, is_trait_method, path_res, path_to_local_id, peel_blocks,
-    peel_blocks_with_stmt, MaybePath,
+    MaybePath, eq_expr_value, is_diag_trait_item, is_in_const_context, is_trait_method, path_res, path_to_local_id,
+    peel_blocks, peel_blocks_with_stmt,
 };
 use itertools::Itertools;
 use rustc_errors::{Applicability, Diag};
@@ -17,8 +17,8 @@ use rustc_hir::{Arm, BinOpKind, Block, Expr, ExprKind, HirId, PatKind, PathSegme
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::Ty;
 use rustc_session::impl_lint_pass;
-use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_span::symbol::sym;
 use std::cmp::Ordering;
 use std::ops::Deref;
 
diff --git a/clippy_lints/src/manual_div_ceil.rs b/clippy_lints/src/manual_div_ceil.rs
index 024c2547dc6eb..00e02e2a33652 100644
--- a/clippy_lints/src/manual_div_ceil.rs
+++ b/clippy_lints/src/manual_div_ceil.rs
@@ -1,8 +1,8 @@
 use clippy_config::msrvs::{self, Msrv};
+use clippy_utils::SpanlessEq;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
-use clippy_utils::SpanlessEq;
 use rustc_ast::{BinOpKind, LitKind};
 use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
diff --git a/clippy_lints/src/manual_hash_one.rs b/clippy_lints/src/manual_hash_one.rs
index 11716a539ab5c..c62bd65bea683 100644
--- a/clippy_lints/src/manual_hash_one.rs
+++ b/clippy_lints/src/manual_hash_one.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::visitors::{is_local_used, local_used_once};
diff --git a/clippy_lints/src/manual_is_ascii_check.rs b/clippy_lints/src/manual_is_ascii_check.rs
index 31c37c3bc3b14..24207705743d1 100644
--- a/clippy_lints/src/manual_is_ascii_check.rs
+++ b/clippy_lints/src/manual_is_ascii_check.rs
@@ -1,17 +1,17 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::matching_root_macro_call;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{higher, is_in_const_context, path_to_local, peel_ref_operators};
-use rustc_ast::ast::RangeLimits;
 use rustc_ast::LitKind::{Byte, Char};
+use rustc_ast::ast::RangeLimits;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Node, Param, PatKind, RangeEnd};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/manual_is_power_of_two.rs b/clippy_lints/src/manual_is_power_of_two.rs
index d7879403ebb5a..da2a982ee170a 100644
--- a/clippy_lints/src/manual_is_power_of_two.rs
+++ b/clippy_lints/src/manual_is_power_of_two.rs
@@ -1,6 +1,6 @@
+use clippy_utils::SpanlessEq;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::SpanlessEq;
 use rustc_ast::LitKind;
 use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs
index ebebdf679a863..17185df5d76fa 100644
--- a/clippy_lints/src/manual_let_else.rs
+++ b/clippy_lints/src/manual_let_else.rs
@@ -1,4 +1,4 @@
-use crate::question_mark::{QuestionMark, QUESTION_MARK};
+use crate::question_mark::{QUESTION_MARK, QuestionMark};
 use clippy_config::msrvs;
 use clippy_config::types::MatchLintBehaviour;
 use clippy_utils::diagnostics::span_lint_and_then;
@@ -12,8 +12,8 @@ use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
 
-use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
+use rustc_span::symbol::{Symbol, sym};
 use std::slice;
 
 declare_clippy_lint! {
diff --git a/clippy_lints/src/manual_main_separator_str.rs b/clippy_lints/src/manual_main_separator_str.rs
index 5198d7838a281..85e99a92cf598 100644
--- a/clippy_lints/src/manual_main_separator_str.rs
+++ b/clippy_lints/src/manual_main_separator_str.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::{is_trait_method, peel_hir_expr_refs};
 use rustc_errors::Applicability;
diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs
index 01f1d9c3beba2..25868ccae4003 100644
--- a/clippy_lints/src/manual_non_exhaustive.rs
+++ b/clippy_lints/src/manual_non_exhaustive.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
 use clippy_utils::is_doc_hidden;
 use clippy_utils::source::snippet_indent;
@@ -12,7 +12,7 @@ use rustc_hir::{Expr, ExprKind, Item, ItemKind, QPath, TyKind, VariantData};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/manual_range_patterns.rs b/clippy_lints/src/manual_range_patterns.rs
index 66d2ab6b24a4c..ffa3eacf3544f 100644
--- a/clippy_lints/src/manual_range_patterns.rs
+++ b/clippy_lints/src/manual_range_patterns.rs
@@ -7,7 +7,7 @@ use rustc_hir::{Expr, ExprKind, PatKind, RangeEnd, UnOp};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::declare_lint_pass;
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::{DUMMY_SP, Span};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/manual_rem_euclid.rs b/clippy_lints/src/manual_rem_euclid.rs
index 6cf5d272d7d82..86293169ea28c 100644
--- a/clippy_lints/src/manual_rem_euclid.rs
+++ b/clippy_lints/src/manual_rem_euclid.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, FullInt};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
diff --git a/clippy_lints/src/manual_retain.rs b/clippy_lints/src/manual_retain.rs
index a35b0f914e058..a60163be770d0 100644
--- a/clippy_lints/src/manual_retain.rs
+++ b/clippy_lints/src/manual_retain.rs
@@ -1,17 +1,17 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
+use clippy_utils::SpanlessEq;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item};
-use clippy_utils::SpanlessEq;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
 use rustc_hir::ExprKind::Assign;
+use rustc_hir::def_id::DefId;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
-use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
+use rustc_span::symbol::{Symbol, sym};
 
 const ACCEPTABLE_METHODS: [Symbol; 5] = [
     sym::binaryheap_iter,
diff --git a/clippy_lints/src/manual_string_new.rs b/clippy_lints/src/manual_string_new.rs
index 781db4b97f083..198f7aaddc71b 100644
--- a/clippy_lints/src/manual_string_new.rs
+++ b/clippy_lints/src/manual_string_new.rs
@@ -5,7 +5,7 @@ use rustc_hir::{Expr, ExprKind, PathSegment, QPath, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, symbol, Span};
+use rustc_span::{Span, sym, symbol};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs
index 02d433ecc5aaa..9aceca66bf774 100644
--- a/clippy_lints/src/manual_strip.rs
+++ b/clippy_lints/src/manual_strip.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
@@ -8,13 +8,13 @@ use clippy_utils::{eq_expr_value, higher};
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
 use rustc_span::source_map::Spanned;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 use std::iter;
 
 declare_clippy_lint! {
diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs
index 2db71b1f7a388..a97dbbbc33fd0 100644
--- a/clippy_lints/src/map_unit_fn.rs
+++ b/clippy_lints/src/map_unit_fn.rs
@@ -7,7 +7,7 @@ use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, Ty};
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs
index b666e77c09ecb..50e6dfc6298dc 100644
--- a/clippy_lints/src/matches/collapsible_match.rs
+++ b/clippy_lints/src/matches/collapsible_match.rs
@@ -4,7 +4,7 @@ use clippy_utils::higher::IfLetOrMatch;
 use clippy_utils::source::snippet;
 use clippy_utils::visitors::is_local_used;
 use clippy_utils::{
-    is_res_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_stmt, peel_ref_operators, SpanlessEq,
+    SpanlessEq, is_res_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_stmt, peel_ref_operators,
 };
 use rustc_errors::MultiSpan;
 use rustc_hir::LangItem::OptionNone;
@@ -12,7 +12,7 @@ use rustc_hir::{Arm, Expr, HirId, Pat, PatKind};
 use rustc_lint::LateContext;
 use rustc_span::Span;
 
-use super::{pat_contains_disallowed_or, COLLAPSIBLE_MATCH};
+use super::{COLLAPSIBLE_MATCH, pat_contains_disallowed_or};
 
 pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], msrv: &Msrv) {
     if let Some(els_arm) = arms.iter().rfind(|arm| arm_is_wild_like(cx, arm)) {
diff --git a/clippy_lints/src/matches/manual_filter.rs b/clippy_lints/src/matches/manual_filter.rs
index 619ec83127aba..cfa054706d6bf 100644
--- a/clippy_lints/src/matches/manual_filter.rs
+++ b/clippy_lints/src/matches/manual_filter.rs
@@ -6,10 +6,10 @@ use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id};
 use rustc_hir::LangItem::{OptionNone, OptionSome};
 use rustc_hir::{Arm, Expr, ExprKind, HirId, Pat, PatKind};
 use rustc_lint::LateContext;
-use rustc_span::{sym, SyntaxContext};
+use rustc_span::{SyntaxContext, sym};
 
-use super::manual_utils::{check_with, SomeExpr};
 use super::MANUAL_FILTER;
+use super::manual_utils::{SomeExpr, check_with};
 
 // Function called on the <expr> of `[&+]Some((ref | ref mut) x) => <expr>`
 // Need to check if it's of the form `<expr>=if <cond> {<then_expr>} else {<else_expr>}`
diff --git a/clippy_lints/src/matches/manual_map.rs b/clippy_lints/src/matches/manual_map.rs
index ed3d8b09fdcda..de57d1eee9249 100644
--- a/clippy_lints/src/matches/manual_map.rs
+++ b/clippy_lints/src/matches/manual_map.rs
@@ -1,5 +1,5 @@
-use super::manual_utils::{check_with, SomeExpr};
 use super::MANUAL_MAP;
+use super::manual_utils::{SomeExpr, check_with};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 
 use clippy_utils::{is_res_lang_ctor, path_res};
diff --git a/clippy_lints/src/matches/manual_unwrap_or.rs b/clippy_lints/src/matches/manual_unwrap_or.rs
index d5d83df93471c..59d3752001178 100644
--- a/clippy_lints/src/matches/manual_unwrap_or.rs
+++ b/clippy_lints/src/matches/manual_unwrap_or.rs
@@ -1,12 +1,12 @@
 use clippy_utils::consts::ConstEvalCtxt;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, indent_of, reindent_multiline};
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::usage::contains_return_break_continue_macro;
 use clippy_utils::{is_res_lang_ctor, path_to_local_id, peel_blocks, sugg};
 use rustc_errors::Applicability;
-use rustc_hir::def::{DefKind, Res};
 use rustc_hir::LangItem::{OptionNone, ResultErr};
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Arm, Expr, Pat, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::Ty;
diff --git a/clippy_lints/src/matches/manual_utils.rs b/clippy_lints/src/matches/manual_utils.rs
index be80aebed6dfb..d38560998a5a7 100644
--- a/clippy_lints/src/matches/manual_utils.rs
+++ b/clippy_lints/src/matches/manual_utils.rs
@@ -4,16 +4,16 @@ use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{is_copy, is_type_diagnostic_item, peel_mid_ty_refs_is_mutable, type_is_unsafe_function};
 use clippy_utils::{
-    can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res, path_to_local_id,
-    peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, CaptureKind,
+    CaptureKind, can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res,
+    path_to_local_id, peel_blocks, peel_hir_expr_refs, peel_hir_expr_while,
 };
 use rustc_ast::util::parser::PREC_UNAMBIGUOUS;
 use rustc_errors::Applicability;
-use rustc_hir::def::Res;
 use rustc_hir::LangItem::{OptionNone, OptionSome};
+use rustc_hir::def::Res;
 use rustc_hir::{BindingMode, Expr, ExprKind, HirId, Mutability, Pat, PatKind, Path, QPath};
 use rustc_lint::LateContext;
-use rustc_span::{sym, SyntaxContext};
+use rustc_span::{SyntaxContext, sym};
 
 #[expect(clippy::too_many_arguments)]
 #[expect(clippy::too_many_lines)]
diff --git a/clippy_lints/src/matches/match_same_arms.rs b/clippy_lints/src/matches/match_same_arms.rs
index da8c918a62bb6..f9ffbc5dc0b8e 100644
--- a/clippy_lints/src/matches/match_same_arms.rs
+++ b/clippy_lints/src/matches/match_same_arms.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_lint_allowed, path_to_local, search_same, SpanlessEq, SpanlessHash};
+use clippy_utils::{SpanlessEq, SpanlessHash, is_lint_allowed, path_to_local, search_same};
 use core::cmp::Ordering;
 use core::{iter, slice};
 use rustc_arena::DroplessArena;
diff --git a/clippy_lints/src/matches/match_str_case_mismatch.rs b/clippy_lints/src/matches/match_str_case_mismatch.rs
index 322e9c3ebe5b3..40518ce2ca775 100644
--- a/clippy_lints/src/matches/match_str_case_mismatch.rs
+++ b/clippy_lints/src/matches/match_str_case_mismatch.rs
@@ -2,12 +2,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::ty::is_type_lang_item;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 use rustc_hir::{Arm, Expr, ExprKind, LangItem, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::symbol::Symbol;
 use rustc_span::Span;
+use rustc_span::symbol::Symbol;
 
 use super::MATCH_STR_CASE_MISMATCH;
 
diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs
index cf5377e0725dd..686fc4a0fa0a5 100644
--- a/clippy_lints/src/matches/mod.rs
+++ b/clippy_lints/src/matches/mod.rs
@@ -24,8 +24,8 @@ mod single_match;
 mod try_err;
 mod wild_in_or_pats;
 
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::source::walk_span_to_context;
 use clippy_utils::{higher, is_direct_expn_of, is_in_const_context, is_span_match, span_contains_cfg};
 use rustc_hir::{Arm, Expr, ExprKind, LetStmt, MatchSource, Pat, PatKind};
diff --git a/clippy_lints/src/matches/overlapping_arms.rs b/clippy_lints/src/matches/overlapping_arms.rs
index 71f211be925bf..6a4c553cee0ee 100644
--- a/clippy_lints/src/matches/overlapping_arms.rs
+++ b/clippy_lints/src/matches/overlapping_arms.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{mir_to_const, ConstEvalCtxt, FullInt};
+use clippy_utils::consts::{ConstEvalCtxt, FullInt, mir_to_const};
 use clippy_utils::diagnostics::span_lint_and_note;
 use core::cmp::Ordering;
 use rustc_hir::{Arm, Expr, PatKind, RangeEnd};
diff --git a/clippy_lints/src/matches/redundant_guards.rs b/clippy_lints/src/matches/redundant_guards.rs
index 8222c3057f73e..564c598a334c7 100644
--- a/clippy_lints/src/matches/redundant_guards.rs
+++ b/clippy_lints/src/matches/redundant_guards.rs
@@ -10,11 +10,11 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Arm, BinOpKind, Expr, ExprKind, MatchSource, Node, PatKind, UnOp};
 use rustc_lint::LateContext;
 use rustc_span::symbol::Ident;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{Span, Symbol, sym};
 use std::borrow::Cow;
 use std::ops::ControlFlow;
 
-use super::{pat_contains_disallowed_or, REDUNDANT_GUARDS};
+use super::{REDUNDANT_GUARDS, pat_contains_disallowed_or};
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>], msrv: &Msrv) {
     for outer_arm in arms {
diff --git a/clippy_lints/src/matches/redundant_pattern_match.rs b/clippy_lints/src/matches/redundant_pattern_match.rs
index 0e4b2d9d34a02..b646e87a43930 100644
--- a/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/clippy_lints/src/matches/redundant_pattern_match.rs
@@ -1,18 +1,18 @@
 use super::REDUNDANT_PATTERN_MATCHING;
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::{snippet, walk_span_to_context};
-use clippy_utils::sugg::{make_unop, Sugg};
+use clippy_utils::sugg::{Sugg, make_unop};
 use clippy_utils::ty::{is_type_diagnostic_item, needs_ordered_drop};
 use clippy_utils::visitors::{any_temporaries_need_ordered_drop, for_each_expr_without_closures};
 use clippy_utils::{higher, is_expn_of, is_trait_method};
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
-use rustc_hir::def::{DefKind, Res};
 use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, GenericArgKind, Ty};
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{Span, Symbol, sym};
 use std::fmt::Write;
 use std::ops::ControlFlow;
 
diff --git a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
index 9c2f42d218702..537f7272f7f34 100644
--- a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
+++ b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
@@ -8,7 +8,7 @@ use clippy_utils::{get_attr, is_lint_allowed};
 use itertools::Itertools;
 use rustc_ast::Mutability;
 use rustc_errors::{Applicability, Diag};
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 use rustc_hir::{Arm, Expr, ExprKind, MatchSource};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::ty::{GenericArgKind, Region, RegionKind, Ty, TyCtxt, TypeVisitable, TypeVisitor};
diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs
index e7cef5bdbd767..2eda238ae8cdb 100644
--- a/clippy_lints/src/matches/single_match.rs
+++ b/clippy_lints/src/matches/single_match.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{expr_block, snippet, snippet_block_with_context, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, expr_block, snippet, snippet_block_with_context};
 use clippy_utils::ty::implements_trait;
 use clippy_utils::{
     is_lint_allowed, is_unit_expr, peel_blocks, peel_hir_pat_refs, peel_middle_ty_refs, peel_n_hir_expr_refs,
@@ -8,11 +8,11 @@ use core::ops::ControlFlow;
 use rustc_arena::DroplessArena;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{walk_pat, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_pat};
 use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatKind, QPath, StmtKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, AdtDef, ParamEnv, TyCtxt, TypeckResults, VariantDef};
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE};
 
diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs
index 72a5945ad9bca..146748734cff4 100644
--- a/clippy_lints/src/mem_replace.rs
+++ b/clippy_lints/src/mem_replace.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
@@ -13,8 +13,8 @@ use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::impl_lint_pass;
-use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_span::symbol::sym;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/methods/bind_instead_of_map.rs b/clippy_lints/src/methods/bind_instead_of_map.rs
index 2a8a5fcc3b6f9..91a5de16e9670 100644
--- a/clippy_lints/src/methods/bind_instead_of_map.rs
+++ b/clippy_lints/src/methods/bind_instead_of_map.rs
@@ -1,4 +1,4 @@
-use super::{contains_return, BIND_INSTEAD_OF_MAP};
+use super::{BIND_INSTEAD_OF_MAP, contains_return};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::peel_blocks;
 use clippy_utils::source::{snippet, snippet_with_context};
diff --git a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
index 740cce0a6c235..76bdbe55e2f3b 100644
--- a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
+++ b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
@@ -1,12 +1,12 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, indent_of, reindent_multiline};
 use clippy_utils::ty::is_type_lang_item;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem};
 use rustc_lint::LateContext;
-use rustc_span::source_map::Spanned;
 use rustc_span::Span;
+use rustc_span::source_map::Spanned;
 
 use super::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS;
 
diff --git a/clippy_lints/src/methods/clear_with_drain.rs b/clippy_lints/src/methods/clear_with_drain.rs
index 5389861245a28..6e24cabca8bba 100644
--- a/clippy_lints/src/methods/clear_with_drain.rs
+++ b/clippy_lints/src/methods/clear_with_drain.rs
@@ -4,8 +4,8 @@ use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem, QPath};
 use rustc_lint::LateContext;
-use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_span::symbol::sym;
 
 use super::CLEAR_WITH_DRAIN;
 
diff --git a/clippy_lints/src/methods/clone_on_copy.rs b/clippy_lints/src/methods/clone_on_copy.rs
index e7a2060be046a..79a473e0e6f58 100644
--- a/clippy_lints/src/methods/clone_on_copy.rs
+++ b/clippy_lints/src/methods/clone_on_copy.rs
@@ -7,7 +7,7 @@ use rustc_lint::LateContext;
 use rustc_middle::ty::adjustment::Adjust;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_middle::ty::{self};
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{Symbol, sym};
 
 use super::CLONE_ON_COPY;
 
diff --git a/clippy_lints/src/methods/clone_on_ref_ptr.rs b/clippy_lints/src/methods/clone_on_ref_ptr.rs
index e0826b53004b6..96e2de0dc1cbd 100644
--- a/clippy_lints/src/methods/clone_on_ref_ptr.rs
+++ b/clippy_lints/src/methods/clone_on_ref_ptr.rs
@@ -4,7 +4,7 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{Symbol, sym};
 
 use super::CLONE_ON_REF_PTR;
 
diff --git a/clippy_lints/src/methods/cloned_instead_of_copied.rs b/clippy_lints/src/methods/cloned_instead_of_copied.rs
index fcafa16223658..fa04f74eec107 100644
--- a/clippy_lints/src/methods/cloned_instead_of_copied.rs
+++ b/clippy_lints/src/methods/cloned_instead_of_copied.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::CLONED_INSTEAD_OF_COPIED;
 
diff --git a/clippy_lints/src/methods/collapsible_str_replace.rs b/clippy_lints/src/methods/collapsible_str_replace.rs
index 1fab6c0e499d4..f7bf8764bdebc 100644
--- a/clippy_lints/src/methods/collapsible_str_replace.rs
+++ b/clippy_lints/src/methods/collapsible_str_replace.rs
@@ -8,7 +8,7 @@ use rustc_hir as hir;
 use rustc_lint::LateContext;
 use std::collections::VecDeque;
 
-use super::{method_call, COLLAPSIBLE_STR_REPLACE};
+use super::{COLLAPSIBLE_STR_REPLACE, method_call};
 
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
diff --git a/clippy_lints/src/methods/drain_collect.rs b/clippy_lints/src/methods/drain_collect.rs
index 56171a134522d..10360b4817bc9 100644
--- a/clippy_lints/src/methods/drain_collect.rs
+++ b/clippy_lints/src/methods/drain_collect.rs
@@ -8,7 +8,7 @@ use rustc_hir::{Expr, ExprKind, LangItem, Path, QPath};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_middle::ty::Ty;
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
 
 /// Checks if both types match the given diagnostic item, e.g.:
 ///
diff --git a/clippy_lints/src/methods/err_expect.rs b/clippy_lints/src/methods/err_expect.rs
index dc978c8a58456..3b1adb16b80e9 100644
--- a/clippy_lints/src/methods/err_expect.rs
+++ b/clippy_lints/src/methods/err_expect.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_middle::ty::Ty;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 pub(super) fn check(
     cx: &LateContext<'_>,
diff --git a/clippy_lints/src/methods/expect_fun_call.rs b/clippy_lints/src/methods/expect_fun_call.rs
index c9f56e1d98097..2922086522c2a 100644
--- a/clippy_lints/src/methods/expect_fun_call.rs
+++ b/clippy_lints/src/methods/expect_fun_call.rs
@@ -1,13 +1,13 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::{format_args_inputs_span, root_macro_call_first_node, FormatArgsStorage};
+use clippy_utils::macros::{FormatArgsStorage, format_args_inputs_span, root_macro_call_first_node};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_span::symbol::sym;
 use std::borrow::Cow;
 
 use super::EXPECT_FUN_CALL;
diff --git a/clippy_lints/src/methods/filetype_is_file.rs b/clippy_lints/src/methods/filetype_is_file.rs
index 2ab0401947c4c..35008c39c084d 100644
--- a/clippy_lints/src/methods/filetype_is_file.rs
+++ b/clippy_lints/src/methods/filetype_is_file.rs
@@ -3,7 +3,7 @@ use clippy_utils::get_parent_expr;
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::FILETYPE_IS_FILE;
 
diff --git a/clippy_lints/src/methods/filter_map.rs b/clippy_lints/src/methods/filter_map.rs
index 02a11257007a9..06482a743ddf4 100644
--- a/clippy_lints/src/methods/filter_map.rs
+++ b/clippy_lints/src/methods/filter_map.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::macros::{is_panic, matching_root_macro_call, root_macro_call};
 use clippy_utils::source::{indent_of, reindent_multiline, snippet};
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{higher, is_trait_method, path_to_local_id, peel_blocks, SpanlessEq};
+use clippy_utils::{SpanlessEq, higher, is_trait_method, path_to_local_id, peel_blocks};
 use hir::{Body, HirId, MatchSource, Pat};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -10,8 +10,8 @@ use rustc_hir::def::Res;
 use rustc_hir::{Closure, Expr, ExprKind, PatKind, PathSegment, QPath, UnOp};
 use rustc_lint::LateContext;
 use rustc_middle::ty::adjustment::Adjust;
-use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
+use rustc_span::symbol::{Ident, Symbol, sym};
 use std::borrow::Cow;
 
 use super::{MANUAL_FILTER_MAP, MANUAL_FIND_MAP, OPTION_FILTER_MAP, RESULT_FILTER_MAP};
diff --git a/clippy_lints/src/methods/filter_map_bool_then.rs b/clippy_lints/src/methods/filter_map_bool_then.rs
index 77a62fbb4fb92..129e692542894 100644
--- a/clippy_lints/src/methods/filter_map_bool_then.rs
+++ b/clippy_lints/src/methods/filter_map_bool_then.rs
@@ -7,9 +7,9 @@ use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::adjustment::Adjust;
 use rustc_middle::ty::Binder;
-use rustc_span::{sym, Span};
+use rustc_middle::ty::adjustment::Adjust;
+use rustc_span::{Span, sym};
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &Expr<'_>, call_span: Span) {
     if !in_external_macro(cx.sess(), expr.span)
diff --git a/clippy_lints/src/methods/filter_map_identity.rs b/clippy_lints/src/methods/filter_map_identity.rs
index 999df875c753f..cf7f276dabb10 100644
--- a/clippy_lints/src/methods/filter_map_identity.rs
+++ b/clippy_lints/src/methods/filter_map_identity.rs
@@ -3,7 +3,7 @@ use clippy_utils::{is_expr_identity_function, is_expr_untyped_identity_function,
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::FILTER_MAP_IDENTITY;
 
diff --git a/clippy_lints/src/methods/flat_map_identity.rs b/clippy_lints/src/methods/flat_map_identity.rs
index 651ea34f9d0e8..0c2ecfbc8ffdf 100644
--- a/clippy_lints/src/methods/flat_map_identity.rs
+++ b/clippy_lints/src/methods/flat_map_identity.rs
@@ -3,7 +3,7 @@ use clippy_utils::{is_expr_untyped_identity_function, is_trait_method};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::FLAT_MAP_IDENTITY;
 
diff --git a/clippy_lints/src/methods/flat_map_option.rs b/clippy_lints/src/methods/flat_map_option.rs
index 0a4a381b86186..3242dcadb7013 100644
--- a/clippy_lints/src/methods/flat_map_option.rs
+++ b/clippy_lints/src/methods/flat_map_option.rs
@@ -4,7 +4,7 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::FLAT_MAP_OPTION;
 use clippy_utils::ty::is_type_diagnostic_item;
diff --git a/clippy_lints/src/methods/get_last_with_len.rs b/clippy_lints/src/methods/get_last_with_len.rs
index 6203765113428..5f6fb4c821d57 100644
--- a/clippy_lints/src/methods/get_last_with_len.rs
+++ b/clippy_lints/src/methods/get_last_with_len.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_integer_literal, SpanlessEq};
+use clippy_utils::{SpanlessEq, is_integer_literal};
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
diff --git a/clippy_lints/src/methods/inefficient_to_string.rs b/clippy_lints/src/methods/inefficient_to_string.rs
index 230a8eb2ec47a..4ed7de81ea3d0 100644
--- a/clippy_lints/src/methods/inefficient_to_string.rs
+++ b/clippy_lints/src/methods/inefficient_to_string.rs
@@ -5,7 +5,7 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{Symbol, sym};
 
 use super::INEFFICIENT_TO_STRING;
 
diff --git a/clippy_lints/src/methods/inspect_for_each.rs b/clippy_lints/src/methods/inspect_for_each.rs
index ad4b6fa130e35..3706f3b670ba1 100644
--- a/clippy_lints/src/methods/inspect_for_each.rs
+++ b/clippy_lints/src/methods/inspect_for_each.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::is_trait_method;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::INSPECT_FOR_EACH;
 
diff --git a/clippy_lints/src/methods/into_iter_on_ref.rs b/clippy_lints/src/methods/into_iter_on_ref.rs
index bbc7ce8d78ab9..bedeb63367d06 100644
--- a/clippy_lints/src/methods/into_iter_on_ref.rs
+++ b/clippy_lints/src/methods/into_iter_on_ref.rs
@@ -5,8 +5,8 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
-use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
+use rustc_span::symbol::{Symbol, sym};
 
 use super::INTO_ITER_ON_REF;
 
diff --git a/clippy_lints/src/methods/iter_filter.rs b/clippy_lints/src/methods/iter_filter.rs
index b93d51eac647b..f6612c984a7eb 100644
--- a/clippy_lints/src/methods/iter_filter.rs
+++ b/clippy_lints/src/methods/iter_filter.rs
@@ -10,8 +10,8 @@ use clippy_utils::{get_parent_expr, is_trait_method, peel_blocks, span_contains_
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::QPath;
-use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
+use rustc_span::symbol::{Ident, Symbol, sym};
 use std::borrow::Cow;
 
 ///
diff --git a/clippy_lints/src/methods/iter_nth.rs b/clippy_lints/src/methods/iter_nth.rs
index e31fa2f777d8e..82bda5d951225 100644
--- a/clippy_lints/src/methods/iter_nth.rs
+++ b/clippy_lints/src/methods/iter_nth.rs
@@ -3,8 +3,8 @@ use clippy_utils::ty::get_type_diagnostic_name;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
-use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_span::symbol::sym;
 
 use super::ITER_NTH;
 
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 7f6b666e434e9..9d562f5e51d2c 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
@@ -5,9 +5,9 @@ use clippy_utils::source::snippet;
 use clippy_utils::{get_expr_use_or_unification_node, is_res_lang_ctor, path_res, std_or_core};
 
 use rustc_errors::Applicability;
+use rustc_hir::LangItem::{OptionNone, OptionSome};
 use rustc_hir::def_id::DefId;
 use rustc_hir::hir_id::HirId;
-use rustc_hir::LangItem::{OptionNone, OptionSome};
 use rustc_hir::{Expr, ExprKind, Node};
 use rustc_lint::LateContext;
 
diff --git a/clippy_lints/src/methods/iter_with_drain.rs b/clippy_lints/src/methods/iter_with_drain.rs
index 1378a07cbc477..163058713377b 100644
--- a/clippy_lints/src/methods/iter_with_drain.rs
+++ b/clippy_lints/src/methods/iter_with_drain.rs
@@ -3,8 +3,8 @@ use clippy_utils::is_range_full;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::LateContext;
-use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_span::symbol::sym;
 
 use super::ITER_WITH_DRAIN;
 
diff --git a/clippy_lints/src/methods/join_absolute_paths.rs b/clippy_lints/src/methods/join_absolute_paths.rs
index 2dad7fcf3c129..2ad070793cbb2 100644
--- a/clippy_lints/src/methods/join_absolute_paths.rs
+++ b/clippy_lints/src/methods/join_absolute_paths.rs
@@ -6,8 +6,8 @@ use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
-use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_span::symbol::sym;
 
 use super::JOIN_ABSOLUTE_PATHS;
 
diff --git a/clippy_lints/src/methods/manual_c_str_literals.rs b/clippy_lints/src/methods/manual_c_str_literals.rs
index cb9fb373c10a6..96af9db1af709 100644
--- a/clippy_lints/src/methods/manual_c_str_literals.rs
+++ b/clippy_lints/src/methods/manual_c_str_literals.rs
@@ -6,7 +6,7 @@ use rustc_ast::{LitKind, StrStyle};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Node, QPath, TyKind};
 use rustc_lint::LateContext;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{Span, Symbol, sym};
 
 use super::MANUAL_C_STR_LITERALS;
 
diff --git a/clippy_lints/src/methods/manual_inspect.rs b/clippy_lints/src/methods/manual_inspect.rs
index cac2e11f59166..64c19c327b254 100644
--- a/clippy_lints/src/methods/manual_inspect.rs
+++ b/clippy_lints/src/methods/manual_inspect.rs
@@ -3,13 +3,13 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::{IntoSpan, SpanRangeExt};
 use clippy_utils::ty::get_field_by_name;
 use clippy_utils::visitors::{for_each_expr, for_each_expr_without_closures};
-use clippy_utils::{expr_use_ctxt, is_diag_item_method, is_diag_trait_item, path_to_local_id, ExprUseNode};
+use clippy_utils::{ExprUseNode, expr_use_ctxt, is_diag_item_method, is_diag_trait_item, path_to_local_id};
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
 use rustc_hir::{BindingMode, BorrowKind, ByRef, ClosureKind, Expr, ExprKind, Mutability, Node, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
-use rustc_span::{sym, Span, Symbol, DUMMY_SP};
+use rustc_span::{DUMMY_SP, Span, Symbol, sym};
 
 use super::MANUAL_INSPECT;
 
diff --git a/clippy_lints/src/methods/manual_is_variant_and.rs b/clippy_lints/src/methods/manual_is_variant_and.rs
index d29acd4622a0b..c377abd62377a 100644
--- a/clippy_lints/src/methods/manual_is_variant_and.rs
+++ b/clippy_lints/src/methods/manual_is_variant_and.rs
@@ -4,7 +4,7 @@ use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_errors::Applicability;
 use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::MANUAL_IS_VARIANT_AND;
 
diff --git a/clippy_lints/src/methods/manual_ok_or.rs b/clippy_lints/src/methods/manual_ok_or.rs
index b1a8e1e5e4709..4321dd6b0e098 100644
--- a/clippy_lints/src/methods/manual_ok_or.rs
+++ b/clippy_lints/src/methods/manual_ok_or.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, indent_of, reindent_multiline};
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id};
 use rustc_errors::Applicability;
diff --git a/clippy_lints/src/methods/manual_try_fold.rs b/clippy_lints/src/methods/manual_try_fold.rs
index 11fba35c16ea3..31449d417701c 100644
--- a/clippy_lints/src/methods/manual_try_fold.rs
+++ b/clippy_lints/src/methods/manual_try_fold.rs
@@ -8,7 +8,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::MANUAL_TRY_FOLD;
 
diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs
index 08ce7e204dd27..ac378ff3702bb 100644
--- a/clippy_lints/src/methods/map_clone.rs
+++ b/clippy_lints/src/methods/map_clone.rs
@@ -11,7 +11,7 @@ use rustc_middle::mir::Mutability;
 use rustc_middle::ty;
 use rustc_middle::ty::adjustment::Adjust;
 use rustc_span::symbol::Ident;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::MAP_CLONE;
 
diff --git a/clippy_lints/src/methods/map_flatten.rs b/clippy_lints/src/methods/map_flatten.rs
index 22a03825194e0..07a7a12b16279 100644
--- a/clippy_lints/src/methods/map_flatten.rs
+++ b/clippy_lints/src/methods/map_flatten.rs
@@ -6,8 +6,8 @@ use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_span::symbol::sym;
 
 use super::MAP_FLATTEN;
 
diff --git a/clippy_lints/src/methods/map_identity.rs b/clippy_lints/src/methods/map_identity.rs
index 5dd7b1b02adef..1f204de01da06 100644
--- a/clippy_lints/src/methods/map_identity.rs
+++ b/clippy_lints/src/methods/map_identity.rs
@@ -4,7 +4,7 @@ use clippy_utils::{is_expr_untyped_identity_function, is_trait_method};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::MAP_IDENTITY;
 
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 098d3fca9b259..7696dd16b251c 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -132,8 +132,8 @@ mod waker_clone_wake;
 mod wrong_self_convention;
 mod zst_offset;
 
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
 use clippy_utils::macros::FormatArgsStorage;
@@ -147,7 +147,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, TraitRef, Ty};
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -5174,12 +5174,9 @@ impl ShouldImplTraitCase {
     fn lifetime_param_cond(&self, impl_item: &hir::ImplItem<'_>) -> bool {
         self.lint_explicit_lifetime
             || !impl_item.generics.params.iter().any(|p| {
-                matches!(
-                    p.kind,
-                    hir::GenericParamKind::Lifetime {
-                        kind: hir::LifetimeParamKind::Explicit
-                    }
-                )
+                matches!(p.kind, hir::GenericParamKind::Lifetime {
+                    kind: hir::LifetimeParamKind::Explicit
+                })
             })
     }
 }
diff --git a/clippy_lints/src/methods/mut_mutex_lock.rs b/clippy_lints/src/methods/mut_mutex_lock.rs
index 1a0fce2876d40..83e8370f939bc 100644
--- a/clippy_lints/src/methods/mut_mutex_lock.rs
+++ b/clippy_lints/src/methods/mut_mutex_lock.rs
@@ -5,7 +5,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{Expr, Mutability};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::MUT_MUTEX_LOCK;
 
diff --git a/clippy_lints/src/methods/needless_character_iteration.rs b/clippy_lints/src/methods/needless_character_iteration.rs
index 332da722a37dc..348f740e7ddf7 100644
--- a/clippy_lints/src/methods/needless_character_iteration.rs
+++ b/clippy_lints/src/methods/needless_character_iteration.rs
@@ -4,8 +4,8 @@ use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_span::Span;
 
-use super::utils::get_last_chain_binding_hir_id;
 use super::NEEDLESS_CHARACTER_ITERATION;
+use super::utils::get_last_chain_binding_hir_id;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::{match_def_path, path_to_local_id, peel_blocks};
diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs
index f61923e5bf569..421c7a5e070d9 100644
--- a/clippy_lints/src/methods/needless_collect.rs
+++ b/clippy_lints/src/methods/needless_collect.rs
@@ -4,12 +4,12 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{get_type_diagnostic_name, make_normalized_projection, make_projection};
 use clippy_utils::{
-    can_move_expr_to_closure, fn_def_id, get_enclosing_block, higher, is_trait_method, path_to_local, path_to_local_id,
-    CaptureKind,
+    CaptureKind, can_move_expr_to_closure, fn_def_id, get_enclosing_block, higher, is_trait_method, path_to_local,
+    path_to_local_id,
 };
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, MultiSpan};
-use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_block, walk_expr};
 use rustc_hir::{
     BindingMode, Block, Expr, ExprKind, HirId, HirIdSet, LetStmt, Mutability, Node, PatKind, Stmt, StmtKind,
 };
@@ -17,7 +17,7 @@ use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, AssocKind, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, Ty};
 use rustc_span::symbol::Ident;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed";
 
diff --git a/clippy_lints/src/methods/needless_option_as_deref.rs b/clippy_lints/src/methods/needless_option_as_deref.rs
index 9f714fdd47bb3..538aa9097a40f 100644
--- a/clippy_lints/src/methods/needless_option_as_deref.rs
+++ b/clippy_lints/src/methods/needless_option_as_deref.rs
@@ -4,8 +4,8 @@ use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::usage::local_used_after_expr;
 use rustc_errors::Applicability;
-use rustc_hir::def::Res;
 use rustc_hir::Expr;
+use rustc_hir::def::Res;
 use rustc_lint::LateContext;
 use rustc_span::sym;
 
diff --git a/clippy_lints/src/methods/no_effect_replace.rs b/clippy_lints/src/methods/no_effect_replace.rs
index a301a5f7d65be..32f32f1b21673 100644
--- a/clippy_lints/src/methods/no_effect_replace.rs
+++ b/clippy_lints/src/methods/no_effect_replace.rs
@@ -1,6 +1,6 @@
+use clippy_utils::SpanlessEq;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::is_type_lang_item;
-use clippy_utils::SpanlessEq;
 use rustc_ast::LitKind;
 use rustc_hir::{ExprKind, LangItem};
 use rustc_lint::LateContext;
diff --git a/clippy_lints/src/methods/open_options.rs b/clippy_lints/src/methods/open_options.rs
index f1a3c81cebbdb..da084871402a7 100644
--- a/clippy_lints/src/methods/open_options.rs
+++ b/clippy_lints/src/methods/open_options.rs
@@ -8,7 +8,7 @@ use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::Ty;
 use rustc_span::source_map::Spanned;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::{NONSENSICAL_OPEN_OPTIONS, SUSPICIOUS_OPEN_OPTIONS};
 
@@ -126,17 +126,13 @@ fn get_open_options(
         && let ExprKind::Path(path) = callee.kind
         && let Some(did) = cx.qpath_res(&path, callee.hir_id).opt_def_id()
     {
-        let std_file_options = [
-            sym::file_options,
-            sym::open_options_new,
-        ];
+        let std_file_options = [sym::file_options, sym::open_options_new];
 
-        let tokio_file_options: &[&[&str]] = &[
-            &paths::TOKIO_IO_OPEN_OPTIONS_NEW,
-            &paths::TOKIO_FILE_OPTIONS,
-        ];
+        let tokio_file_options: &[&[&str]] = &[&paths::TOKIO_IO_OPEN_OPTIONS_NEW, &paths::TOKIO_FILE_OPTIONS];
 
-        let is_std_options = std_file_options.into_iter().any(|sym| cx.tcx.is_diagnostic_item(sym, did));
+        let is_std_options = std_file_options
+            .into_iter()
+            .any(|sym| cx.tcx.is_diagnostic_item(sym, did));
         is_std_options || match_any_def_paths(cx, did, tokio_file_options).is_some()
     } else {
         false
diff --git a/clippy_lints/src/methods/option_as_ref_cloned.rs b/clippy_lints/src/methods/option_as_ref_cloned.rs
index ba167f9d9c230..9b22494888fb2 100644
--- a/clippy_lints/src/methods/option_as_ref_cloned.rs
+++ b/clippy_lints/src/methods/option_as_ref_cloned.rs
@@ -3,9 +3,9 @@ use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
-use super::{method_call, OPTION_AS_REF_CLONED};
+use super::{OPTION_AS_REF_CLONED, method_call};
 
 pub(super) fn check(cx: &LateContext<'_>, cloned_recv: &Expr<'_>, cloned_ident_span: Span) {
     if let Some((method @ ("as_ref" | "as_mut"), as_ref_recv, [], as_ref_ident_span, _)) = method_call(cloned_recv)
diff --git a/clippy_lints/src/methods/option_as_ref_deref.rs b/clippy_lints/src/methods/option_as_ref_deref.rs
index 9a18d8a14219f..389e02056b2b8 100644
--- a/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -7,7 +7,7 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
 
 use super::OPTION_AS_REF_DEREF;
 
@@ -48,7 +48,9 @@ pub(super) fn check(
                 .map_or(false, |fun_def_id| {
                     cx.tcx.is_diagnostic_item(sym::deref_method, fun_def_id)
                         || cx.tcx.is_diagnostic_item(sym::deref_mut_method, fun_def_id)
-                        || deref_aliases.iter().any(|&sym| cx.tcx.is_diagnostic_item(sym, fun_def_id))
+                        || deref_aliases
+                            .iter()
+                            .any(|&sym| cx.tcx.is_diagnostic_item(sym, fun_def_id))
                 })
         },
         hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
@@ -69,7 +71,9 @@ pub(super) fn check(
                         let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap();
                         cx.tcx.is_diagnostic_item(sym::deref_method, method_did)
                             || cx.tcx.is_diagnostic_item(sym::deref_mut_method, method_did)
-                            || deref_aliases.iter().any(|&sym| cx.tcx.is_diagnostic_item(sym, method_did))
+                            || deref_aliases
+                                .iter()
+                                .any(|&sym| cx.tcx.is_diagnostic_item(sym, method_did))
                     } else {
                         false
                     }
diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs
index ed3bed42eb3a9..b160ab6de8e95 100644
--- a/clippy_lints/src/methods/option_map_unwrap_or.rs
+++ b/clippy_lints/src/methods/option_map_unwrap_or.rs
@@ -5,11 +5,11 @@ use clippy_utils::ty::{is_copy, is_type_diagnostic_item};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
-use rustc_hir::intravisit::{walk_path, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_path};
 use rustc_hir::{ExprKind, HirId, Node, PatKind, Path, QPath};
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 use std::ops::ControlFlow;
 
 use super::MAP_UNWRAP_OR;
diff --git a/clippy_lints/src/methods/or_fun_call.rs b/clippy_lints/src/methods/or_fun_call.rs
index e4326cb958e5f..8a7e72b63bb5e 100644
--- a/clippy_lints/src/methods/or_fun_call.rs
+++ b/clippy_lints/src/methods/or_fun_call.rs
@@ -11,8 +11,8 @@ use clippy_utils::{
 use rustc_errors::Applicability;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::symbol::{self, sym, Symbol};
 use rustc_span::Span;
+use rustc_span::symbol::{self, Symbol, sym};
 use {rustc_ast as ast, rustc_hir as hir};
 
 use super::{OR_FUN_CALL, UNWRAP_OR_DEFAULT};
diff --git a/clippy_lints/src/methods/or_then_unwrap.rs b/clippy_lints/src/methods/or_then_unwrap.rs
index 7b0bdcf99e736..3e64e15dc8602 100644
--- a/clippy_lints/src/methods/or_then_unwrap.rs
+++ b/clippy_lints/src/methods/or_then_unwrap.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::OR_THEN_UNWRAP;
 
diff --git a/clippy_lints/src/methods/range_zip_with_len.rs b/clippy_lints/src/methods/range_zip_with_len.rs
index 28ca76832eb3a..f4d206c5307c1 100644
--- a/clippy_lints/src/methods/range_zip_with_len.rs
+++ b/clippy_lints/src/methods/range_zip_with_len.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::source::snippet;
-use clippy_utils::{higher, is_integer_const, is_trait_method, SpanlessEq};
+use clippy_utils::{SpanlessEq, higher, is_integer_const, is_trait_method};
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::LateContext;
 use rustc_span::sym;
diff --git a/clippy_lints/src/methods/search_is_some.rs b/clippy_lints/src/methods/search_is_some.rs
index 3b2dd285b8c99..4ab165a5528bb 100644
--- a/clippy_lints/src/methods/search_is_some.rs
+++ b/clippy_lints/src/methods/search_is_some.rs
@@ -8,8 +8,8 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::PatKind;
 use rustc_lint::LateContext;
-use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_span::symbol::sym;
 
 use super::SEARCH_IS_SOME;
 
diff --git a/clippy_lints/src/methods/seek_from_current.rs b/clippy_lints/src/methods/seek_from_current.rs
index 8bc535ac47a84..7ef07fe899c08 100644
--- a/clippy_lints/src/methods/seek_from_current.rs
+++ b/clippy_lints/src/methods/seek_from_current.rs
@@ -6,9 +6,9 @@ use rustc_lint::LateContext;
 use rustc_span::sym;
 
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_enum_variant_ctor;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::is_enum_variant_ctor;
 
 use super::SEEK_FROM_CURRENT;
 
diff --git a/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs b/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
index 7c09cc252e13a..9c966f010f130 100644
--- a/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
+++ b/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
@@ -1,12 +1,12 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{is_expr_used_or_unified, is_enum_variant_ctor};
+use clippy_utils::{is_enum_variant_ctor, is_expr_used_or_unified};
 use rustc_ast::ast::{LitIntType, LitKind};
 use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::SEEK_TO_START_INSTEAD_OF_REWIND;
 
diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs
index 12cabd43cb1b2..69032776b2b9f 100644
--- a/clippy_lints/src/methods/str_splitn.rs
+++ b/clippy_lints/src/methods/str_splitn.rs
@@ -3,7 +3,7 @@ use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::usage::local_used_after_expr;
-use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::visitors::{Descend, for_each_expr};
 use clippy_utils::{is_diag_item_method, match_def_path, path_to_local_id, paths};
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
@@ -12,7 +12,7 @@ use rustc_hir::{
 };
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::{sym, Span, Symbol, SyntaxContext};
+use rustc_span::{Span, Symbol, SyntaxContext, sym};
 
 use super::{MANUAL_SPLIT_ONCE, NEEDLESS_SPLITN};
 
diff --git a/clippy_lints/src/methods/suspicious_command_arg_space.rs b/clippy_lints/src/methods/suspicious_command_arg_space.rs
index 38f2c9169124a..c60a49067ec09 100644
--- a/clippy_lints/src/methods/suspicious_command_arg_space.rs
+++ b/clippy_lints/src/methods/suspicious_command_arg_space.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_errors::{Applicability, Diag};
 use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 use {rustc_ast as ast, rustc_hir as hir};
 
 use super::SUSPICIOUS_COMMAND_ARG_SPACE;
diff --git a/clippy_lints/src/methods/type_id_on_box.rs b/clippy_lints/src/methods/type_id_on_box.rs
index db8cc4595d4df..e67ba5c4d3148 100644
--- a/clippy_lints/src/methods/type_id_on_box.rs
+++ b/clippy_lints/src/methods/type_id_on_box.rs
@@ -7,7 +7,7 @@ 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};
+use rustc_span::{Span, sym};
 
 /// 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
diff --git a/clippy_lints/src/methods/unnecessary_fallible_conversions.rs b/clippy_lints/src/methods/unnecessary_fallible_conversions.rs
index d46b584f8f444..ce81282ddfeb0 100644
--- a/clippy_lints/src/methods/unnecessary_fallible_conversions.rs
+++ b/clippy_lints/src/methods/unnecessary_fallible_conversions.rs
@@ -6,7 +6,7 @@ use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::UNNECESSARY_FALLIBLE_CONVERSIONS;
 
diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs
index c9b9d98dbe607..ca46da81fa053 100644
--- a/clippy_lints/src/methods/unnecessary_filter_map.rs
+++ b/clippy_lints/src/methods/unnecessary_filter_map.rs
@@ -2,7 +2,7 @@ use super::utils::clone_or_copy_needed;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::is_copy;
 use clippy_utils::usage::mutated_variables;
-use clippy_utils::visitors::{for_each_expr_without_closures, Descend};
+use clippy_utils::visitors::{Descend, for_each_expr_without_closures};
 use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id};
 use core::ops::ControlFlow;
 use rustc_hir as hir;
diff --git a/clippy_lints/src/methods/unnecessary_fold.rs b/clippy_lints/src/methods/unnecessary_fold.rs
index 380ea317b946a..b5d8972d7aad5 100644
--- a/clippy_lints/src/methods/unnecessary_fold.rs
+++ b/clippy_lints/src/methods/unnecessary_fold.rs
@@ -8,7 +8,7 @@ use rustc_hir as hir;
 use rustc_hir::PatKind;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::UNNECESSARY_FOLD;
 
@@ -123,60 +123,32 @@ pub(super) fn check(
     if let hir::ExprKind::Lit(lit) = init.kind {
         match lit.node {
             ast::LitKind::Bool(false) => {
-                check_fold_with_op(
-                    cx,
-                    expr,
-                    acc,
-                    fold_span,
-                    hir::BinOpKind::Or,
-                    Replacement {
-                        has_args: true,
-                        has_generic_return: false,
-                        method_name: "any",
-                    },
-                );
+                check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Or, Replacement {
+                    has_args: true,
+                    has_generic_return: false,
+                    method_name: "any",
+                });
             },
             ast::LitKind::Bool(true) => {
-                check_fold_with_op(
-                    cx,
-                    expr,
-                    acc,
-                    fold_span,
-                    hir::BinOpKind::And,
-                    Replacement {
-                        has_args: true,
-                        has_generic_return: false,
-                        method_name: "all",
-                    },
-                );
+                check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::And, Replacement {
+                    has_args: true,
+                    has_generic_return: false,
+                    method_name: "all",
+                });
             },
             ast::LitKind::Int(Pu128(0), _) => {
-                check_fold_with_op(
-                    cx,
-                    expr,
-                    acc,
-                    fold_span,
-                    hir::BinOpKind::Add,
-                    Replacement {
-                        has_args: false,
-                        has_generic_return: needs_turbofish(cx, expr),
-                        method_name: "sum",
-                    },
-                );
+                check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Add, Replacement {
+                    has_args: false,
+                    has_generic_return: needs_turbofish(cx, expr),
+                    method_name: "sum",
+                });
             },
             ast::LitKind::Int(Pu128(1), _) => {
-                check_fold_with_op(
-                    cx,
-                    expr,
-                    acc,
-                    fold_span,
-                    hir::BinOpKind::Mul,
-                    Replacement {
-                        has_args: false,
-                        has_generic_return: needs_turbofish(cx, expr),
-                        method_name: "product",
-                    },
-                );
+                check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, Replacement {
+                    has_args: false,
+                    has_generic_return: needs_turbofish(cx, expr),
+                    method_name: "product",
+                });
             },
             _ => (),
         }
diff --git a/clippy_lints/src/methods/unnecessary_get_then_check.rs b/clippy_lints/src/methods/unnecessary_get_then_check.rs
index 64eb84117954c..39fce2c40c91d 100644
--- a/clippy_lints/src/methods/unnecessary_get_then_check.rs
+++ b/clippy_lints/src/methods/unnecessary_get_then_check.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::Ty;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::UNNECESSARY_GET_THEN_CHECK;
 
diff --git a/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/clippy_lints/src/methods/unnecessary_iter_cloned.rs
index 4d18bc7ac7777..029704882dde2 100644
--- a/clippy_lints/src/methods/unnecessary_iter_cloned.rs
+++ b/clippy_lints/src/methods/unnecessary_iter_cloned.rs
@@ -10,7 +10,7 @@ use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{BindingMode, Expr, ExprKind, Node, PatKind};
 use rustc_lint::LateContext;
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
 
 use super::UNNECESSARY_TO_OWNED;
 
diff --git a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
index 494d71fc053f6..6dc8adb42dfbe 100644
--- a/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
+++ b/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::{is_res_lang_ctor, last_path_segment, path_res, MaybePath};
+use clippy_utils::{MaybePath, is_res_lang_ctor, last_path_segment, path_res};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
diff --git a/clippy_lints/src/methods/unnecessary_min_or_max.rs b/clippy_lints/src/methods/unnecessary_min_or_max.rs
index ff5fa7d33e3ee..062d1348555cd 100644
--- a/clippy_lints/src/methods/unnecessary_min_or_max.rs
+++ b/clippy_lints/src/methods/unnecessary_min_or_max.rs
@@ -9,7 +9,7 @@ use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
diff --git a/clippy_lints/src/methods/unnecessary_result_map_or_else.rs b/clippy_lints/src/methods/unnecessary_result_map_or_else.rs
index c14a87c153414..dc50717112d89 100644
--- a/clippy_lints/src/methods/unnecessary_result_map_or_else.rs
+++ b/clippy_lints/src/methods/unnecessary_result_map_or_else.rs
@@ -8,8 +8,8 @@ use rustc_hir::{Closure, Expr, ExprKind, HirId, QPath};
 use rustc_lint::LateContext;
 use rustc_span::symbol::sym;
 
-use super::utils::get_last_chain_binding_hir_id;
 use super::UNNECESSARY_RESULT_MAP_OR_ELSE;
+use super::utils::get_last_chain_binding_hir_id;
 
 fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def_arg: &Expr<'_>) {
     let msg = "unused \"map closure\" when calling `Result::map_or_else` value";
diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs
index f62cf55e72a82..cfa1fdb81372f 100644
--- a/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -2,12 +2,11 @@ use super::implicit_clone::is_clone_like;
 use super::unnecessary_iter_cloned::{self, is_into_iter};
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::source::{snippet, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet};
 use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item};
 use clippy_utils::visitors::find_all_ret_expressions;
 use clippy_utils::{
-    fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, peel_middle_ty_refs,
-    return_ty,
+    fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, peel_middle_ty_refs, return_ty,
 };
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
@@ -20,7 +19,7 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
 use rustc_middle::ty::{
     self, ClauseKind, GenericArg, GenericArgKind, GenericArgsRef, ParamTy, ProjectionPredicate, TraitPredicate, Ty,
 };
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::{Obligation, ObligationCause};
 
diff --git a/clippy_lints/src/methods/unused_enumerate_index.rs b/clippy_lints/src/methods/unused_enumerate_index.rs
index ee5177d1ffaa1..6c2ae9cc6bffd 100644
--- a/clippy_lints/src/methods/unused_enumerate_index.rs
+++ b/clippy_lints/src/methods/unused_enumerate_index.rs
@@ -1,11 +1,11 @@
 use clippy_utils::diagnostics::span_lint_hir_and_then;
-use clippy_utils::source::{snippet, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet};
 use clippy_utils::{expr_or_init, is_trait_method, pat_is_wild};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, FnDecl, PatKind, TyKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::AdtDef;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use crate::loops::UNUSED_ENUMERATE_INDEX;
 
diff --git a/clippy_lints/src/methods/useless_asref.rs b/clippy_lints/src/methods/useless_asref.rs
index ebad4ae6ee95d..eafe7486bb05a 100644
--- a/clippy_lints/src/methods/useless_asref.rs
+++ b/clippy_lints/src/methods/useless_asref.rs
@@ -9,7 +9,7 @@ use rustc_hir::{self as hir, LangItem};
 use rustc_lint::LateContext;
 use rustc_middle::ty::adjustment::Adjust;
 use rustc_middle::ty::{Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use core::ops::ControlFlow;
 
diff --git a/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs
index fe860e5ae2601..4e33dc1df54d8 100644
--- a/clippy_lints/src/methods/utils.rs
+++ b/clippy_lints/src/methods/utils.rs
@@ -1,12 +1,12 @@
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{get_parent_expr, path_to_local_id, usage};
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, Mutability, Pat, QPath, Stmt, StmtKind};
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, Ty};
-use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_span::symbol::sym;
 
 pub(super) fn derefs_to_slice<'tcx>(
     cx: &LateContext<'tcx>,
diff --git a/clippy_lints/src/methods/vec_resize_to_zero.rs b/clippy_lints/src/methods/vec_resize_to_zero.rs
index 3e271a606115a..5ea4ada128a24 100644
--- a/clippy_lints/src/methods/vec_resize_to_zero.rs
+++ b/clippy_lints/src/methods/vec_resize_to_zero.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_span::source_map::Spanned;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use super::VEC_RESIZE_TO_ZERO;
 
diff --git a/clippy_lints/src/methods/waker_clone_wake.rs b/clippy_lints/src/methods/waker_clone_wake.rs
index 9b64cc7589ccc..b5f34a9be2e23 100644
--- a/clippy_lints/src/methods/waker_clone_wake.rs
+++ b/clippy_lints/src/methods/waker_clone_wake.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::is_trait_method;
+use clippy_utils::source::snippet_with_applicability;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
diff --git a/clippy_lints/src/min_ident_chars.rs b/clippy_lints/src/min_ident_chars.rs
index c83e5198c2748..a99e21d938c64 100644
--- a/clippy_lints/src/min_ident_chars.rs
+++ b/clippy_lints/src/min_ident_chars.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_from_proc_macro;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{walk_item, walk_trait_item, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_item, walk_trait_item};
 use rustc_hir::{GenericParamKind, HirId, Item, ItemKind, ItemLocalId, Node, Pat, PatKind, TraitItem, UsePath};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs
index 3e80e48a9485d..408dbef9cb16a 100644
--- a/clippy_lints/src/misc.rs
+++ b/clippy_lints/src/misc.rs
@@ -2,8 +2,8 @@ use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir, span_lint_hir
 use clippy_utils::source::{snippet, snippet_with_context};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
-    fulfill_or_allowed, get_parent_expr, in_automatically_derived, is_lint_allowed, iter_input_pats, last_path_segment,
-    SpanlessEq,
+    SpanlessEq, fulfill_or_allowed, get_parent_expr, in_automatically_derived, is_lint_allowed, iter_input_pats,
+    last_path_segment,
 };
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
@@ -15,8 +15,8 @@ use rustc_hir::{
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::declare_lint_pass;
-use rustc_span::def_id::LocalDefId;
 use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
 
 use crate::ref_patterns::REF_PATTERNS;
 
diff --git a/clippy_lints/src/missing_assert_message.rs b/clippy_lints/src/missing_assert_message.rs
index a9ea11f4c2b06..86348f04600b8 100644
--- a/clippy_lints/src/missing_assert_message.rs
+++ b/clippy_lints/src/missing_assert_message.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_in_test;
-use clippy_utils::macros::{find_assert_args, find_assert_eq_args, root_macro_call_first_node, PanicExpn};
+use clippy_utils::macros::{PanicExpn, find_assert_args, find_assert_eq_args, root_macro_call_first_node};
 use rustc_hir::Expr;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
diff --git a/clippy_lints/src/missing_asserts_for_indexing.rs b/clippy_lints/src/missing_asserts_for_indexing.rs
index 94c91b095171f..b40d7eba15e5e 100644
--- a/clippy_lints/src/missing_asserts_for_indexing.rs
+++ b/clippy_lints/src/missing_asserts_for_indexing.rs
@@ -1,7 +1,7 @@
 use std::mem;
 use std::ops::ControlFlow;
 
-use clippy_utils::comparisons::{normalize_comparison, Rel};
+use clippy_utils::comparisons::{Rel, normalize_comparison};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use clippy_utils::visitors::for_each_expr_without_closures;
@@ -14,7 +14,7 @@ use rustc_hir::{BinOp, Block, Body, Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 use rustc_span::source_map::Spanned;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs
index 859afe1b9636e..eea0459e026e8 100644
--- a/clippy_lints/src/missing_const_for_fn.rs
+++ b/clippy_lints/src/missing_const_for_fn.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::qualify_min_const_fn::is_min_const_fn;
 use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, is_from_proc_macro, trait_ref_of_method};
@@ -11,8 +11,8 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
-use rustc_span::def_id::LocalDefId;
 use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
 use rustc_target::spec::abi::Abi;
 
 declare_clippy_lint! {
diff --git a/clippy_lints/src/missing_const_for_thread_local.rs b/clippy_lints/src/missing_const_for_thread_local.rs
index 954216038fb58..c2f524a635316 100644
--- a/clippy_lints/src/missing_const_for_thread_local.rs
+++ b/clippy_lints/src/missing_const_for_thread_local.rs
@@ -1,12 +1,12 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::macros::macro_backtrace;
 use clippy_utils::qualify_min_const_fn::is_min_const_fn;
 use clippy_utils::source::snippet;
 use clippy_utils::{fn_has_unsatisfiable_preds, peel_blocks};
 use rustc_errors::Applicability;
-use rustc_hir::{intravisit, Expr, ExprKind};
+use rustc_hir::{Expr, ExprKind, intravisit};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
 use rustc_span::sym::{self, thread_local_macro};
diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs
index 2166b0fe5a06d..64fc1a8a1a580 100644
--- a/clippy_lints/src/missing_doc.rs
+++ b/clippy_lints/src/missing_doc.rs
@@ -17,7 +17,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty::Visibility;
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::CRATE_DEF_ID;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/missing_fields_in_debug.rs b/clippy_lints/src/missing_fields_in_debug.rs
index 77595b121aadb..fc01b6753f1c7 100644
--- a/clippy_lints/src/missing_fields_in_debug.rs
+++ b/clippy_lints/src/missing_fields_in_debug.rs
@@ -3,7 +3,7 @@ use std::ops::ControlFlow;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_path_lang_item;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::visitors::{for_each_expr, Visitable};
+use clippy_utils::visitors::{Visitable, for_each_expr};
 use rustc_ast::LitKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind, Res};
@@ -13,7 +13,7 @@ use rustc_hir::{
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{Ty, TypeckResults};
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{Span, Symbol, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs
index 33a14d8b7fed3..d342be4545cea 100644
--- a/clippy_lints/src/missing_inline.rs
+++ b/clippy_lints/src/missing_inline.rs
@@ -3,7 +3,7 @@ use rustc_ast::ast;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs
index 0b7d97c32c5c8..d333b71edb1ae 100644
--- a/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::macros::root_macro_call_first_node;
 use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id};
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, LetStmt, Node, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
diff --git a/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/clippy_lints/src/multiple_unsafe_ops_per_block.rs
index 0bde0da3cd814..12bcc608174f2 100644
--- a/clippy_lints/src/multiple_unsafe_ops_per_block.rs
+++ b/clippy_lints/src/multiple_unsafe_ops_per_block.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::visitors::{for_each_expr, Descend, Visitable};
+use clippy_utils::visitors::{Descend, Visitable, for_each_expr};
 use core::ops::ControlFlow::Continue;
 use hir::def::{DefKind, Res};
 use hir::{BlockCheckMode, ExprKind, QPath, Safety, UnOp};
@@ -153,19 +153,16 @@ fn collect_unsafe_exprs<'tcx>(
             ExprKind::AssignOp(_, lhs, rhs) | ExprKind::Assign(lhs, rhs, _) => {
                 if matches!(
                     lhs.kind,
-                    ExprKind::Path(QPath::Resolved(
-                        _,
-                        hir::Path {
-                            res: Res::Def(
-                                DefKind::Static {
-                                    mutability: Mutability::Mut,
-                                    ..
-                                },
-                                _
-                            ),
-                            ..
-                        }
-                    ))
+                    ExprKind::Path(QPath::Resolved(_, hir::Path {
+                        res: Res::Def(
+                            DefKind::Static {
+                                mutability: Mutability::Mut,
+                                ..
+                            },
+                            _
+                        ),
+                        ..
+                    }))
                 ) {
                     unsafe_ops.push(("modification of a mutable static occurs here", expr.span));
                     collect_unsafe_exprs(cx, rhs, unsafe_ops);
diff --git a/clippy_lints/src/mut_key.rs b/clippy_lints/src/mut_key.rs
index f52b3a6a5a160..8118c14bd4a28 100644
--- a/clippy_lints/src/mut_key.rs
+++ b/clippy_lints/src/mut_key.rs
@@ -6,9 +6,9 @@ use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::impl_lint_pass;
+use rustc_span::Span;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::sym;
-use rustc_span::Span;
 use std::iter;
 
 declare_clippy_lint! {
diff --git a/clippy_lints/src/mutable_debug_assertion.rs b/clippy_lints/src/mutable_debug_assertion.rs
index 563ce2d82ea3c..6ab811b4f2f9b 100644
--- a/clippy_lints/src/mutable_debug_assertion.rs
+++ b/clippy_lints/src/mutable_debug_assertion.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::macros::{find_assert_eq_args, root_macro_call_first_node};
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 use rustc_hir::{BorrowKind, Expr, ExprKind, MatchSource, Mutability};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
diff --git a/clippy_lints/src/needless_arbitrary_self_type.rs b/clippy_lints/src/needless_arbitrary_self_type.rs
index 60c44382059a5..3c47d0edfdc5b 100644
--- a/clippy_lints/src/needless_arbitrary_self_type.rs
+++ b/clippy_lints/src/needless_arbitrary_self_type.rs
@@ -3,8 +3,8 @@ use rustc_ast::ast::{BindingMode, ByRef, Lifetime, Mutability, Param, PatKind, P
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::symbol::kw;
 use rustc_span::Span;
+use rustc_span::symbol::kw;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs
index df155a7a41257..2eacd6875d6b4 100644
--- a/clippy_lints/src/needless_bool.rs
+++ b/clippy_lints/src/needless_bool.rs
@@ -2,16 +2,16 @@ 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::{
-    get_parent_expr, higher, is_block_like, is_else_clause, is_expn_of, is_parent_stmt, is_receiver_of_method_call,
-    peel_blocks, peel_blocks_with_stmt, span_extract_comment, SpanlessEq,
+    SpanlessEq, get_parent_expr, higher, is_block_like, is_else_clause, is_expn_of, is_parent_stmt,
+    is_receiver_of_method_call, peel_blocks, peel_blocks_with_stmt, span_extract_comment,
 };
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::source_map::Spanned;
 use rustc_span::Span;
+use rustc_span::source_map::Spanned;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/needless_borrows_for_generic_args.rs b/clippy_lints/src/needless_borrows_for_generic_args.rs
index 32e7fde03b2c8..f6db12ed84e86 100644
--- a/clippy_lints/src/needless_borrows_for_generic_args.rs
+++ b/clippy_lints/src/needless_borrows_for_generic_args.rs
@@ -1,10 +1,10 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exactly_once, PossibleBorrowerMap};
+use clippy_utils::mir::{PossibleBorrowerMap, enclosing_mir, expr_local, local_assignments, used_exactly_once};
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::{implements_trait, is_copy};
-use clippy_utils::{expr_use_ctxt, peel_n_hir_expr_refs, DefinedTy, ExprUseNode};
+use clippy_utils::{DefinedTy, ExprUseNode, expr_use_ctxt, peel_n_hir_expr_refs};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
diff --git a/clippy_lints/src/needless_for_each.rs b/clippy_lints/src/needless_for_each.rs
index 6390e51f916b2..b54eb164e81d5 100644
--- a/clippy_lints/src/needless_for_each.rs
+++ b/clippy_lints/src/needless_for_each.rs
@@ -1,9 +1,9 @@
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 use rustc_hir::{Block, BlockCheckMode, Closure, Expr, ExprKind, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_trait_method;
diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs
index d543fd467abe7..19cbf59590840 100644
--- a/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -17,9 +17,9 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::{self, Ty, TyCtxt, UpvarId, UpvarPath};
 use rustc_session::impl_lint_pass;
+use rustc_span::Span;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::kw;
-use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
 declare_clippy_lint! {
diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs
index 887070bcf9af5..0775d7abdbb37 100644
--- a/clippy_lints/src/needless_pass_by_value.rs
+++ b/clippy_lints/src/needless_pass_by_value.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_self;
 use clippy_utils::ptr::get_spans;
-use clippy_utils::source::{snippet, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet};
 use clippy_utils::ty::{
     implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item,
 };
@@ -19,7 +19,7 @@ use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::kw;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::misc::type_allowed_to_implement_copy;
@@ -182,14 +182,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                 && !is_copy(cx, ty)
                 && ty.is_sized(cx.tcx, cx.param_env)
                 && !allowed_traits.iter().any(|&t| {
-                    implements_trait_with_env_from_iter(
-                        cx.tcx,
-                        cx.param_env,
-                        ty,
-                        t,
-                        None,
-                        [Option::<ty::GenericArg<'tcx>>::None],
-                    )
+                    implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, t, None, [Option::<
+                        ty::GenericArg<'tcx>,
+                    >::None])
                 })
                 && !implements_borrow_trait
                 && !all_borrowable_trait
diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs
index b181791699a5b..392cfcb813e85 100644
--- a/clippy_lints/src/no_effect.rs
+++ b/clippy_lints/src/no_effect.rs
@@ -7,8 +7,8 @@ use clippy_utils::{
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{
-    is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, HirId, HirIdMap, ItemKind, LocalSource, Node, PatKind,
-    Stmt, StmtKind, UnsafeSource,
+    BinOpKind, BlockCheckMode, Expr, ExprKind, HirId, HirIdMap, ItemKind, LocalSource, Node, PatKind, Stmt, StmtKind,
+    UnsafeSource, is_range_literal,
 };
 use rustc_infer::infer::TyCtxtInferExt as _;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs
index 25f547f1a43c0..5e20b40642607 100644
--- a/clippy_lints/src/non_copy_const.rs
+++ b/clippy_lints/src/non_copy_const.rs
@@ -4,7 +4,7 @@ use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_in_const_context;
 use clippy_utils::macros::macro_backtrace;
-use clippy_utils::ty::{implements_trait, InteriorMut};
+use clippy_utils::ty::{InteriorMut, implements_trait};
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{
@@ -15,7 +15,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, Span, DUMMY_SP};
+use rustc_span::{DUMMY_SP, Span, sym};
 use rustc_target::abi::VariantIdx;
 
 // FIXME: this is a correctness problem but there's no suitable
diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs
index 832518d2d35b4..d85032e9eee84 100644
--- a/clippy_lints/src/non_expressive_names.rs
+++ b/clippy_lints/src/non_expressive_names.rs
@@ -3,12 +3,12 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use rustc_ast::ast::{
     self, Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Item, ItemKind, Local, Pat, PatKind,
 };
-use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor};
+use rustc_ast::visit::{Visitor, walk_block, walk_expr, walk_pat};
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::impl_lint_pass;
 use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 use std::cmp::Ordering;
 
 declare_clippy_lint! {
diff --git a/clippy_lints/src/non_octal_unix_permissions.rs b/clippy_lints/src/non_octal_unix_permissions.rs
index cfc15d9271583..3f156aa551040 100644
--- a/clippy_lints/src/non_octal_unix_permissions.rs
+++ b/clippy_lints/src/non_octal_unix_permissions.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{snippet_with_applicability, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet_with_applicability};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/clippy_lints/src/nonstandard_macro_braces.rs b/clippy_lints/src/nonstandard_macro_braces.rs
index 51ba29d7389b9..a13391a59457a 100644
--- a/clippy_lints/src/nonstandard_macro_braces.rs
+++ b/clippy_lints/src/nonstandard_macro_braces.rs
@@ -1,5 +1,5 @@
-use clippy_config::types::MacroMatcher;
 use clippy_config::Conf;
+use clippy_config::types::MacroMatcher;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{SourceText, SpanRangeExt};
 use rustc_ast::ast;
@@ -8,8 +8,8 @@ use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::impl_lint_pass;
-use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::Span;
+use rustc_span::hygiene::{ExpnKind, MacroKind};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/only_used_in_recursion.rs b/clippy_lints/src/only_used_in_recursion.rs
index aadd729f32a45..372128ac16f0f 100644
--- a/clippy_lints/src/only_used_in_recursion.rs
+++ b/clippy_lints/src/only_used_in_recursion.rs
@@ -9,8 +9,8 @@ use rustc_hir::{Body, Expr, ExprKind, HirId, ImplItem, ImplItemKind, Node, PatKi
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, ConstKind, EarlyBinder, GenericArgKind, GenericArgsRef};
 use rustc_session::impl_lint_pass;
-use rustc_span::symbol::{kw, Ident};
 use rustc_span::Span;
+use rustc_span::symbol::{Ident, kw};
 use std::iter;
 
 declare_clippy_lint! {
diff --git a/clippy_lints/src/operators/absurd_extreme_comparisons.rs b/clippy_lints/src/operators/absurd_extreme_comparisons.rs
index a0de5ea711ca0..dbc9948eeedc7 100644
--- a/clippy_lints/src/operators/absurd_extreme_comparisons.rs
+++ b/clippy_lints/src/operators/absurd_extreme_comparisons.rs
@@ -2,7 +2,7 @@ use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 
-use clippy_utils::comparisons::{normalize_comparison, Rel};
+use clippy_utils::comparisons::{Rel, normalize_comparison};
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::source::snippet;
diff --git a/clippy_lints/src/operators/const_comparisons.rs b/clippy_lints/src/operators/const_comparisons.rs
index c131752439628..5d94cfab3b02a 100644
--- a/clippy_lints/src/operators/const_comparisons.rs
+++ b/clippy_lints/src/operators/const_comparisons.rs
@@ -7,12 +7,12 @@ use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::layout::HasTyCtxt;
 use rustc_middle::ty::{Ty, TypeckResults};
-use rustc_span::source_map::Spanned;
 use rustc_span::Span;
+use rustc_span::source_map::Spanned;
 
+use clippy_utils::SpanlessEq;
 use clippy_utils::diagnostics::span_lint_and_note;
 use clippy_utils::source::snippet;
-use clippy_utils::SpanlessEq;
 
 use super::{IMPOSSIBLE_COMPARISONS, REDUNDANT_COMPARISONS};
 
diff --git a/clippy_lints/src/operators/float_equality_without_abs.rs b/clippy_lints/src/operators/float_equality_without_abs.rs
index be97ad389bf60..34f7dbea84e49 100644
--- a/clippy_lints/src/operators/float_equality_without_abs.rs
+++ b/clippy_lints/src/operators/float_equality_without_abs.rs
@@ -6,7 +6,8 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::{sym, source_map::Spanned};
+use rustc_span::source_map::Spanned;
+use rustc_span::sym;
 
 use super::FLOAT_EQUALITY_WITHOUT_ABS;
 
diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs
index ae02d22512e31..6d9e75f51d66e 100644
--- a/clippy_lints/src/option_if_let_else.rs
+++ b/clippy_lints/src/option_if_let_else.rs
@@ -1,12 +1,12 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
-    can_move_expr_to_closure, eager_or_lazy, higher, is_else_clause, is_in_const_context, is_res_lang_ctor,
-    peel_blocks, peel_hir_expr_while, CaptureKind,
+    CaptureKind, can_move_expr_to_closure, eager_or_lazy, higher, is_else_clause, is_in_const_context,
+    is_res_lang_ctor, peel_blocks, peel_hir_expr_while,
 };
 use rustc_errors::Applicability;
-use rustc_hir::def::Res;
 use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
+use rustc_hir::def::Res;
 use rustc_hir::{Arm, BindingMode, Expr, ExprKind, MatchSource, Mutability, Pat, PatKind, Path, QPath, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
diff --git a/clippy_lints/src/panic_in_result_fn.rs b/clippy_lints/src/panic_in_result_fn.rs
index fa15d5e4f9f5a..eebc62e2a5a96 100644
--- a/clippy_lints/src/panic_in_result_fn.rs
+++ b/clippy_lints/src/panic_in_result_fn.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::root_macro_call_first_node;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::visitors::{Descend, for_each_expr};
 use clippy_utils::{is_inside_always_const_context, return_ty};
 use core::ops::ControlFlow;
 use rustc_hir as hir;
@@ -9,7 +9,7 @@ use rustc_hir::intravisit::FnKind;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs
index 5ca244f0141cb..75d8c09f2b08d 100644
--- a/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/clippy_lints/src/pass_by_ref_or_value.rs
@@ -18,7 +18,7 @@ use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, RegionKind, TyCtxt};
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 use rustc_target::spec::abi::Abi;
 
 declare_clippy_lint! {
diff --git a/clippy_lints/src/pathbuf_init_then_push.rs b/clippy_lints/src/pathbuf_init_then_push.rs
index d7fa48c1e38dd..1b9a5a4438297 100644
--- a/clippy_lints/src/pathbuf_init_then_push.rs
+++ b/clippy_lints/src/pathbuf_init_then_push.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::path_to_local_id;
-use clippy_utils::source::{snippet, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet};
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_ast::{LitKind, StrStyle};
 use rustc_errors::Applicability;
@@ -9,7 +9,7 @@ use rustc_hir::{BindingMode, Block, Expr, ExprKind, HirId, LetStmt, PatKind, QPa
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{Span, Symbol, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/pattern_type_mismatch.rs b/clippy_lints/src/pattern_type_mismatch.rs
index c1296b04387a0..42fbba8ef6dcd 100644
--- a/clippy_lints/src/pattern_type_mismatch.rs
+++ b/clippy_lints/src/pattern_type_mismatch.rs
@@ -1,13 +1,13 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_hir::{
-    intravisit, Body, Expr, ExprKind, FnDecl, LetExpr, LocalSource, Mutability, Pat, PatKind, Stmt, StmtKind,
+    Body, Expr, ExprKind, FnDecl, LetExpr, LocalSource, Mutability, Pat, PatKind, Stmt, StmtKind, intravisit,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
-use rustc_span::def_id::LocalDefId;
 use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs
index cd8e921347cc3..807636bb642b2 100644
--- a/clippy_lints/src/ptr.rs
+++ b/clippy_lints/src/ptr.rs
@@ -5,7 +5,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::hir_id::{HirId, HirIdMap};
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 use rustc_hir::{
     self as hir, AnonConst, BinOpKind, BindingMode, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg, ImplItemKind,
     ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, Safety, TraitFn, TraitItem, TraitItemKind, TyKind,
@@ -17,7 +17,7 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, Binder, ClauseKind, ExistentialPredicate, List, PredicateKind, Ty};
 use rustc_session::declare_lint_pass;
 use rustc_span::symbol::Symbol;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
diff --git a/clippy_lints/src/pub_underscore_fields.rs b/clippy_lints/src/pub_underscore_fields.rs
index 77b707567e4b4..db03657c9af43 100644
--- a/clippy_lints/src/pub_underscore_fields.rs
+++ b/clippy_lints/src/pub_underscore_fields.rs
@@ -1,5 +1,5 @@
-use clippy_config::types::PubUnderscoreFieldsBehaviour;
 use clippy_config::Conf;
+use clippy_config::types::PubUnderscoreFieldsBehaviour;
 use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::is_path_lang_item;
diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs
index e1e3ded2c795d..aa9a9001afb7b 100644
--- a/clippy_lints/src/question_mark.rs
+++ b/clippy_lints/src/question_mark.rs
@@ -1,8 +1,8 @@
 use crate::manual_let_else::MANUAL_LET_ELSE;
 use crate::question_mark_used::QUESTION_MARK_USED;
+use clippy_config::Conf;
 use clippy_config::msrvs::Msrv;
 use clippy_config::types::MatchLintBehaviour;
-use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
@@ -12,8 +12,8 @@ use clippy_utils::{
     span_contains_comment,
 };
 use rustc_errors::Applicability;
-use rustc_hir::def::Res;
 use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk};
+use rustc_hir::def::Res;
 use rustc_hir::{
     BindingMode, Block, Body, ByRef, Expr, ExprKind, LetStmt, Mutability, Node, PatKind, PathSegment, QPath, Stmt,
     StmtKind,
diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs
index 81189fe517c00..21cd33672624f 100644
--- a/clippy_lints/src/ranges.rs
+++ b/clippy_lints/src/ranges.rs
@@ -1,8 +1,8 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::source::{snippet, snippet_with_applicability, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{get_parent_expr, higher, is_in_const_context, is_integer_const, path_to_local};
 use rustc_ast::ast::RangeLimits;
@@ -11,8 +11,8 @@ use rustc_hir::{BinOpKind, Expr, ExprKind, HirId};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
-use rustc_span::source_map::Spanned;
 use rustc_span::Span;
+use rustc_span::source_map::Spanned;
 use std::cmp::Ordering;
 
 declare_clippy_lint! {
diff --git a/clippy_lints/src/rc_clone_in_vec_init.rs b/clippy_lints/src/rc_clone_in_vec_init.rs
index d0b45b59526fc..e877f5d6ed432 100644
--- a/clippy_lints/src/rc_clone_in_vec_init.rs
+++ b/clippy_lints/src/rc_clone_in_vec_init.rs
@@ -8,7 +8,7 @@ use rustc_hir::{Expr, ExprKind, QPath, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{Span, Symbol, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/read_zero_byte_vec.rs b/clippy_lints/src/read_zero_byte_vec.rs
index 7f4735c6a889b..6bd68dd4109d4 100644
--- a/clippy_lints/src/read_zero_byte_vec.rs
+++ b/clippy_lints/src/read_zero_byte_vec.rs
@@ -1,13 +1,13 @@
 use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
 use clippy_utils::get_enclosing_block;
-use clippy_utils::higher::{get_vec_init_kind, VecInitKind};
+use clippy_utils::higher::{VecInitKind, get_vec_init_kind};
 use clippy_utils::source::snippet;
 
 use hir::{Expr, ExprKind, HirId, LetStmt, PatKind, PathSegment, QPath, StmtKind};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 
diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs
index 4e24ddad83a56..b9e0106fc86b3 100644
--- a/clippy_lints/src/redundant_clone.rs
+++ b/clippy_lints/src/redundant_clone.rs
@@ -1,17 +1,17 @@
 use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
-use clippy_utils::mir::{visit_local_usage, LocalUsage, PossibleBorrowerMap};
+use clippy_utils::fn_has_unsatisfiable_preds;
+use clippy_utils::mir::{LocalUsage, PossibleBorrowerMap, visit_local_usage};
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, is_type_lang_item, walk_ptrs_ty_depth};
-use clippy_utils::fn_has_unsatisfiable_preds;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
-use rustc_hir::{def_id, Body, FnDecl, LangItem};
+use rustc_hir::{Body, FnDecl, LangItem, def_id};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, BytePos, Span};
+use rustc_span::{BytePos, Span, sym};
 
 macro_rules! unwrap_or_continue {
     ($x:expr) => {
@@ -349,14 +349,10 @@ fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>,
             local_use_locs: _,
             local_consume_or_mutate_locs: clone_consume_or_mutate_locs,
         },
-    )) = visit_local_usage(
-        &[cloned, clone],
-        mir,
-        mir::Location {
-            block: bb,
-            statement_index: mir.basic_blocks[bb].statements.len(),
-        },
-    )
+    )) = visit_local_usage(&[cloned, clone], mir, mir::Location {
+        block: bb,
+        statement_index: mir.basic_blocks[bb].statements.len(),
+    })
     .map(|mut vec| (vec.remove(0), vec.remove(0)))
     {
         CloneUsage {
diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs
index bad9b979203f9..6930a01d48be4 100644
--- a/clippy_lints/src/redundant_closure_call.rs
+++ b/clippy_lints/src/redundant_closure_call.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor};
 use rustc_hir::{
-    intravisit as hir_visit, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, ExprKind, Node,
+    ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, ExprKind, Node, intravisit as hir_visit,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::nested_filter;
diff --git a/clippy_lints/src/redundant_else.rs b/clippy_lints/src/redundant_else.rs
index 3bdf13dbbea65..6a1d40334e755 100644
--- a/clippy_lints/src/redundant_else.rs
+++ b/clippy_lints/src/redundant_else.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_ast::ast::{Block, Expr, ExprKind, Stmt, StmtKind};
-use rustc_ast::visit::{walk_expr, Visitor};
+use rustc_ast::visit::{Visitor, walk_expr};
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::declare_lint_pass;
diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs
index 0e637538615e1..d0dbff081f905 100644
--- a/clippy_lints/src/redundant_field_names.rs
+++ b/clippy_lints/src/redundant_field_names.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use rustc_ast::ast::{Expr, ExprKind};
 use rustc_errors::Applicability;
diff --git a/clippy_lints/src/redundant_locals.rs b/clippy_lints/src/redundant_locals.rs
index d94ca5bc7ec2c..4f46ca3c71505 100644
--- a/clippy_lints/src/redundant_locals.rs
+++ b/clippy_lints/src/redundant_locals.rs
@@ -9,8 +9,8 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::UpvarCapture;
 use rustc_session::declare_lint_pass;
-use rustc_span::symbol::Ident;
 use rustc_span::DesugaringKind;
+use rustc_span::symbol::Ident;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/redundant_static_lifetimes.rs b/clippy_lints/src/redundant_static_lifetimes.rs
index d6e741dd974b7..b27bb2e78afed 100644
--- a/clippy_lints/src/redundant_static_lifetimes.rs
+++ b/clippy_lints/src/redundant_static_lifetimes.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use rustc_ast::ast::{ConstItem, Item, ItemKind, StaticItem, Ty, TyKind};
diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs
index 2b4ef21fc48e1..4bff37216eda8 100644
--- a/clippy_lints/src/reference.rs
+++ b/clippy_lints/src/reference.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{snippet_with_applicability, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet_with_applicability};
 use rustc_ast::ast::{Expr, ExprKind, Mutability, UnOp};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
diff --git a/clippy_lints/src/repeat_vec_with_capacity.rs b/clippy_lints/src/repeat_vec_with_capacity.rs
index 08de10f69b059..f54cafffb83c9 100644
--- a/clippy_lints/src/repeat_vec_with_capacity.rs
+++ b/clippy_lints/src/repeat_vec_with_capacity.rs
@@ -8,7 +8,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/reserve_after_initialization.rs b/clippy_lints/src/reserve_after_initialization.rs
index caf3fb8707da3..6157adad059cd 100644
--- a/clippy_lints/src/reserve_after_initialization.rs
+++ b/clippy_lints/src/reserve_after_initialization.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::higher::{get_vec_init_kind, VecInitKind};
+use clippy_utils::higher::{VecInitKind, get_vec_init_kind};
 use clippy_utils::source::snippet;
 use clippy_utils::{is_from_proc_macro, path_to_local_id};
 use rustc_errors::Applicability;
diff --git a/clippy_lints/src/return_self_not_must_use.rs b/clippy_lints/src/return_self_not_must_use.rs
index 5962e8be9594b..42d9cf2c88c16 100644
--- a/clippy_lints/src/return_self_not_must_use.rs
+++ b/clippy_lints/src/return_self_not_must_use.rs
@@ -7,7 +7,7 @@ use rustc_hir::{Body, FnDecl, OwnerId, TraitItem, TraitItemKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs
index 1e7096496957f..3754fdddedfd1 100644
--- a/clippy_lints/src/returns.rs
+++ b/clippy_lints/src/returns.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
-use clippy_utils::source::{snippet_with_context, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet_with_context};
 use clippy_utils::sugg::has_enclosing_paren;
-use clippy_utils::visitors::{for_each_expr, for_each_unconsumed_temporary, Descend};
+use clippy_utils::visitors::{Descend, for_each_expr, for_each_unconsumed_temporary};
 use clippy_utils::{
     binary_expr_needs_parentheses, 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,
@@ -9,8 +9,8 @@ use clippy_utils::{
 use core::ops::ControlFlow;
 use rustc_ast::NestedMetaItem;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::FnKind;
 use rustc_hir::LangItem::ResultErr;
+use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
     Block, Body, Expr, ExprKind, FnDecl, HirId, ItemKind, LangItem, MatchSource, Node, OwnerNode, PatKind, QPath, Stmt,
     StmtKind,
@@ -21,7 +21,7 @@ use rustc_middle::ty::adjustment::Adjust;
 use rustc_middle::ty::{self, GenericArgKind, Ty};
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, BytePos, Pos, Span};
+use rustc_span::{BytePos, Pos, Span, sym};
 use std::borrow::Cow;
 use std::fmt::Display;
 
diff --git a/clippy_lints/src/same_name_method.rs b/clippy_lints/src/same_name_method.rs
index 508f3ae6def02..8d31641d4836c 100644
--- a/clippy_lints/src/same_name_method.rs
+++ b/clippy_lints/src/same_name_method.rs
@@ -5,8 +5,8 @@ use rustc_hir::{HirId, Impl, ItemKind, Node, Path, QPath, TraitRef, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::AssocKind;
 use rustc_session::declare_lint_pass;
-use rustc_span::symbol::Symbol;
 use rustc_span::Span;
+use rustc_span::symbol::Symbol;
 use std::collections::{BTreeMap, BTreeSet};
 
 declare_clippy_lint! {
@@ -62,13 +62,10 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
                 && let TyKind::Path(QPath::Resolved(_, Path { res, .. })) = self_ty.kind
             {
                 if !map.contains_key(res) {
-                    map.insert(
-                        *res,
-                        ExistingName {
-                            impl_methods: BTreeMap::new(),
-                            trait_methods: BTreeMap::new(),
-                        },
-                    );
+                    map.insert(*res, ExistingName {
+                        impl_methods: BTreeMap::new(),
+                        trait_methods: BTreeMap::new(),
+                    });
                 }
                 let existing_name = map.get_mut(res).unwrap();
 
diff --git a/clippy_lints/src/set_contains_or_insert.rs b/clippy_lints/src/set_contains_or_insert.rs
index bc2a71c42b9f8..1185d67b1258b 100644
--- a/clippy_lints/src/set_contains_or_insert.rs
+++ b/clippy_lints/src/set_contains_or_insert.rs
@@ -3,12 +3,12 @@ use std::ops::ControlFlow;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::for_each_expr;
-use clippy_utils::{higher, peel_hir_expr_while, SpanlessEq};
+use clippy_utils::{SpanlessEq, higher, peel_hir_expr_while};
 use rustc_hir::{Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 use rustc_span::symbol::Symbol;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs
index 979d6dc77aede..d1114cb29f7a3 100644
--- a/clippy_lints/src/significant_drop_tightening.rs
+++ b/clippy_lints/src/significant_drop_tightening.rs
@@ -4,13 +4,13 @@ use clippy_utils::{expr_or_init, get_attr, path_to_local, peel_hir_expr_unary};
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 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;
 use rustc_span::symbol::Ident;
-use rustc_span::{sym, Span, DUMMY_SP};
+use rustc_span::{DUMMY_SP, Span, sym};
 use std::borrow::Cow;
 use std::collections::hash_map::Entry;
 
diff --git a/clippy_lints/src/single_component_path_imports.rs b/clippy_lints/src/single_component_path_imports.rs
index acf44a9bb5ab4..c986c3e8aa6e8 100644
--- a/clippy_lints/src/single_component_path_imports.rs
+++ b/clippy_lints/src/single_component_path_imports.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
 use rustc_ast::node_id::{NodeId, NodeMap};
 use rustc_ast::ptr::P;
-use rustc_ast::visit::{walk_expr, Visitor};
+use rustc_ast::visit::{Visitor, walk_expr};
 use rustc_ast::{Crate, Expr, ExprKind, Item, ItemKind, MacroDef, ModKind, Ty, TyKind, UseTreeKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs
index 04c16281ec4be..5129bbf26655e 100644
--- a/clippy_lints/src/slow_vector_initialization.rs
+++ b/clippy_lints/src/slow_vector_initialization.rs
@@ -2,11 +2,10 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::matching_root_macro_call;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
-    get_enclosing_block, is_integer_literal, is_path_diagnostic_item, path_to_local,
-    path_to_local_id, SpanlessEq,
+    SpanlessEq, get_enclosing_block, is_integer_literal, is_path_diagnostic_item, path_to_local, path_to_local_id,
 };
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_stmt};
 use rustc_hir::{BindingMode, Block, Expr, ExprKind, HirId, PatKind, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs
index 44283a49e84b9..8dd9985879323 100644
--- a/clippy_lints/src/std_instead_of_core.rs
+++ b/clippy_lints/src/std_instead_of_core.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::Msrv;
 use clippy_config::Conf;
+use clippy_config::msrvs::Msrv;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_from_proc_macro;
 use rustc_attr::{StabilityLevel, StableSince};
@@ -11,7 +11,7 @@ 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, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/string_patterns.rs b/clippy_lints/src/string_patterns.rs
index 8af50ca87d631..ba2ddac2ec339 100644
--- a/clippy_lints/src/string_patterns.rs
+++ b/clippy_lints/src/string_patterns.rs
@@ -1,13 +1,13 @@
 use std::ops::ControlFlow;
 
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::eager_or_lazy::switch_to_eager_eval;
 use clippy_utils::macros::matching_root_macro_call;
 use clippy_utils::path_to_local_id;
 use clippy_utils::source::{snippet, str_literal_to_char_literal};
-use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::visitors::{Descend, for_each_expr};
 use itertools::Itertools;
 use rustc_ast::{BinOpKind, LitKind};
 use rustc_errors::Applicability;
@@ -15,7 +15,7 @@ use rustc_hir::{Expr, ExprKind, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs
index 6ca4ca000e9b4..1fb82b66ab85f 100644
--- a/clippy_lints/src/strings.rs
+++ b/clippy_lints/src/strings.rs
@@ -2,8 +2,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_the
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::ty::is_type_lang_item;
 use clippy_utils::{
-    get_expr_use_or_unification_node, get_parent_expr, is_lint_allowed, is_path_diagnostic_item, method_calls,
-    peel_blocks, SpanlessEq,
+    SpanlessEq, get_expr_use_or_unification_node, get_parent_expr, is_lint_allowed, is_path_diagnostic_item,
+    method_calls, peel_blocks,
 };
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
diff --git a/clippy_lints/src/suspicious_operation_groupings.rs b/clippy_lints/src/suspicious_operation_groupings.rs
index 1c1de805db0c6..be32dc0aab0b6 100644
--- a/clippy_lints/src/suspicious_operation_groupings.rs
+++ b/clippy_lints/src/suspicious_operation_groupings.rs
@@ -1,4 +1,4 @@
-use clippy_utils::ast_utils::{eq_id, is_useless_with_eq_exprs, IdentIter};
+use clippy_utils::ast_utils::{IdentIter, eq_id, is_useless_with_eq_exprs};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use core::ops::{Add, AddAssign};
@@ -7,9 +7,9 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::declare_lint_pass;
+use rustc_span::Span;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::Ident;
-use rustc_span::Span;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs
index 744d6392e065c..e9779d437d432 100644
--- a/clippy_lints/src/suspicious_trait_impl.rs
+++ b/clippy_lints/src/suspicious_trait_impl.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::visitors::for_each_expr_without_closures;
-use clippy_utils::{binop_traits, trait_ref_of_method, BINOP_TRAITS, OP_ASSIGN_TRAITS};
+use clippy_utils::{BINOP_TRAITS, OP_ASSIGN_TRAITS, binop_traits, trait_ref_of_method};
 use core::ops::ControlFlow;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs
index 197011cde3a1a..e05fa4095b8e3 100644
--- a/clippy_lints/src/swap.rs
+++ b/clippy_lints/src/swap.rs
@@ -6,7 +6,7 @@ use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{can_mut_borrow_both, eq_expr_value, is_in_const_context, std_or_core};
 use itertools::Itertools;
 
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 
 use crate::FxHashSet;
 use rustc_errors::Applicability;
@@ -17,7 +17,7 @@ use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::Ident;
-use rustc_span::{sym, Span, SyntaxContext};
+use rustc_span::{Span, SyntaxContext, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/swap_ptr_to_ref.rs b/clippy_lints/src/swap_ptr_to_ref.rs
index 20e9608a15dc8..8c5cf93ab6e80 100644
--- a/clippy_lints/src/swap_ptr_to_ref.rs
+++ b/clippy_lints/src/swap_ptr_to_ref.rs
@@ -5,7 +5,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span, SyntaxContext};
+use rustc_span::{Span, SyntaxContext, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/tests_outside_test_module.rs b/clippy_lints/src/tests_outside_test_module.rs
index 25d0a16e2ab45..3cd4fefffadf3 100644
--- a/clippy_lints/src/tests_outside_test_module.rs
+++ b/clippy_lints/src/tests_outside_test_module.rs
@@ -4,8 +4,8 @@ use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, FnDecl};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::def_id::LocalDefId;
 use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/to_digit_is_some.rs b/clippy_lints/src/to_digit_is_some.rs
index dafe9e38818f5..4f96a566b63c2 100644
--- a/clippy_lints/src/to_digit_is_some.rs
+++ b/clippy_lints/src/to_digit_is_some.rs
@@ -56,11 +56,13 @@ impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome {
                         && let hir::ExprKind::Path(to_digits_path) = &to_digits_call.kind
                         && let to_digits_call_res = cx.qpath_res(to_digits_path, to_digits_call.hir_id)
                         && let Some(to_digits_def_id) = to_digits_call_res.opt_def_id()
-                        && match_def_path(
-                            cx,
-                            to_digits_def_id,
-                            &["core", "char", "methods", "<impl char>", "to_digit"],
-                        )
+                        && match_def_path(cx, to_digits_def_id, &[
+                            "core",
+                            "char",
+                            "methods",
+                            "<impl char>",
+                            "to_digit",
+                        ])
                     {
                         Some((false, char_arg, radix_arg))
                     } else {
diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs
index 2e87d36df3121..00277593622aa 100644
--- a/clippy_lints/src/trait_bounds.rs
+++ b/clippy_lints/src/trait_bounds.rs
@@ -1,8 +1,8 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
-use clippy_utils::source::{snippet, snippet_with_applicability, SpanRangeExt};
-use clippy_utils::{is_from_proc_macro, SpanlessEq, SpanlessHash};
+use clippy_utils::source::{SpanRangeExt, snippet, snippet_with_applicability};
+use clippy_utils::{SpanlessEq, SpanlessHash, is_from_proc_macro};
 use core::hash::{Hash, Hasher};
 use itertools::Itertools;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs
index ced53a808f9e3..25fec9f688ca3 100644
--- a/clippy_lints/src/transmute/mod.rs
+++ b/clippy_lints/src/transmute/mod.rs
@@ -19,8 +19,8 @@ mod useless_transmute;
 mod utils;
 mod wrong_transmute;
 
-use clippy_config::msrvs::Msrv;
 use clippy_config::Conf;
+use clippy_config::msrvs::Msrv;
 use clippy_utils::is_in_const_context;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
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 ba8c7d6bfcb40..fca332dba401a 100644
--- a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
+++ b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
@@ -6,8 +6,8 @@ use rustc_errors::Applicability;
 use rustc_hir::{Expr, Node};
 use rustc_hir_typeck::cast::check_cast;
 use rustc_lint::LateContext;
-use rustc_middle::ty::cast::CastKind;
 use rustc_middle::ty::Ty;
+use rustc_middle::ty::cast::CastKind;
 
 /// Checks for `transmutes_expressible_as_ptr_casts` lint.
 /// Returns `true` if it's triggered, otherwise returns `false`.
diff --git a/clippy_lints/src/transmute/unsound_collection_transmute.rs b/clippy_lints/src/transmute/unsound_collection_transmute.rs
index 35e9383076606..f46e95b0b8329 100644
--- a/clippy_lints/src/transmute/unsound_collection_transmute.rs
+++ b/clippy_lints/src/transmute/unsound_collection_transmute.rs
@@ -1,5 +1,5 @@
-use super::utils::is_layout_incompatible;
 use super::UNSOUND_COLLECTION_TRANSMUTE;
+use super::utils::is_layout_incompatible;
 use clippy_utils::diagnostics::span_lint;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
diff --git a/clippy_lints/src/tuple_array_conversions.rs b/clippy_lints/src/tuple_array_conversions.rs
index 1d0de9327546f..3da8a449a7c58 100644
--- a/clippy_lints/src/tuple_array_conversions.rs
+++ b/clippy_lints/src/tuple_array_conversions.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::visitors::for_each_local_use_after_expr;
 use clippy_utils::{is_from_proc_macro, path_to_local};
diff --git a/clippy_lints/src/types/box_collection.rs b/clippy_lints/src/types/box_collection.rs
index 9ac73394548c7..24fe4e08a5b44 100644
--- a/clippy_lints/src/types/box_collection.rs
+++ b/clippy_lints/src/types/box_collection.rs
@@ -3,7 +3,7 @@ use clippy_utils::{path_def_id, qpath_generic_tys};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, QPath};
 use rustc_lint::LateContext;
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
 
 use super::BOX_COLLECTION;
 
diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs
index 120d5ffbbd33f..363aea8be72e9 100644
--- a/clippy_lints/src/types/mod.rs
+++ b/clippy_lints/src/types/mod.rs
@@ -18,8 +18,8 @@ use rustc_hir::{
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
-use rustc_span::def_id::LocalDefId;
 use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -386,30 +386,22 @@ impl<'tcx> LateLintPass<'tcx> for Types {
 
         let is_exported = cx.effective_visibilities.is_exported(def_id);
 
-        self.check_fn_decl(
-            cx,
-            decl,
-            CheckTyContext {
-                is_in_trait_impl,
-                is_exported,
-                in_body: matches!(fn_kind, FnKind::Closure),
-                ..CheckTyContext::default()
-            },
-        );
+        self.check_fn_decl(cx, decl, CheckTyContext {
+            is_in_trait_impl,
+            is_exported,
+            in_body: matches!(fn_kind, FnKind::Closure),
+            ..CheckTyContext::default()
+        });
     }
 
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
         let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
 
         match item.kind {
-            ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _, _) => self.check_ty(
-                cx,
-                ty,
-                CheckTyContext {
-                    is_exported,
-                    ..CheckTyContext::default()
-                },
-            ),
+            ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _, _) => self.check_ty(cx, ty, CheckTyContext {
+                is_exported,
+                ..CheckTyContext::default()
+            }),
             // functions, enums, structs, impls and traits are covered
             _ => (),
         }
@@ -427,14 +419,10 @@ impl<'tcx> LateLintPass<'tcx> for Types {
                     false
                 };
 
-                self.check_ty(
-                    cx,
-                    ty,
-                    CheckTyContext {
-                        is_in_trait_impl,
-                        ..CheckTyContext::default()
-                    },
-                );
+                self.check_ty(cx, ty, CheckTyContext {
+                    is_in_trait_impl,
+                    ..CheckTyContext::default()
+                });
             },
             // Methods are covered by check_fn.
             // Type aliases are ignored because oftentimes it's impossible to
@@ -450,14 +438,10 @@ impl<'tcx> LateLintPass<'tcx> for Types {
 
         let is_exported = cx.effective_visibilities.is_exported(field.def_id);
 
-        self.check_ty(
-            cx,
-            field.ty,
-            CheckTyContext {
-                is_exported,
-                ..CheckTyContext::default()
-            },
-        );
+        self.check_ty(cx, field.ty, CheckTyContext {
+            is_exported,
+            ..CheckTyContext::default()
+        });
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'tcx>) {
@@ -485,14 +469,10 @@ impl<'tcx> LateLintPass<'tcx> for Types {
 
     fn check_local(&mut self, cx: &LateContext<'tcx>, local: &LetStmt<'tcx>) {
         if let Some(ty) = local.ty {
-            self.check_ty(
-                cx,
-                ty,
-                CheckTyContext {
-                    in_body: true,
-                    ..CheckTyContext::default()
-                },
-            );
+            self.check_ty(cx, ty, CheckTyContext {
+                in_body: true,
+                ..CheckTyContext::default()
+            });
         }
     }
 }
diff --git a/clippy_lints/src/types/redundant_allocation.rs b/clippy_lints/src/types/redundant_allocation.rs
index 0801eace4fcfd..1a656088b1747 100644
--- a/clippy_lints/src/types/redundant_allocation.rs
+++ b/clippy_lints/src/types/redundant_allocation.rs
@@ -9,7 +9,7 @@ use rustc_lint::LateContext;
 use rustc_middle::ty::TypeVisitableExt;
 use rustc_span::symbol::sym;
 
-use super::{utils, REDUNDANT_ALLOCATION};
+use super::{REDUNDANT_ALLOCATION, utils};
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath: &QPath<'tcx>, def_id: DefId) -> bool {
     let mut applicability = Applicability::MaybeIncorrect;
diff --git a/clippy_lints/src/types/type_complexity.rs b/clippy_lints/src/types/type_complexity.rs
index 7fcfd5c8f350d..0b64fddb447b5 100644
--- a/clippy_lints/src/types/type_complexity.rs
+++ b/clippy_lints/src/types/type_complexity.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint;
 use rustc_hir as hir;
-use rustc_hir::intravisit::{walk_inf, walk_ty, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_inf, walk_ty};
 use rustc_hir::{GenericParamKind, TyKind};
 use rustc_lint::LateContext;
 use rustc_target::spec::abi::Abi;
diff --git a/clippy_lints/src/types/vec_box.rs b/clippy_lints/src/types/vec_box.rs
index 29996a6f783e1..230239335c65f 100644
--- a/clippy_lints/src/types/vec_box.rs
+++ b/clippy_lints/src/types/vec_box.rs
@@ -6,8 +6,8 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, GenericArg, LangItem, QPath, TyKind};
 use rustc_hir_analysis::lower_ty;
 use rustc_lint::LateContext;
-use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::TypeVisitableExt;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_span::symbol::sym;
 
 use super::VEC_BOX;
diff --git a/clippy_lints/src/unconditional_recursion.rs b/clippy_lints/src/unconditional_recursion.rs
index 42100e1d755c7..3fc08e8192d4c 100644
--- a/clippy_lints/src/unconditional_recursion.rs
+++ b/clippy_lints/src/unconditional_recursion.rs
@@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit::{walk_body, walk_expr, FnKind, Visitor};
+use rustc_hir::intravisit::{FnKind, Visitor, walk_body, walk_expr};
 use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, Item, ItemKind, Node, QPath, TyKind};
 use rustc_hir_analysis::lower_ty;
 use rustc_lint::{LateContext, LateLintPass};
@@ -13,8 +13,8 @@ use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, AssocKind, Ty, TyCtxt};
 use rustc_session::impl_lint_pass;
-use rustc_span::symbol::{kw, Ident};
-use rustc_span::{sym, Span};
+use rustc_span::symbol::{Ident, kw};
+use rustc_span::{Span, sym};
 use rustc_trait_selection::error_reporting::traits::suggestions::ReturnsVisitor;
 use std::ops::ControlFlow;
 
@@ -257,13 +257,10 @@ fn is_default_method_on_current_ty<'tcx>(tcx: TyCtxt<'tcx>, qpath: QPath<'tcx>,
             }
             if matches!(
                 ty.kind,
-                TyKind::Path(QPath::Resolved(
-                    _,
-                    hir::Path {
-                        res: Res::SelfTyAlias { .. },
-                        ..
-                    },
-                ))
+                TyKind::Path(QPath::Resolved(_, hir::Path {
+                    res: Res::SelfTyAlias { .. },
+                    ..
+                },))
             ) {
                 return true;
             }
diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs
index f51c5f74d9930..44eb0a6c593da 100644
--- a/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -4,12 +4,12 @@ use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_lint_allowed;
 use clippy_utils::source::walk_span_to_context;
-use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::visitors::{Descend, for_each_expr};
 use hir::HirId;
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
 use rustc_hir::{Block, BlockCheckMode, ItemKind, Node, UnsafeSource};
-use rustc_lexer::{tokenize, TokenKind};
+use rustc_lexer::{TokenKind, tokenize};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::impl_lint_pass;
diff --git a/clippy_lints/src/uninhabited_references.rs b/clippy_lints/src/uninhabited_references.rs
index 88039372ebd2c..cfa565cf80379 100644
--- a/clippy_lints/src/uninhabited_references.rs
+++ b/clippy_lints/src/uninhabited_references.rs
@@ -5,8 +5,8 @@ use rustc_hir_analysis::lower_ty;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::declare_lint_pass;
-use rustc_span::def_id::LocalDefId;
 use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/uninit_vec.rs b/clippy_lints/src/uninit_vec.rs
index 9ffcfcc0f50cb..93ed15777e015 100644
--- a/clippy_lints/src/uninit_vec.rs
+++ b/clippy_lints/src/uninit_vec.rs
@@ -1,13 +1,13 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
-use clippy_utils::higher::{get_vec_init_kind, VecInitKind};
+use clippy_utils::higher::{VecInitKind, get_vec_init_kind};
 use clippy_utils::ty::{is_type_diagnostic_item, is_uninit_value_valid_for_ty};
-use clippy_utils::{is_integer_literal, is_lint_allowed, path_to_local_id, peel_hir_expr_while, SpanlessEq};
+use clippy_utils::{SpanlessEq, is_integer_literal, is_lint_allowed, path_to_local_id, peel_hir_expr_while};
 use rustc_hir::{Block, Expr, ExprKind, HirId, PatKind, PathSegment, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 // TODO: add `ReadBuf` (RFC 2930) in "How to fix" once it is available in std
 declare_clippy_lint! {
diff --git a/clippy_lints/src/unit_return_expecting_ord.rs b/clippy_lints/src/unit_return_expecting_ord.rs
index a8cc2f9796339..87478a120dd0b 100644
--- a/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/clippy_lints/src/unit_return_expecting_ord.rs
@@ -5,7 +5,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_middle::ty::{ClauseKind, GenericPredicates, ProjectionPredicate, TraitPredicate};
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, BytePos, Span};
+use rustc_span::{BytePos, Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/unit_types/let_unit_value.rs b/clippy_lints/src/unit_types/let_unit_value.rs
index 80b661a757c21..bf2d75ea1a963 100644
--- a/clippy_lints/src/unit_types/let_unit_value.rs
+++ b/clippy_lints/src/unit_types/let_unit_value.rs
@@ -4,7 +4,7 @@ use clippy_utils::visitors::{for_each_local_assignment, for_each_value_source, i
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{walk_body, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_body};
 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};
diff --git a/clippy_lints/src/unit_types/unit_arg.rs b/clippy_lints/src/unit_types/unit_arg.rs
index 978d49f09c3a8..41b2ca5d268c2 100644
--- a/clippy_lints/src/unit_types/unit_arg.rs
+++ b/clippy_lints/src/unit_types/unit_arg.rs
@@ -1,11 +1,11 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_from_proc_macro;
-use clippy_utils::source::{indent_of, reindent_multiline, SourceText, SpanRangeExt};
+use clippy_utils::source::{SourceText, SpanRangeExt, indent_of, reindent_multiline};
 use rustc_errors::Applicability;
 use rustc_hir::{Block, Expr, ExprKind, MatchSource, Node, StmtKind};
 use rustc_lint::LateContext;
 
-use super::{utils, UNIT_ARG};
+use super::{UNIT_ARG, utils};
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
     if expr.span.from_expansion() {
diff --git a/clippy_lints/src/unnecessary_wraps.rs b/clippy_lints/src/unnecessary_wraps.rs
index 080efe983c2a8..937e35dea96d9 100644
--- a/clippy_lints/src/unnecessary_wraps.rs
+++ b/clippy_lints/src/unnecessary_wraps.rs
@@ -4,15 +4,15 @@ use clippy_utils::source::snippet;
 use clippy_utils::visitors::find_all_ret_expressions;
 use clippy_utils::{contains_return, is_res_lang_ctor, path_res, return_ty};
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::FnKind;
 use rustc_hir::LangItem::{OptionSome, ResultOk};
+use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, ExprKind, FnDecl, Impl, ItemKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
+use rustc_span::Span;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::sym;
-use rustc_span::Span;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs
index 98f0be3135dba..104be63bb1579 100644
--- a/clippy_lints/src/unnested_or_patterns.rs
+++ b/clippy_lints/src/unnested_or_patterns.rs
@@ -1,14 +1,14 @@
 #![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
 
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_maybe_qself, eq_pat, eq_path};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::over;
+use rustc_ast::PatKind::*;
 use rustc_ast::mut_visit::*;
 use rustc_ast::ptr::P;
-use rustc_ast::PatKind::*;
-use rustc_ast::{self as ast, Mutability, Pat, PatKind, DUMMY_NODE_ID};
+use rustc_ast::{self as ast, DUMMY_NODE_ID, Mutability, Pat, PatKind};
 use rustc_ast_pretty::pprust;
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
@@ -16,7 +16,7 @@ use rustc_session::impl_lint_pass;
 use rustc_span::DUMMY_SP;
 use std::cell::Cell;
 use std::mem;
-use thin_vec::{thin_vec, ThinVec};
+use thin_vec::{ThinVec, thin_vec};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs
index 309eaedac8d29..e70d2a2dafeea 100644
--- a/clippy_lints/src/unsafe_removed_from_name.rs
+++ b/clippy_lints/src/unsafe_removed_from_name.rs
@@ -2,8 +2,8 @@ use clippy_utils::diagnostics::span_lint;
 use rustc_ast::ast::{Item, ItemKind, UseTree, UseTreeKind};
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::symbol::Ident;
 use rustc_span::Span;
+use rustc_span::symbol::Ident;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/unused_async.rs b/clippy_lints/src/unused_async.rs
index 738fba54fa83f..a1f08cf6623bc 100644
--- a/clippy_lints/src/unused_async.rs
+++ b/clippy_lints/src/unused_async.rs
@@ -1,13 +1,13 @@
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::is_def_id_trait_method;
 use rustc_hir::def::DefKind;
-use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor};
+use rustc_hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn};
 use rustc_hir::{Body, Expr, ExprKind, FnDecl, Node, YieldSource};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
 use rustc_session::impl_lint_pass;
-use rustc_span::def_id::{LocalDefId, LocalDefIdSet};
 use rustc_span::Span;
+use rustc_span::def_id::{LocalDefId, LocalDefIdSet};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs
index af7abd009d250..d2a21b11ef47d 100644
--- a/clippy_lints/src/unused_io_amount.rs
+++ b/clippy_lints/src/unused_io_amount.rs
@@ -5,7 +5,7 @@ use hir::{ExprKind, HirId, PatKind};
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/unused_peekable.rs b/clippy_lints/src/unused_peekable.rs
index 86a811e17ca93..71aa57e0a14c2 100644
--- a/clippy_lints/src/unused_peekable.rs
+++ b/clippy_lints/src/unused_peekable.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable};
 use clippy_utils::{fn_def_id, is_trait_method, path_to_local_id, peel_ref_operators};
 use rustc_ast::Mutability;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 use rustc_hir::{Block, Expr, ExprKind, HirId, LetStmt, Node, PatKind, PathSegment, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter::OnlyBodies;
diff --git a/clippy_lints/src/unused_trait_names.rs b/clippy_lints/src/unused_trait_names.rs
index c1cf58dcfce3d..9fd6ebccd02f4 100644
--- a/clippy_lints/src/unused_trait_names.rs
+++ b/clippy_lints/src/unused_trait_names.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_from_proc_macro;
 use clippy_utils::source::snippet_opt;
diff --git a/clippy_lints/src/unused_unit.rs b/clippy_lints/src/unused_unit.rs
index 65f431d338bdb..d5309aade7aac 100644
--- a/clippy_lints/src/unused_unit.rs
+++ b/clippy_lints/src/unused_unit.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{position_before_rarrow, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, position_before_rarrow};
 use rustc_ast::visit::FnKind;
-use rustc_ast::{ast, ClosureBinder};
+use rustc_ast::{ClosureBinder, ast};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::declare_lint_pass;
diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs
index 0b4ea0752b6ba..596f0fd9c8b02 100644
--- a/clippy_lints/src/unwrap.rs
+++ b/clippy_lints/src/unwrap.rs
@@ -3,7 +3,7 @@ use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::usage::is_potentially_local_place;
 use clippy_utils::{higher, path_to_local};
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor};
+use rustc_hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn};
 use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Node, PathSegment, UnOp};
 use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceWithHirId};
 use rustc_lint::{LateContext, LateLintPass};
@@ -13,7 +13,7 @@ use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/unwrap_in_result.rs b/clippy_lints/src/unwrap_in_result.rs
index f77badd97b7a3..9b9a2ffbbc807 100644
--- a/clippy_lints/src/unwrap_in_result.rs
+++ b/clippy_lints/src/unwrap_in_result.rs
@@ -7,7 +7,7 @@ use rustc_hir as hir;
 use rustc_hir::ImplItemKind;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs
index 5da48f4f7fbd7..e340b419bd07b 100644
--- a/clippy_lints/src/use_self.rs
+++ b/clippy_lints/src/use_self.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_from_proc_macro;
 use clippy_utils::ty::same_type_and_consts;
@@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::intravisit::{walk_inf, walk_ty, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_inf, walk_ty};
 use rustc_hir::{
     self as hir, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParam, GenericParamKind, HirId, Impl,
     ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind,
diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs
index 1890b3fdd4020..29a7949b34358 100644
--- a/clippy_lints/src/useless_conversion.rs
+++ b/clippy_lints/src/useless_conversion.rs
@@ -12,7 +12,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, EarlyBinder, GenericArg, GenericArgsRef, Ty, TypeVisitableExt};
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 
 declare_clippy_lint! {
diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs
index 0cce45290cfe7..31f9d84f5e466 100644
--- a/clippy_lints/src/utils/author.rs
+++ b/clippy_lints/src/utils/author.rs
@@ -1,6 +1,6 @@
 use clippy_utils::{get_attr, higher};
-use rustc_ast::ast::{LitFloatType, LitKind};
 use rustc_ast::LitIntType;
+use rustc_ast::ast::{LitFloatType, LitKind};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::{
     self as hir, ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind,
diff --git a/clippy_lints/src/utils/format_args_collector.rs b/clippy_lints/src/utils/format_args_collector.rs
index f50ce6c99deac..8f314ce7a60ce 100644
--- a/clippy_lints/src/utils/format_args_collector.rs
+++ b/clippy_lints/src/utils/format_args_collector.rs
@@ -3,10 +3,10 @@ use clippy_utils::source::SpanRangeExt;
 use itertools::Itertools;
 use rustc_ast::{Crate, Expr, ExprKind, FormatArgs};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_lexer::{tokenize, TokenKind};
+use rustc_lexer::{TokenKind, tokenize};
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::impl_lint_pass;
-use rustc_span::{hygiene, Span};
+use rustc_span::{Span, hygiene};
 use std::iter::once;
 use std::mem;
 
diff --git a/clippy_lints/src/utils/internal_lints/collapsible_calls.rs b/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
index f752968267553..d8f101a8614d8 100644
--- a/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
+++ b/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
@@ -1,6 +1,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 clippy_utils::{SpanlessEq, is_expr_path_def_path, is_lint_allowed, peel_blocks_with_stmt};
 use rustc_errors::Applicability;
 use rustc_hir::{Closure, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/clippy_lints/src/utils/internal_lints/invalid_paths.rs
index 0ffcb433481e4..d444ad45087cf 100644
--- a/clippy_lints/src/utils/internal_lints/invalid_paths.rs
+++ b/clippy_lints/src/utils/internal_lints/invalid_paths.rs
@@ -2,11 +2,11 @@ use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::def_path_res;
 use clippy_utils::diagnostics::span_lint;
 use rustc_hir as hir;
-use rustc_hir::def::DefKind;
 use rustc_hir::Item;
+use rustc_hir::def::DefKind;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::FloatTy;
+use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_session::declare_lint_pass;
 use rustc_span::symbol::Symbol;
 
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 20526113d69e3..7c45a5b2f0971 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
@@ -12,7 +12,7 @@ use rustc_middle::hir::nested_filter;
 use rustc_session::impl_lint_pass;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::Symbol;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 use {rustc_ast as ast, rustc_hir as hir};
 
 declare_clippy_lint! {
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 41183700f09e8..76b0a52621be4 100644
--- a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
+++ b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
@@ -8,12 +8,12 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 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;
+use rustc_middle::mir::interpret::{Allocation, GlobalAlloc};
 use rustc_middle::ty::{self, Ty};
 use rustc_session::impl_lint_pass;
-use rustc_span::symbol::Symbol;
 use rustc_span::Span;
+use rustc_span::symbol::Symbol;
 
 use std::str;
 
diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs
index d3e49bff422ca..ce4f41e854d5e 100644
--- a/clippy_lints/src/vec.rs
+++ b/clippy_lints/src/vec.rs
@@ -1,8 +1,8 @@
 use std::collections::BTreeMap;
 use std::ops::ControlFlow;
 
-use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::source::SpanRangeExt;
@@ -15,7 +15,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, DesugaringKind, Span};
+use rustc_span::{DesugaringKind, Span, sym};
 
 #[expect(clippy::module_name_repetitions)]
 pub struct UselessVec {
diff --git a/clippy_lints/src/vec_init_then_push.rs b/clippy_lints/src/vec_init_then_push.rs
index a599415a2dd57..91dff5a95236e 100644
--- a/clippy_lints/src/vec_init_then_push.rs
+++ b/clippy_lints/src/vec_init_then_push.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::higher::{get_vec_init_kind, VecInitKind};
+use clippy_utils::higher::{VecInitKind, get_vec_init_kind};
 use clippy_utils::source::snippet;
 use clippy_utils::visitors::for_each_local_use_after_expr;
 use clippy_utils::{get_parent_expr, path_to_local_id};
diff --git a/clippy_lints/src/visibility.rs b/clippy_lints/src/visibility.rs
index 7a85196cecaaa..2e5fc5834e24f 100644
--- a/clippy_lints/src/visibility.rs
+++ b/clippy_lints/src/visibility.rs
@@ -5,8 +5,8 @@ use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::declare_lint_pass;
-use rustc_span::symbol::kw;
 use rustc_span::Span;
+use rustc_span::symbol::kw;
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs
index 7d9e58ad2f8d5..405310512dff3 100644
--- a/clippy_lints/src/wildcard_imports.rs
+++ b/clippy_lints/src/wildcard_imports.rs
@@ -10,7 +10,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
 use rustc_span::symbol::kw;
-use rustc_span::{sym, BytePos};
+use rustc_span::{BytePos, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs
index ec5a5896fb2bf..1dd46ed5a8915 100644
--- a/clippy_lints/src/write.rs
+++ b/clippy_lints/src/write.rs
@@ -1,8 +1,8 @@
 use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::is_in_test;
-use clippy_utils::macros::{format_arg_removal_span, root_macro_call_first_node, FormatArgsStorage, MacroCall};
-use clippy_utils::source::{expand_past_previous_comma, SpanRangeExt};
+use clippy_utils::macros::{FormatArgsStorage, MacroCall, format_arg_removal_span, root_macro_call_first_node};
+use clippy_utils::source::{SpanRangeExt, expand_past_previous_comma};
 use rustc_ast::token::LitKind;
 use rustc_ast::{
     FormatArgPosition, FormatArgPositionKind, FormatArgs, FormatArgsPiece, FormatOptions, FormatPlaceholder,
@@ -12,7 +12,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{Expr, Impl, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, BytePos, Span};
+use rustc_span::{BytePos, Span, sym};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_lints/src/zombie_processes.rs b/clippy_lints/src/zombie_processes.rs
index eda3d7820c169..ba2a80ee66b05 100644
--- a/clippy_lints/src/zombie_processes.rs
+++ b/clippy_lints/src/zombie_processes.rs
@@ -1,14 +1,14 @@
+use ControlFlow::{Break, Continue};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::{fn_def_id, get_enclosing_block, match_any_def_paths, match_def_path, path_to_local_id, paths};
 use rustc_ast::Mutability;
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_block, walk_expr, walk_local, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_local};
 use rustc_hir::{Expr, ExprKind, HirId, LetStmt, Node, PatKind, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 use rustc_span::sym;
 use std::ops::ControlFlow;
-use ControlFlow::{Break, Continue};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/clippy_utils/src/ast_utils/ident_iter.rs b/clippy_utils/src/ast_utils/ident_iter.rs
index eefcbabd835d2..032cd3ed7399f 100644
--- a/clippy_utils/src/ast_utils/ident_iter.rs
+++ b/clippy_utils/src/ast_utils/ident_iter.rs
@@ -1,5 +1,5 @@
 use core::iter::FusedIterator;
-use rustc_ast::visit::{walk_attribute, walk_expr, Visitor};
+use rustc_ast::visit::{Visitor, walk_attribute, walk_expr};
 use rustc_ast::{Attribute, Expr};
 use rustc_span::symbol::Ident;
 
diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs
index 935a1686c0af5..edc9c6ccdff84 100644
--- a/clippy_utils/src/attrs.rs
+++ b/clippy_utils/src/attrs.rs
@@ -4,7 +4,7 @@ use rustc_lexer::TokenKind;
 use rustc_lint::LateContext;
 use rustc_middle::ty::{AdtDef, TyCtxt};
 use rustc_session::Session;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 use std::str::FromStr;
 
 use crate::source::SpanRangeExt;
diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs
index 2bd6837d973bb..9143d292f670f 100644
--- a/clippy_utils/src/check_proc_macro.rs
+++ b/clippy_utils/src/check_proc_macro.rs
@@ -12,9 +12,9 @@
 //! code was written, and check if the span contains that text. Note this will only work correctly
 //! if the span is not from a `macro_rules` based macro.
 
+use rustc_ast::AttrStyle;
 use rustc_ast::ast::{AttrKind, Attribute, IntTy, LitIntType, LitKind, StrStyle, TraitObjectSyntax, UintTy};
 use rustc_ast::token::CommentKind;
-use rustc_ast::AttrStyle;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
     Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, FnRetTy, HirId, Impl,
@@ -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::{kw, Ident};
+use rustc_span::symbol::{Ident, kw};
 use rustc_span::{Span, Symbol};
 use rustc_target::spec::abi::Abi;
 
diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs
index 760d5bc95f7fb..bf47cf6d372d2 100644
--- a/clippy_utils/src/consts.rs
+++ b/clippy_utils/src/consts.rs
@@ -1,24 +1,24 @@
 #![allow(clippy::float_cmp)]
 
 use crate::macros::HirNode;
-use crate::source::{walk_span_to_context, SpanRangeExt};
+use crate::source::{SpanRangeExt, walk_span_to_context};
 use crate::{clip, is_direct_expn_of, sext, unsext};
 
-use rustc_apfloat::ieee::{Half, Quad};
 use rustc_apfloat::Float;
+use rustc_apfloat::ieee::{Half, Quad};
 use rustc_ast::ast::{self, LitFloatType, LitKind};
 use rustc_data_structures::sync::Lrc;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
 use rustc_lexer::tokenize;
 use rustc_lint::LateContext;
-use rustc_middle::mir::interpret::{alloc_range, Scalar};
 use rustc_middle::mir::ConstValue;
+use rustc_middle::mir::interpret::{Scalar, alloc_range};
 use rustc_middle::ty::{self, FloatTy, IntTy, ParamEnv, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy};
 use rustc_middle::{bug, mir, span_bug};
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::Ident;
-use rustc_span::{sym, SyntaxContext};
+use rustc_span::{SyntaxContext, sym};
 use rustc_target::abi::Size;
 use std::cell::Cell;
 use std::cmp::Ordering;
@@ -581,7 +581,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
     }
 
     fn constant_negate(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option<Constant<'tcx>> {
-        use self::Constant::{Int, F32, F64};
+        use self::Constant::{F32, F64, Int};
         match *o {
             Int(value) => {
                 let ty::Int(ity) = *ty.kind() else { return None };
diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs
index a6dd12a28c5bc..9420d84b9591d 100644
--- a/clippy_utils/src/eager_or_lazy.rs
+++ b/clippy_utils/src/eager_or_lazy.rs
@@ -14,12 +14,12 @@ use crate::ty::{all_predicates_of, is_copy};
 use crate::visitors::is_const_evaluatable;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
 use rustc_hir::{BinOpKind, Block, Expr, ExprKind, QPath, UnOp};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_middle::ty::adjustment::Adjust;
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
 use std::{cmp, ops};
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs
index e09cc9edf3ac3..3175a9a1dd31f 100644
--- a/clippy_utils/src/higher.rs
+++ b/clippy_utils/src/higher.rs
@@ -3,14 +3,14 @@
 #![deny(clippy::missing_docs_in_private_items)]
 
 use crate::consts::{ConstEvalCtxt, Constant};
-use crate::ty::is_type_diagnostic_item;
 use crate::is_expn_of;
+use crate::ty::is_type_diagnostic_item;
 
 use rustc_ast::ast;
 use rustc_hir as hir;
 use rustc_hir::{Arm, Block, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, QPath};
 use rustc_lint::LateContext;
-use rustc_span::{sym, symbol, Span};
+use rustc_span::{Span, sym, symbol};
 
 /// The essential nodes of a desugared for loop as well as the entire span:
 /// `for pat in arg { body }` becomes `(pat, arg, body)`. Returns `(pat, arg, body, span)`.
diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs
index c1e21ec4e3917..76900379ac787 100644
--- a/clippy_utils/src/hir_utils.rs
+++ b/clippy_utils/src/hir_utils.rs
@@ -1,20 +1,20 @@
 use crate::consts::ConstEvalCtxt;
 use crate::macros::macro_backtrace;
-use crate::source::{walk_span_to_context, SpanRange, SpanRangeExt};
+use crate::source::{SpanRange, SpanRangeExt, walk_span_to_context};
 use crate::tokenize_with_text;
 use rustc_ast::ast::InlineAsmTemplatePiece;
 use rustc_data_structures::fx::FxHasher;
-use rustc_hir::def::Res;
 use rustc_hir::MatchSource::TryDesugar;
+use rustc_hir::def::Res;
 use rustc_hir::{
     ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr,
     ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime,
     LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind,
 };
-use rustc_lexer::{tokenize, TokenKind};
+use rustc_lexer::{TokenKind, tokenize};
 use rustc_lint::LateContext;
 use rustc_middle::ty::TypeckResults;
-use rustc_span::{sym, BytePos, ExpnKind, MacroKind, Symbol, SyntaxContext};
+use rustc_span::{BytePos, ExpnKind, MacroKind, Symbol, SyntaxContext, sym};
 use std::hash::{Hash, Hasher};
 use std::ops::Range;
 
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 5a68b0860bcd3..a925549b0bff0 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -78,7 +78,7 @@ pub mod visitors;
 pub use self::attrs::*;
 pub use self::check_proc_macro::{is_from_proc_macro, is_span_if, is_span_match};
 pub use self::hir_utils::{
-    both, count_eq, eq_expr_value, hash_expr, hash_stmt, is_bool, over, HirEqInterExpr, SpanlessEq, SpanlessHash,
+    HirEqInterExpr, SpanlessEq, SpanlessHash, both, count_eq, eq_expr_value, hash_expr, hash_stmt, is_bool, over,
 };
 
 use core::mem;
@@ -94,20 +94,20 @@ use rustc_ast::ast::{self, LitKind, RangeLimits};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::packed::Pu128;
 use rustc_data_structures::unhash::UnhashMap;
+use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalModDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId, LocalModDefId};
 use rustc_hir::definitions::{DefPath, DefPathData};
 use rustc_hir::hir_id::{HirIdMap, HirIdSet};
-use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
-use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
+use rustc_hir::intravisit::{FnKind, Visitor, walk_expr};
 use rustc_hir::{
-    self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind,
-    ConstContext, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem,
-    ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode,
-    Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef,
-    TraitRef, TyKind, UnOp,
+    self as hir, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext,
+    Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind,
+    ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat,
+    PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef,
+    TyKind, UnOp, def,
 };
-use rustc_lexer::{tokenize, TokenKind};
+use rustc_lexer::{TokenKind, tokenize};
 use rustc_lint::{LateContext, Level, Lint, LintContext};
 use rustc_middle::hir::place::PlaceBase;
 use rustc_middle::mir::Const;
@@ -120,12 +120,12 @@ use rustc_middle::ty::{
 };
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::source_map::SourceMap;
-use rustc_span::symbol::{kw, Ident, Symbol};
-use rustc_span::{sym, InnerSpan, Span};
+use rustc_span::symbol::{Ident, Symbol, kw};
+use rustc_span::{InnerSpan, Span, sym};
 use rustc_target::abi::Integer;
 use visitors::Visitable;
 
-use crate::consts::{mir_to_const, ConstEvalCtxt, Constant};
+use crate::consts::{ConstEvalCtxt, Constant, mir_to_const};
 use crate::higher::Range;
 use crate::ty::{adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type};
 use crate::visitors::for_each_expr_without_closures;
@@ -263,9 +263,13 @@ pub fn is_res_lang_ctor(cx: &LateContext<'_>, res: Res, lang_item: LangItem) ->
     }
 }
 
-
 /// Checks if `{ctor_call_id}(...)` is `{enum_item}::{variant_name}(...)`.
-pub fn is_enum_variant_ctor(cx: &LateContext<'_>, enum_item: Symbol, variant_name: Symbol, ctor_call_id: DefId) -> bool {
+pub fn is_enum_variant_ctor(
+    cx: &LateContext<'_>,
+    enum_item: Symbol,
+    variant_name: Symbol,
+    ctor_call_id: DefId,
+) -> bool {
     let Some(enum_def_id) = cx.tcx.get_diagnostic_item(enum_item) else {
         return false;
     };
diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs
index 1d7479bff82d9..9c4d19ac1f1dd 100644
--- a/clippy_utils/src/macros.rs
+++ b/clippy_utils/src/macros.rs
@@ -1,6 +1,6 @@
 #![allow(clippy::similar_names)] // `expr` and `expn`
 
-use crate::visitors::{for_each_expr_without_closures, Descend};
+use crate::visitors::{Descend, for_each_expr_without_closures};
 
 use arrayvec::ArrayVec;
 use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder};
@@ -10,7 +10,7 @@ use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath};
 use rustc_lint::LateContext;
 use rustc_span::def_id::DefId;
 use rustc_span::hygiene::{self, MacroKind, SyntaxContext};
-use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Span, SpanData, Symbol};
+use rustc_span::{BytePos, ExpnData, ExpnId, ExpnKind, Span, SpanData, Symbol, sym};
 use std::ops::ControlFlow;
 
 const FORMAT_MACRO_DIAG_ITEMS: &[Symbol] = &[
diff --git a/clippy_utils/src/mir/mod.rs b/clippy_utils/src/mir/mod.rs
index 654fb564848e2..59bb5e35cda66 100644
--- a/clippy_utils/src/mir/mod.rs
+++ b/clippy_utils/src/mir/mod.rs
@@ -2,7 +2,7 @@ use rustc_hir::{Expr, HirId};
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::{
-    traversal, BasicBlock, Body, InlineAsmOperand, Local, Location, Place, StatementKind, TerminatorKind, START_BLOCK,
+    BasicBlock, Body, InlineAsmOperand, Local, Location, Place, START_BLOCK, StatementKind, TerminatorKind, traversal,
 };
 use rustc_middle::ty::TyCtxt;
 
@@ -112,14 +112,10 @@ pub fn block_in_cycle(body: &Body<'_>, block: BasicBlock) -> bool {
 
 /// Convenience wrapper around `visit_local_usage`.
 pub fn used_exactly_once(mir: &Body<'_>, local: Local) -> Option<bool> {
-    visit_local_usage(
-        &[local],
-        mir,
-        Location {
-            block: START_BLOCK,
-            statement_index: 0,
-        },
-    )
+    visit_local_usage(&[local], mir, Location {
+        block: START_BLOCK,
+        statement_index: 0,
+    })
     .map(|mut vec| {
         let LocalUsage { local_use_locs, .. } = vec.remove(0);
         let mut locations = local_use_locs
diff --git a/clippy_utils/src/ptr.rs b/clippy_utils/src/ptr.rs
index 991ea428dc33b..273c1b0defab0 100644
--- a/clippy_utils/src/ptr.rs
+++ b/clippy_utils/src/ptr.rs
@@ -1,5 +1,5 @@
 use crate::source::snippet;
-use crate::visitors::{for_each_expr_without_closures, Descend};
+use crate::visitors::{Descend, for_each_expr_without_closures};
 use crate::{path_to_local_id, strip_pat_refs};
 use core::ops::ControlFlow;
 use rustc_hir::{Body, BodyId, ExprKind, HirId, PatKind};
diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs
index d9befb3c157a3..2ed20b7202cc3 100644
--- a/clippy_utils/src/qualify_min_const_fn.rs
+++ b/clippy_utils/src/qualify_min_const_fn.rs
@@ -18,8 +18,8 @@ use rustc_middle::mir::{
 use rustc_middle::traits::{BuiltinImplSource, ImplSource, ObligationCause};
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::{self, GenericArgKind, TraitRef, Ty, TyCtxt};
-use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_span::symbol::sym;
 use rustc_trait_selection::traits::{ObligationCtxt, SelectionContext};
 use std::borrow::Cow;
 
diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs
index f97fb4a6471dc..4ad7575e7201f 100644
--- a/clippy_utils/src/source.rs
+++ b/clippy_utils/src/source.rs
@@ -9,10 +9,10 @@ use rustc_hir::{BlockCheckMode, Expr, ExprKind, UnsafeSource};
 use rustc_lint::{EarlyContext, LateContext};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
-use rustc_span::source_map::{original_sp, SourceMap};
+use rustc_span::source_map::{SourceMap, original_sp};
 use rustc_span::{
-    hygiene, BytePos, FileNameDisplayPreference, Pos, SourceFile, SourceFileAndLine, Span, SpanData, SyntaxContext,
-    DUMMY_SP,
+    BytePos, DUMMY_SP, FileNameDisplayPreference, Pos, SourceFile, SourceFileAndLine, Span, SpanData, SyntaxContext,
+    hygiene,
 };
 use std::borrow::Cow;
 use std::fmt;
@@ -725,15 +725,12 @@ pub fn str_literal_to_char_literal(
             &snip[1..(snip.len() - 1)]
         };
 
-        let hint = format!(
-            "'{}'",
-            match ch {
-                "'" => "\\'",
-                r"\" => "\\\\",
-                "\\\"" => "\"", // no need to escape `"` in `'"'`
-                _ => ch,
-            }
-        );
+        let hint = format!("'{}'", match ch {
+            "'" => "\\'",
+            r"\" => "\\\\",
+            "\\\"" => "\"", // no need to escape `"` in `'"'`
+            _ => ch,
+        });
 
         Some(hint)
     } else {
diff --git a/clippy_utils/src/str_utils.rs b/clippy_utils/src/str_utils.rs
index 421b25a77fe8b..1588ee452daea 100644
--- a/clippy_utils/src/str_utils.rs
+++ b/clippy_utils/src/str_utils.rs
@@ -370,9 +370,11 @@ mod test {
         assert_eq!(camel_case_split("AbcDef"), vec!["Abc", "Def"]);
         assert_eq!(camel_case_split("Abc"), vec!["Abc"]);
         assert_eq!(camel_case_split("abcDef"), vec!["abc", "Def"]);
-        assert_eq!(
-            camel_case_split("\u{f6}\u{f6}AabABcd"),
-            vec!["\u{f6}\u{f6}", "Aab", "A", "Bcd"]
-        );
+        assert_eq!(camel_case_split("\u{f6}\u{f6}AabABcd"), vec![
+            "\u{f6}\u{f6}",
+            "Aab",
+            "A",
+            "Bcd"
+        ]);
     }
 }
diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs
index 9c5e761abe4c3..775a98fe361d8 100644
--- a/clippy_utils/src/ty.rs
+++ b/clippy_utils/src/ty.rs
@@ -12,8 +12,8 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, FnDecl, LangItem, Safety, TyKind};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
-use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::ConstValue;
+use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::traits::EvaluationResult;
 use rustc_middle::ty::layout::ValidityRequirement;
 use rustc_middle::ty::{
@@ -22,7 +22,7 @@ use rustc_middle::ty::{
     TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr,
 };
 use rustc_span::symbol::Ident;
-use rustc_span::{sym, Span, Symbol, DUMMY_SP};
+use rustc_span::{DUMMY_SP, Span, Symbol, sym};
 use rustc_target::abi::VariantIdx;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
diff --git a/clippy_utils/src/ty/type_certainty/mod.rs b/clippy_utils/src/ty/type_certainty/mod.rs
index 875ddec259ee8..e612e9c6cb606 100644
--- a/clippy_utils/src/ty/type_certainty/mod.rs
+++ b/clippy_utils/src/ty/type_certainty/mod.rs
@@ -14,14 +14,14 @@
 use crate::def_path_res;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
-use rustc_hir::intravisit::{walk_qpath, walk_ty, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_qpath, walk_ty};
 use rustc_hir::{self as hir, Expr, ExprKind, GenericArgs, HirId, Node, PathSegment, QPath, TyKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, AdtDef, GenericArgKind, Ty};
 use rustc_span::{Span, Symbol};
 
 mod certainty;
-use certainty::{join, meet, Certainty, Meet};
+use certainty::{Certainty, Meet, join, meet};
 
 pub fn expr_type_is_certain(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     expr_type_certainty(cx, expr).is_certain()
diff --git a/clippy_utils/src/usage.rs b/clippy_utils/src/usage.rs
index fbf3d95365acb..1230b60c3a6b7 100644
--- a/clippy_utils/src/usage.rs
+++ b/clippy_utils/src/usage.rs
@@ -1,4 +1,4 @@
-use crate::visitors::{for_each_expr, for_each_expr_without_closures, Descend, Visitable};
+use crate::visitors::{Descend, Visitable, for_each_expr, for_each_expr_without_closures};
 use crate::{self as utils, get_enclosing_loop_or_multi_call_closure};
 use core::ops::ControlFlow;
 use hir::def::Res;
diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs
index e5b6d3965e930..6d9a85a1181c4 100644
--- a/clippy_utils/src/visitors.rs
+++ b/clippy_utils/src/visitors.rs
@@ -1,10 +1,10 @@
 use crate::ty::needs_ordered_drop;
 use crate::{get_enclosing_block, path_to_local_id};
 use core::ops::ControlFlow;
-use rustc_ast::visit::{try_visit, VisitorResult};
+use rustc_ast::visit::{VisitorResult, try_visit};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor};
+use rustc_hir::intravisit::{self, Visitor, walk_block, walk_expr};
 use rustc_hir::{
     AnonConst, Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, LetExpr, Pat, QPath,
     Safety, Stmt, UnOp, UnsafeSource,
diff --git a/declare_clippy_lint/src/lib.rs b/declare_clippy_lint/src/lib.rs
index 6aa24329b0659..fefc1a0a6c402 100644
--- a/declare_clippy_lint/src/lib.rs
+++ b/declare_clippy_lint/src/lib.rs
@@ -5,7 +5,7 @@
 use proc_macro::TokenStream;
 use quote::{format_ident, quote};
 use syn::parse::{Parse, ParseStream};
-use syn::{parse_macro_input, Attribute, Error, Expr, ExprLit, Ident, Lit, LitStr, Meta, Result, Token};
+use syn::{Attribute, Error, Expr, ExprLit, Ident, Lit, LitStr, Meta, Result, Token, parse_macro_input};
 
 fn parse_attr<const LEN: usize>(path: [&'static str; LEN], attr: &Attribute) -> Option<LitStr> {
     if let Meta::NameValue(name_value) = &attr.meta {
@@ -140,15 +140,12 @@ pub fn declare_clippy_lint(input: TokenStream) -> TokenStream {
 
     let mut category = category.to_string();
 
-    let level = format_ident!(
-        "{}",
-        match category.as_str() {
-            "correctness" => "Deny",
-            "style" | "suspicious" | "complexity" | "perf" => "Warn",
-            "pedantic" | "restriction" | "cargo" | "nursery" | "internal" => "Allow",
-            _ => panic!("unknown category {category}"),
-        },
-    );
+    let level = format_ident!("{}", match category.as_str() {
+        "correctness" => "Deny",
+        "style" | "suspicious" | "complexity" | "perf" => "Warn",
+        "pedantic" | "restriction" | "cargo" | "nursery" | "internal" => "Allow",
+        _ => panic!("unknown category {category}"),
+    },);
 
     let info_name = format_ident!("{name}_INFO");
 
diff --git a/lintcheck/src/driver.rs b/lintcheck/src/driver.rs
index 2fda2b00f873b..87ab14ba0cf83 100644
--- a/lintcheck/src/driver.rs
+++ b/lintcheck/src/driver.rs
@@ -1,4 +1,4 @@
-use crate::recursive::{deserialize_line, serialize_line, DriverInfo};
+use crate::recursive::{DriverInfo, deserialize_line, serialize_line};
 
 use std::io::{self, BufReader, Write};
 use std::net::TcpStream;
diff --git a/lintcheck/src/recursive.rs b/lintcheck/src/recursive.rs
index 6a662970ae84d..57073f523648e 100644
--- a/lintcheck/src/recursive.rs
+++ b/lintcheck/src/recursive.rs
@@ -3,8 +3,8 @@
 //! [`LintcheckServer`] to ask if it should be skipped, and if not sends the stderr of running
 //! clippy on the crate to the server
 
-use crate::input::RecursiveOptions;
 use crate::ClippyWarning;
+use crate::input::RecursiveOptions;
 
 use std::collections::HashSet;
 use std::io::{BufRead, BufReader, Read, Write};
diff --git a/src/driver.rs b/src/driver.rs
index 414957938a492..324f754e61556 100644
--- a/src/driver.rs
+++ b/src/driver.rs
@@ -15,9 +15,9 @@ extern crate rustc_session;
 extern crate rustc_span;
 
 use rustc_interface::interface;
+use rustc_session::EarlyDiagCtxt;
 use rustc_session::config::ErrorOutputType;
 use rustc_session::parse::ParseSess;
-use rustc_session::EarlyDiagCtxt;
 use rustc_span::symbol::Symbol;
 
 use std::env;
diff --git a/tests/compile-test.rs b/tests/compile-test.rs
index c7243348ce46f..af2aa51925777 100644
--- a/tests/compile-test.rs
+++ b/tests/compile-test.rs
@@ -2,25 +2,25 @@
 #![warn(rust_2018_idioms, unused_lifetimes)]
 #![allow(unused_extern_crates)]
 
-use cargo_metadata::diagnostic::{Applicability, Diagnostic};
 use cargo_metadata::Message;
+use cargo_metadata::diagnostic::{Applicability, Diagnostic};
 use clippy_config::ClippyConfiguration;
+use clippy_lints::LintInfo;
 use clippy_lints::declared_lints::LINTS;
 use clippy_lints::deprecated_lints::{DEPRECATED, DEPRECATED_VERSION, RENAMED};
-use clippy_lints::LintInfo;
 use serde::{Deserialize, Serialize};
 use test_utils::IS_RUSTC_TEST_SUITE;
-use ui_test::custom_flags::rustfix::RustfixMode;
 use ui_test::custom_flags::Flag;
+use ui_test::custom_flags::rustfix::RustfixMode;
 use ui_test::spanned::Spanned;
-use ui_test::{status_emitter, Args, CommandBuilder, Config, Match, OutputConflictHandling};
+use ui_test::{Args, CommandBuilder, Config, Match, OutputConflictHandling, status_emitter};
 
 use std::collections::{BTreeMap, HashMap};
 use std::env::{self, set_var, var_os};
 use std::ffi::{OsStr, OsString};
 use std::fmt::Write;
 use std::path::{Path, PathBuf};
-use std::sync::mpsc::{channel, Sender};
+use std::sync::mpsc::{Sender, channel};
 use std::{fs, iter, thread};
 
 // Test dependencies may need an `extern crate` here to ensure that they show up
diff --git a/tests/config-metadata.rs b/tests/config-metadata.rs
index 3e3711873baa5..628dfc8f758ac 100644
--- a/tests/config-metadata.rs
+++ b/tests/config-metadata.rs
@@ -1,6 +1,6 @@
 #![feature(rustc_private)]
 
-use clippy_config::{get_configuration_metadata, ClippyConfiguration};
+use clippy_config::{ClippyConfiguration, get_configuration_metadata};
 use itertools::Itertools;
 use regex::Regex;
 use std::borrow::Cow;
diff --git a/tests/ui-internal/unnecessary_def_path.fixed b/tests/ui-internal/unnecessary_def_path.fixed
index 04d990896e54b..0a9948428341d 100644
--- a/tests/ui-internal/unnecessary_def_path.fixed
+++ b/tests/ui-internal/unnecessary_def_path.fixed
@@ -22,8 +22,8 @@ use rustc_hir::LangItem;
 #[allow(unused)]
 use rustc_span::sym;
 
-use rustc_hir::def_id::DefId;
 use rustc_hir::Expr;
+use rustc_hir::def_id::DefId;
 use rustc_lint::LateContext;
 use rustc_middle::ty::Ty;
 
diff --git a/tests/ui-internal/unnecessary_def_path.rs b/tests/ui-internal/unnecessary_def_path.rs
index ade5e9280e354..ba68de6c6d016 100644
--- a/tests/ui-internal/unnecessary_def_path.rs
+++ b/tests/ui-internal/unnecessary_def_path.rs
@@ -22,8 +22,8 @@ use rustc_hir::LangItem;
 #[allow(unused)]
 use rustc_span::sym;
 
-use rustc_hir::def_id::DefId;
 use rustc_hir::Expr;
+use rustc_hir::def_id::DefId;
 use rustc_lint::LateContext;
 use rustc_middle::ty::Ty;
 
diff --git a/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.fixed b/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.fixed
index 5f4f007cf5c7f..a6072111dc061 100644
--- a/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.fixed
+++ b/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.fixed
@@ -2,7 +2,7 @@
 
 use std::alloc as colla;
 use std::option::Option as Maybe;
-use std::process::{exit as goodbye, Child as Kid};
+use std::process::{Child as Kid, exit as goodbye};
 use std::thread::sleep as thread_sleep;
 #[rustfmt::skip]
 use std::{
diff --git a/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs b/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs
index f60058c862888..c2b61aab5b3c4 100644
--- a/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs
+++ b/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs
@@ -2,7 +2,7 @@
 
 use std::alloc as colla;
 use std::option::Option as Maybe;
-use std::process::{exit as wrong_exit, Child as Kid};
+use std::process::{Child as Kid, exit as wrong_exit};
 use std::thread::sleep;
 #[rustfmt::skip]
 use std::{
diff --git a/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr b/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr
index f66938c83fbf8..d3bb07ec47fd3 100644
--- a/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr
+++ b/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr
@@ -1,8 +1,8 @@
 error: this import should be renamed
-  --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:5:20
+  --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:5:34
    |
-LL | use std::process::{exit as wrong_exit, Child as Kid};
-   |                    ^^^^^^^^^^^^^^^^^^ help: try: `exit as goodbye`
+LL | use std::process::{Child as Kid, exit as wrong_exit};
+   |                                  ^^^^^^^^^^^^^^^^^^ help: try: `exit as goodbye`
    |
    = note: `-D clippy::missing-enforced-import-renames` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::missing_enforced_import_renames)]`
diff --git a/tests/ui/arithmetic_side_effects.rs b/tests/ui/arithmetic_side_effects.rs
index 0838d064a5fa1..3f20407308516 100644
--- a/tests/ui/arithmetic_side_effects.rs
+++ b/tests/ui/arithmetic_side_effects.rs
@@ -2,7 +2,6 @@
 
 #![feature(f128)]
 #![feature(f16)]
-
 #![allow(
     clippy::assign_op_pattern,
     clippy::erasing_op,
diff --git a/tests/ui/arithmetic_side_effects.stderr b/tests/ui/arithmetic_side_effects.stderr
index 78914667bf305..78b1aca4b8a47 100644
--- a/tests/ui/arithmetic_side_effects.stderr
+++ b/tests/ui/arithmetic_side_effects.stderr
@@ -1,5 +1,5 @@
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:167:13
+  --> tests/ui/arithmetic_side_effects.rs:166:13
    |
 LL |     let _ = 1f16 + 1f16;
    |             ^^^^^^^^^^^
@@ -8,733 +8,733 @@ LL |     let _ = 1f16 + 1f16;
    = help: to override `-D warnings` add `#[allow(clippy::arithmetic_side_effects)]`
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:170:13
+  --> tests/ui/arithmetic_side_effects.rs:169:13
    |
 LL |     let _ = 1f128 + 1f128;
    |             ^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:308:5
+  --> tests/ui/arithmetic_side_effects.rs:307:5
    |
 LL |     _n += 1;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:309:5
+  --> tests/ui/arithmetic_side_effects.rs:308:5
    |
 LL |     _n += &1;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:310:5
+  --> tests/ui/arithmetic_side_effects.rs:309:5
    |
 LL |     _n -= 1;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:311:5
+  --> tests/ui/arithmetic_side_effects.rs:310:5
    |
 LL |     _n -= &1;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:312:5
+  --> tests/ui/arithmetic_side_effects.rs:311:5
    |
 LL |     _n /= 0;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:313:5
+  --> tests/ui/arithmetic_side_effects.rs:312:5
    |
 LL |     _n /= &0;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:314:5
+  --> tests/ui/arithmetic_side_effects.rs:313:5
    |
 LL |     _n %= 0;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:315:5
+  --> tests/ui/arithmetic_side_effects.rs:314:5
    |
 LL |     _n %= &0;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:316:5
+  --> tests/ui/arithmetic_side_effects.rs:315:5
    |
 LL |     _n *= 2;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:317:5
+  --> tests/ui/arithmetic_side_effects.rs:316:5
    |
 LL |     _n *= &2;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:318:5
+  --> tests/ui/arithmetic_side_effects.rs:317:5
    |
 LL |     _n += -1;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:319:5
+  --> tests/ui/arithmetic_side_effects.rs:318:5
    |
 LL |     _n += &-1;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:320:5
+  --> tests/ui/arithmetic_side_effects.rs:319:5
    |
 LL |     _n -= -1;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:321:5
+  --> tests/ui/arithmetic_side_effects.rs:320:5
    |
 LL |     _n -= &-1;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:322:5
+  --> tests/ui/arithmetic_side_effects.rs:321:5
    |
 LL |     _n /= -0;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:323:5
+  --> tests/ui/arithmetic_side_effects.rs:322:5
    |
 LL |     _n /= &-0;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:324:5
+  --> tests/ui/arithmetic_side_effects.rs:323:5
    |
 LL |     _n %= -0;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:325:5
+  --> tests/ui/arithmetic_side_effects.rs:324:5
    |
 LL |     _n %= &-0;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:326:5
+  --> tests/ui/arithmetic_side_effects.rs:325:5
    |
 LL |     _n *= -2;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:327:5
+  --> tests/ui/arithmetic_side_effects.rs:326:5
    |
 LL |     _n *= &-2;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:328:5
+  --> tests/ui/arithmetic_side_effects.rs:327:5
    |
 LL |     _custom += Custom;
    |     ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:329:5
+  --> tests/ui/arithmetic_side_effects.rs:328:5
    |
 LL |     _custom += &Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:330:5
+  --> tests/ui/arithmetic_side_effects.rs:329:5
    |
 LL |     _custom -= Custom;
    |     ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:331:5
+  --> tests/ui/arithmetic_side_effects.rs:330:5
    |
 LL |     _custom -= &Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:332:5
+  --> tests/ui/arithmetic_side_effects.rs:331:5
    |
 LL |     _custom /= Custom;
    |     ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:333:5
+  --> tests/ui/arithmetic_side_effects.rs:332:5
    |
 LL |     _custom /= &Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:334:5
+  --> tests/ui/arithmetic_side_effects.rs:333:5
    |
 LL |     _custom %= Custom;
    |     ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:335:5
+  --> tests/ui/arithmetic_side_effects.rs:334:5
    |
 LL |     _custom %= &Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:336:5
+  --> tests/ui/arithmetic_side_effects.rs:335:5
    |
 LL |     _custom *= Custom;
    |     ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:337:5
+  --> tests/ui/arithmetic_side_effects.rs:336:5
    |
 LL |     _custom *= &Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:338:5
+  --> tests/ui/arithmetic_side_effects.rs:337:5
    |
 LL |     _custom >>= Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:339:5
+  --> tests/ui/arithmetic_side_effects.rs:338:5
    |
 LL |     _custom >>= &Custom;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:340:5
+  --> tests/ui/arithmetic_side_effects.rs:339:5
    |
 LL |     _custom <<= Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:341:5
+  --> tests/ui/arithmetic_side_effects.rs:340:5
    |
 LL |     _custom <<= &Custom;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:342:5
+  --> tests/ui/arithmetic_side_effects.rs:341:5
    |
 LL |     _custom += -Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:343:5
+  --> tests/ui/arithmetic_side_effects.rs:342:5
    |
 LL |     _custom += &-Custom;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:344:5
+  --> tests/ui/arithmetic_side_effects.rs:343:5
    |
 LL |     _custom -= -Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:345:5
+  --> tests/ui/arithmetic_side_effects.rs:344:5
    |
 LL |     _custom -= &-Custom;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:346:5
+  --> tests/ui/arithmetic_side_effects.rs:345:5
    |
 LL |     _custom /= -Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:347:5
+  --> tests/ui/arithmetic_side_effects.rs:346:5
    |
 LL |     _custom /= &-Custom;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:348:5
+  --> tests/ui/arithmetic_side_effects.rs:347:5
    |
 LL |     _custom %= -Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:349:5
+  --> tests/ui/arithmetic_side_effects.rs:348:5
    |
 LL |     _custom %= &-Custom;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:350:5
+  --> tests/ui/arithmetic_side_effects.rs:349:5
    |
 LL |     _custom *= -Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:351:5
+  --> tests/ui/arithmetic_side_effects.rs:350:5
    |
 LL |     _custom *= &-Custom;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:352:5
+  --> tests/ui/arithmetic_side_effects.rs:351:5
    |
 LL |     _custom >>= -Custom;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:353:5
+  --> tests/ui/arithmetic_side_effects.rs:352:5
    |
 LL |     _custom >>= &-Custom;
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:354:5
+  --> tests/ui/arithmetic_side_effects.rs:353:5
    |
 LL |     _custom <<= -Custom;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:355:5
+  --> tests/ui/arithmetic_side_effects.rs:354:5
    |
 LL |     _custom <<= &-Custom;
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:358:10
+  --> tests/ui/arithmetic_side_effects.rs:357:10
    |
 LL |     _n = _n + 1;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:359:10
+  --> tests/ui/arithmetic_side_effects.rs:358:10
    |
 LL |     _n = _n + &1;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:360:10
+  --> tests/ui/arithmetic_side_effects.rs:359:10
    |
 LL |     _n = 1 + _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:361:10
+  --> tests/ui/arithmetic_side_effects.rs:360:10
    |
 LL |     _n = &1 + _n;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:362:10
+  --> tests/ui/arithmetic_side_effects.rs:361:10
    |
 LL |     _n = _n - 1;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:363:10
+  --> tests/ui/arithmetic_side_effects.rs:362:10
    |
 LL |     _n = _n - &1;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:364:10
+  --> tests/ui/arithmetic_side_effects.rs:363:10
    |
 LL |     _n = 1 - _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:365:10
+  --> tests/ui/arithmetic_side_effects.rs:364:10
    |
 LL |     _n = &1 - _n;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:366:10
+  --> tests/ui/arithmetic_side_effects.rs:365:10
    |
 LL |     _n = _n / 0;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:367:10
+  --> tests/ui/arithmetic_side_effects.rs:366:10
    |
 LL |     _n = _n / &0;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:368:10
+  --> tests/ui/arithmetic_side_effects.rs:367:10
    |
 LL |     _n = _n % 0;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:369:10
+  --> tests/ui/arithmetic_side_effects.rs:368:10
    |
 LL |     _n = _n % &0;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:370:10
+  --> tests/ui/arithmetic_side_effects.rs:369:10
    |
 LL |     _n = _n * 2;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:371:10
+  --> tests/ui/arithmetic_side_effects.rs:370:10
    |
 LL |     _n = _n * &2;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:372:10
+  --> tests/ui/arithmetic_side_effects.rs:371:10
    |
 LL |     _n = 2 * _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:373:10
+  --> tests/ui/arithmetic_side_effects.rs:372:10
    |
 LL |     _n = &2 * _n;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:374:10
+  --> tests/ui/arithmetic_side_effects.rs:373:10
    |
 LL |     _n = 23 + &85;
    |          ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:375:10
+  --> tests/ui/arithmetic_side_effects.rs:374:10
    |
 LL |     _n = &23 + 85;
    |          ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:376:10
+  --> tests/ui/arithmetic_side_effects.rs:375:10
    |
 LL |     _n = &23 + &85;
    |          ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:377:15
+  --> tests/ui/arithmetic_side_effects.rs:376:15
    |
 LL |     _custom = _custom + _custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:378:15
+  --> tests/ui/arithmetic_side_effects.rs:377:15
    |
 LL |     _custom = _custom + &_custom;
    |               ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:379:15
+  --> tests/ui/arithmetic_side_effects.rs:378:15
    |
 LL |     _custom = Custom + _custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:380:15
+  --> tests/ui/arithmetic_side_effects.rs:379:15
    |
 LL |     _custom = &Custom + _custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:381:15
+  --> tests/ui/arithmetic_side_effects.rs:380:15
    |
 LL |     _custom = _custom - Custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:382:15
+  --> tests/ui/arithmetic_side_effects.rs:381:15
    |
 LL |     _custom = _custom - &Custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:383:15
+  --> tests/ui/arithmetic_side_effects.rs:382:15
    |
 LL |     _custom = Custom - _custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:384:15
+  --> tests/ui/arithmetic_side_effects.rs:383:15
    |
 LL |     _custom = &Custom - _custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:385:15
+  --> tests/ui/arithmetic_side_effects.rs:384:15
    |
 LL |     _custom = _custom / Custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:386:15
+  --> tests/ui/arithmetic_side_effects.rs:385:15
    |
 LL |     _custom = _custom / &Custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:387:15
+  --> tests/ui/arithmetic_side_effects.rs:386:15
    |
 LL |     _custom = _custom % Custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:388:15
+  --> tests/ui/arithmetic_side_effects.rs:387:15
    |
 LL |     _custom = _custom % &Custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:389:15
+  --> tests/ui/arithmetic_side_effects.rs:388:15
    |
 LL |     _custom = _custom * Custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:390:15
+  --> tests/ui/arithmetic_side_effects.rs:389:15
    |
 LL |     _custom = _custom * &Custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:391:15
+  --> tests/ui/arithmetic_side_effects.rs:390:15
    |
 LL |     _custom = Custom * _custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:392:15
+  --> tests/ui/arithmetic_side_effects.rs:391:15
    |
 LL |     _custom = &Custom * _custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:393:15
+  --> tests/ui/arithmetic_side_effects.rs:392:15
    |
 LL |     _custom = Custom + &Custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:394:15
+  --> tests/ui/arithmetic_side_effects.rs:393:15
    |
 LL |     _custom = &Custom + Custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:395:15
+  --> tests/ui/arithmetic_side_effects.rs:394:15
    |
 LL |     _custom = &Custom + &Custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:396:15
+  --> tests/ui/arithmetic_side_effects.rs:395:15
    |
 LL |     _custom = _custom >> _custom;
    |               ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:397:15
+  --> tests/ui/arithmetic_side_effects.rs:396:15
    |
 LL |     _custom = _custom >> &_custom;
    |               ^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:398:15
+  --> tests/ui/arithmetic_side_effects.rs:397:15
    |
 LL |     _custom = Custom << _custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:399:15
+  --> tests/ui/arithmetic_side_effects.rs:398:15
    |
 LL |     _custom = &Custom << _custom;
    |               ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:402:23
+  --> tests/ui/arithmetic_side_effects.rs:401:23
    |
 LL |     _n.saturating_div(0);
    |                       ^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:403:21
+  --> tests/ui/arithmetic_side_effects.rs:402:21
    |
 LL |     _n.wrapping_div(0);
    |                     ^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:404:21
+  --> tests/ui/arithmetic_side_effects.rs:403:21
    |
 LL |     _n.wrapping_rem(0);
    |                     ^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:405:28
+  --> tests/ui/arithmetic_side_effects.rs:404:28
    |
 LL |     _n.wrapping_rem_euclid(0);
    |                            ^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:407:23
+  --> tests/ui/arithmetic_side_effects.rs:406:23
    |
 LL |     _n.saturating_div(_n);
    |                       ^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:408:21
+  --> tests/ui/arithmetic_side_effects.rs:407:21
    |
 LL |     _n.wrapping_div(_n);
    |                     ^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:409:21
+  --> tests/ui/arithmetic_side_effects.rs:408:21
    |
 LL |     _n.wrapping_rem(_n);
    |                     ^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:410:28
+  --> tests/ui/arithmetic_side_effects.rs:409:28
    |
 LL |     _n.wrapping_rem_euclid(_n);
    |                            ^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:413:10
+  --> tests/ui/arithmetic_side_effects.rs:412:10
    |
 LL |     _n = -_n;
    |          ^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:414:10
+  --> tests/ui/arithmetic_side_effects.rs:413:10
    |
 LL |     _n = -&_n;
    |          ^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:415:15
+  --> tests/ui/arithmetic_side_effects.rs:414:15
    |
 LL |     _custom = -_custom;
    |               ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:416:15
+  --> tests/ui/arithmetic_side_effects.rs:415:15
    |
 LL |     _custom = -&_custom;
    |               ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:425:5
+  --> tests/ui/arithmetic_side_effects.rs:424:5
    |
 LL |     1 + i;
    |     ^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:426:5
+  --> tests/ui/arithmetic_side_effects.rs:425:5
    |
 LL |     i * 2;
    |     ^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:427:5
+  --> tests/ui/arithmetic_side_effects.rs:426:5
    |
 LL |     1 % i / 2;
    |     ^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:428:5
+  --> tests/ui/arithmetic_side_effects.rs:427:5
    |
 LL |     i - 2 + 2 - i;
    |     ^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:429:5
+  --> tests/ui/arithmetic_side_effects.rs:428:5
    |
 LL |     -i;
    |     ^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:440:5
+  --> tests/ui/arithmetic_side_effects.rs:439:5
    |
 LL |     i += 1;
    |     ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:441:5
+  --> tests/ui/arithmetic_side_effects.rs:440:5
    |
 LL |     i -= 1;
    |     ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:442:5
+  --> tests/ui/arithmetic_side_effects.rs:441:5
    |
 LL |     i *= 2;
    |     ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:444:5
+  --> tests/ui/arithmetic_side_effects.rs:443:5
    |
 LL |     i /= 0;
    |     ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:446:5
+  --> tests/ui/arithmetic_side_effects.rs:445:5
    |
 LL |     i /= var1;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:447:5
+  --> tests/ui/arithmetic_side_effects.rs:446:5
    |
 LL |     i /= var2;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:449:5
+  --> tests/ui/arithmetic_side_effects.rs:448:5
    |
 LL |     i %= 0;
    |     ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:451:5
+  --> tests/ui/arithmetic_side_effects.rs:450:5
    |
 LL |     i %= var1;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:452:5
+  --> tests/ui/arithmetic_side_effects.rs:451:5
    |
 LL |     i %= var2;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:462:5
+  --> tests/ui/arithmetic_side_effects.rs:461:5
    |
 LL |     10 / a
    |     ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:516:9
+  --> tests/ui/arithmetic_side_effects.rs:515:9
    |
 LL |         x / maybe_zero
    |         ^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:520:9
+  --> tests/ui/arithmetic_side_effects.rs:519:9
    |
 LL |         x % maybe_zero
    |         ^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:531:5
+  --> tests/ui/arithmetic_side_effects.rs:530:5
    |
 LL |     one.add_assign(1);
    |     ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> tests/ui/arithmetic_side_effects.rs:535:5
+  --> tests/ui/arithmetic_side_effects.rs:534:5
    |
 LL |     one.sub_assign(1);
    |     ^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/auxiliary/proc_macro_attr.rs b/tests/ui/auxiliary/proc_macro_attr.rs
index f6fdebaf25274..e72d6b6ceadfd 100644
--- a/tests/ui/auxiliary/proc_macro_attr.rs
+++ b/tests/ui/auxiliary/proc_macro_attr.rs
@@ -11,8 +11,8 @@ use quote::{quote, quote_spanned};
 use syn::spanned::Spanned;
 use syn::token::Star;
 use syn::{
-    parse_macro_input, parse_quote, FnArg, ImplItem, ItemFn, ItemImpl, ItemStruct, ItemTrait, Lifetime, Pat, PatIdent,
-    PatType, Signature, TraitItem, Type, Visibility,
+    FnArg, ImplItem, ItemFn, ItemImpl, ItemStruct, ItemTrait, Lifetime, Pat, PatIdent, PatType, Signature, TraitItem,
+    Type, Visibility, parse_macro_input, parse_quote,
 };
 
 #[proc_macro_attribute]
diff --git a/tests/ui/auxiliary/proc_macro_derive.rs b/tests/ui/auxiliary/proc_macro_derive.rs
index 4c3df47226909..bd90042c1da82 100644
--- a/tests/ui/auxiliary/proc_macro_derive.rs
+++ b/tests/ui/auxiliary/proc_macro_derive.rs
@@ -5,7 +5,7 @@
 
 extern crate proc_macro;
 
-use proc_macro::{quote, Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
+use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree, quote};
 
 #[proc_macro_derive(DeriveSomething)]
 pub fn derive(_: TokenStream) -> TokenStream {
diff --git a/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs b/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs
index 79e8eff3aa101..3d6f164d35833 100644
--- a/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs
+++ b/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs
@@ -1,5 +1,5 @@
 extern crate proc_macro;
-use proc_macro::{token_stream, Delimiter, Group, Ident, Span, TokenStream, TokenTree};
+use proc_macro::{Delimiter, Group, Ident, Span, TokenStream, TokenTree, token_stream};
 
 fn read_ident(iter: &mut token_stream::IntoIter) -> Ident {
     match iter.next() {
diff --git a/tests/ui/auxiliary/proc_macros.rs b/tests/ui/auxiliary/proc_macros.rs
index ed7412f7c4076..1a2a4ec231143 100644
--- a/tests/ui/auxiliary/proc_macros.rs
+++ b/tests/ui/auxiliary/proc_macros.rs
@@ -5,9 +5,9 @@
 extern crate proc_macro;
 
 use core::mem;
-use proc_macro::token_stream::IntoIter;
 use proc_macro::Delimiter::{self, Brace, Parenthesis};
 use proc_macro::Spacing::{self, Alone, Joint};
+use proc_macro::token_stream::IntoIter;
 use proc_macro::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree as TT};
 use syn::spanned::Spanned;
 
diff --git a/tests/ui/borrow_interior_mutable_const/others.rs b/tests/ui/borrow_interior_mutable_const/others.rs
index 452d1b198133e..de220505c3e08 100644
--- a/tests/ui/borrow_interior_mutable_const/others.rs
+++ b/tests/ui/borrow_interior_mutable_const/others.rs
@@ -5,8 +5,8 @@
 use std::borrow::Cow;
 use std::cell::{Cell, UnsafeCell};
 use std::fmt::Display;
-use std::sync::atomic::{AtomicUsize, Ordering};
 use std::sync::Once;
+use std::sync::atomic::{AtomicUsize, Ordering};
 
 const ATOMIC: AtomicUsize = AtomicUsize::new(5);
 const CELL: Cell<usize> = Cell::new(6);
diff --git a/tests/ui/declare_interior_mutable_const/others.rs b/tests/ui/declare_interior_mutable_const/others.rs
index 9dafad8b784b9..0dccf18c49303 100644
--- a/tests/ui/declare_interior_mutable_const/others.rs
+++ b/tests/ui/declare_interior_mutable_const/others.rs
@@ -4,8 +4,8 @@ use std::borrow::Cow;
 use std::cell::Cell;
 use std::fmt::Display;
 use std::ptr;
-use std::sync::atomic::AtomicUsize;
 use std::sync::Once;
+use std::sync::atomic::AtomicUsize;
 
 const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR: interior mutable
 const CELL: Cell<usize> = Cell::new(6); //~ ERROR: interior mutable
diff --git a/tests/ui/field_reassign_with_default.rs b/tests/ui/field_reassign_with_default.rs
index 620cffb4f04da..2a432751952d0 100644
--- a/tests/ui/field_reassign_with_default.rs
+++ b/tests/ui/field_reassign_with_default.rs
@@ -192,8 +192,8 @@ struct WrapperMulti<T, U> {
 }
 
 mod issue6312 {
-    use std::sync::atomic::AtomicBool;
     use std::sync::Arc;
+    use std::sync::atomic::AtomicBool;
 
     // do not lint: type implements `Drop` but not all fields are `Copy`
     #[derive(Clone, Default)]
diff --git a/tests/ui/format_args.fixed b/tests/ui/format_args.fixed
index 4d812f6bf1dce..20d1e3d905042 100644
--- a/tests/ui/format_args.fixed
+++ b/tests/ui/format_args.fixed
@@ -8,7 +8,7 @@
     clippy::uninlined_format_args
 )]
 
-use std::io::{stdout, Write};
+use std::io::{Write, stdout};
 use std::ops::Deref;
 use std::panic::Location;
 
diff --git a/tests/ui/format_args.rs b/tests/ui/format_args.rs
index d242623feb62a..18ab223db78a1 100644
--- a/tests/ui/format_args.rs
+++ b/tests/ui/format_args.rs
@@ -8,7 +8,7 @@
     clippy::uninlined_format_args
 )]
 
-use std::io::{stdout, Write};
+use std::io::{Write, stdout};
 use std::ops::Deref;
 use std::panic::Location;
 
diff --git a/tests/ui/format_args_unfixable.rs b/tests/ui/format_args_unfixable.rs
index b7492e38b256b..f04715f4f0182 100644
--- a/tests/ui/format_args_unfixable.rs
+++ b/tests/ui/format_args_unfixable.rs
@@ -2,7 +2,7 @@
 #![allow(unused)]
 #![allow(clippy::assertions_on_constants, clippy::eq_op, clippy::uninlined_format_args)]
 
-use std::io::{stdout, Error, ErrorKind, Write};
+use std::io::{Error, ErrorKind, Write, stdout};
 use std::ops::Deref;
 use std::panic::Location;
 
diff --git a/tests/ui/ignored_unit_patterns.fixed b/tests/ui/ignored_unit_patterns.fixed
index 118f0b4889529..fde4043730986 100644
--- a/tests/ui/ignored_unit_patterns.fixed
+++ b/tests/ui/ignored_unit_patterns.fixed
@@ -21,15 +21,12 @@ fn main() {
     let _ = foo().map_err(|()| todo!());
     //~^ ERROR: matching over `()` is more explicit
 
-    println!(
-        "{:?}",
-        match foo() {
-            Ok(()) => {},
-            //~^ ERROR: matching over `()` is more explicit
-            Err(()) => {},
-            //~^ ERROR: matching over `()` is more explicit
-        }
-    );
+    println!("{:?}", match foo() {
+        Ok(()) => {},
+        //~^ ERROR: matching over `()` is more explicit
+        Err(()) => {},
+        //~^ ERROR: matching over `()` is more explicit
+    });
 }
 
 // ignored_unit_patterns in derive macro should be ok
diff --git a/tests/ui/ignored_unit_patterns.rs b/tests/ui/ignored_unit_patterns.rs
index 92feb9e6c2814..528844d76e051 100644
--- a/tests/ui/ignored_unit_patterns.rs
+++ b/tests/ui/ignored_unit_patterns.rs
@@ -21,15 +21,12 @@ fn main() {
     let _ = foo().map_err(|_| todo!());
     //~^ ERROR: matching over `()` is more explicit
 
-    println!(
-        "{:?}",
-        match foo() {
-            Ok(_) => {},
-            //~^ ERROR: matching over `()` is more explicit
-            Err(_) => {},
-            //~^ ERROR: matching over `()` is more explicit
-        }
-    );
+    println!("{:?}", match foo() {
+        Ok(_) => {},
+        //~^ ERROR: matching over `()` is more explicit
+        Err(_) => {},
+        //~^ ERROR: matching over `()` is more explicit
+    });
 }
 
 // ignored_unit_patterns in derive macro should be ok
diff --git a/tests/ui/ignored_unit_patterns.stderr b/tests/ui/ignored_unit_patterns.stderr
index 00a254e39192c..54ff4454d6bdf 100644
--- a/tests/ui/ignored_unit_patterns.stderr
+++ b/tests/ui/ignored_unit_patterns.stderr
@@ -26,31 +26,31 @@ LL |     let _ = foo().map_err(|_| todo!());
    |                            ^ help: use `()` instead of `_`: `()`
 
 error: matching over `()` is more explicit
-  --> tests/ui/ignored_unit_patterns.rs:27:16
+  --> tests/ui/ignored_unit_patterns.rs:25:12
    |
-LL |             Ok(_) => {},
-   |                ^ help: use `()` instead of `_`: `()`
+LL |         Ok(_) => {},
+   |            ^ help: use `()` instead of `_`: `()`
 
 error: matching over `()` is more explicit
-  --> tests/ui/ignored_unit_patterns.rs:29:17
+  --> tests/ui/ignored_unit_patterns.rs:27:13
    |
-LL |             Err(_) => {},
-   |                 ^ help: use `()` instead of `_`: `()`
+LL |         Err(_) => {},
+   |             ^ help: use `()` instead of `_`: `()`
 
 error: matching over `()` is more explicit
-  --> tests/ui/ignored_unit_patterns.rs:41:9
+  --> tests/ui/ignored_unit_patterns.rs:38:9
    |
 LL |     let _ = foo().unwrap();
    |         ^ help: use `()` instead of `_`: `()`
 
 error: matching over `()` is more explicit
-  --> tests/ui/ignored_unit_patterns.rs:50:13
+  --> tests/ui/ignored_unit_patterns.rs:47:13
    |
 LL |         (1, _) => unimplemented!(),
    |             ^ help: use `()` instead of `_`: `()`
 
 error: matching over `()` is more explicit
-  --> tests/ui/ignored_unit_patterns.rs:57:13
+  --> tests/ui/ignored_unit_patterns.rs:54:13
    |
 LL |     for (x, _) in v {
    |             ^ help: use `()` instead of `_`: `()`
diff --git a/tests/ui/incompatible_msrv.rs b/tests/ui/incompatible_msrv.rs
index 8ef1f554bc35d..c23df223d5088 100644
--- a/tests/ui/incompatible_msrv.rs
+++ b/tests/ui/incompatible_msrv.rs
@@ -2,8 +2,8 @@
 #![feature(custom_inner_attributes)]
 #![clippy::msrv = "1.3.0"]
 
-use std::collections::hash_map::Entry;
 use std::collections::HashMap;
+use std::collections::hash_map::Entry;
 use std::future::Future;
 use std::thread::sleep;
 use std::time::Duration;
diff --git a/tests/ui/legacy_numeric_constants.fixed b/tests/ui/legacy_numeric_constants.fixed
index a6ef8f8c119a5..3a2294ef4c59b 100644
--- a/tests/ui/legacy_numeric_constants.fixed
+++ b/tests/ui/legacy_numeric_constants.fixed
@@ -22,8 +22,8 @@ macro_rules! b {
     };
 }
 
-use std::u32::MAX;
 use std::u8::MIN;
+use std::u32::MAX;
 use std::{f64, u32};
 
 #[warn(clippy::legacy_numeric_constants)]
@@ -99,8 +99,8 @@ fn allow() {
     ::std::primitive::u8::MIN;
     ::std::u8::MIN;
     ::std::primitive::u8::min_value();
-    use std::u64;
     use std::u8::MIN;
+    use std::u64;
 }
 
 #[warn(clippy::legacy_numeric_constants)]
diff --git a/tests/ui/legacy_numeric_constants.rs b/tests/ui/legacy_numeric_constants.rs
index cd633545372cd..6cb3e694ea145 100644
--- a/tests/ui/legacy_numeric_constants.rs
+++ b/tests/ui/legacy_numeric_constants.rs
@@ -22,8 +22,8 @@ macro_rules! b {
     };
 }
 
-use std::u32::MAX;
 use std::u8::MIN;
+use std::u32::MAX;
 use std::{f64, u32};
 
 #[warn(clippy::legacy_numeric_constants)]
@@ -99,8 +99,8 @@ fn allow() {
     ::std::primitive::u8::MIN;
     ::std::u8::MIN;
     ::std::primitive::u8::min_value();
-    use std::u64;
     use std::u8::MIN;
+    use std::u64;
 }
 
 #[warn(clippy::legacy_numeric_constants)]
diff --git a/tests/ui/manual_saturating_arithmetic.fixed b/tests/ui/manual_saturating_arithmetic.fixed
index 41a32df32ee40..528a65790c4c8 100644
--- a/tests/ui/manual_saturating_arithmetic.fixed
+++ b/tests/ui/manual_saturating_arithmetic.fixed
@@ -1,6 +1,6 @@
 #![allow(clippy::legacy_numeric_constants, unused_imports)]
 
-use std::{i128, i32, u128, u32};
+use std::{i32, i128, u32, u128};
 
 fn main() {
     let _ = 1u32.saturating_add(1);
diff --git a/tests/ui/manual_saturating_arithmetic.rs b/tests/ui/manual_saturating_arithmetic.rs
index 3a6b32d806904..55f3720dfcc06 100644
--- a/tests/ui/manual_saturating_arithmetic.rs
+++ b/tests/ui/manual_saturating_arithmetic.rs
@@ -1,6 +1,6 @@
 #![allow(clippy::legacy_numeric_constants, unused_imports)]
 
-use std::{i128, i32, u128, u32};
+use std::{i32, i128, u32, u128};
 
 fn main() {
     let _ = 1u32.checked_add(1).unwrap_or(u32::max_value());
diff --git a/tests/ui/must_use_candidates.fixed b/tests/ui/must_use_candidates.fixed
index adb266ffbc8dd..2459af6068845 100644
--- a/tests/ui/must_use_candidates.fixed
+++ b/tests/ui/must_use_candidates.fixed
@@ -7,8 +7,8 @@
 )]
 #![warn(clippy::must_use_candidate)]
 use std::rc::Rc;
-use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::Arc;
+use std::sync::atomic::{AtomicBool, Ordering};
 
 pub struct MyAtomic(AtomicBool);
 pub struct MyPure;
diff --git a/tests/ui/must_use_candidates.rs b/tests/ui/must_use_candidates.rs
index 49bb16af788f1..5f9b2449552a9 100644
--- a/tests/ui/must_use_candidates.rs
+++ b/tests/ui/must_use_candidates.rs
@@ -7,8 +7,8 @@
 )]
 #![warn(clippy::must_use_candidate)]
 use std::rc::Rc;
-use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::Arc;
+use std::sync::atomic::{AtomicBool, Ordering};
 
 pub struct MyAtomic(AtomicBool);
 pub struct MyPure;
diff --git a/tests/ui/mut_key.rs b/tests/ui/mut_key.rs
index 81d8732b3b210..43ff705c47750 100644
--- a/tests/ui/mut_key.rs
+++ b/tests/ui/mut_key.rs
@@ -2,9 +2,9 @@ use std::cell::Cell;
 use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
 use std::hash::{Hash, Hasher};
 use std::rc::Rc;
+use std::sync::Arc;
 use std::sync::atomic::AtomicUsize;
 use std::sync::atomic::Ordering::Relaxed;
-use std::sync::Arc;
 
 struct Key(AtomicUsize);
 
diff --git a/tests/ui/non_zero_suggestions.fixed b/tests/ui/non_zero_suggestions.fixed
index 9851063782e70..e67c992fdde01 100644
--- a/tests/ui/non_zero_suggestions.fixed
+++ b/tests/ui/non_zero_suggestions.fixed
@@ -1,5 +1,5 @@
 #![warn(clippy::non_zero_suggestions)]
-use std::num::{NonZeroI16, NonZeroI8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
+use std::num::{NonZeroI8, NonZeroI16, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize};
 
 fn main() {
     /// Positive test cases (lint should trigger)
diff --git a/tests/ui/non_zero_suggestions.rs b/tests/ui/non_zero_suggestions.rs
index 1605c459248c2..de82371a8f294 100644
--- a/tests/ui/non_zero_suggestions.rs
+++ b/tests/ui/non_zero_suggestions.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::non_zero_suggestions)]
-use std::num::{NonZeroI16, NonZeroI8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
+use std::num::{NonZeroI8, NonZeroI16, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize};
 
 fn main() {
     /// Positive test cases (lint should trigger)
diff --git a/tests/ui/non_zero_suggestions_unfixable.rs b/tests/ui/non_zero_suggestions_unfixable.rs
index 4eb22a8d4c717..193c710e589ff 100644
--- a/tests/ui/non_zero_suggestions_unfixable.rs
+++ b/tests/ui/non_zero_suggestions_unfixable.rs
@@ -1,6 +1,6 @@
 #![warn(clippy::non_zero_suggestions)]
 //@no-rustfix
-use std::num::{NonZeroI16, NonZeroI8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
+use std::num::{NonZeroI8, NonZeroI16, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize};
 
 fn main() {
     let x: u64 = u64::from(NonZeroU32::new(5).unwrap().get());
diff --git a/tests/ui/single_match.fixed b/tests/ui/single_match.fixed
index dcf5a1d33c2ac..4016b2699d6b4 100644
--- a/tests/ui/single_match.fixed
+++ b/tests/ui/single_match.fixed
@@ -39,8 +39,8 @@ enum Foo {
     Bar,
     Baz(u8),
 }
-use std::borrow::Cow;
 use Foo::*;
+use std::borrow::Cow;
 
 fn single_match_know_enum() {
     let x = Some(1u8);
diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs
index 3ba5eebd01b71..75edaa606053d 100644
--- a/tests/ui/single_match.rs
+++ b/tests/ui/single_match.rs
@@ -51,8 +51,8 @@ enum Foo {
     Bar,
     Baz(u8),
 }
-use std::borrow::Cow;
 use Foo::*;
+use std::borrow::Cow;
 
 fn single_match_know_enum() {
     let x = Some(1u8);
diff --git a/tests/ui/suspicious_to_owned.rs b/tests/ui/suspicious_to_owned.rs
index f32b07d45f635..794c2e7174afe 100644
--- a/tests/ui/suspicious_to_owned.rs
+++ b/tests/ui/suspicious_to_owned.rs
@@ -3,7 +3,7 @@
 #![warn(clippy::implicit_clone)]
 #![allow(clippy::redundant_clone)]
 use std::borrow::Cow;
-use std::ffi::{c_char, CStr};
+use std::ffi::{CStr, c_char};
 
 fn main() {
     let moo = "Moooo";
diff --git a/tests/ui/transmute_collection.rs b/tests/ui/transmute_collection.rs
index e30b34a5d7d6f..6748b66e0eb6c 100644
--- a/tests/ui/transmute_collection.rs
+++ b/tests/ui/transmute_collection.rs
@@ -2,7 +2,7 @@
 #![allow(clippy::missing_transmute_annotations)]
 
 use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
-use std::mem::{transmute, MaybeUninit};
+use std::mem::{MaybeUninit, transmute};
 
 fn main() {
     unsafe {
diff --git a/tests/ui/transmute_undefined_repr.rs b/tests/ui/transmute_undefined_repr.rs
index dd4bac7f1ed72..5b16d71f1142a 100644
--- a/tests/ui/transmute_undefined_repr.rs
+++ b/tests/ui/transmute_undefined_repr.rs
@@ -8,7 +8,7 @@
 
 use core::any::TypeId;
 use core::ffi::c_void;
-use core::mem::{size_of, transmute, MaybeUninit};
+use core::mem::{MaybeUninit, size_of, transmute};
 use core::ptr::NonNull;
 
 fn value<T>() -> T {

From 009134d079a9b5c55de7877a070ee8de1d9843b5 Mon Sep 17 00:00:00 2001
From: Philipp Krones <hello@philkrones.com>
Date: Sun, 22 Sep 2024 20:52:58 +0200
Subject: [PATCH 106/114] Bump nightly version -> 2024-09-22

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

diff --git a/rust-toolchain b/rust-toolchain
index 854fcda2dabda..b431599c224ef 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,4 +1,4 @@
 [toolchain]
-channel = "nightly-2024-09-05"
+channel = "nightly-2024-09-22"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
 profile = "minimal"

From cc2f447f073abdd103b749ce6725c9c6f60934f1 Mon Sep 17 00:00:00 2001
From: Samuel Tardieu <sam@rfc1149.net>
Date: Thu, 12 Sep 2024 11:34:07 +0200
Subject: [PATCH 107/114] Check that #[deny(allow_attributes)] do not issue
 spurious messages

---
 tests/ui/allow_attributes.fixed | 7 +++++++
 tests/ui/allow_attributes.rs    | 7 +++++++
 2 files changed, 14 insertions(+)

diff --git a/tests/ui/allow_attributes.fixed b/tests/ui/allow_attributes.fixed
index 49ee3ee17c70f..058dbb77a3205 100644
--- a/tests/ui/allow_attributes.fixed
+++ b/tests/ui/allow_attributes.fixed
@@ -58,3 +58,10 @@ fn msrv_1_80() {
     #[allow(unused)]
     let x = 1;
 }
+
+#[deny(clippy::allow_attributes)]
+fn deny_allow_attributes() -> Option<u8> {
+    let allow = None;
+    allow?;
+    Some(42)
+}
diff --git a/tests/ui/allow_attributes.rs b/tests/ui/allow_attributes.rs
index 854acf8348dcb..6d94ce50e4c37 100644
--- a/tests/ui/allow_attributes.rs
+++ b/tests/ui/allow_attributes.rs
@@ -58,3 +58,10 @@ fn msrv_1_80() {
     #[allow(unused)]
     let x = 1;
 }
+
+#[deny(clippy::allow_attributes)]
+fn deny_allow_attributes() -> Option<u8> {
+    let allow = None;
+    allow?;
+    Some(42)
+}

From acff51187115444038662ff4e9e23403a96d085d Mon Sep 17 00:00:00 2001
From: Samuel Tardieu <sam@rfc1149.net>
Date: Sat, 21 Sep 2024 19:13:37 +0200
Subject: [PATCH 108/114] Lint comparison to empty slice using `PartialEq`
 methods

---
 clippy_lints/src/len_zero.rs        | 15 ++++++++++++++-
 tests/ui/comparison_to_empty.fixed  |  8 ++++++++
 tests/ui/comparison_to_empty.rs     |  8 ++++++++
 tests/ui/comparison_to_empty.stderr | 26 +++++++++++++++++++++++++-
 4 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs
index c1ba66de57e5a..3cd5f76e6b674 100644
--- a/clippy_lints/src/len_zero.rs
+++ b/clippy_lints/src/len_zero.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::{SpanRangeExt, snippet_with_context};
 use clippy_utils::sugg::{Sugg, has_enclosing_paren};
-use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators};
+use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, is_trait_method, peel_ref_operators};
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
@@ -185,6 +185,19 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
             );
         }
 
+        if let ExprKind::MethodCall(method, lhs_expr, [rhs_expr], _) = expr.kind
+            && is_trait_method(cx, expr, sym::PartialEq)
+            && !expr.span.from_expansion()
+        {
+            check_empty_expr(
+                cx,
+                expr.span,
+                lhs_expr,
+                peel_ref_operators(cx, rhs_expr),
+                (method.ident.name == sym::ne).then_some("!").unwrap_or_default(),
+            );
+        }
+
         if let ExprKind::Binary(Spanned { node: cmp, .. }, left, right) = expr.kind
             && !expr.span.from_expansion()
         {
diff --git a/tests/ui/comparison_to_empty.fixed b/tests/ui/comparison_to_empty.fixed
index e102b13a76185..a2a3dd9086d4c 100644
--- a/tests/ui/comparison_to_empty.fixed
+++ b/tests/ui/comparison_to_empty.fixed
@@ -33,4 +33,12 @@ fn main() {
     if let [0] = &*s
         && s == [0]
     {}
+
+    // Also lint the `PartialEq` methods
+    let s = String::new();
+    let _ = s.is_empty();
+    let _ = !s.is_empty();
+    let v = vec![0];
+    let _ = v.is_empty();
+    let _ = !v.is_empty();
 }
diff --git a/tests/ui/comparison_to_empty.rs b/tests/ui/comparison_to_empty.rs
index 69a6c967d3821..7c5689a4bbec9 100644
--- a/tests/ui/comparison_to_empty.rs
+++ b/tests/ui/comparison_to_empty.rs
@@ -33,4 +33,12 @@ fn main() {
     if let [0] = &*s
         && s == [0]
     {}
+
+    // Also lint the `PartialEq` methods
+    let s = String::new();
+    let _ = s.eq("");
+    let _ = s.ne("");
+    let v = vec![0];
+    let _ = v.eq(&[]);
+    let _ = v.ne(&[]);
 }
diff --git a/tests/ui/comparison_to_empty.stderr b/tests/ui/comparison_to_empty.stderr
index 6b027459ed347..2ee0efc7dbb19 100644
--- a/tests/ui/comparison_to_empty.stderr
+++ b/tests/ui/comparison_to_empty.stderr
@@ -55,5 +55,29 @@ error: comparison to empty slice
 LL |         && s == []
    |            ^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()`
 
-error: aborting due to 9 previous errors
+error: comparison to empty slice
+  --> tests/ui/comparison_to_empty.rs:39:13
+   |
+LL |     let _ = s.eq("");
+   |             ^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()`
+
+error: comparison to empty slice
+  --> tests/ui/comparison_to_empty.rs:40:13
+   |
+LL |     let _ = s.ne("");
+   |             ^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!s.is_empty()`
+
+error: comparison to empty slice
+  --> tests/ui/comparison_to_empty.rs:42:13
+   |
+LL |     let _ = v.eq(&[]);
+   |             ^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `v.is_empty()`
+
+error: comparison to empty slice
+  --> tests/ui/comparison_to_empty.rs:43:13
+   |
+LL |     let _ = v.ne(&[]);
+   |             ^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!v.is_empty()`
+
+error: aborting due to 13 previous errors
 

From d099ceddadde4197b08c2de404100a627d3ba605 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Sat, 21 Sep 2024 16:11:15 +0100
Subject: [PATCH 109/114] Split def_path_res into two parts

---
 clippy_utils/src/lib.rs | 40 +++++++++++++++++++++++++---------------
 1 file changed, 25 insertions(+), 15 deletions(-)

diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index a925549b0bff0..2fee6473910b4 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -671,6 +671,17 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Re
     }
 }
 
+/// Finds the crates called `name`, may be multiple due to multiple major versions.
+pub fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> Vec<Res> {
+    tcx.crates(())
+        .iter()
+        .copied()
+        .filter(move |&num| tcx.crate_name(num) == name)
+        .map(CrateNum::as_def_id)
+        .map(|id| Res::Def(tcx.def_kind(id), id))
+        .collect()
+}
+
 /// Resolves a def path like `std::vec::Vec`.
 ///
 /// Can return multiple resolutions when there are multiple versions of the same crate, e.g.
@@ -681,15 +692,7 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Re
 ///
 /// This function is expensive and should be used sparingly.
 pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> {
-    fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator<Item = DefId> + '_ {
-        tcx.crates(())
-            .iter()
-            .copied()
-            .filter(move |&num| tcx.crate_name(num) == name)
-            .map(CrateNum::as_def_id)
-    }
-
-    let (base, mut path) = match *path {
+    let (base, path) = match *path {
         [primitive] => {
             return vec![PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy)];
         },
@@ -705,18 +708,25 @@ pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> {
         None
     };
 
-    let starts = find_primitive_impls(tcx, base)
-        .chain(find_crates(tcx, base_sym))
+    let crates = find_primitive_impls(tcx, base)
         .chain(local_crate)
-        .map(|id| Res::Def(tcx.def_kind(id), id));
+        .map(|id| Res::Def(tcx.def_kind(id), id))
+        .chain(find_crates(tcx, base_sym))
+        .collect();
 
-    let mut resolutions: Vec<Res> = starts.collect();
+    def_path_res_with_base(tcx, crates, path)
+}
 
+/// Resolves a def path like `vec::Vec` with the base `std`.
+///
+/// This is lighter than [`def_path_res`], and should be called with [`find_crates`] looking up
+/// items from the same crate repeatedly, although should still be used sparingly.
+pub fn def_path_res_with_base(tcx: TyCtxt<'_>, mut base: Vec<Res>, mut path: &[&str]) -> Vec<Res> {
     while let [segment, rest @ ..] = path {
         path = rest;
         let segment = Symbol::intern(segment);
 
-        resolutions = resolutions
+        base = base
             .into_iter()
             .filter_map(|res| res.opt_def_id())
             .flat_map(|def_id| {
@@ -735,7 +745,7 @@ pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> {
             .collect();
     }
 
-    resolutions
+    base
 }
 
 /// Resolves a def path like `std::vec::Vec` to its [`DefId`]s, see [`def_path_res`].

From 6b34c8df2cd5db6626e00564446b886b3827b080 Mon Sep 17 00:00:00 2001
From: GnomedDev <david2005thomas@gmail.com>
Date: Sat, 21 Sep 2024 16:21:05 +0100
Subject: [PATCH 110/114] Avoid looking regex crate up multiple times

---
 clippy_lints/src/regex.rs | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs
index f6ef02b7c2330..12cbdb854eff1 100644
--- a/clippy_lints/src/regex.rs
+++ b/clippy_lints/src/regex.rs
@@ -3,7 +3,7 @@ use std::fmt::Display;
 use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
 use clippy_utils::source::SpanRangeExt;
-use clippy_utils::{def_path_def_ids, path_def_id, paths};
+use clippy_utils::{def_path_res_with_base, find_crates, path_def_id, paths};
 use rustc_ast::ast::{LitKind, StrStyle};
 use rustc_hir::def_id::DefIdMap;
 use rustc_hir::{BorrowKind, Expr, ExprKind};
@@ -75,11 +75,14 @@ impl<'tcx> LateLintPass<'tcx> for Regex {
         // We don't use `match_def_path` here because that relies on matching the exact path, which changed
         // between regex 1.8 and 1.9
         //
-        // `def_path_def_ids` will resolve through re-exports but is relatively heavy, so we only perform
-        // the operation once and store the results
-        let mut resolve = |path, kind| {
-            for id in def_path_def_ids(cx.tcx, path) {
-                self.definitions.insert(id, kind);
+        // `def_path_res_with_base` will resolve through re-exports but is relatively heavy, so we only
+        // perform the operation once and store the results
+        let regex_crates = find_crates(cx.tcx, sym!(regex));
+        let mut resolve = |path: &[&str], kind: RegexKind| {
+            for res in def_path_res_with_base(cx.tcx, regex_crates.clone(), &path[1..]) {
+                if let Some(id) = res.opt_def_id() {
+                    self.definitions.insert(id, kind);
+                }
             }
         };
 

From 7f30dafa9b669379471f48ba6765c2f20e24dc14 Mon Sep 17 00:00:00 2001
From: Philipp Krones <hello@philkrones.com>
Date: Mon, 23 Sep 2024 17:56:32 +0200
Subject: [PATCH 111/114] Use contiguous spans for empty_line_after_*
 suggestion

Replacing an empty span (which an empty line is) with an empty string triggers a
debug assertion in rustc. This fixes the debug assertion by using contiguous
spans, with the same resulting suggestion.
---
 clippy_lints/src/doc/empty_line_after.rs      | 20 +++++++++++++++++--
 .../empty_line_after/outer_attribute.1.fixed  |  5 +++++
 .../empty_line_after/outer_attribute.2.fixed  |  5 +++++
 tests/ui/empty_line_after/outer_attribute.rs  |  7 +++++++
 .../empty_line_after/outer_attribute.stderr   | 15 +++++++++++++-
 5 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/clippy_lints/src/doc/empty_line_after.rs b/clippy_lints/src/doc/empty_line_after.rs
index 125b907706146..de7a2c2433f46 100644
--- a/clippy_lints/src/doc/empty_line_after.rs
+++ b/clippy_lints/src/doc/empty_line_after.rs
@@ -8,7 +8,7 @@ use rustc_errors::{Applicability, Diag, SuggestionStyle};
 use rustc_hir::{ItemKind, Node};
 use rustc_lexer::TokenKind;
 use rustc_lint::LateContext;
-use rustc_span::{ExpnKind, InnerSpan, Span, SpanData};
+use rustc_span::{BytePos, ExpnKind, InnerSpan, Span, SpanData};
 
 use super::{EMPTY_LINE_AFTER_DOC_COMMENTS, EMPTY_LINE_AFTER_OUTER_ATTR};
 
@@ -144,6 +144,19 @@ impl<'a> Gap<'a> {
             prev_chunk,
         })
     }
+
+    fn contiguous_empty_lines(&self) -> impl Iterator<Item = Span> + '_ {
+        self.empty_lines
+            // The `+ BytePos(1)` means "next line", because each empty line span is "N:1-N:1".
+            .chunk_by(|a, b| a.hi() + BytePos(1) == b.lo())
+            .map(|chunk| {
+                let first = chunk.first().expect("at least one empty line");
+                let last = chunk.last().expect("at least one empty line");
+                // The BytePos subtraction here is safe, as before an empty line, there must be at least one
+                // attribute/comment. The span needs to start at the end of the previous line.
+                first.with_lo(first.lo() - BytePos(1)).with_hi(last.hi())
+            })
+    }
 }
 
 /// If the node the attributes/docs apply to is the first in the module/crate suggest converting
@@ -192,6 +205,7 @@ fn check_gaps(cx: &LateContext<'_>, gaps: &[Gap<'_>]) -> bool {
         return false;
     };
     let empty_lines = || gaps.iter().flat_map(|gap| gap.empty_lines.iter().copied());
+    let contiguous_empty_lines = || gaps.iter().flat_map(Gap::contiguous_empty_lines);
     let mut has_comment = false;
     let mut has_attr = false;
     for gap in gaps {
@@ -227,7 +241,9 @@ fn check_gaps(cx: &LateContext<'_>, gaps: &[Gap<'_>]) -> bool {
 
             diag.multipart_suggestion_with_style(
                 format!("if the empty {lines} {are} unintentional remove {them}"),
-                empty_lines().map(|empty_line| (empty_line, String::new())).collect(),
+                contiguous_empty_lines()
+                    .map(|empty_lines| (empty_lines, String::new()))
+                    .collect(),
                 Applicability::MaybeIncorrect,
                 SuggestionStyle::HideCodeAlways,
             );
diff --git a/tests/ui/empty_line_after/outer_attribute.1.fixed b/tests/ui/empty_line_after/outer_attribute.1.fixed
index cd7ea24b6be35..36d80a2c95bf6 100644
--- a/tests/ui/empty_line_after/outer_attribute.1.fixed
+++ b/tests/ui/empty_line_after/outer_attribute.1.fixed
@@ -51,6 +51,11 @@ mod foo {}
 // Still lint cases where the empty line does not immediately follow the attribute
 fn comment_before_empty_line() {}
 
+//~v empty_line_after_outer_attr
+#[allow(unused)]
+// This comment is isolated
+pub fn isolated_comment() {}
+
 #[doc = "
 Returns the escaped value of the textual representation of
 
diff --git a/tests/ui/empty_line_after/outer_attribute.2.fixed b/tests/ui/empty_line_after/outer_attribute.2.fixed
index 1b044d2fcde41..0e8e4129e858c 100644
--- a/tests/ui/empty_line_after/outer_attribute.2.fixed
+++ b/tests/ui/empty_line_after/outer_attribute.2.fixed
@@ -54,6 +54,11 @@ mod foo {}
 // Still lint cases where the empty line does not immediately follow the attribute
 fn comment_before_empty_line() {}
 
+//~v empty_line_after_outer_attr
+#[allow(unused)]
+// This comment is isolated
+pub fn isolated_comment() {}
+
 #[doc = "
 Returns the escaped value of the textual representation of
 
diff --git a/tests/ui/empty_line_after/outer_attribute.rs b/tests/ui/empty_line_after/outer_attribute.rs
index 81e1a7ab8ed54..1295088ac00ed 100644
--- a/tests/ui/empty_line_after/outer_attribute.rs
+++ b/tests/ui/empty_line_after/outer_attribute.rs
@@ -60,6 +60,13 @@ mod foo {}
 
 fn comment_before_empty_line() {}
 
+//~v empty_line_after_outer_attr
+#[allow(unused)]
+
+// This comment is isolated
+
+pub fn isolated_comment() {}
+
 #[doc = "
 Returns the escaped value of the textual representation of
 
diff --git a/tests/ui/empty_line_after/outer_attribute.stderr b/tests/ui/empty_line_after/outer_attribute.stderr
index b73ebb4f6623f..958b40424a928 100644
--- a/tests/ui/empty_line_after/outer_attribute.stderr
+++ b/tests/ui/empty_line_after/outer_attribute.stderr
@@ -99,5 +99,18 @@ LL |   fn comment_before_empty_line() {}
    |
    = help: if the empty line is unintentional remove it
 
-error: aborting due to 8 previous errors
+error: empty lines after outer attribute
+  --> tests/ui/empty_line_after/outer_attribute.rs:64:1
+   |
+LL | / #[allow(unused)]
+LL | |
+LL | | // This comment is isolated
+LL | |
+   | |_
+LL |   pub fn isolated_comment() {}
+   |   ------------------------- the attribute applies to this function
+   |
+   = help: if the empty lines are unintentional remove them
+
+error: aborting due to 9 previous errors
 

From 907b6a1bc30f420c917e331ce006037b89d0e86e Mon Sep 17 00:00:00 2001
From: Philipp Krones <hello@philkrones.com>
Date: Tue, 24 Sep 2024 11:58:12 +0200
Subject: [PATCH 112/114] Update Cargo.lock

---
 Cargo.lock | 41 +++++++----------------------------------
 1 file changed, 7 insertions(+), 34 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index e973d7f9a2ae0..7555fb415fde9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -524,7 +524,7 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
 
 [[package]]
 name = "clippy"
-version = "0.1.82"
+version = "0.1.83"
 dependencies = [
  "anstream",
  "cargo_metadata 0.18.1",
@@ -547,13 +547,13 @@ dependencies = [
  "termize",
  "tokio",
  "toml 0.7.8",
- "ui_test 0.25.0",
+ "ui_test",
  "walkdir",
 ]
 
 [[package]]
 name = "clippy_config"
-version = "0.1.82"
+version = "0.1.83"
 dependencies = [
  "itertools",
  "serde",
@@ -576,7 +576,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_lints"
-version = "0.1.82"
+version = "0.1.83"
 dependencies = [
  "arrayvec",
  "cargo_metadata 0.18.1",
@@ -600,7 +600,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_utils"
-version = "0.1.82"
+version = "0.1.83"
 dependencies = [
  "arrayvec",
  "clippy_config",
@@ -902,7 +902,7 @@ dependencies = [
 
 [[package]]
 name = "declare_clippy_lint"
-version = "0.1.82"
+version = "0.1.83"
 dependencies = [
  "itertools",
  "quote",
@@ -2269,7 +2269,7 @@ dependencies = [
  "rustc_version",
  "smallvec",
  "tempfile",
- "ui_test 0.26.5",
+ "ui_test",
  "windows-sys 0.52.0",
 ]
 
@@ -5485,33 +5485,6 @@ version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
 
-[[package]]
-name = "ui_test"
-version = "0.25.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7e4f339f62edc873975c47115f9e71c5454ddaa37c1142b42fc0b2672c8dacb"
-dependencies = [
- "annotate-snippets 0.11.4",
- "anyhow",
- "bstr",
- "cargo-platform",
- "cargo_metadata 0.18.1",
- "color-eyre",
- "colored",
- "comma",
- "crossbeam-channel",
- "indicatif",
- "lazy_static",
- "levenshtein",
- "prettydiff",
- "regex",
- "rustc_version",
- "rustfix",
- "serde",
- "serde_json",
- "spanned",
-]
-
 [[package]]
 name = "ui_test"
 version = "0.26.5"

From f38b569ab64ae85308d7750af43863d11a74973c Mon Sep 17 00:00:00 2001
From: Philipp Krones <hello@philkrones.com>
Date: Tue, 24 Sep 2024 11:58:48 +0200
Subject: [PATCH 113/114] Hotfix: remove profile from clippy Cargo.toml

---
 src/tools/clippy/Cargo.toml | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index ddc27179ef2f2..cf810798d8cc1 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -67,10 +67,3 @@ harness = false
 [[test]]
 name = "dogfood"
 harness = false
-
-# quine-mc_cluskey makes up a significant part of the runtime in dogfood
-# due to the number of conditions in the clippy_lints crate
-# and enabling optimizations for that specific dependency helps a bit
-# without increasing total build times.
-[profile.dev.package.quine-mc_cluskey]
-opt-level = 3

From e60098bf8c09732eef92e9d2f2876508d9f39913 Mon Sep 17 00:00:00 2001
From: Philipp Krones <hello@philkrones.com>
Date: Tue, 24 Sep 2024 18:13:17 +0200
Subject: [PATCH 114/114] Remove unused import from Clippy versions.py file

---
 src/tools/clippy/util/versions.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/tools/clippy/util/versions.py b/src/tools/clippy/util/versions.py
index 7a21a840a6d9a..fee0d292df16f 100755
--- a/src/tools/clippy/util/versions.py
+++ b/src/tools/clippy/util/versions.py
@@ -2,7 +2,6 @@
 
 from string import Template
 import argparse
-import json
 import os
 import sys