about summary refs log tree commit diff
path: root/src/tools/clippy/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/tests')
-rw-r--r--src/tools/clippy/tests/ui-internal/symbol_as_str.fixed21
-rw-r--r--src/tools/clippy/tests/ui-internal/symbol_as_str.rs21
-rw-r--r--src/tools/clippy/tests/ui-internal/symbol_as_str.stderr76
-rw-r--r--src/tools/clippy/tests/ui-internal/symbol_as_str_unfixable.rs15
-rw-r--r--src/tools/clippy/tests/ui-internal/symbol_as_str_unfixable.stderr40
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions.fixed1
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions.rs1
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions.stderr6
-rw-r--r--src/tools/clippy/tests/ui/equatable_if_let.fixed36
-rw-r--r--src/tools/clippy/tests/ui/equatable_if_let.rs36
-rw-r--r--src/tools/clippy/tests/ui/equatable_if_let.stderr20
-rw-r--r--src/tools/clippy/tests/ui/manual_div_ceil.fixed23
-rw-r--r--src/tools/clippy/tests/ui/manual_div_ceil.rs23
-rw-r--r--src/tools/clippy/tests/ui/manual_div_ceil.stderr62
-rw-r--r--src/tools/clippy/tests/ui/needless_if.fixed4
-rw-r--r--src/tools/clippy/tests/ui/needless_if.rs4
-rw-r--r--src/tools/clippy/tests/ui/needless_if.stderr8
-rw-r--r--src/tools/clippy/tests/ui/needless_late_init.fixed4
-rw-r--r--src/tools/clippy/tests/ui/needless_late_init.rs4
-rw-r--r--src/tools/clippy/tests/ui/needless_late_init.stderr2
-rw-r--r--src/tools/clippy/tests/ui/needless_question_mark.stderr148
-rw-r--r--src/tools/clippy/tests/ui/ptr_eq.fixed28
-rw-r--r--src/tools/clippy/tests/ui/ptr_eq.rs18
-rw-r--r--src/tools/clippy/tests/ui/ptr_eq.stderr38
-rw-r--r--src/tools/clippy/tests/ui/ptr_eq_no_std.fixed20
-rw-r--r--src/tools/clippy/tests/ui/ptr_eq_no_std.rs12
-rw-r--r--src/tools/clippy/tests/ui/ptr_eq_no_std.stderr26
-rw-r--r--src/tools/clippy/tests/ui/question_mark.fixed5
-rw-r--r--src/tools/clippy/tests/ui/question_mark.rs5
-rw-r--r--src/tools/clippy/tests/ui/question_mark.stderr20
-rw-r--r--src/tools/clippy/tests/ui/question_mark_used.stderr2
-rw-r--r--src/tools/clippy/tests/ui/return_and_then.stderr14
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_cast.fixed16
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_cast.rs14
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_cast.stderr22
-rw-r--r--src/tools/clippy/tests/ui/unused_unit.edition2021.fixed146
-rw-r--r--src/tools/clippy/tests/ui/unused_unit.edition2021.stderr128
-rw-r--r--src/tools/clippy/tests/ui/unused_unit.edition2024.fixed146
-rw-r--r--src/tools/clippy/tests/ui/unused_unit.edition2024.stderr122
-rw-r--r--src/tools/clippy/tests/ui/unused_unit.fixed21
-rw-r--r--src/tools/clippy/tests/ui/unused_unit.rs26
-rw-r--r--src/tools/clippy/tests/ui/unused_unit.stderr32
-rw-r--r--src/tools/clippy/tests/ui/zombie_processes.rs22
43 files changed, 1243 insertions, 195 deletions
diff --git a/src/tools/clippy/tests/ui-internal/symbol_as_str.fixed b/src/tools/clippy/tests/ui-internal/symbol_as_str.fixed
new file mode 100644
index 00000000000..3e26732836c
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/symbol_as_str.fixed
@@ -0,0 +1,21 @@
+#![feature(rustc_private)]
+
+extern crate rustc_span;
+
+use clippy_utils::sym;
+use rustc_span::{Symbol, kw};
+
+fn f(s: Symbol) {
+    s == sym::f32;
+    //~^ symbol_as_str
+    s == sym::proc_dash_macro;
+    //~^ symbol_as_str
+    s == kw::SelfLower;
+    //~^ symbol_as_str
+    s == sym::msrv;
+    //~^ symbol_as_str
+    s == sym::Cargo_toml;
+    //~^ symbol_as_str
+    sym::get == s;
+    //~^ symbol_as_str
+}
diff --git a/src/tools/clippy/tests/ui-internal/symbol_as_str.rs b/src/tools/clippy/tests/ui-internal/symbol_as_str.rs
new file mode 100644
index 00000000000..334c32d1898
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/symbol_as_str.rs
@@ -0,0 +1,21 @@
+#![feature(rustc_private)]
+
+extern crate rustc_span;
+
+use clippy_utils::sym;
+use rustc_span::{Symbol, kw};
+
+fn f(s: Symbol) {
+    s.as_str() == "f32";
+    //~^ symbol_as_str
+    s.as_str() == "proc-macro";
+    //~^ symbol_as_str
+    s.as_str() == "self";
+    //~^ symbol_as_str
+    s.as_str() == "msrv";
+    //~^ symbol_as_str
+    s.as_str() == "Cargo.toml";
+    //~^ symbol_as_str
+    "get" == s.as_str();
+    //~^ symbol_as_str
+}
diff --git a/src/tools/clippy/tests/ui-internal/symbol_as_str.stderr b/src/tools/clippy/tests/ui-internal/symbol_as_str.stderr
new file mode 100644
index 00000000000..39f81f3833c
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/symbol_as_str.stderr
@@ -0,0 +1,76 @@
+error: converting a Symbol to a string
+  --> tests/ui-internal/symbol_as_str.rs:9:5
+   |
+LL |     s.as_str() == "f32";
+   |     ^^^^^^^^^^
+   |
+   = note: `-D clippy::symbol-as-str` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::symbol_as_str)]`
+help: use the preinterned symbol
+   |
+LL -     s.as_str() == "f32";
+LL +     s == sym::f32;
+   |
+
+error: converting a Symbol to a string
+  --> tests/ui-internal/symbol_as_str.rs:11:5
+   |
+LL |     s.as_str() == "proc-macro";
+   |     ^^^^^^^^^^
+   |
+help: use the preinterned symbol
+   |
+LL -     s.as_str() == "proc-macro";
+LL +     s == sym::proc_dash_macro;
+   |
+
+error: converting a Symbol to a string
+  --> tests/ui-internal/symbol_as_str.rs:13:5
+   |
+LL |     s.as_str() == "self";
+   |     ^^^^^^^^^^
+   |
+help: use the preinterned symbol
+   |
+LL -     s.as_str() == "self";
+LL +     s == kw::SelfLower;
+   |
+
+error: converting a Symbol to a string
+  --> tests/ui-internal/symbol_as_str.rs:15:5
+   |
+LL |     s.as_str() == "msrv";
+   |     ^^^^^^^^^^
+   |
+help: use the preinterned symbol
+   |
+LL -     s.as_str() == "msrv";
+LL +     s == sym::msrv;
+   |
+
+error: converting a Symbol to a string
+  --> tests/ui-internal/symbol_as_str.rs:17:5
+   |
+LL |     s.as_str() == "Cargo.toml";
+   |     ^^^^^^^^^^
+   |
+help: use the preinterned symbol
+   |
+LL -     s.as_str() == "Cargo.toml";
+LL +     s == sym::Cargo_toml;
+   |
+
+error: converting a Symbol to a string
+  --> tests/ui-internal/symbol_as_str.rs:19:14
+   |
+LL |     "get" == s.as_str();
+   |              ^^^^^^^^^^
+   |
+help: use the preinterned symbol
+   |
+LL -     "get" == s.as_str();
+LL +     sym::get == s;
+   |
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui-internal/symbol_as_str_unfixable.rs b/src/tools/clippy/tests/ui-internal/symbol_as_str_unfixable.rs
new file mode 100644
index 00000000000..635f28007e9
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/symbol_as_str_unfixable.rs
@@ -0,0 +1,15 @@
+//@no-rustfix: paths that don't exist yet
+#![feature(rustc_private)]
+
+extern crate rustc_span;
+
+use rustc_span::Symbol;
+
+fn f(s: Symbol) {
+    s.as_str() == "xyz123";
+    //~^ symbol_as_str
+    s.as_str() == "with-dash";
+    //~^ symbol_as_str
+    s.as_str() == "with.dot";
+    //~^ symbol_as_str
+}
diff --git a/src/tools/clippy/tests/ui-internal/symbol_as_str_unfixable.stderr b/src/tools/clippy/tests/ui-internal/symbol_as_str_unfixable.stderr
new file mode 100644
index 00000000000..5349983ca51
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/symbol_as_str_unfixable.stderr
@@ -0,0 +1,40 @@
+error: converting a Symbol to a string
+  --> tests/ui-internal/symbol_as_str_unfixable.rs:9:5
+   |
+LL |     s.as_str() == "xyz123";
+   |     ^^^^^^^^^^
+   |
+   = note: `-D clippy::symbol-as-str` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::symbol_as_str)]`
+help: add the symbol to `clippy_utils/src/sym.rs` and use it
+   |
+LL -     s.as_str() == "xyz123";
+LL +     s == sym::xyz123;
+   |
+
+error: converting a Symbol to a string
+  --> tests/ui-internal/symbol_as_str_unfixable.rs:11:5
+   |
+LL |     s.as_str() == "with-dash";
+   |     ^^^^^^^^^^
+   |
+help: add the symbol to `clippy_utils/src/sym.rs` and use it
+   |
+LL -     s.as_str() == "with-dash";
+LL +     s == sym::with_dash;
+   |
+
+error: converting a Symbol to a string
+  --> tests/ui-internal/symbol_as_str_unfixable.rs:13:5
+   |
+LL |     s.as_str() == "with.dot";
+   |     ^^^^^^^^^^
+   |
+help: add the symbol to `clippy_utils/src/sym.rs` and use it
+   |
+LL -     s.as_str() == "with.dot";
+LL +     s == sym::with_dot;
+   |
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions.fixed b/src/tools/clippy/tests/ui/blocks_in_conditions.fixed
index e696896538e..6ae5b0cb2f0 100644
--- a/src/tools/clippy/tests/ui/blocks_in_conditions.fixed
+++ b/src/tools/clippy/tests/ui/blocks_in_conditions.fixed
@@ -4,7 +4,6 @@
 #![allow(
     unused,
     unnecessary_transmutes,
