about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlejandra González <blyxyas@gmail.com>2025-01-14 19:06:32 +0000
committerGitHub <noreply@github.com>2025-01-14 19:06:32 +0000
commit7e83ec57c60ae0d4ff8bdbc1d10291a5bb7ca558 (patch)
tree3b63eabbdef6ef444a848423b72aee44876037b0
parent8c1ea9fa01435d7d9c460d229b52edafe2a05d13 (diff)
parentdc23fa5e6c2b6b783a23ef7e6835f7867361ddaf (diff)
downloadrust-7e83ec57c60ae0d4ff8bdbc1d10291a5bb7ca558.tar.gz
rust-7e83ec57c60ae0d4ff8bdbc1d10291a5bb7ca558.zip
Suggest `manual_div_ceil` even when right operand is a constant (#13951)
changelog: [`manual_div_ceil`]: lint constants as well

Fix #13950
-rw-r--r--clippy_lints/src/manual_div_ceil.rs36
-rw-r--r--tests/ui/manual_div_ceil.fixed11
-rw-r--r--tests/ui/manual_div_ceil.rs11
-rw-r--r--tests/ui/manual_div_ceil.stderr14
-rw-r--r--tests/ui/manual_div_ceil_with_feature.fixed11
-rw-r--r--tests/ui/manual_div_ceil_with_feature.rs11
-rw-r--r--tests/ui/manual_div_ceil_with_feature.stderr32
7 files changed, 124 insertions, 2 deletions
diff --git a/clippy_lints/src/manual_div_ceil.rs b/clippy_lints/src/manual_div_ceil.rs
index aa59b047b16..816ca17b3d2 100644
--- a/clippy_lints/src/manual_div_ceil.rs
+++ b/clippy_lints/src/manual_div_ceil.rs
@@ -102,12 +102,48 @@ impl<'tcx> LateLintPass<'tcx> for ManualDivCeil {
             {
                 build_suggestion(cx, expr, add_lhs, div_rhs, &mut applicability);
             }
+
+            // (x + (Y - 1)) / Y
+            if inner_op.node == BinOpKind::Add && differ_by_one(inner_rhs, div_rhs) {
+                build_suggestion(cx, expr, inner_lhs, div_rhs, &mut applicability);
+            }
+
+            // ((Y - 1) + x) / Y
+            if inner_op.node == BinOpKind::Add && differ_by_one(inner_lhs, div_rhs) {
+                build_suggestion(cx, expr, inner_rhs, div_rhs, &mut applicability);
+            }
+
+            // (x - (-Y - 1)) / Y
+            if inner_op.node == BinOpKind::Sub
+                && let ExprKind::Unary(UnOp::Neg, abs_div_rhs) = div_rhs.kind
+                && differ_by_one(abs_div_rhs, inner_rhs)
+            {
+                build_suggestion(cx, expr, inner_lhs, div_rhs, &mut applicability);
+            }
         }
     }
 
     extract_msrv_attr!(LateContext);
 }
 
