From db4bd965750291a7676f530e335de123833c4794 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 3 Apr 2025 00:02:44 +0200 Subject: [PATCH] Ensure that peeling does not recurse into macros We do not want to remove casts done inside macros. Also, when printing the suggestion, take it from the same context as the origin expression (the root context). --- clippy_lints/src/ptr.rs | 13 ++++++++----- tests/ui/ptr_eq.fixed | 7 +++++++ tests/ui/ptr_eq.rs | 7 +++++++ tests/ui/ptr_eq.stderr | 26 ++++++++++++++++---------- 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 597894fe9872..0dc4880110fe 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -799,8 +799,9 @@ fn check_ptr_eq<'tcx>( let (left_var, right_var) = (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty)); - if let Some(left_snip) = left_var.span.get_source_text(cx) - && let Some(right_snip) = right_var.span.get_source_text(cx) + let mut app = Applicability::MachineApplicable; + let left_snip = Sugg::hir_with_context(cx, left_var, expr.span.ctxt(), "_", &mut app); + let right_snip = Sugg::hir_with_context(cx, right_var, expr.span.ctxt(), "_", &mut app); { let Some(top_crate) = std_or_core(cx) else { return }; let invert = if op == BinOpKind::Eq { "" } else { "!" }; @@ -811,7 +812,7 @@ fn check_ptr_eq<'tcx>( format!("use `{top_crate}::ptr::eq` when comparing raw pointers"), "try", format!("{invert}{top_crate}::ptr::eq({left_snip}, {right_snip})"), - Applicability::MachineApplicable, + app, ); } } @@ -819,7 +820,8 @@ fn check_ptr_eq<'tcx>( // If the given expression is a cast to a usize, return the lhs of the cast // E.g., `foo as *const _ as usize` returns `foo as *const _`. fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { - if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize + if !cast_expr.span.from_expansion() + && cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize && let ExprKind::Cast(expr, _) = cast_expr.kind { Some(expr) @@ -830,7 +832,8 @@ 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> { - if let ExprKind::Cast(inner, _) = expr.kind + if !expr.span.from_expansion() + && let ExprKind::Cast(inner, _) = expr.kind && let ty::RawPtr(target_ty, _) = expr_ty.kind() && let inner_ty = cx.typeck_results().expr_ty(inner) && let ty::RawPtr(inner_target_ty, _) | ty::Ref(_, inner_target_ty, _) = inner_ty.kind() diff --git a/tests/ui/ptr_eq.fixed b/tests/ui/ptr_eq.fixed index df6305ed497e..484ff3073239 100644 --- a/tests/ui/ptr_eq.fixed +++ b/tests/ui/ptr_eq.fixed @@ -4,6 +4,9 @@ macro_rules! mac { ($a:expr, $b:expr) => { $a as *const _ as usize == $b as *const _ as usize }; + (cast $a:expr) => { + $a as *const [i32; 3] + }; } macro_rules! another_mac { @@ -51,4 +54,8 @@ fn main() { #[allow(clippy::eq_op)] let _issue14337 = std::ptr::eq(main as *const (), main as *const ()); //~^ ptr_eq + + // Do not peel the content of macros + let _ = std::ptr::eq(mac!(cast a), mac!(cast b)); + //~^ ptr_eq } diff --git a/tests/ui/ptr_eq.rs b/tests/ui/ptr_eq.rs index 0ed0ff0d1371..f28707cc3e92 100644 --- a/tests/ui/ptr_eq.rs +++ b/tests/ui/ptr_eq.rs @@ -4,6 +4,9 @@ macro_rules! mac { ($a:expr, $b:expr) => { $a as *const _ as usize == $b as *const _ as usize }; + (cast $a:expr) => { + $a as *const [i32; 3] + }; } macro_rules! another_mac { @@ -51,4 +54,8 @@ fn main() { #[allow(clippy::eq_op)] 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 _; + //~^ ptr_eq } diff --git a/tests/ui/ptr_eq.stderr b/tests/ui/ptr_eq.stderr index 33190df284a3..906831b9e031 100644 --- a/tests/ui/ptr_eq.stderr +++ b/tests/ui/ptr_eq.stderr @@ -1,5 +1,5 @@ error: use `std::ptr::eq` when comparing raw pointers - --> tests/ui/ptr_eq.rs:19:13 + --> tests/ui/ptr_eq.rs:22:13 | LL | let _ = a as *const _ as usize == b as *const _ as usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a, b)` @@ -8,52 +8,58 @@ LL | let _ = a as *const _ as usize == b as *const _ as usize; = help: to override `-D warnings` add `#[allow(clippy::ptr_eq)]` error: use `std::ptr::eq` when comparing raw pointers - --> tests/ui/ptr_eq.rs:21:13 + --> tests/ui/ptr_eq.rs:24:13 | 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:23:13 + --> 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:25:13 + --> 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:36:13 + --> 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:38:13 + --> 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:45:13 + --> tests/ui/ptr_eq.rs:48: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:48:13 + --> tests/ui/ptr_eq.rs:51: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:52:23 + --> 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: aborting due to 9 previous errors +error: use `std::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq.rs:59: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