Skip to content

Commit 2422f0b

Browse files
authored
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 #14525
2 parents 0621446 + cbfe1f5 commit 2422f0b

File tree

7 files changed

+60
-100
lines changed

7 files changed

+60
-100
lines changed

clippy_lints/src/ptr.rs

+14-8
Original file line numberDiff line numberDiff line change
@@ -743,9 +743,9 @@ fn check_ptr_eq<'tcx>(
743743
}
744744

745745
// Remove one level of usize conversion if any
746-
let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
747-
(Some(lhs), Some(rhs)) => (lhs, rhs),
748-
_ => (left, right),
746+
let (left, right, usize_peeled) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
747+
(Some(lhs), Some(rhs)) => (lhs, rhs, true),
748+
_ => (left, right, false),
749749
};
750750

751751
// This lint concerns raw pointers
@@ -754,7 +754,12 @@ fn check_ptr_eq<'tcx>(
754754
return;
755755
}
756756

757-
let (left_var, right_var) = (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
757+
let ((left_var, left_casts_peeled), (right_var, right_casts_peeled)) =
758+
(peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
759+
760+
if !(usize_peeled || left_casts_peeled || right_casts_peeled) {
761+
return;
762+
}
758763

759764
let mut app = Applicability::MachineApplicable;
760765
let left_snip = Sugg::hir_with_context(cx, left_var, expr.span.ctxt(), "_", &mut app);
@@ -787,17 +792,18 @@ fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>
787792
}
788793
}
789794

790-
// Peel raw casts if the remaining expression can be coerced to it
791-
fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> &'tcx Expr<'tcx> {
795+
// Peel raw casts if the remaining expression can be coerced to it, and whether casts have been
796+
// peeled or not.
797+
fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> (&'tcx Expr<'tcx>, bool) {
792798
if !expr.span.from_expansion()
793799
&& let ExprKind::Cast(inner, _) = expr.kind
794800
&& let ty::RawPtr(target_ty, _) = expr_ty.kind()
795801
&& let inner_ty = cx.typeck_results().expr_ty(inner)
796802
&& let ty::RawPtr(inner_target_ty, _) | ty::Ref(_, inner_target_ty, _) = inner_ty.kind()
797803
&& target_ty == inner_target_ty
798804
{
799-
peel_raw_casts(cx, inner, inner_ty)
805+
(peel_raw_casts(cx, inner, inner_ty).0, true)
800806
} else {
801-
expr
807+
(expr, false)
802808
}
803809
}

tests/ui/ptr_eq.fixed

+14-12
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,25 @@ fn main() {
2323
//~^ ptr_eq
2424
let _ = std::ptr::eq(a, b);
2525
//~^ ptr_eq
26-
let _ = std::ptr::eq(a.as_ptr(), b as *const _);
27-
//~^ ptr_eq
28-
let _ = std::ptr::eq(a.as_ptr(), b.as_ptr());
29-
//~^ ptr_eq
3026

31-
// Do not lint
27+
// Do not lint: the rhs conversion is needed
28+
let _ = a.as_ptr() == b as *const _;
3229

30+
// Do not lint: we have two raw pointers already
31+
let _ = a.as_ptr() == b.as_ptr();
32+
33+
// Do not lint
3334
let _ = mac!(a, b);
3435
let _ = another_mac!(a, b);
3536

3637
let a = &mut [1, 2, 3];
3738
let b = &mut [1, 2, 3];
3839

39-
let _ = std::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _);
40-
//~^ ptr_eq
41-
let _ = std::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr());
42-
//~^ ptr_eq
40+
// Do not lint: the rhs conversion is needed
41+
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
42+
43+
// Do not lint: we have two raw pointers already
44+
let _ = a.as_mut_ptr() == b.as_mut_ptr();
4345

