about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Macleod <alex@macleod.io>2025-04-22 16:05:34 +0000
committerPietro Albini <pietro@pietroalbini.org>2025-05-09 17:41:24 +0200
commit287610b489e6e9139d14f86309919c89d15c181b (patch)
tree16e6d25a822ba7b2ba30caab2413db3c0191fdaf
parent6e8f95f7ce6f83801433abc31ef472d7fba62946 (diff)
downloadrust-287610b489e6e9139d14f86309919c89d15c181b.tar.gz
rust-287610b489e6e9139d14f86309919c89d15c181b.zip
Restrict the cases where `ptr_eq` triggers (#14526)
`ptr_eq` was recently enhanced to lint on more cases of raw pointers
comparison:

- lint on all raw pointer comparison, by proposing to use
`[core|std]::ptr::eq(lhs, rhs)` instead of `lhs == rhs`;
- removing one symetric `as usize` on each size if needed
- peeling any level of `as *[const|mut] _` if the remaining expression
can still be coerced into the original one (i.e., is a ref or raw
pointer to the same type as before)

The current change restricts the lint to the cases where at least one
level of symetric `as usize`, or any conversion to a raw pointer, could
be removed. For example, a direct comparaison of two raw pointers will
not trigger the lint anymore.

changelog: [`ptr_eq`]: do not lint when comparing two raw pointers
directly with no casts involved

Fixes rust-lang/rust-clippy#14525
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs22
-rw-r--r--src/tools/clippy/tests/ui/ptr_eq.fixed26
-rw-r--r--src/tools/clippy/tests/ui/ptr_eq.rs16
-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
7 files changed, 60 insertions, 100 deletions
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 0911ed66de2..596f1e3471f 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -786,9 +786,9 @@ fn check_ptr_eq<'tcx>(
     }
 
     // Remove one level of usize conversion if any
-    let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
-        (Some(lhs), Some(rhs)) => (lhs, rhs),
-        _ => (left, right),
+    let (left, right, usize_peeled) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
+        (Some(lhs), Some(rhs)) => (lhs, rhs, true),
+        _ => (left, right, false),
     };
 
     // This lint concerns raw pointers
@@ -797,7 +797,12 @@ fn check_ptr_eq<'tcx>(
         return;
     }
 
-    let (left_var, right_var) = (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
+    let ((left_var, left_casts_peeled), (right_var, right_casts_peeled)) =
+        (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
+
+    if !(usize_peeled || left_casts_peeled || right_casts_peeled) {
+        return;
+    }
 
     let mut app = Applicability::MachineApplicable;
     let left_snip = Sugg::hir_with_context(cx, left_var, expr.span.ctxt(), "_", &mut app);
@@ -830,8 +835,9 @@ fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>
     }
 }
 
-// Peel raw casts if the remaining expression can be coerced to it
-fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> &'tcx Expr<'tcx> {
+// Peel raw casts if the remaining expression can be coerced to it, and whether casts have been
+// peeled or not.
+fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> (&'tcx Expr<'tcx>, bool) {
     if !expr.span.from_expansion()
         && let ExprKind::Cast(inner, _) = expr.kind
         && let ty::RawPtr(target_ty, _) = expr_ty.kind()
@@ -839,8 +845,8 @@ fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty:
         && let ty::RawPtr(inner_target_ty, _) | ty::Ref(_, inner_target_ty, _) = inner_ty.kind()
         && target_ty == inner_target_ty
     {
-        peel_raw_casts(cx, inner, inner_ty)
+        (peel_raw_casts(cx, inner, inner_ty).0, true)
     } else {
-        expr
+        (expr, false)
     }
 }
diff --git a/src/tools/clippy/tests/ui/ptr_eq.fixed b/src/tools/clippy/tests/ui/ptr_eq.fixed
index 484ff307323..f0150e6784b 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,9 +53,9 @@ 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 ());
-    //~^ ptr_eq
+    #[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));
diff --git a/src/tools/clippy/tests/ui/ptr_eq.rs b/src/tools/clippy/tests/ui/ptr_eq.rs
index f28707cc3e9..3fb89257cf1 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,9 +53,9 @@ 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 ();
-    //~^ ptr_eq
 
     // Do not peel the content of macros
     let _ = mac!(cast a) as *const _ == mac!(cast b) as *const _;
diff --git a/src/tools/clippy/tests/ui/ptr_eq.stderr b/src/tools/clippy/tests/ui/ptr_eq.stderr
index 906831b9e03..f613e164b87 100644
--- a/src/tools/clippy/tests/ui/ptr_eq.stderr
+++ b/src/tools/clippy/tests/ui/ptr_eq.stderr
@@ -14,52 +14,22 @@ 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
-   |
-LL |     let _issue14337 = main as *const () == main as *const ();
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(main as *const (), main as *const ())`
-
-error: use `std::ptr::eq` when comparing raw pointers
-  --> tests/ui/ptr_eq.rs:59:13
+  --> tests/ui/ptr_eq.rs:61: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 5 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