+/// Checks if two expressions represent non-zero integer literals such that `small_expr + 1 ==
+/// large_expr`.
+fn differ_by_one(small_expr: &Expr<'_>, large_expr: &Expr<'_>) -> bool {
+    if let ExprKind::Lit(small) = small_expr.kind
+        && let ExprKind::Lit(large) = large_expr.kind
+        && let LitKind::Int(s, _) = small.node
+        && let LitKind::Int(l, _) = large.node
+    {
+        Some(l.get()) == s.get().checked_add(1)
+    } else if let ExprKind::Unary(UnOp::Neg, small_inner_expr) = small_expr.kind
+        && let ExprKind::Unary(UnOp::Neg, large_inner_expr) = large_expr.kind
+    {
+        differ_by_one(large_inner_expr, small_inner_expr)
+    } else {
+        false
+    }
+}
+
 fn check_int_ty_and_feature(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let expr_ty = cx.typeck_results().expr_ty(expr);
     match expr_ty.peel_refs().kind() {
diff --git a/tests/ui/manual_div_ceil.fixed b/tests/ui/manual_div_ceil.fixed
index 1fb1df5b442..f6eb5a9784a 100644
--- a/tests/ui/manual_div_ceil.fixed
+++ b/tests/ui/manual_div_ceil.fixed
@@ -50,3 +50,14 @@ fn issue_13843() {
 
     let _ = 1_000_000_u32.div_ceil(6u32);
 }
+
+fn issue_13950() {
+    let x = 33u32;
+    let _ = x.div_ceil(8);
+    let _ = x.div_ceil(8);
+
+    let y = -33i32;
+    let _ = (y + -8) / -7;
+    let _ = (-8 + y) / -7;
+    let _ = (y - 8) / -7;
+}
diff --git a/tests/ui/manual_div_ceil.rs b/tests/ui/manual_div_ceil.rs
index 4f6d38f0d14..2f063afe787 100644
--- a/tests/ui/manual_div_ceil.rs
+++ b/tests/ui/manual_div_ceil.rs
@@ -50,3 +50,14 @@ fn issue_13843() {
 
     let _ = (1_000_000 + 6u32 - 1) / 6u32;
 }
+
+fn issue_13950() {
+    let x = 33u32;
+    let _ = (x + 7) / 8;
+    let _ = (7 + x) / 8;
+
+    let y = -33i32;
+    let _ = (y + -8) / -7;
+    let _ = (-8 + y) / -7;
+    let _ = (y - 8) / -7;
+}
diff --git a/tests/ui/manual_div_ceil.stderr b/tests/ui/manual_div_ceil.stderr
index 3d87fe8e040..0bac5d8ef1c 100644
--- a/tests/ui/manual_div_ceil.stderr
+++ b/tests/ui/manual_div_ceil.stderr
@@ -85,5 +85,17 @@ error: manually reimplementing `div_ceil`
 LL |     let _ = (1_000_000 + 6u32 - 1) / 6u32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `1_000_000_u32.div_ceil(6u32)`
 
-error: aborting due to 14 previous errors
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil.rs:56:13
+   |
+LL |     let _ = (x + 7) / 8;
+   |             ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil.rs:57:13
+   |
+LL |     let _ = (7 + x) / 8;
+   |             ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
+
+error: aborting due to 16 previous errors
 
diff --git a/tests/ui/manual_div_ceil_with_feature.fixed b/tests/ui/manual_div_ceil_with_feature.fixed
index f32b78aa14d..01c58151bc9 100644
--- a/tests/ui/manual_div_ceil_with_feature.fixed
+++ b/tests/ui/manual_div_ceil_with_feature.fixed
@@ -50,3 +50,14 @@ fn issue_13843() {
 
     let _ = 1_000_000_u32.div_ceil(6u32);
 }
+
+fn issue_13950() {
+    let x = 33u32;
+    let _ = x.div_ceil(8);
+    let _ = x.div_ceil(8);
+
+    let y = -33i32;
+    let _ = y.div_ceil(-7);
+    let _ = y.div_ceil(-7);
+    let _ = y.div_ceil(-7);
+}
diff --git a/tests/ui/manual_div_ceil_with_feature.rs b/tests/ui/manual_div_ceil_with_feature.rs
index 54d89fcbd46..048ff401581 100644
--- a/tests/ui/manual_div_ceil_with_feature.rs
+++ b/tests/ui/manual_div_ceil_with_feature.rs
@@ -50,3 +50,14 @@ fn issue_13843() {
 
     let _ = (1_000_000 + 6u32 - 1) / 6u32;
 }
+
+fn issue_13950() {
+    let x = 33u32;
+    let _ = (x + 7) / 8;
+    let _ = (7 + x) / 8;
+
+    let y = -33i32;
+    let _ = (y + -8) / -7;
+    let _ = (-8 + y) / -7;
+    let _ = (y - 8) / -7;
+}
diff --git a/tests/ui/manual_div_ceil_with_feature.stderr b/tests/ui/manual_div_ceil_with_feature.stderr
index c5e8c1a687c..807cfd82724 100644
--- a/tests/ui/manual_div_ceil_with_feature.stderr
+++ b/tests/ui/manual_div_ceil_with_feature.stderr
@@ -109,5 +109,35 @@ error: manually reimplementing `div_ceil`
 LL |     let _ = (1_000_000 + 6u32 - 1) / 6u32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `1_000_000_u32.div_ceil(6u32)`
 
-error: aborting due to 18 previous errors
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil_with_feature.rs:56:13
+   |
+LL |     let _ = (x + 7) / 8;
+   |             ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil_with_feature.rs:57:13
+   |
+LL |     let _ = (7 + x) / 8;
+   |             ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil_with_feature.rs:60:13
+   |
+LL |     let _ = (y + -8) / -7;
+   |             ^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `y.div_ceil(-7)`
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil_with_feature.rs:61:13
+   |
+LL |     let _ = (-8 + y) / -7;
+   |             ^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `y.div_ceil(-7)`
+
+error: manually reimplementing `div_ceil`
+  --> tests/ui/manual_div_ceil_with_feature.rs:62:13
+   |
+LL |     let _ = (y - 8) / -7;
+   |             ^^^^^^^^^^^^ help: consider using `.div_ceil()`: `y.div_ceil(-7)`
+
+error: aborting due to 23 previous errors