4446
let _ = a == b;
4547
let _ = core::ptr::eq(a, b);
@@ -51,9 +53,9 @@ fn main() {
5153
let _ = !std::ptr::eq(x, y);
5254
//~^ ptr_eq
5355

54-
#[allow(clippy::eq_op)]
55-
let _issue14337 = std::ptr::eq(main as *const (), main as *const ());
56-
//~^ ptr_eq
56+
#[expect(clippy::eq_op)]
57+
// Do not lint: casts are needed to not change type
58+
let _issue14337 = main as *const () == main as *const ();
5759

5860
// Do not peel the content of macros
5961
let _ = std::ptr::eq(mac!(cast a), mac!(cast b));

tests/ui/ptr_eq.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,25 @@ fn main() {
2323
//~^ ptr_eq
2424
let _ = a as *const _ == b as *const _;
2525
//~^ ptr_eq
26+
27+
// Do not lint: the rhs conversion is needed
2628
let _ = a.as_ptr() == b as *const _;
27-
//~^ ptr_eq
29+
30+
// Do not lint: we have two raw pointers already
2831
let _ = a.as_ptr() == b.as_ptr();
29-
//~^ ptr_eq
3032

3133
// Do not lint
32-
3334
let _ = mac!(a, b);
3435
let _ = another_mac!(a, b);
3536

3637
let a = &mut [1, 2, 3];
3738
let b = &mut [1, 2, 3];
3839

40+
// Do not lint: the rhs conversion is needed
3941
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
40-
//~^ ptr_eq
42+
43+
// Do not lint: we have two raw pointers already
4144
let _ = a.as_mut_ptr() == b.as_mut_ptr();
42-
//~^ ptr_eq
4345

4446
let _ = a == b;
4547
let _ = core::ptr::eq(a, b);
@@ -51,9 +53,9 @@ fn main() {
5153
let _ = x as *const u32 != y as *mut u32 as *const u32;
5254
//~^ ptr_eq
5355

54-
#[allow(clippy::eq_op)]
56+
#[expect(clippy::eq_op)]
57+
// Do not lint: casts are needed to not change type
5558
let _issue14337 = main as *const () == main as *const ();
56-
//~^ ptr_eq
5759

5860
// Do not peel the content of macros
5961
let _ = mac!(cast a) as *const _ == mac!(cast b) as *const _;

tests/ui/ptr_eq.stderr

+4-34
Original file line numberDiff line numberDiff line change
@@ -14,52 +14,22 @@ LL | let _ = a as *const _ == b as *const _;
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a, b)`
1515

1616
error: use `std::ptr::eq` when comparing raw pointers
17-
--> tests/ui/ptr_eq.rs:26:13
18-
|
19-
LL | let _ = a.as_ptr() == b as *const _;
20-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_ptr(), b as *const _)`
21-
22-
error: use `std::ptr::eq` when comparing raw pointers
23-
--> tests/ui/ptr_eq.rs:28:13
24-
|
25-
LL | let _ = a.as_ptr() == b.as_ptr();
26-
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_ptr(), b.as_ptr())`
27-
28-
error: use `std::ptr::eq` when comparing raw pointers
29-
--> tests/ui/ptr_eq.rs:39:13
30-
|
31-
LL | let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
32-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _)`
33-
34-
error: use `std::ptr::eq` when comparing raw pointers
35-
--> tests/ui/ptr_eq.rs:41:13
36-
|
37-
LL | let _ = a.as_mut_ptr() == b.as_mut_ptr();
38-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr())`
39-
40-
error: use `std::ptr::eq` when comparing raw pointers
41-
--> tests/ui/ptr_eq.rs:48:13
17+
--> tests/ui/ptr_eq.rs:50:13
4218
|
4319
LL | let _ = x as *const u32 == y as *mut u32 as *const u32;
4420
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(x, y)`
4521

