Skip to content

Commit 3be34fb

Browse files
committed
Restrict the cases where ptr_eq triggers
`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.
1 parent 0ca62d1 commit 3be34fb

File tree

7 files changed

+59
-100
lines changed

7 files changed

+59
-100
lines changed

clippy_lints/src/ptr.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -786,9 +786,9 @@ fn check_ptr_eq<'tcx>(
786786
}
787787

788788
// Remove one level of usize conversion if any
789-
let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
790-
(Some(lhs), Some(rhs)) => (lhs, rhs),
791-
_ => (left, right),
789+
let (left, right, usize_peeled) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
790+
(Some(lhs), Some(rhs)) => (lhs, rhs, true),
791+
_ => (left, right, false),
792792
};
793793

794794
// This lint concerns raw pointers
@@ -797,9 +797,13 @@ fn check_ptr_eq<'tcx>(
797797
return;
798798
}
799799

800-
let (left_var, right_var) = (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
800+
let ((left_var, left_casts_peeled), (right_var, right_casts_peeled)) =
801+
(peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
801802

802-
if let Some(left_snip) = left_var.span.get_source_text(cx)
803+
// Lint only if at least one level of symetric usize cast or at least one cast to raw pointer can be
804+
// removed.
805+
if (usize_peeled || left_casts_peeled || right_casts_peeled)
806+
&& let Some(left_snip) = left_var.span.get_source_text(cx)
803807
&& let Some(right_snip) = right_var.span.get_source_text(cx)
804808
{
805809
let Some(top_crate) = std_or_core(cx) else { return };
@@ -828,16 +832,17 @@ fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>
828832
}
829833
}
830834

831-
// Peel raw casts if the remaining expression can be coerced to it
832-
fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> &'tcx Expr<'tcx> {
835+
// Peel raw casts if the remaining expression can be coerced to it, and whether casts have been
836+
// peeled or not.
837+
fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> (&'tcx Expr<'tcx>, bool) {
833838
if let ExprKind::Cast(inner, _) = expr.kind
834839
&& let ty::RawPtr(target_ty, _) = expr_ty.kind()
835840
&& let inner_ty = cx.typeck_results().expr_ty(inner)
836841
&& let ty::RawPtr(inner_target_ty, _) | ty::Ref(_, inner_target_ty, _) = inner_ty.kind()
837842
&& target_ty == inner_target_ty
838843
{
839-
peel_raw_casts(cx, inner, inner_ty)
844+
(peel_raw_casts(cx, inner, inner_ty).0, true)
840845
} else {
841-
expr
846+
(expr, false)
842847
}
843848
}

tests/ui/ptr_eq.fixed

+14-12
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,25 @@ fn main() {
2020
//~^ ptr_eq
2121
let _ = std::ptr::eq(a, b);
2222
//~^ ptr_eq
23-
let _ = std::ptr::eq(a.as_ptr(), b as *const _);
24-
//~^ ptr_eq
25-
let _ = std::ptr::eq(a.as_ptr(), b.as_ptr());
26-
//~^ ptr_eq
2723

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

27+
// Do not lint: we have two raw pointers already
28+
let _ = a.as_ptr() == b.as_ptr();
29+
30+
// Do not lint
3031
let _ = mac!(a, b);
3132
let _ = another_mac!(a, b);
3233

3334
let a = &mut [1, 2, 3];
3435
let b = &mut [1, 2, 3];
3536

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

4143
let _ = a == b;
4244
let _ = core::ptr::eq(a, b);
@@ -48,7 +50,7 @@ fn main() {
4850
let _ = !std::ptr::eq(x, y);
4951
//~^ ptr_eq
5052

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

tests/ui/ptr_eq.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,25 @@ fn main() {
2020
//~^ ptr_eq
2121
let _ = a as *const _ == b as *const _;
2222
//~^ ptr_eq
23+
24+
// Do not lint: the rhs conversion is needed
2325
let _ = a.as_ptr() == b as *const _;
24-
//~^ ptr_eq
26+
27+
// Do not lint: we have two raw pointers already
2528
let _ = a.as_ptr() == b.as_ptr();
26-
//~^ ptr_eq
2729

2830
// Do not lint
29-
3031
let _ = mac!(a, b);
3132
let _ = another_mac!(a, b);
3233

3334
let a = &mut [1, 2, 3];
3435
let b = &mut [1, 2, 3];
3536

37+
// Do not lint: the rhs conversion is needed
3638
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
37-
//~^ ptr_eq
39+
40+
// Do not lint: we have two raw pointers already
3841
let _ = a.as_mut_ptr() == b.as_mut_ptr();
39-
//~^ ptr_eq
4042

4143
let _ = a == b;
4244
let _ = core::ptr::eq(a, b);
@@ -48,7 +50,7 @@ fn main() {
4850
let _ = x as *const u32 != y as *mut u32 as *const u32;
4951
//~^ ptr_eq
5052

51-
#[allow(clippy::eq_op)]
53+
#[expect(clippy::eq_op)]
54+
// Do not lint: casts are needed to not change type
5255
let _issue14337 = main as *const () == main as *const ();
53-
//~^ ptr_eq
5456
}

tests/ui/ptr_eq.stderr

+3-33
Original file line numberDiff line numberDiff line change
@@ -14,46 +14,16 @@ 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:23: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:25: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:36: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:38: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:45:13
17+
--> tests/ui/ptr_eq.rs:47: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:48:13
23+
--> tests/ui/ptr_eq.rs:50: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

52-
error: use `std::ptr::eq` when comparing raw pointers
53-
--> tests/ui/ptr_eq.rs:52: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: aborting due to 9 previous errors
28+
error: aborting due to 4 previous errors
5929

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)