about summary refs log tree commit diff
diff options
context:
space:
mode:
authoryanglsh <yanglsh@shanghaitech.edu.cn>2025-07-13 21:13:57 +0800
committeryanglsh <yanglsh@shanghaitech.edu.cn>2025-07-13 21:23:51 +0800
commit9d964048ecd56b53682aae9d01222840a977600a (patch)
tree65493a9e888d63f7a9db179c07805cef9b5b682d
parent7e2d26f4b29f316dd049750b35f9004bb43aece7 (diff)
downloadrust-9d964048ecd56b53682aae9d01222840a977600a.tar.gz
rust-9d964048ecd56b53682aae9d01222840a977600a.zip
fix: `manual_abs_diff` suggests wrongly behind refs
-rw-r--r--clippy_lints/src/manual_abs_diff.rs13
-rw-r--r--tests/ui/manual_abs_diff.fixed4
-rw-r--r--tests/ui/manual_abs_diff.rs9
-rw-r--r--tests/ui/manual_abs_diff.stderr13
4 files changed, 33 insertions, 6 deletions
diff --git a/clippy_lints/src/manual_abs_diff.rs b/clippy_lints/src/manual_abs_diff.rs
index bac4b3d32f2..288f27db8ca 100644
--- a/clippy_lints/src/manual_abs_diff.rs
+++ b/clippy_lints/src/manual_abs_diff.rs
@@ -5,7 +5,7 @@ use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::HasSession as _;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{eq_expr_value, peel_blocks, span_contains_comment};
+use clippy_utils::{eq_expr_value, peel_blocks, peel_middle_ty_refs, span_contains_comment};
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAbsDiff {
             && let ExprKind::Binary(op, rhs, lhs) = if_expr.cond.kind
             && let (BinOpKind::Gt | BinOpKind::Ge, mut a, mut b) | (BinOpKind::Lt | BinOpKind::Le, mut b, mut a) =
                 (op.node, rhs, lhs)
-            && let Some(ty) = self.are_ty_eligible(cx, a, b)
+            && let Some((ty, b_n_refs)) = self.are_ty_eligible(cx, a, b)
             && is_sub_expr(cx, if_expr.then, a, b, ty)
             && is_sub_expr(cx, r#else, b, a, ty)
         {
@@ -86,8 +86,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualAbsDiff {
                         }
                     };
                     let sugg = format!(
-                        "{}.abs_diff({})",
+                        "{}.abs_diff({}{})",
                         Sugg::hir(cx, a, "..").maybe_paren(),
+                        "*".repeat(b_n_refs),
                         Sugg::hir(cx, b, "..")
                     );
                     diag.span_suggestion(expr.span, "replace with `abs_diff`", sugg, applicability);
@@ -100,13 +101,15 @@ impl<'tcx> LateLintPass<'tcx> for ManualAbsDiff {
 impl ManualAbsDiff {
     /// Returns a type if `a` and `b` are both of it, and this lint can be applied to that
     /// type (currently, any primitive int, or a `Duration`)
-    fn are_ty_eligible<'tcx>(&self, cx: &LateContext<'tcx>, a: &Expr<'_>, b: &Expr<'_>) -> Option<Ty<'tcx>> {
+    fn are_ty_eligible<'tcx>(&self, cx: &LateContext<'tcx>, a: &Expr<'_>, b: &Expr<'_>) -> Option<(Ty<'tcx>, usize)> {
         let is_int = |ty: Ty<'_>| matches!(ty.kind(), ty::Uint(_) | ty::Int(_)) && self.msrv.meets(cx, msrvs::ABS_DIFF);
         let is_duration =
             |ty| is_type_diagnostic_item(cx, ty, sym::Duration) && self.msrv.meets(cx, msrvs::DURATION_ABS_DIFF);
 
         let a_ty = cx.typeck_results().expr_ty(a).peel_refs();
-        (a_ty == cx.typeck_results().expr_ty(b).peel_refs() && (is_int(a_ty) || is_duration(a_ty))).then_some(a_ty)
+        let (b_ty, b_n_refs) = peel_middle_ty_refs(cx.typeck_results().expr_ty(b));
+
+        (a_ty == b_ty && (is_int(a_ty) || is_duration(a_ty))).then_some((a_ty, b_n_refs))
     }
 }
 
diff --git a/tests/ui/manual_abs_diff.fixed b/tests/ui/manual_abs_diff.fixed
index f1b1278ea6d..2766942140c 100644
--- a/tests/ui/manual_abs_diff.fixed
+++ b/tests/ui/manual_abs_diff.fixed
@@ -104,3 +104,7 @@ fn non_primitive_ty() {
     let (a, b) = (S(10), S(20));
     let _ = if a < b { b - a } else { a - b };
 }
+
+fn issue15254(a: &usize, b: &usize) -> usize {
+    b.abs_diff(*a)
+}
diff --git a/tests/ui/manual_abs_diff.rs b/tests/ui/manual_abs_diff.rs
index 60ef819c12d..2c408f2be37 100644
--- a/tests/ui/manual_abs_diff.rs
+++ b/tests/ui/manual_abs_diff.rs
@@ -114,3 +114,12 @@ fn non_primitive_ty() {
     let (a, b) = (S(10), S(20));
     let _ = if a < b { b - a } else { a - b };
 }
+
+fn issue15254(a: &usize, b: &usize) -> usize {
+    if a < b {
+        //~^ manual_abs_diff
+        b - a
+    } else {
+        a - b
+    }
+}
diff --git a/tests/ui/manual_abs_diff.stderr b/tests/ui/manual_abs_diff.stderr
index c14c1dc830f..bb6d312b435 100644
--- a/tests/ui/manual_abs_diff.stderr
+++ b/tests/ui/manual_abs_diff.stderr
@@ -79,5 +79,16 @@ error: manual absolute difference pattern without using `abs_diff`
 LL |     let _ = if a > b { (a - b) as u32 } else { (b - a) as u32 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `abs_diff`: `a.abs_diff(b)`
 
-error: aborting due to 11 previous errors
+error: manual absolute difference pattern without using `abs_diff`
+  --> tests/ui/manual_abs_diff.rs:119:5
+   |
+LL | /     if a < b {
+LL | |
+LL | |         b - a
+LL | |     } else {
+LL | |         a - b
+LL | |     }
+   | |_____^ help: replace with `abs_diff`: `b.abs_diff(*a)`
+
+error: aborting due to 12 previous errors