-    clippy::let_and_return,
     clippy::needless_if,
     clippy::missing_transmute_annotations
 )]
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions.rs b/src/tools/clippy/tests/ui/blocks_in_conditions.rs
index 8c8f3249b8a..3fd06062072 100644
--- a/src/tools/clippy/tests/ui/blocks_in_conditions.rs
+++ b/src/tools/clippy/tests/ui/blocks_in_conditions.rs
@@ -4,7 +4,6 @@
 #![allow(
     unused,
     unnecessary_transmutes,
-    clippy::let_and_return,
     clippy::needless_if,
     clippy::missing_transmute_annotations
 )]
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions.stderr b/src/tools/clippy/tests/ui/blocks_in_conditions.stderr
index 41ff59c683e..282c42a98bf 100644
--- a/src/tools/clippy/tests/ui/blocks_in_conditions.stderr
+++ b/src/tools/clippy/tests/ui/blocks_in_conditions.stderr
@@ -1,5 +1,5 @@
 error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
-  --> tests/ui/blocks_in_conditions.rs:31:5
+  --> tests/ui/blocks_in_conditions.rs:30:5
    |
 LL | /     if {
 LL | |
@@ -20,13 +20,13 @@ LL ~     }; if res {
    |
 
 error: omit braces around single expression condition
-  --> tests/ui/blocks_in_conditions.rs:43:8
+  --> tests/ui/blocks_in_conditions.rs:42:8
    |
 LL |     if { true } { 6 } else { 10 }
    |        ^^^^^^^^ help: try: `true`
 
 error: this boolean expression can be simplified
-  --> tests/ui/blocks_in_conditions.rs:49:8
+  --> tests/ui/blocks_in_conditions.rs:48:8
    |
 LL |     if true && x == 3 { 6 } else { 10 }
    |        ^^^^^^^^^^^^^^ help: try: `x == 3`
diff --git a/src/tools/clippy/tests/ui/equatable_if_let.fixed b/src/tools/clippy/tests/ui/equatable_if_let.fixed
index 166b1387ba2..ce8b67f9ca7 100644
--- a/src/tools/clippy/tests/ui/equatable_if_let.fixed
+++ b/src/tools/clippy/tests/ui/equatable_if_let.fixed
@@ -103,3 +103,39 @@ fn main() {
 
     external!({ if let 2 = $a {} });
 }
+
+mod issue8710 {
+    fn str_ref(cs: &[char]) {
+        if matches!(cs.iter().next(), Some('i')) {
+            //~^ equatable_if_let
+        } else {
+            todo!();
+        }
+    }
+
+    fn i32_ref(cs: &[i32]) {
+        if matches!(cs.iter().next(), Some(1)) {
+            //~^ equatable_if_let
+        } else {
+            todo!();
+        }
+    }
+
+    fn enum_ref() {
+        #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
+        enum MyEnum {
+            A(i32),
+            B,
+        }
+
+        fn get_enum() -> Option<&'static MyEnum> {
+            todo!()
+        }
+
+        if matches!(get_enum(), Some(MyEnum::B)) {
+            //~^ equatable_if_let
+        } else {
+            todo!();
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/equatable_if_let.rs b/src/tools/clippy/tests/ui/equatable_if_let.rs
index 09c2483ae6d..ff09533f265 100644
--- a/src/tools/clippy/tests/ui/equatable_if_let.rs
+++ b/src/tools/clippy/tests/ui/equatable_if_let.rs
@@ -103,3 +103,39 @@ fn main() {
 
     external!({ if let 2 = $a {} });
 }
+
+mod issue8710 {
+    fn str_ref(cs: &[char]) {
+        if let Some('i') = cs.iter().next() {
+            //~^ equatable_if_let
+        } else {
+            todo!();
+        }
+    }
+
+    fn i32_ref(cs: &[i32]) {
+        if let Some(1) = cs.iter().next() {
+            //~^ equatable_if_let
+        } else {
+            todo!();
+        }
+    }
+
+    fn enum_ref() {
+        #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
+        enum MyEnum {
+            A(i32),
+            B,
+        }
+
+        fn get_enum() -> Option<&'static MyEnum> {
+            todo!()
+        }
+
+        if let Some(MyEnum::B) = get_enum() {
+            //~^ equatable_if_let
+        } else {
+            todo!();
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/equatable_if_let.stderr b/src/tools/clippy/tests/ui/equatable_if_let.stderr
index 81e0e15a5c7..dd1832ad68b 100644
--- a/src/tools/clippy/tests/ui/equatable_if_let.stderr
+++ b/src/tools/clippy/tests/ui/equatable_if_let.stderr
@@ -85,5 +85,23 @@ error: this pattern matching can be expressed using equality
 LL |     if let inline!("abc") = "abc" {
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"abc" == inline!("abc")`
 
-error: aborting due to 14 previous errors
+error: this pattern matching can be expressed using `matches!`
+  --> tests/ui/equatable_if_let.rs:109:12
+   |
+LL |         if let Some('i') = cs.iter().next() {
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(cs.iter().next(), Some('i'))`
+
+error: this pattern matching can be expressed using `matches!`
+  --> tests/ui/equatable_if_let.rs:117:12
+   |
+LL |         if let Some(1) = cs.iter().next() {
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(cs.iter().next(), Some(1))`
+
+error: this pattern matching can be expressed using `matches!`
+  --> tests/ui/equatable_if_let.rs:135:12
+   |
+LL |         if let Some(MyEnum::B) = get_enum() {
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(get_enum(), Some(MyEnum::B))`
+
+error: aborting due to 17 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_div_ceil.fixed b/src/tools/clippy/tests/ui/manual_div_ceil.fixed
index 57fe8917afe..58ee6978fc1 100644
--- a/src/tools/clippy/tests/ui/manual_div_ceil.fixed
+++ b/src/tools/clippy/tests/ui/manual_div_ceil.fixed
@@ -1,5 +1,21 @@
 #![warn(clippy::manual_div_ceil)]
 
+macro_rules! y {
+    () => {
+        let x = 33u32;
+        let _ = x.div_ceil(8);
+        //~^ manual_div_ceil
+        let _ = x.div_ceil(8);
+        //~^ manual_div_ceil
+    };
+}
+
+macro_rules! eight {
+    () => {
+        8
+    };
+}
+
 fn main() {
     let x = 7_u32;
     let y = 4_u32;
@@ -32,6 +48,13 @@ fn main() {
     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;
+
+    // Test lint with macro
+    y!();
+
+    // Also test if RHS should be result of macro expansion
+    let _ = 33u32.div_ceil(eight!());
+    //~^ manual_div_ceil
 }
 
 fn issue_13843() {
diff --git a/src/tools/clippy/tests/ui/manual_div_ceil.rs b/src/tools/clippy/tests/ui/manual_div_ceil.rs
index ec343513e5c..aa0d81b22a0 100644
--- a/src/tools/clippy/tests/ui/manual_div_ceil.rs
+++ b/src/tools/clippy/tests/ui/manual_div_ceil.rs
@@ -1,5 +1,21 @@
 #![warn(clippy::manual_div_ceil)]
 
+macro_rules! y {
+    () => {
+        let x = 33u32;
+        let _ = (x + 7) / 8;
+        //~^ manual_div_ceil
+        let _ = (7 + x) / 8;
+        //~^ manual_div_ceil
+    };
+}
+
+macro_rules! eight {
+    () => {
+        8
+    };
+}
+
 fn main() {
     let x = 7_u32;
     let y = 4_u32;
@@ -32,6 +48,13 @@ fn main() {
     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;
+
+    // Test lint with macro
+    y!();
+
+    // Also test if RHS should be result of macro expansion
+    let _ = (33u32 + 7) / eight!();
+    //~^ manual_div_ceil
 }
 
 fn issue_13843() {
diff --git a/src/tools/clippy/tests/ui/manual_div_ceil.stderr b/src/tools/clippy/tests/ui/manual_div_ceil.stderr
index 8e14ab27426..9be5a19bf39 100644
--- a/src/tools/clippy/tests/ui/manual_div_ceil.stderr
+++ b/src/tools/clippy/tests/ui/manual_div_ceil.stderr
@@ -1,5 +1,5 @@
 error: manually reimplementing `div_ceil`
-  --> tests/ui/manual_div_ceil.rs:9:13
+  --> tests/ui/manual_div_ceil.rs:25:13
    |
 LL |     let _ = (x + (y - 1)) / y;
    |             ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)`
@@ -8,94 +8,122 @@ LL |     let _ = (x + (y - 1)) / y;
    = help: to override `-D warnings` add `#[allow(clippy::manual_div_ceil)]`
 
 error: manually reimplementing `div_ceil`
-  --> tests/ui/manual_div_ceil.rs:11:13
+  --> tests/ui/manual_div_ceil.rs:27: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:13:13
+  --> tests/ui/manual_div_ceil.rs:29: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:16:13
+  --> tests/ui/manual_div_ceil.rs:32: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:18:13
+  --> tests/ui/manual_div_ceil.rs:34: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.rs:39:13
+  --> tests/ui/manual_div_ceil.rs:6:17
+   |
+LL |         let _ = (x + 7) / 8;
+   |                 ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
+...
+LL |     y!();
+   |     ---- in this macro invocation
+   |
+   = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil.rs:8:17
+   |
+LL |         let _ = (7 + x) / 8;
+   |                 ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
+...
+LL |     y!();
+   |     ---- in this macro invocation
+   |
+   = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil.rs:56:13
+   |
+LL |     let _ = (33u32 + 7) / eight!();
+   |             ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `33u32.div_ceil(eight!())`
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil.rs:62:13
    |
 LL |     let _ = (2048 + x - 1) / x;
    |             ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(x)`
 
 error: manually reimplementing `div_ceil`
-  --> tests/ui/manual_div_ceil.rs:43:13
+  --> tests/ui/manual_div_ceil.rs:66:13
    |
 LL |     let _ = (2048usize + x - 1) / x;
    |             ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048usize.div_ceil(x)`
 
 error: manually reimplementing `div_ceil`
-  --> tests/ui/manual_div_ceil.rs:47:13
+  --> tests/ui/manual_div_ceil.rs:70:13
    |
 LL |     let _ = (2048_usize + x - 1) / x;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(x)`
 
 error: manually reimplementing `div_ceil`
-  --> tests/ui/manual_div_ceil.rs:51:13
+  --> tests/ui/manual_div_ceil.rs:74:13
    |
 LL |     let _ = (x + 4 - 1) / 4;
    |             ^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(4)`
 
 error: manually reimplementing `div_ceil`
-  --> tests/ui/manual_div_ceil.rs:54:18
+  --> tests/ui/manual_div_ceil.rs:77:18
    |
 LL |     let _: u32 = (2048 + 6 - 1) / 6;
    |                  ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_u32.div_ceil(6)`
 
 error: manually reimplementing `div_ceil`
-  --> tests/ui/manual_div_ceil.rs:56:20
+  --> tests/ui/manual_div_ceil.rs:79:20
    |
 LL |     let _: usize = (2048 + 6 - 1) / 6;
    |                    ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(6)`
 
 error: manually reimplementing `div_ceil`
-  --> tests/ui/manual_div_ceil.rs:58:18
+  --> tests/ui/manual_div_ceil.rs:81:18
    |
 LL |     let _: u32 = (0x2048 + 0x6 - 1) / 0x6;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `0x2048_u32.div_ceil(0x6)`
 
 error: manually reimplementing `div_ceil`
-  --> tests/ui/manual_div_ceil.rs:61:13
+  --> tests/ui/manual_div_ceil.rs:84:13
    |
 LL |     let _ = (2048 + 6u32 - 1) / 6u32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_u32.div_ceil(6u32)`
 
 error: manually reimplementing `div_ceil`
-  --> tests/ui/manual_div_ceil.rs:64:13
+  --> tests/ui/manual_div_ceil.rs:87:13
    |
 LL |     let _ = (1_000_000 + 6u32 - 1) / 6u32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `1_000_000_u32.div_ceil(6u32)`
 
 error: manually reimplementing `div_ceil`
-  --> tests/ui/manual_div_ceil.rs:70:13
+  --> tests/ui/manual_div_ceil.rs:93:13
    |
 LL |     let _ = (x + 7) / 8;
    |             ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
 
 error: manually reimplementing `div_ceil`
-  --> tests/ui/manual_div_ceil.rs:72:13
+  --> tests/ui/manual_div_ceil.rs:95:13
    |
 LL |     let _ = (7 + x) / 8;
    |             ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
 
-error: aborting due to 16 previous errors
+error: aborting due to 19 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_if.fixed b/src/tools/clippy/tests/ui/needless_if.fixed
index 6208ca19b82..347dbff7c59 100644
--- a/src/tools/clippy/tests/ui/needless_if.fixed
+++ b/src/tools/clippy/tests/ui/needless_if.fixed
@@ -46,9 +46,7 @@ fn main() {
     if let true = true
         && true
     {}
-    if true
-        && let true = true
-    {}
+    if true && let true = true {}
     // Can lint nested `if let`s
     ({
         //~^ needless_if
diff --git a/src/tools/clippy/tests/ui/needless_if.rs b/src/tools/clippy/tests/ui/needless_if.rs
index b459ff877be..5e0f2a14408 100644
--- a/src/tools/clippy/tests/ui/needless_if.rs
+++ b/src/tools/clippy/tests/ui/needless_if.rs
@@ -46,9 +46,7 @@ fn main() {
     if let true = true
         && true
     {}
-    if true
-        && let true = true
-    {}
+    if true && let true = true {}
     // Can lint nested `if let`s
     if {
         //~^ needless_if
diff --git a/src/tools/clippy/tests/ui/needless_if.stderr b/src/tools/clippy/tests/ui/needless_if.stderr
index eeb8d044526..62cdf245944 100644
--- a/src/tools/clippy/tests/ui/needless_if.stderr
+++ b/src/tools/clippy/tests/ui/needless_if.stderr
@@ -31,7 +31,7 @@ LL +     });
    |
 
 error: this `if` branch is empty
-  --> tests/ui/needless_if.rs:53:5
+  --> tests/ui/needless_if.rs:51:5
    |
 LL | /     if {
 LL | |
@@ -57,19 +57,19 @@ LL +     } && true);
    |
 
 error: this `if` branch is empty
-  --> tests/ui/needless_if.rs:98:5
+  --> tests/ui/needless_if.rs:96:5
    |
 LL |     if { maybe_side_effect() } {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `({ maybe_side_effect() });`
 
 error: this `if` branch is empty
-  --> tests/ui/needless_if.rs:101:5
+  --> tests/ui/needless_if.rs:99:5
    |
 LL |     if { maybe_side_effect() } && true {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can remove it: `({ maybe_side_effect() } && true);`
 
 error: this `if` branch is empty
-  --> tests/ui/needless_if.rs:106:5
+  --> tests/ui/needless_if.rs:104:5
    |
 LL |     if true {}
    |     ^^^^^^^^^^ help: you can remove it: `true;`
diff --git a/src/tools/clippy/tests/ui/needless_late_init.fixed b/src/tools/clippy/tests/ui/needless_late_init.fixed
index 391d4bc3fcc..f832752ccd7 100644
--- a/src/tools/clippy/tests/ui/needless_late_init.fixed
+++ b/src/tools/clippy/tests/ui/needless_late_init.fixed
@@ -246,9 +246,7 @@ fn does_not_lint() {
     }
 
     let x;
-    if true
-        && let Some(n) = Some("let chains too")
-    {
+    if true && let Some(n) = Some("let chains too") {
         x = 1;
     } else {
         x = 2;
diff --git a/src/tools/clippy/tests/ui/needless_late_init.rs b/src/tools/clippy/tests/ui/needless_late_init.rs
index 6096e8300e1..a52fbf52923 100644
--- a/src/tools/clippy/tests/ui/needless_late_init.rs
+++ b/src/tools/clippy/tests/ui/needless_late_init.rs
@@ -246,9 +246,7 @@ fn does_not_lint() {
     }
 
     let x;
-    if true
-        && let Some(n) = Some("let chains too")
-    {
+    if true && let Some(n) = Some("let chains too") {
         x = 1;
     } else {
         x = 2;
diff --git a/src/tools/clippy/tests/ui/needless_late_init.stderr b/src/tools/clippy/tests/ui/needless_late_init.stderr
index e7c36136847..b24c1275881 100644
--- a/src/tools/clippy/tests/ui/needless_late_init.stderr
+++ b/src/tools/clippy/tests/ui/needless_late_init.stderr
@@ -276,7 +276,7 @@ LL ~     };
    |
 
 error: unneeded late initialization
-  --> tests/ui/needless_late_init.rs:302:5
+  --> tests/ui/needless_late_init.rs:300:5
    |
 LL |     let r;
    |     ^^^^^^ created here
diff --git a/src/tools/clippy/tests/ui/needless_question_mark.stderr b/src/tools/clippy/tests/ui/needless_question_mark.stderr
index 55da4f28976..8516cee48e6 100644
--- a/src/tools/clippy/tests/ui/needless_question_mark.stderr
+++ b/src/tools/clippy/tests/ui/needless_question_mark.stderr
@@ -1,100 +1,188 @@
-error: question mark operator is useless here
+error: enclosing `Some` and `?` operator are unneeded
   --> tests/ui/needless_question_mark.rs:20:12
    |
 LL |     return Some(to.magic?);
-   |            ^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `to.magic`
+   |            ^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::needless-question-mark` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::needless_question_mark)]`
+help: remove the enclosing `Some` and `?` operator
+   |
+LL -     return Some(to.magic?);
+LL +     return to.magic;
+   |
 
-error: question mark operator is useless here
+error: enclosing `Some` and `?` operator are unneeded
   --> tests/ui/needless_question_mark.rs:29:12
    |
 LL |     return Some(to.magic?)
-   |            ^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `to.magic`
+   |            ^^^^^^^^^^^^^^^
+   |
+help: remove the enclosing `Some` and `?` operator
+   |
+LL -     return Some(to.magic?)
+LL +     return to.magic
+   |
 
-error: question mark operator is useless here
+error: enclosing `Some` and `?` operator are unneeded
   --> tests/ui/needless_question_mark.rs:35:5
    |
 LL |     Some(to.magic?)
-   |     ^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `to.magic`
+   |     ^^^^^^^^^^^^^^^
+   |
+help: remove the enclosing `Some` and `?` operator
+   |
+LL -     Some(to.magic?)
+LL +     to.magic
+   |
 
-error: question mark operator is useless here
+error: enclosing `Some` and `?` operator are unneeded
   --> tests/ui/needless_question_mark.rs:41:21
    |
 LL |     to.and_then(|t| Some(t.magic?))
-   |                     ^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `t.magic`
+   |                     ^^^^^^^^^^^^^^
+   |
+help: remove the enclosing `Some` and `?` operator
+   |
+LL -     to.and_then(|t| Some(t.magic?))
+LL +     to.and_then(|t| t.magic)
+   |
 
-error: question mark operator is useless here
+error: enclosing `Some` and `?` operator are unneeded
   --> tests/ui/needless_question_mark.rs:51:9
    |
 LL |         Some(t.magic?)
-   |         ^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `t.magic`
+   |         ^^^^^^^^^^^^^^
+   |
+help: remove the enclosing `Some` and `?` operator
+   |
+LL -         Some(t.magic?)
+LL +         t.magic
+   |
 
-error: question mark operator is useless here
+error: enclosing `Ok` and `?` operator are unneeded
   --> tests/ui/needless_question_mark.rs:57:12
    |
 LL |     return Ok(tr.magic?);
-   |            ^^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `tr.magic`
+   |            ^^^^^^^^^^^^^
+   |
+help: remove the enclosing `Ok` and `?` operator
+   |
+LL -     return Ok(tr.magic?);
+LL +     return tr.magic;
+   |
 
-error: question mark operator is useless here
+error: enclosing `Ok` and `?` operator are unneeded
   --> tests/ui/needless_question_mark.rs:65:12
    |
 LL |     return Ok(tr.magic?)
-   |            ^^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `tr.magic`
+   |            ^^^^^^^^^^^^^
+   |
+help: remove the enclosing `Ok` and `?` operator
+   |
+LL -     return Ok(tr.magic?)
+LL +     return tr.magic
+   |
 
-error: question mark operator is useless here
+error: enclosing `Ok` and `?` operator are unneeded
   --> tests/ui/needless_question_mark.rs:70:5
    |
 LL |     Ok(tr.magic?)
-   |     ^^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `tr.magic`
+   |     ^^^^^^^^^^^^^
+   |
+help: remove the enclosing `Ok` and `?` operator
+   |
+LL -     Ok(tr.magic?)
+LL +     tr.magic
+   |
 
-error: question mark operator is useless here
+error: enclosing `Ok` and `?` operator are unneeded
   --> tests/ui/needless_question_mark.rs:75:21
    |
 LL |     tr.and_then(|t| Ok(t.magic?))
-   |                     ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `t.magic`
+   |                     ^^^^^^^^^^^^
+   |
+help: remove the enclosing `Ok` and `?` operator
+   |
+LL -     tr.and_then(|t| Ok(t.magic?))
+LL +     tr.and_then(|t| t.magic)
+   |
 
-error: question mark operator is useless here
+error: enclosing `Ok` and `?` operator are unneeded
   --> tests/ui/needless_question_mark.rs:84:9
    |
 LL |         Ok(t.magic?)
-   |         ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `t.magic`
+   |         ^^^^^^^^^^^^
+   |
+help: remove the enclosing `Ok` and `?` operator
+   |
+LL -         Ok(t.magic?)
+LL +         t.magic
+   |
 
-error: question mark operator is useless here
+error: enclosing `Ok` and `?` operator are unneeded
   --> tests/ui/needless_question_mark.rs:92:16
    |
 LL |         return Ok(t.magic?);
-   |                ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `t.magic`
+   |                ^^^^^^^^^^^^
+   |
+help: remove the enclosing `Ok` and `?` operator
+   |
+LL -         return Ok(t.magic?);
+LL +         return t.magic;
+   |
 
-error: question mark operator is useless here
+error: enclosing `Some` and `?` operator are unneeded
   --> tests/ui/needless_question_mark.rs:128:27
    |
 LL |         || -> Option<_> { Some(Some($expr)?) }()
-   |                           ^^^^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `Some($expr)`
+   |                           ^^^^^^^^^^^^^^^^^^
 ...
 LL |     let _x = some_and_qmark_in_macro!(x?);
    |              ---------------------------- in this macro invocation
    |
    = note: this error originates in the macro `some_and_qmark_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: remove the enclosing `Some` and `?` operator
+   |
+LL -         || -> Option<_> { Some(Some($expr)?) }()
+LL +         || -> Option<_> { Some($expr) }()
+   |
 
-error: question mark operator is useless here
+error: enclosing `Some` and `?` operator are unneeded
   --> tests/ui/needless_question_mark.rs:140:5
    |
 LL |     Some(to.magic?)
-   |     ^^^^^^^^^^^^^^^ help: try removing question mark and `Some()`: `to.magic`
+   |     ^^^^^^^^^^^^^^^
+   |
+help: remove the enclosing `Some` and `?` operator
+   |
+LL -     Some(to.magic?)
+LL +     to.magic
+   |
 
-error: question mark operator is useless here
+error: enclosing `Ok` and `?` operator are unneeded
   --> tests/ui/needless_question_mark.rs:149:5
    |
 LL |     Ok(s.magic?)
-   |     ^^^^^^^^^^^^ help: try removing question mark and `Ok()`: `s.magic`
+   |     ^^^^^^^^^^^^
+   |
+help: remove the enclosing `Ok` and `?` operator
+   |
+LL -     Ok(s.magic?)
+LL +     s.magic
+   |
 
-error: question mark operator is useless here
+error: enclosing `Some` and `?` operator are unneeded
   --> tests/ui/needless_question_mark.rs:154:7
    |
 LL |     { Some(a?) }
-   |       ^^^^^^^^ help: try removing question mark and `Some()`: `a`
+   |       ^^^^^^^^
+   |
+help: remove the enclosing `Some` and `?` operator
+   |
+LL -     { Some(a?) }
+LL +     { a }
+   |
 
 error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/ptr_eq.fixed b/src/tools/clippy/tests/ui/ptr_eq.fixed
index 484ff307323..9629b3eea58 100644
--- a/src/tools/clippy/tests/ui/ptr_eq.fixed
+++ b/src/tools/clippy/tests/ui/ptr_eq.fixed
@@ -23,23 +23,25 @@ fn main() {
     //~^ ptr_eq
     let _ = std::ptr::eq(a, b);
     //~^ ptr_eq
-    let _ = std::ptr::eq(a.as_ptr(), b as *const _);
-    //~^ ptr_eq
-    let _ = std::ptr::eq(a.as_ptr(), b.as_ptr());
-    //~^ ptr_eq
 
-    // Do not lint
+    // Do not lint: the rhs conversion is needed
+    let _ = a.as_ptr() == b as *const _;
 
+    // Do not lint: we have two raw pointers already
+    let _ = a.as_ptr() == b.as_ptr();
+
+    // Do not lint
     let _ = mac!(a, b);
     let _ = another_mac!(a, b);
 
     let a = &mut [1, 2, 3];
     let b = &mut [1, 2, 3];
 
-    let _ = std::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _);
-    //~^ ptr_eq
-    let _ = std::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr());
-    //~^ ptr_eq
+    // Do not lint: the rhs conversion is needed
+    let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
+
+    // Do not lint: we have two raw pointers already
+    let _ = a.as_mut_ptr() == b.as_mut_ptr();
 
     let _ = a == b;
     let _ = core::ptr::eq(a, b);
@@ -51,8 +53,12 @@ fn main() {
     let _ = !std::ptr::eq(x, y);
     //~^ ptr_eq
 
-    #[allow(clippy::eq_op)]
-    let _issue14337 = std::ptr::eq(main as *const (), main as *const ());
+    #[expect(clippy::eq_op)]
+    // Do not lint: casts are needed to not change type
+    let _issue14337 = main as *const () == main as *const ();
+
+    // Do not peel the content of macros
+    let _ = std::ptr::eq(mac!(cast a), mac!(cast b));
     //~^ ptr_eq
 
     // Do not peel the content of macros
diff --git a/src/tools/clippy/tests/ui/ptr_eq.rs b/src/tools/clippy/tests/ui/ptr_eq.rs
index f28707cc3e9..2b741d8df46 100644
--- a/src/tools/clippy/tests/ui/ptr_eq.rs
+++ b/src/tools/clippy/tests/ui/ptr_eq.rs
@@ -23,23 +23,25 @@ fn main() {
     //~^ ptr_eq
     let _ = a as *const _ == b as *const _;
     //~^ ptr_eq
+
+    // Do not lint: the rhs conversion is needed
     let _ = a.as_ptr() == b as *const _;
-    //~^ ptr_eq
+
+    // Do not lint: we have two raw pointers already
     let _ = a.as_ptr() == b.as_ptr();
-    //~^ ptr_eq
 
     // Do not lint
-
     let _ = mac!(a, b);
     let _ = another_mac!(a, b);
 
     let a = &mut [1, 2, 3];
     let b = &mut [1, 2, 3];
 
+    // Do not lint: the rhs conversion is needed
     let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
-    //~^ ptr_eq
+
+    // Do not lint: we have two raw pointers already
     let _ = a.as_mut_ptr() == b.as_mut_ptr();
-    //~^ ptr_eq
 
     let _ = a == b;
     let _ = core::ptr::eq(a, b);
@@ -51,8 +53,12 @@ fn main() {
     let _ = x as *const u32 != y as *mut u32 as *const u32;
     //~^ ptr_eq
 
-    #[allow(clippy::eq_op)]
+    #[expect(clippy::eq_op)]
+    // Do not lint: casts are needed to not change type
     let _issue14337 = main as *const () == main as *const ();
+
+    // Do not peel the content of macros
+    let _ = mac!(cast a) as *const _ == mac!(cast b) as *const _;
     //~^ ptr_eq
 
     // Do not peel the content of macros
diff --git a/src/tools/clippy/tests/ui/ptr_eq.stderr b/src/tools/clippy/tests/ui/ptr_eq.stderr
index 906831b9e03..e7340624b59 100644
--- a/src/tools/clippy/tests/ui/ptr_eq.stderr
+++ b/src/tools/clippy/tests/ui/ptr_eq.stderr
@@ -14,52 +14,28 @@ LL |     let _ = a as *const _ == b as *const _;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a, b)`
 
 error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:26:13
-   |
-LL |     let _ = a.as_ptr() == b as *const _;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_ptr(), b as *const _)`
-
-error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:28:13
-   |
-LL |     let _ = a.as_ptr() == b.as_ptr();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_ptr(), b.as_ptr())`
-
-error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:39:13
-   |
-LL |     let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _)`
-
-error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:41:13
-   |
-LL |     let _ = a.as_mut_ptr() == b.as_mut_ptr();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr())`
-
-error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:48:13
+  --> tests/ui/ptr_eq.rs:50:13
    |
 LL |     let _ = x as *const u32 == y as *mut u32 as *const u32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(x, y)`
 
 error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:51:13
+  --> tests/ui/ptr_eq.rs:53:13
    |
 LL |     let _ = x as *const u32 != y as *mut u32 as *const u32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!std::ptr::eq(x, y)`
 
 error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:55:23
+  --> tests/ui/ptr_eq.rs:61:13
    |
-LL |     let _issue14337 = main as *const () == main as *const ();
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(main as *const (), main as *const ())`
+LL |     let _ = mac!(cast a) as *const _ == mac!(cast b) as *const _;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(mac!(cast a), mac!(cast b))`
 
 error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:59:13
+  --> tests/ui/ptr_eq.rs:65:13
    |
 LL |     let _ = mac!(cast a) as *const _ == mac!(cast b) as *const _;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(mac!(cast a), mac!(cast b))`
 
-error: aborting due to 10 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/ptr_eq_no_std.fixed b/src/tools/clippy/tests/ui/ptr_eq_no_std.fixed
index d8ee4ea88f8..48cbad62e1a 100644
--- a/src/tools/clippy/tests/ui/ptr_eq_no_std.fixed
+++ b/src/tools/clippy/tests/ui/ptr_eq_no_std.fixed
@@ -32,23 +32,25 @@ fn main() {
     //~^ ptr_eq
     let _ = core::ptr::eq(a, b);
     //~^ ptr_eq
-    let _ = core::ptr::eq(a.as_ptr(), b as *const _);
-    //~^ ptr_eq
-    let _ = core::ptr::eq(a.as_ptr(), b.as_ptr());
-    //~^ ptr_eq
 
-    // Do not lint
+    // Do not lint: the rhs conversion is needed
+    let _ = a.as_ptr() == b as *const _;
+
+    // Do not lint: we have two raw pointers already
+    let _ = a.as_ptr() == b.as_ptr();
 
+    // Do not lint
     let _ = mac!(a, b);
     let _ = another_mac!(a, b);
 
     let a = &mut [1, 2, 3];
     let b = &mut [1, 2, 3];
 
-    let _ = core::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _);
-    //~^ ptr_eq
-    let _ = core::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr());
-    //~^ ptr_eq
+    // Do not lint: the rhs conversion is needed
+    let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
+
+    // Do not lint: we have two raw pointers already
+    let _ = a.as_mut_ptr() == b.as_mut_ptr();
 
     let _ = a == b;
     let _ = core::ptr::eq(a, b);
diff --git a/src/tools/clippy/tests/ui/ptr_eq_no_std.rs b/src/tools/clippy/tests/ui/ptr_eq_no_std.rs
index a236314c29b..3827178640e 100644
--- a/src/tools/clippy/tests/ui/ptr_eq_no_std.rs
+++ b/src/tools/clippy/tests/ui/ptr_eq_no_std.rs
@@ -32,23 +32,25 @@ fn main() {
     //~^ ptr_eq
     let _ = a as *const _ == b as *const _;
     //~^ ptr_eq
+
+    // Do not lint: the rhs conversion is needed
     let _ = a.as_ptr() == b as *const _;
-    //~^ ptr_eq
+
+    // Do not lint: we have two raw pointers already
     let _ = a.as_ptr() == b.as_ptr();
-    //~^ ptr_eq
 
     // Do not lint
-
     let _ = mac!(a, b);
     let _ = another_mac!(a, b);
 
     let a = &mut [1, 2, 3];
     let b = &mut [1, 2, 3];
 
+    // Do not lint: the rhs conversion is needed
     let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
-    //~^ ptr_eq
+
+    // Do not lint: we have two raw pointers already
     let _ = a.as_mut_ptr() == b.as_mut_ptr();
-    //~^ ptr_eq
 
     let _ = a == b;
     let _ = core::ptr::eq(a, b);
diff --git a/src/tools/clippy/tests/ui/ptr_eq_no_std.stderr b/src/tools/clippy/tests/ui/ptr_eq_no_std.stderr
index 5b8135dc8e8..8c7b1ff7666 100644
--- a/src/tools/clippy/tests/ui/ptr_eq_no_std.stderr
+++ b/src/tools/clippy/tests/ui/ptr_eq_no_std.stderr
@@ -13,29 +13,5 @@ error: use `core::ptr::eq` when comparing raw pointers
 LL |     let _ = a as *const _ == b as *const _;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a, b)`
 
-error: use `core::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq_no_std.rs:35:13
-   |
-LL |     let _ = a.as_ptr() == b as *const _;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_ptr(), b as *const _)`
-
-error: use `core::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq_no_std.rs:37:13
-   |
-LL |     let _ = a.as_ptr() == b.as_ptr();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_ptr(), b.as_ptr())`
-
-error: use `core::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq_no_std.rs:48:13
-   |
-LL |     let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _)`
-
-error: use `core::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq_no_std.rs:50:13
-   |
-LL |     let _ = a.as_mut_ptr() == b.as_mut_ptr();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr())`
-
-error: aborting due to 6 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed
index 6bd071d07f5..507bc2b29d8 100644
--- a/src/tools/clippy/tests/ui/question_mark.fixed
+++ b/src/tools/clippy/tests/ui/question_mark.fixed
@@ -301,6 +301,11 @@ fn pattern() -> Result<(), PatternedError> {
     res
 }
 
+fn expect_expr(a: Option<usize>) -> Option<usize> {
+    #[expect(clippy::needless_question_mark)]
+    Some(a?)
+}
+
 fn main() {}
 
 // `?` is not the same as `return None;` if inside of a try block
diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs
index dd093c9bf48..64b51b849ed 100644
--- a/src/tools/clippy/tests/ui/question_mark.rs
+++ b/src/tools/clippy/tests/ui/question_mark.rs
@@ -371,6 +371,11 @@ fn pattern() -> Result<(), PatternedError> {
     res
 }
 
+fn expect_expr(a: Option<usize>) -> Option<usize> {
+    #[expect(clippy::needless_question_mark)]
+    Some(a?)
+}
+
 fn main() {}
 
 // `?` is not the same as `return None;` if inside of a try block
diff --git a/src/tools/clippy/tests/ui/question_mark.stderr b/src/tools/clippy/tests/ui/question_mark.stderr
index 8fe04b895ce..d8ce4420aee 100644
--- a/src/tools/clippy/tests/ui/question_mark.stderr
+++ b/src/tools/clippy/tests/ui/question_mark.stderr
@@ -198,7 +198,7 @@ LL | |     }
    | |_____^ help: replace it with: `func_returning_result()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:390:13
+  --> tests/ui/question_mark.rs:395:13
    |
 LL | /             if a.is_none() {
 LL | |
@@ -208,7 +208,7 @@ LL | |             }
    | |_____________^ help: replace it with: `a?;`
 
 error: this `let...else` may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:451:5
+  --> tests/ui/question_mark.rs:456:5
    |
 LL | /     let Some(v) = bar.foo.owned.clone() else {
 LL | |         return None;
@@ -216,7 +216,7 @@ LL | |     };
    | |______^ help: replace it with: `let v = bar.foo.owned.clone()?;`
 
 error: this `let...else` may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:466:5
+  --> tests/ui/question_mark.rs:471:5
    |
 LL | /     let Some(ref x) = foo.opt_x else {
 LL | |         return None;
@@ -224,7 +224,7 @@ LL | |     };
    | |______^ help: replace it with: `let x = foo.opt_x.as_ref()?;`
 
 error: this `let...else` may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:476:5
+  --> tests/ui/question_mark.rs:481:5
    |
 LL | /     let Some(ref mut x) = foo.opt_x else {
 LL | |         return None;
@@ -232,7 +232,7 @@ LL | |     };
    | |______^ help: replace it with: `let x = foo.opt_x.as_mut()?;`
 
 error: this `let...else` may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:487:5
+  --> tests/ui/question_mark.rs:492:5
    |
 LL | /     let Some(ref x @ ref y) = foo.opt_x else {
 LL | |         return None;
@@ -240,7 +240,7 @@ LL | |     };
    | |______^ help: replace it with: `let x @ y = foo.opt_x.as_ref()?;`
 
 error: this `let...else` may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:491:5
+  --> tests/ui/question_mark.rs:496:5
    |
 LL | /     let Some(ref x @ WrapperStructWithString(_)) = bar else {
 LL | |         return None;
@@ -248,7 +248,7 @@ LL | |     };
    | |______^ help: replace it with: `let x @ &WrapperStructWithString(_) = bar.as_ref()?;`
 
 error: this `let...else` may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:495:5
+  --> tests/ui/question_mark.rs:500:5
    |
 LL | /     let Some(ref mut x @ WrapperStructWithString(_)) = bar else {
 LL | |         return None;
@@ -256,7 +256,7 @@ LL | |     };
    | |______^ help: replace it with: `let x @ &mut WrapperStructWithString(_) = bar.as_mut()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:517:5
+  --> tests/ui/question_mark.rs:522:5
    |
 LL | /     if arg.is_none() {
 LL | |
@@ -265,7 +265,7 @@ LL | |     }
    | |_____^ help: replace it with: `arg?;`
 
 error: this `match` expression can be replaced with `?`
-  --> tests/ui/question_mark.rs:521:15
+  --> tests/ui/question_mark.rs:526:15
    |
 LL |       let val = match arg {
    |  _______________^
@@ -276,7 +276,7 @@ LL | |     };
    | |_____^ help: try instead: `arg?`
 
 error: this `let...else` may be rewritten with the `?` operator
-  --> tests/ui/question_mark.rs:531:5
+  --> tests/ui/question_mark.rs:536:5
    |
 LL | /     let Some(a) = *a else {
 LL | |         return None;
diff --git a/src/tools/clippy/tests/ui/question_mark_used.stderr b/src/tools/clippy/tests/ui/question_mark_used.stderr
index 53cb59c0216..82f0d325040 100644
--- a/src/tools/clippy/tests/ui/question_mark_used.stderr
+++ b/src/tools/clippy/tests/ui/question_mark_used.stderr
@@ -1,4 +1,4 @@
-error: question mark operator was used
+error: the `?` operator was used
   --> tests/ui/question_mark_used.rs:11:5
    |
 LL |     other_function()?;
diff --git a/src/tools/clippy/tests/ui/return_and_then.stderr b/src/tools/clippy/tests/ui/return_and_then.stderr
index cc611c3dba6..a7acbe7b340 100644
--- a/src/tools/clippy/tests/ui/return_and_then.stderr
+++ b/src/tools/clippy/tests/ui/return_and_then.stderr
@@ -1,4 +1,4 @@
-error: use the question mark operator instead of an `and_then` call
+error: use the `?` operator instead of an `and_then` call
   --> tests/ui/return_and_then.rs:5:9
    |
 LL | /         opt.and_then(|n| {
@@ -20,7 +20,7 @@ LL +         ret += n;
 LL +         if n > 1 { Some(ret) } else { None }
    |
 
-error: use the question mark operator instead of an `and_then` call
+error: use the `?` operator instead of an `and_then` call
   --> tests/ui/return_and_then.rs:14:9
    |
 LL |         opt.and_then(|n| test_opt_block(Some(n)))
@@ -32,7 +32,7 @@ LL ~         let n = opt?;
 LL +         test_opt_block(Some(n))
    |
 
-error: use the question mark operator instead of an `and_then` call
+error: use the `?` operator instead of an `and_then` call
   --> tests/ui/return_and_then.rs:19:9
    |
 LL |         gen_option(1).and_then(|n| test_opt_block(Some(n)))
@@ -44,7 +44,7 @@ LL ~         let n = gen_option(1)?;
 LL +         test_opt_block(Some(n))
    |
 
-error: use the question mark operator instead of an `and_then` call
+error: use the `?` operator instead of an `and_then` call
   --> tests/ui/return_and_then.rs:24:9
    |
 LL |         opt.and_then(|n| if n > 1 { Ok(n + 1) } else { Err(n) })
@@ -56,7 +56,7 @@ LL ~         let n = opt?;
 LL +         if n > 1 { Ok(n + 1) } else { Err(n) }
    |
 
-error: use the question mark operator instead of an `and_then` call
+error: use the `?` operator instead of an `and_then` call
   --> tests/ui/return_and_then.rs:29:9
    |
 LL |         opt.and_then(|n| test_res_block(Ok(n)))
@@ -68,7 +68,7 @@ LL ~         let n = opt?;
 LL +         test_res_block(Ok(n))
    |
 
-error: use the question mark operator instead of an `and_then` call
+error: use the `?` operator instead of an `and_then` call
   --> tests/ui/return_and_then.rs:35:9
    |
 LL |         Some("").and_then(|x| if x.len() > 2 { Some(3) } else { None })
@@ -80,7 +80,7 @@ LL ~         let x = Some("")?;
 LL +         if x.len() > 2 { Some(3) } else { None }
    |
 
-error: use the question mark operator instead of an `and_then` call
+error: use the `?` operator instead of an `and_then` call
   --> tests/ui/return_and_then.rs:41:9
    |
 LL | /         Some(match (vec![1, 2, 3], vec![1, 2, 4]) {
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.fixed b/src/tools/clippy/tests/ui/unnecessary_cast.fixed
index ba167e79a30..91ff4b9ee77 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_cast.fixed
@@ -266,7 +266,21 @@ mod fixable {
     // Issue #11968: The suggestion for this lint removes the parentheses and leave the code as
     // `*x.pow(2)` which tries to dereference the return value rather than `x`.
     fn issue_11968(x: &usize) -> usize {
-        { *x }.pow(2)
+        (*x).pow(2)
+        //~^ unnecessary_cast
+    }
+
+    #[allow(clippy::cast_lossless)]
+    fn issue_14640() {
+        let x = 5usize;
+        let vec: Vec<u64> = vec![1, 2, 3, 4, 5];
+        assert_eq!(vec.len(), x);
+        //~^ unnecessary_cast
+
+        let _ = (5i32 as i64).abs();
+        //~^ unnecessary_cast
+
+        let _ = 5i32 as i64;
         //~^ unnecessary_cast
     }
 }
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.rs b/src/tools/clippy/tests/ui/unnecessary_cast.rs
index 0f90a8b0596..5444a914db1 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_cast.rs
@@ -269,4 +269,18 @@ mod fixable {
         (*x as usize).pow(2)
         //~^ unnecessary_cast
     }
+
+    #[allow(clippy::cast_lossless)]
+    fn issue_14640() {
+        let x = 5usize;
+        let vec: Vec<u64> = vec![1, 2, 3, 4, 5];
+        assert_eq!(vec.len(), x as usize);
+        //~^ unnecessary_cast
+
+        let _ = (5i32 as i64 as i64).abs();
+        //~^ unnecessary_cast
+
+        let _ = 5i32 as i64 as i64;
+        //~^ unnecessary_cast
+    }
 }
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.stderr b/src/tools/clippy/tests/ui/unnecessary_cast.stderr
index c83770c1a29..3e3c5eb81c1 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_cast.stderr
@@ -245,7 +245,25 @@ error: casting to the same type is unnecessary (`usize` -> `usize`)
   --> tests/ui/unnecessary_cast.rs:269:9
    |
 LL |         (*x as usize).pow(2)
-   |         ^^^^^^^^^^^^^ help: try: `{ *x }`
+   |         ^^^^^^^^^^^^^ help: try: `(*x)`
 
-error: aborting due to 41 previous errors
+error: casting to the same type is unnecessary (`usize` -> `usize`)
+  --> tests/ui/unnecessary_cast.rs:277:31
+   |
+LL |         assert_eq!(vec.len(), x as usize);
+   |                               ^^^^^^^^^^ help: try: `x`
+
+error: casting to the same type is unnecessary (`i64` -> `i64`)
+  --> tests/ui/unnecessary_cast.rs:280:17
+   |
+LL |         let _ = (5i32 as i64 as i64).abs();
+   |                 ^^^^^^^^^^^^^^^^^^^^ help: try: `(5i32 as i64)`
+
+error: casting to the same type is unnecessary (`i64` -> `i64`)
+  --> tests/ui/unnecessary_cast.rs:283:17
+   |
+LL |         let _ = 5i32 as i64 as i64;
+   |                 ^^^^^^^^^^^^^^^^^^ help: try: `5i32 as i64`
+
+error: aborting due to 44 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unused_unit.edition2021.fixed b/src/tools/clippy/tests/ui/unused_unit.edition2021.fixed
new file mode 100644
index 00000000000..93dd58b8e9d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unused_unit.edition2021.fixed
@@ -0,0 +1,146 @@
+//@revisions: edition2021 edition2024
+//@[edition2021] edition:2021
+//@[edition2024] edition:2024
+
+// The output for humans should just highlight the whole span without showing
+// the suggested replacement, but we also want to test that suggested
+// replacement only removes one set of parentheses, rather than naïvely
+// stripping away any starting or ending parenthesis characters—hence this
+// test of the JSON error format.
+
+#![feature(custom_inner_attributes)]
+#![feature(closure_lifetime_binder)]
+#![rustfmt::skip]
+
+#![deny(clippy::unused_unit)]
+#![allow(dead_code)]
+#![allow(clippy::from_over_into)]
+
+struct Unitter;
+impl Unitter {
+    #[allow(clippy::no_effect)]
+    pub fn get_unit<F: Fn(), G>(&self, f: F, _g: G)
+    //~^ unused_unit
+    //~| unused_unit
+    where G: Fn() {
+    //~^ unused_unit
+        let _y: &dyn Fn() = &f;
+        //~^ unused_unit
+        (); // this should not lint, as it's not in return type position
+    }
+}
+
+impl Into<()> for Unitter {
+    #[rustfmt::skip]
+    fn into(self) {
+    //~^ unused_unit
+        
+        //~^ unused_unit
+    }
+}
+
+trait Trait {
+    fn redundant<F: FnOnce(), G, H>(&self, _f: F, _g: G, _h: H)
+    //~^ unused_unit
+    where
+        G: FnMut(),
+        //~^ unused_unit
+        H: Fn();
+        //~^ unused_unit
+}
+
+impl Trait for Unitter {
+    fn redundant<F: FnOnce(), G, H>(&self, _f: F, _g: G, _h: H)
+    //~^ unused_unit
+    where
+        G: FnMut(),
+        //~^ unused_unit
+        H: Fn() {}
+        //~^ unused_unit
+}
+
+fn return_unit() {  }
+//~^ unused_unit
+//~| unused_unit
+
+#[allow(clippy::needless_return)]
+#[allow(clippy::never_loop)]
+#[allow(clippy::unit_cmp)]
+fn main() {
+    let u = Unitter;
+    assert_eq!(u.get_unit(|| {}, return_unit), u.into());
+    return_unit();
+    loop {
+        break;
+        //~^ unused_unit
+    }
+    return;
+    //~^ unused_unit
+}
+
+// https://github.com/rust-lang/rust-clippy/issues/4076
+fn foo() {
+    macro_rules! foo {
+        (recv($r:expr) -> $res:pat => $body:expr) => {
+            $body
+        }
+    }
+
+    foo! {
+        recv(rx) -> _x => ()
+    }
+}
+
+#[rustfmt::skip]
+fn test(){}
+//~^ unused_unit
+
+#[rustfmt::skip]
+fn test2(){}
+//~^ unused_unit
+
+#[rustfmt::skip]
+fn test3(){}
+//~^ unused_unit
+
+fn macro_expr() {
+    macro_rules! e {
+        () => (());
+    }
+    e!()
+}
+
+mod issue9748 {
+    fn main() {
+        let _ = for<'a> |_: &'a u32| -> () {};
+    }
+}
+
+mod issue9949 {
+    fn main() {
+        #[doc = "documentation"]
+        ()
+    }
+}
+
+mod issue14577 {
+    trait Unit {}
+    impl Unit for () {}
+
+    fn run<R: Unit>(f: impl FnOnce() -> R) {
+        f();
+    }
+
+    #[allow(dependency_on_unit_never_type_fallback)]
+    fn bar() {
+        run(|| { todo!() }); 
+        //~[edition2021]^ unused_unit
+    }
+
+    struct UnitStruct;
+    impl UnitStruct {
+        fn apply<F: for<'c> Fn(&'c mut Self)>(&mut self, f: F) {
+            todo!()
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/tools/clippy/tests/ui/unused_unit.edition2021.stderr b/src/tools/clippy/tests/ui/unused_unit.edition2021.stderr
new file mode 100644
index 00000000000..13cc20d4d7a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unused_unit.edition2021.stderr
@@ -0,0 +1,128 @@
+error: unneeded unit expression
+  --> tests/ui/unused_unit.rs:37:9
+   |
+LL |         ()
+   |         ^^ help: remove the final `()`
+   |
+note: the lint level is defined here
+  --> tests/ui/unused_unit.rs:15:9
+   |
+LL | #![deny(clippy::unused_unit)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: unneeded unit expression
+  --> tests/ui/unused_unit.rs:62:26
+   |
+LL | fn return_unit() -> () { () }
+   |                          ^^ help: remove the final `()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:22:28
+   |
+LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
+   |                            ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:25:18
+   |
+LL |     where G: Fn() -> () {
+   |                  ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:22:58
+   |
+LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
+   |                                                          ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:27:26
+   |
+LL |         let _y: &dyn Fn() -> () = &f;
+   |                          ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:35:18
+   |
+LL |     fn into(self) -> () {
+   |                  ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:43:29
+   |
+LL |     fn redundant<F: FnOnce() -> (), G, H>(&self, _f: F, _g: G, _h: H)
+   |                             ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:46:19
+   |
+LL |         G: FnMut() -> (),
+   |                   ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:48:16
+   |
+LL |         H: Fn() -> ();
+   |                ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:53:29
+   |
+LL |     fn redundant<F: FnOnce() -> (), G, H>(&self, _f: F, _g: G, _h: H)
+   |                             ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:56:19
+   |
+LL |         G: FnMut() -> (),
+   |                   ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:58:16
+   |
+LL |         H: Fn() -> () {}
+   |                ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:62:17
+   |
+LL | fn return_unit() -> () { () }
+   |                 ^^^^^^ help: remove the `-> ()`
+
+error: unneeded `()`
+  --> tests/ui/unused_unit.rs:74:14
+   |
+LL |         break();
+   |              ^^ help: remove the `()`
+
+error: unneeded `()`
+  --> tests/ui/unused_unit.rs:77:11
+   |
+LL |     return();
+   |           ^^ help: remove the `()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:95:10
+   |
+LL | fn test()->(){}
+   |          ^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:99:11
+   |
+LL | fn test2() ->(){}
+   |           ^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:103:11
+   |
+LL | fn test3()-> (){}
+   |           ^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:136:15
+   |
+LL |         run(|| -> () { todo!() }); 
+   |               ^^^^^^ help: remove the `-> ()`
+
+error: aborting due to 20 previous errors
+
diff --git a/src/tools/clippy/tests/ui/unused_unit.edition2024.fixed b/src/tools/clippy/tests/ui/unused_unit.edition2024.fixed
new file mode 100644
index 00000000000..987d901b97d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unused_unit.edition2024.fixed
@@ -0,0 +1,146 @@
+//@revisions: edition2021 edition2024
+//@[edition2021] edition:2021
+//@[edition2024] edition:2024
+
+// The output for humans should just highlight the whole span without showing
+// the suggested replacement, but we also want to test that suggested
+// replacement only removes one set of parentheses, rather than naïvely
+// stripping away any starting or ending parenthesis characters—hence this
+// test of the JSON error format.
+
+#![feature(custom_inner_attributes)]
+#![feature(closure_lifetime_binder)]
+#![rustfmt::skip]
+
+#![deny(clippy::unused_unit)]
+#![allow(dead_code)]
+#![allow(clippy::from_over_into)]
+
+struct Unitter;
+impl Unitter {
+    #[allow(clippy::no_effect)]
+    pub fn get_unit<F: Fn(), G>(&self, f: F, _g: G)
+    //~^ unused_unit
+    //~| unused_unit
+    where G: Fn() {
+    //~^ unused_unit
+        let _y: &dyn Fn() = &f;
+        //~^ unused_unit
+        (); // this should not lint, as it's not in return type position
+    }
+}
+
+impl Into<()> for Unitter {
+    #[rustfmt::skip]
+    fn into(self) {
+    //~^ unused_unit
+        
+        //~^ unused_unit
+    }
+}
+
+trait Trait {
+    fn redundant<F: FnOnce(), G, H>(&self, _f: F, _g: G, _h: H)
+    //~^ unused_unit
+    where
+        G: FnMut(),
+        //~^ unused_unit
+        H: Fn();
+        //~^ unused_unit
+}
+
+impl Trait for Unitter {
+    fn redundant<F: FnOnce(), G, H>(&self, _f: F, _g: G, _h: H)
+    //~^ unused_unit
+    where
+        G: FnMut(),
+        //~^ unused_unit
+        H: Fn() {}
+        //~^ unused_unit
+}
+
+fn return_unit() {  }
+//~^ unused_unit
+//~| unused_unit
+
+#[allow(clippy::needless_return)]
+#[allow(clippy::never_loop)]
+#[allow(clippy::unit_cmp)]
+fn main() {
+    let u = Unitter;
+    assert_eq!(u.get_unit(|| {}, return_unit), u.into());
+    return_unit();
+    loop {
+        break;
+        //~^ unused_unit
+    }
+    return;
+    //~^ unused_unit
+}
+
+// https://github.com/rust-lang/rust-clippy/issues/4076
+fn foo() {
+    macro_rules! foo {
+        (recv($r:expr) -> $res:pat => $body:expr) => {
+            $body
+        }
+    }
+
+    foo! {
+        recv(rx) -> _x => ()
+    }
+}
+
+#[rustfmt::skip]
+fn test(){}
+//~^ unused_unit
+
+#[rustfmt::skip]
+fn test2(){}
+//~^ unused_unit
+
+#[rustfmt::skip]
+fn test3(){}
+//~^ unused_unit
+
+fn macro_expr() {
+    macro_rules! e {
+        () => (());
+    }
+    e!()
+}
+
+mod issue9748 {
+    fn main() {
+        let _ = for<'a> |_: &'a u32| -> () {};
+    }
+}
+
+mod issue9949 {
+    fn main() {
+        #[doc = "documentation"]
+        ()
+    }
+}
+
+mod issue14577 {
+    trait Unit {}
+    impl Unit for () {}
+
+    fn run<R: Unit>(f: impl FnOnce() -> R) {
+        f();
+    }
+
+    #[allow(dependency_on_unit_never_type_fallback)]
+    fn bar() {
+        run(|| -> () { todo!() }); 
+        //~[edition2021]^ unused_unit
+    }
+
+    struct UnitStruct;
+    impl UnitStruct {
+        fn apply<F: for<'c> Fn(&'c mut Self)>(&mut self, f: F) {
+            todo!()
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/tools/clippy/tests/ui/unused_unit.edition2024.stderr b/src/tools/clippy/tests/ui/unused_unit.edition2024.stderr
new file mode 100644
index 00000000000..a79e70e066b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unused_unit.edition2024.stderr
@@ -0,0 +1,122 @@
+error: unneeded unit expression
+  --> tests/ui/unused_unit.rs:37:9
+   |
+LL |         ()
+   |         ^^ help: remove the final `()`
+   |
+note: the lint level is defined here
+  --> tests/ui/unused_unit.rs:15:9
+   |
+LL | #![deny(clippy::unused_unit)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: unneeded unit expression
+  --> tests/ui/unused_unit.rs:62:26
+   |
+LL | fn return_unit() -> () { () }
+   |                          ^^ help: remove the final `()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:22:28
+   |
+LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
+   |                            ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:25:18
+   |
+LL |     where G: Fn() -> () {
+   |                  ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:22:58
+   |
+LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
+   |                                                          ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:27:26
+   |
+LL |         let _y: &dyn Fn() -> () = &f;
+   |                          ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:35:18
+   |
+LL |     fn into(self) -> () {
+   |                  ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:43:29
+   |
+LL |     fn redundant<F: FnOnce() -> (), G, H>(&self, _f: F, _g: G, _h: H)
+   |                             ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:46:19
+   |
+LL |         G: FnMut() -> (),
+   |                   ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:48:16
+   |
+LL |         H: Fn() -> ();
+   |                ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:53:29
+   |
+LL |     fn redundant<F: FnOnce() -> (), G, H>(&self, _f: F, _g: G, _h: H)
+   |                             ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:56:19
+   |
+LL |         G: FnMut() -> (),
+   |                   ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:58:16
+   |
+LL |         H: Fn() -> () {}
+   |                ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:62:17
+   |
+LL | fn return_unit() -> () { () }
+   |                 ^^^^^^ help: remove the `-> ()`
+
+error: unneeded `()`
+  --> tests/ui/unused_unit.rs:74:14
+   |
+LL |         break();
+   |              ^^ help: remove the `()`
+
+error: unneeded `()`
+  --> tests/ui/unused_unit.rs:77:11
+   |
+LL |     return();
+   |           ^^ help: remove the `()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:95:10
+   |
+LL | fn test()->(){}
+   |          ^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:99:11
+   |
+LL | fn test2() ->(){}
+   |           ^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:103:11
+   |
+LL | fn test3()-> (){}
+   |           ^^^^^ help: remove the `-> ()`
+
+error: aborting due to 19 previous errors
+
diff --git a/src/tools/clippy/tests/ui/unused_unit.fixed b/src/tools/clippy/tests/ui/unused_unit.fixed
index e3c02681c9f..6668bf90c09 100644
--- a/src/tools/clippy/tests/ui/unused_unit.fixed
+++ b/src/tools/clippy/tests/ui/unused_unit.fixed
@@ -120,3 +120,24 @@ mod issue9949 {
         ()
     }
 }
+
+#[clippy::msrv = "1.85"]
+mod issue14577 {
+    trait Unit {}
+    impl Unit for () {}
+
+    fn run<R: Unit>(f: impl FnOnce() -> R) {
+        f();
+    }
+
+    fn bar() {
+        run(|| -> () { todo!() });
+    }
+
+    struct UnitStruct;
+    impl UnitStruct {
+        fn apply<F: for<'c> Fn(&'c mut Self)>(&mut self, f: F) {
+            todo!()
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/tools/clippy/tests/ui/unused_unit.rs b/src/tools/clippy/tests/ui/unused_unit.rs
index 4353026c594..b7645f7b6a2 100644
--- a/src/tools/clippy/tests/ui/unused_unit.rs
+++ b/src/tools/clippy/tests/ui/unused_unit.rs
@@ -1,4 +1,6 @@
-
+//@revisions: edition2021 edition2024
+//@[edition2021] edition:2021
+//@[edition2024] edition:2024
 
 // The output for humans should just highlight the whole span without showing
 // the suggested replacement, but we also want to test that suggested
@@ -120,3 +122,25 @@ mod issue9949 {
         ()
     }
 }
+
+mod issue14577 {
+    trait Unit {}
+    impl Unit for () {}
+
+    fn run<R: Unit>(f: impl FnOnce() -> R) {
+        f();
+    }
+
+    #[allow(dependency_on_unit_never_type_fallback)]
+    fn bar() {
+        run(|| -> () { todo!() }); 
+        //~[edition2021]^ unused_unit
+    }
+
+    struct UnitStruct;
+    impl UnitStruct {
+        fn apply<F: for<'c> Fn(&'c mut Self)>(&mut self, f: F) {
+            todo!()
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/tools/clippy/tests/ui/unused_unit.stderr b/src/tools/clippy/tests/ui/unused_unit.stderr
index 172fe065502..366f2142095 100644
--- a/src/tools/clippy/tests/ui/unused_unit.stderr
+++ b/src/tools/clippy/tests/ui/unused_unit.stderr
@@ -1,8 +1,8 @@
-error: unneeded unit return type
-  --> tests/ui/unused_unit.rs:20:58
+error: unneeded unit expression
+  --> tests/ui/unused_unit.rs:35:9
    |
-LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
-   |                                                          ^^^^^^ help: remove the `-> ()`
+LL |         ()
+   |         ^^ help: remove the final `()`
    |
 note: the lint level is defined here
   --> tests/ui/unused_unit.rs:13:9
@@ -10,6 +10,12 @@ note: the lint level is defined here
 LL | #![deny(clippy::unused_unit)]
    |         ^^^^^^^^^^^^^^^^^^^
 
+error: unneeded unit expression
+  --> tests/ui/unused_unit.rs:60:26
+   |
+LL | fn return_unit() -> () { () }
+   |                          ^^ help: remove the final `()`
+
 error: unneeded unit return type
   --> tests/ui/unused_unit.rs:20:28
    |
@@ -23,6 +29,12 @@ LL |     where G: Fn() -> () {
    |                  ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
+  --> tests/ui/unused_unit.rs:20:58
+   |
+LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
+   |                                                          ^^^^^^ help: remove the `-> ()`
+
+error: unneeded unit return type
   --> tests/ui/unused_unit.rs:25:26
    |
 LL |         let _y: &dyn Fn() -> () = &f;
@@ -34,12 +46,6 @@ error: unneeded unit return type
 LL |     fn into(self) -> () {
    |                  ^^^^^^ help: remove the `-> ()`
 
-error: unneeded unit expression
-  --> tests/ui/unused_unit.rs:35:9
-   |
-LL |         ()
-   |         ^^ help: remove the final `()`
-
 error: unneeded unit return type
   --> tests/ui/unused_unit.rs:41:29
    |
@@ -82,12 +88,6 @@ error: unneeded unit return type
 LL | fn return_unit() -> () { () }
    |                 ^^^^^^ help: remove the `-> ()`
 
-error: unneeded unit expression
-  --> tests/ui/unused_unit.rs:60:26
-   |
-LL | fn return_unit() -> () { () }
-   |                          ^^ help: remove the final `()`
-
 error: unneeded `()`
   --> tests/ui/unused_unit.rs:72:14
    |
diff --git a/src/tools/clippy/tests/ui/zombie_processes.rs b/src/tools/clippy/tests/ui/zombie_processes.rs
index 25bbc02ffb7..395f9dd2def 100644
--- a/src/tools/clippy/tests/ui/zombie_processes.rs
+++ b/src/tools/clippy/tests/ui/zombie_processes.rs
@@ -176,3 +176,25 @@ fn return_wait() -> ExitStatus {
     let mut x = Command::new("").spawn().unwrap();
     return x.wait().unwrap();
 }
+
+mod issue14677 {
+    use std::io;
+    use std::process::Command;
+
+    fn do_something<F: Fn() -> Result<(), ()>>(f: F) {
+        todo!()
+    }
+
+    fn foo() {
+        let mut child = Command::new("true").spawn().unwrap();
+        let some_condition = true;
+        do_something(|| {
+            if some_condition {
+                return Err(());
+            }
+            Ok(())
+        });
+        child.kill().unwrap();
+        child.wait().unwrap();
+    }
+}