Skip to content

Commit bace424

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 dfca8ff commit bace424

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
@@ -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,7 +797,12 @@ 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));
802+
803+
if !(usize_peeled || left_casts_peeled || right_casts_peeled) {
804+
return;
805+
}
801806

802807
let mut app = Applicability::MachineApplicable;
803808
let left_snip = Sugg::hir_with_context(cx, left_var, expr.span.ctxt(), "_", &mut app);
@@ -830,17 +835,18 @@ fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>
830835
}
831836
}
832837

833-
// Peel raw casts if the remaining expression can be coerced to it
834-
fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> &'tcx Expr<'tcx> {
838+
// Peel raw casts if the remaining expression can be coerced to it, and whether casts have been
839+
// peeled or not.
840+
fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> (&'tcx Expr<'tcx>, bool) {
835841
if !expr.span.from_expansion()
836842
&& let ExprKind::Cast(inner, _) = expr.kind
837843
&& let ty::RawPtr(target_ty, _) = expr_ty.kind()
838844
&& let inner_ty = cx.typeck_results().expr_ty(inner)
839845
&& let ty::RawPtr(inner_target_ty, _) | ty::Ref(_, inner_target_ty, _) = inner_ty.kind()
840846
&& target_ty == inner_target_ty
841847
{
842-
peel_raw_casts(cx, inner, inner_ty)
848+
(peel_raw_casts(cx, inner, inner_ty).0, true)
843849
} else {
844-
expr
850+
(expr, false)
845851
}
846852
}

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)