4622
error: use `std::ptr::eq` when comparing raw pointers
47-
--> tests/ui/ptr_eq.rs:51:13
23+
--> tests/ui/ptr_eq.rs:53:13
4824
|
4925
LL | let _ = x as *const u32 != y as *mut u32 as *const u32;
5026
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!std::ptr::eq(x, y)`
5127

5228
error: use `std::ptr::eq` when comparing raw pointers
53-
--> tests/ui/ptr_eq.rs:55:23
54-
|
55-
LL | let _issue14337 = main as *const () == main as *const ();
56-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(main as *const (), main as *const ())`
57-
58-
error: use `std::ptr::eq` when comparing raw pointers
59-
--> tests/ui/ptr_eq.rs:59:13
29+
--> tests/ui/ptr_eq.rs:61:13
6030
|
6131
LL | let _ = mac!(cast a) as *const _ == mac!(cast b) as *const _;
6232
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(mac!(cast a), mac!(cast b))`
6333

64-
error: aborting due to 10 previous errors
34+
error: aborting due to 5 previous errors
6535

tests/ui/ptr_eq_no_std.fixed

+11-9
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,25 @@ fn main() {
3232
//~^ ptr_eq
3333
let _ = core::ptr::eq(a, b);
3434
//~^ ptr_eq
35-
let _ = core::ptr::eq(a.as_ptr(), b as *const _);
36-
//~^ ptr_eq
37-
let _ = core::ptr::eq(a.as_ptr(), b.as_ptr());
38-
//~^ ptr_eq
3935

40-
// Do not lint
36+
// Do not lint: the rhs conversion is needed
37+
let _ = a.as_ptr() == b as *const _;
38+
39+
// Do not lint: we have two raw pointers already
40+
let _ = a.as_ptr() == b.as_ptr();
4141

42+
// Do not lint
4243
let _ = mac!(a, b);
4344
let _ = another_mac!(a, b);
4445

4546
let a = &mut [1, 2, 3];
4647
let b = &mut [1, 2, 3];
4748

48-
let _ = core::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _);
49-
//~^ ptr_eq
50-
let _ = core::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr());
51-
//~^ ptr_eq
49+
// Do not lint: the rhs conversion is needed
50+
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
51+
52+
// Do not lint: we have two raw pointers already
53+
let _ = a.as_mut_ptr() == b.as_mut_ptr();
5254

5355
let _ = a == b;
5456
let _ = core::ptr::eq(a, b);

tests/ui/ptr_eq_no_std.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,25 @@ fn main() {
3232
//~^ ptr_eq
3333
let _ = a as *const _ == b as *const _;
3434
//~^ ptr_eq
35+
36+
// Do not lint: the rhs conversion is needed
3537
let _ = a.as_ptr() == b as *const _;
36-
//~^ ptr_eq
38+
39+
// Do not lint: we have two raw pointers already
3740
let _ = a.as_ptr() == b.as_ptr();
38-
//~^ ptr_eq
3941

4042
// Do not lint
41-
4243
let _ = mac!(a, b);
4344
let _ = another_mac!(a, b);
4445

4546
let a = &mut [1, 2, 3];
4647
let b = &mut [1, 2, 3];
4748

49+
// Do not lint: the rhs conversion is needed
4850
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
49-
//~^ ptr_eq
51+
52+
// Do not lint: we have two raw pointers already
5053
let _ = a.as_mut_ptr() == b.as_mut_ptr();
51-
//~^ ptr_eq
5254

5355
let _ = a == b;
5456
let _ = core::ptr::eq(a, b);

tests/ui/ptr_eq_no_std.stderr

+1-25
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,5 @@ error: use `core::ptr::eq` when comparing raw pointers
1313
LL | let _ = a as *const _ == b as *const _;
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a, b)`
1515

16-
error: use `core::ptr::eq` when comparing raw pointers
17-
--> tests/ui/ptr_eq_no_std.rs:35:13
18-
|
19-
LL | let _ = a.as_ptr() == b as *const _;
20-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_ptr(), b as *const _)`
21-
22-
error: use `core::ptr::eq` when comparing raw pointers
23-
--> tests/ui/ptr_eq_no_std.rs:37:13
24-
|
25-
LL | let _ = a.as_ptr() == b.as_ptr();
26-
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_ptr(), b.as_ptr())`
27-
28-
error: use `core::ptr::eq` when comparing raw pointers
29-
--> tests/ui/ptr_eq_no_std.rs:48:13
30-
|
31-
LL | let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
32-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _)`
33-
34-
error: use `core::ptr::eq` when comparing raw pointers
35-
--> tests/ui/ptr_eq_no_std.rs:50:13
36-
|
37-
LL | let _ = a.as_mut_ptr() == b.as_mut_ptr();
38-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr())`
39-
40-
error: aborting due to 6 previous errors
16+
error: aborting due to 2 previous errors
4117

0 commit comments

Comments
 (0)