Skip to content

Commit d7d0abd

Browse files
committed
Lint more cases of ptr::eq()
Also, do not strip conversions of a function pointer to a `*const`, as no implicit conversion will take place.
1 parent 62f34f2 commit d7d0abd

File tree

7 files changed

+124
-21
lines changed

7 files changed

+124
-21
lines changed

clippy_lints/src/operators/ptr_eq.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use clippy_utils::std_or_core;
44
use rustc_errors::Applicability;
55
use rustc_hir::{BinOpKind, Expr, ExprKind};
66
use rustc_lint::LateContext;
7+
use rustc_middle::ty::{self, Ty};
78

89
use super::PTR_EQ;
910

@@ -15,14 +16,21 @@ pub(super) fn check<'tcx>(
1516
right: &'tcx Expr<'_>,
1617
) {
1718
if BinOpKind::Eq == op {
19+
// Remove one level of usize conversion if any
1820
let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
1921
(Some(lhs), Some(rhs)) => (lhs, rhs),
2022
_ => (left, right),
2123
};
2224

23-
if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left)
24-
&& let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right)
25-
&& let Some(left_snip) = left_var.span.get_source_text(cx)
25+
// This lint concerns raw pointers
26+
let (left_ty, right_ty) = (cx.typeck_results().expr_ty(left), cx.typeck_results().expr_ty(right));
27+
if !left_ty.is_raw_ptr() || !right_ty.is_raw_ptr() {
28+
return;
29+
}
30+
31+
let (left_var, right_var) = (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
32+
33+
if let Some(left_snip) = left_var.span.get_source_text(cx)
2634
&& let Some(right_snip) = right_var.span.get_source_text(cx)
2735
{
2836
let Some(top_crate) = std_or_core(cx) else { return };
@@ -50,13 +58,16 @@ fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>
5058
None
5159
}
5260

53-
// If the given expression is a cast to a `*const` pointer, return the lhs of the cast
54-
// E.g., `foo as *const _` returns `foo`.
55-
fn expr_as_cast_to_raw_pointer<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
56-
if cx.typeck_results().expr_ty(cast_expr).is_raw_ptr() {
57-
if let ExprKind::Cast(expr, _) = cast_expr.kind {
58-
return Some(expr);
59-
}
61+
// Peel raw casts if the remaining expression can be coerced to it
62+
fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> &'tcx Expr<'tcx> {
63+
if let ExprKind::Cast(inner, _) = expr.kind
64+
&& let ty::RawPtr(target_ty, _) = expr_ty.kind()
65+
&& let inner_ty = cx.typeck_results().expr_ty(inner)
66+
&& let ty::RawPtr(inner_target_ty, _) | ty::Ref(_, inner_target_ty, _) = inner_ty.kind()
67+
&& target_ty == inner_target_ty
68+
{
69+
peel_raw_casts(cx, inner, inner_ty)
70+
} else {
71+
expr
6072
}
61-
None
6273
}

tests/ui/ptr_eq.fixed

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ fn main() {
2020
//~^ ptr_eq
2121
let _ = std::ptr::eq(a, b);
2222
//~^ ptr_eq
23-
let _ = a.as_ptr() == b as *const _;
24-
let _ = a.as_ptr() == b.as_ptr();
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
2527

2628
// Do not lint
2729

@@ -31,9 +33,19 @@ fn main() {
3133
let a = &mut [1, 2, 3];
3234
let b = &mut [1, 2, 3];
3335

34-
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
35-
let _ = a.as_mut_ptr() == b.as_mut_ptr();
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
3640

3741
let _ = a == b;
3842
let _ = core::ptr::eq(a, b);
43+
44+
let (x, y) = (&0u32, &mut 1u32);
45+
let _ = std::ptr::eq(x, y);
46+
//~^ ptr_eq
47+
48+
#[allow(clippy::eq_op)]
49+
let _issue14337 = std::ptr::eq(main as *const (), main as *const ());
50+
//~^ ptr_eq
3951
}

tests/ui/ptr_eq.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ fn main() {
2121
let _ = a as *const _ == b as *const _;
2222
//~^ ptr_eq
2323
let _ = a.as_ptr() == b as *const _;
24+
//~^ ptr_eq
2425
let _ = a.as_ptr() == b.as_ptr();
26+
//~^ ptr_eq
2527

2628
// Do not lint
2729

@@ -32,8 +34,18 @@ fn main() {
3234
let b = &mut [1, 2, 3];
3335

3436
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
37+
//~^ ptr_eq
3538
let _ = a.as_mut_ptr() == b.as_mut_ptr();
39+
//~^ ptr_eq
3640

3741
let _ = a == b;
3842
let _ = core::ptr::eq(a, b);
43+
44+
let (x, y) = (&0u32, &mut 1u32);
45+
let _ = x as *const u32 == y as *mut u32 as *const u32;
46+
//~^ ptr_eq
47+
48+
#[allow(clippy::eq_op)]
49+
let _issue14337 = main as *const () == main as *const ();
50+
//~^ ptr_eq
3951
}

tests/ui/ptr_eq.stderr

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,41 @@ error: use `std::ptr::eq` when comparing raw pointers
1313
LL | let _ = a as *const _ == b as *const _;
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a, b)`
1515

16-
error: aborting due to 2 previous errors
16+
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
42+
|
43+
LL | let _ = x as *const u32 == y as *mut u32 as *const u32;
44+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(x, y)`
45+
46+
error: use `std::ptr::eq` when comparing raw pointers
47+
--> tests/ui/ptr_eq.rs:49:23
48+
|
49+
LL | let _issue14337 = main as *const () == main as *const ();
50+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(main as *const (), main as *const ())`
51+
52+
error: aborting due to 8 previous errors
1753

tests/ui/ptr_eq_no_std.fixed

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ fn main() {
3232
//~^ ptr_eq
3333
let _ = core::ptr::eq(a, b);
3434
//~^ ptr_eq
35-
let _ = a.as_ptr() == b as *const _;
36-
let _ = a.as_ptr() == b.as_ptr();
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
3739

3840
// Do not lint
3941

@@ -43,8 +45,10 @@ fn main() {
4345
let a = &mut [1, 2, 3];
4446
let b = &mut [1, 2, 3];
4547

46-
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
47-
let _ = a.as_mut_ptr() == b.as_mut_ptr();
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
4852

4953
let _ = a == b;
5054
let _ = core::ptr::eq(a, b);

tests/ui/ptr_eq_no_std.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ fn main() {
3333
let _ = a as *const _ == b as *const _;
3434
//~^ ptr_eq
3535
let _ = a.as_ptr() == b as *const _;
36+
//~^ ptr_eq
3637
let _ = a.as_ptr() == b.as_ptr();
38+
//~^ ptr_eq
3739

3840
// Do not lint
3941

@@ -44,7 +46,9 @@ fn main() {
4446
let b = &mut [1, 2, 3];
4547

4648
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
49+
//~^ ptr_eq
4750
let _ = a.as_mut_ptr() == b.as_mut_ptr();
51+
//~^ ptr_eq
4852

4953
let _ = a == b;
5054
let _ = core::ptr::eq(a, b);

tests/ui/ptr_eq_no_std.stderr

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,29 @@ 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: aborting due to 2 previous errors
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
1741

0 commit comments

Comments
 (0)