Skip to content

Commit db4bd96

Browse files
committed
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).
1 parent 0ca62d1 commit db4bd96

File tree

4 files changed

+38
-15
lines changed

4 files changed

+38
-15
lines changed

clippy_lints/src/ptr.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -799,8 +799,9 @@ fn check_ptr_eq<'tcx>(
799799

800800
let (left_var, right_var) = (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
801801

802-
if let Some(left_snip) = left_var.span.get_source_text(cx)
803-
&& let Some(right_snip) = right_var.span.get_source_text(cx)
802+
let mut app = Applicability::MachineApplicable;
803+
let left_snip = Sugg::hir_with_context(cx, left_var, expr.span.ctxt(), "_", &mut app);
804+
let right_snip = Sugg::hir_with_context(cx, right_var, expr.span.ctxt(), "_", &mut app);
804805
{
805806
let Some(top_crate) = std_or_core(cx) else { return };
806807
let invert = if op == BinOpKind::Eq { "" } else { "!" };
@@ -811,15 +812,16 @@ fn check_ptr_eq<'tcx>(
811812
format!("use `{top_crate}::ptr::eq` when comparing raw pointers"),
812813
"try",
813814
format!("{invert}{top_crate}::ptr::eq({left_snip}, {right_snip})"),
814-
Applicability::MachineApplicable,
815+
app,
815816
);
816817
}
817818
}
818819

819820
// If the given expression is a cast to a usize, return the lhs of the cast
820821
// E.g., `foo as *const _ as usize` returns `foo as *const _`.
821822
fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
822-
if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize
823+
if !cast_expr.span.from_expansion()
824+
&& cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize
823825
&& let ExprKind::Cast(expr, _) = cast_expr.kind
824826
{
825827
Some(expr)
@@ -830,7 +832,8 @@ fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>
830832

831833
// Peel raw casts if the remaining expression can be coerced to it
832834
fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> &'tcx Expr<'tcx> {
833-
if let ExprKind::Cast(inner, _) = expr.kind
835+
if !expr.span.from_expansion()
836+
&& let ExprKind::Cast(inner, _) = expr.kind
834837
&& let ty::RawPtr(target_ty, _) = expr_ty.kind()
835838
&& let inner_ty = cx.typeck_results().expr_ty(inner)
836839
&& let ty::RawPtr(inner_target_ty, _) | ty::Ref(_, inner_target_ty, _) = inner_ty.kind()

tests/ui/ptr_eq.fixed

+7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ macro_rules! mac {
44
($a:expr, $b:expr) => {
55
$a as *const _ as usize == $b as *const _ as usize
66
};
7+
(cast $a:expr) => {
8+
$a as *const [i32; 3]
9+
};
710
}
811

912
macro_rules! another_mac {
@@ -51,4 +54,8 @@ fn main() {
5154
#[allow(clippy::eq_op)]
5255
let _issue14337 = std::ptr::eq(main as *const (), main as *const ());
5356
//~^ ptr_eq
57+
58+
// Do not peel the content of macros
59+
let _ = std::ptr::eq(mac!(cast a), mac!(cast b));
60+
//~^ ptr_eq
5461
}

tests/ui/ptr_eq.rs

+7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ macro_rules! mac {
44
($a:expr, $b:expr) => {
55
$a as *const _ as usize == $b as *const _ as usize
66
};
7+
(cast $a:expr) => {
8+
$a as *const [i32; 3]
9+
};
710
}
811

912
macro_rules! another_mac {
@@ -51,4 +54,8 @@ fn main() {
5154
#[allow(clippy::eq_op)]
5255
let _issue14337 = main as *const () == main as *const ();
5356
//~^ ptr_eq
57+
58+
// Do not peel the content of macros
59+
let _ = mac!(cast a) as *const _ == mac!(cast b) as *const _;
60+
//~^ ptr_eq
5461
}

tests/ui/ptr_eq.stderr

+16-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: use `std::ptr::eq` when comparing raw pointers
2-
--> tests/ui/ptr_eq.rs:19:13
2+
--> tests/ui/ptr_eq.rs:22:13
33
|
44
LL | let _ = a as *const _ as usize == b as *const _ as usize;
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a, b)`
@@ -8,52 +8,58 @@ LL | let _ = a as *const _ as usize == b as *const _ as usize;
88
= help: to override `-D warnings` add `#[allow(clippy::ptr_eq)]`
99

1010
error: use `std::ptr::eq` when comparing raw pointers
11-
--> tests/ui/ptr_eq.rs:21:13
11+
--> tests/ui/ptr_eq.rs:24:13
1212
|
1313
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
17+
--> tests/ui/ptr_eq.rs:26:13
1818
|
1919
LL | let _ = a.as_ptr() == b as *const _;
2020
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_ptr(), b as *const _)`
2121

2222
error: use `std::ptr::eq` when comparing raw pointers
23-
--> tests/ui/ptr_eq.rs:25:13
23+
--> tests/ui/ptr_eq.rs:28:13
2424
|
2525
LL | let _ = a.as_ptr() == b.as_ptr();
2626
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_ptr(), b.as_ptr())`
2727

2828
error: use `std::ptr::eq` when comparing raw pointers
29-
--> tests/ui/ptr_eq.rs:36:13
29+
--> tests/ui/ptr_eq.rs:39:13
3030
|
3131
LL | let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
3232
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _)`
3333

3434
error: use `std::ptr::eq` when comparing raw pointers
35-
--> tests/ui/ptr_eq.rs:38:13
35+
--> tests/ui/ptr_eq.rs:41:13
3636
|
3737
LL | let _ = a.as_mut_ptr() == b.as_mut_ptr();
3838
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr())`
3939

4040
error: use `std::ptr::eq` when comparing raw pointers
41-
--> tests/ui/ptr_eq.rs:45:13
41+
--> tests/ui/ptr_eq.rs:48:13
4242
|
4343
LL | let _ = x as *const u32 == y as *mut u32 as *const u32;
4444
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(x, y)`
4545

4646
error: use `std::ptr::eq` when comparing raw pointers
47-
--> tests/ui/ptr_eq.rs:48:13
47+
--> tests/ui/ptr_eq.rs:51:13
4848
|
4949
LL | let _ = x as *const u32 != y as *mut u32 as *const u32;
5050
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!std::ptr::eq(x, y)`
5151

5252
error: use `std::ptr::eq` when comparing raw pointers
53-
--> tests/ui/ptr_eq.rs:52:23
53+
--> tests/ui/ptr_eq.rs:55:23
5454
|
5555
LL | let _issue14337 = main as *const () == main as *const ();
5656
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(main as *const (), main as *const ())`
5757

58-
error: aborting due to 9 previous errors
58+
error: use `std::ptr::eq` when comparing raw pointers
59+
--> tests/ui/ptr_eq.rs:59:13
60+
|
61+
LL | let _ = mac!(cast a) as *const _ == mac!(cast b) as *const _;
62+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(mac!(cast a), mac!(cast b))`
63+
64+
error: aborting due to 10 previous errors
5965

0 commit comments

Comments
 (0)