Skip to content

Commit 7e83ec5

Browse files
authored
Suggest manual_div_ceil even when right operand is a constant (#13951)
changelog: [`manual_div_ceil`]: lint constants as well Fix #13950
2 parents 8c1ea9f + dc23fa5 commit 7e83ec5

7 files changed

+124
-2
lines changed

clippy_lints/src/manual_div_ceil.rs

+36
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,48 @@ impl<'tcx> LateLintPass<'tcx> for ManualDivCeil {
102102
{
103103
build_suggestion(cx, expr, add_lhs, div_rhs, &mut applicability);
104104
}
105+
106+
// (x + (Y - 1)) / Y
107+
if inner_op.node == BinOpKind::Add && differ_by_one(inner_rhs, div_rhs) {
108+
build_suggestion(cx, expr, inner_lhs, div_rhs, &mut applicability);
109+
}
110+
111+
// ((Y - 1) + x) / Y
112+
if inner_op.node == BinOpKind::Add && differ_by_one(inner_lhs, div_rhs) {
113+
build_suggestion(cx, expr, inner_rhs, div_rhs, &mut applicability);
114+
}
115+
116+
// (x - (-Y - 1)) / Y
117+
if inner_op.node == BinOpKind::Sub
118+
&& let ExprKind::Unary(UnOp::Neg, abs_div_rhs) = div_rhs.kind
119+
&& differ_by_one(abs_div_rhs, inner_rhs)
120+
{
121+
build_suggestion(cx, expr, inner_lhs, div_rhs, &mut applicability);
122+
}
105123
}
106124
}
107125

108126
extract_msrv_attr!(LateContext);
109127
}
110128

129+
/// Checks if two expressions represent non-zero integer literals such that `small_expr + 1 ==
130+
/// large_expr`.
131+
fn differ_by_one(small_expr: &Expr<'_>, large_expr: &Expr<'_>) -> bool {
132+
if let ExprKind::Lit(small) = small_expr.kind
133+
&& let ExprKind::Lit(large) = large_expr.kind
134+
&& let LitKind::Int(s, _) = small.node
135+
&& let LitKind::Int(l, _) = large.node
136+
{
137+
Some(l.get()) == s.get().checked_add(1)
138+
} else if let ExprKind::Unary(UnOp::Neg, small_inner_expr) = small_expr.kind
139+
&& let ExprKind::Unary(UnOp::Neg, large_inner_expr) = large_expr.kind
140+
{
141+
differ_by_one(large_inner_expr, small_inner_expr)
142+
} else {
143+
false
144+
}
145+
}
146+
111147
fn check_int_ty_and_feature(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
112148
let expr_ty = cx.typeck_results().expr_ty(expr);
113149
match expr_ty.peel_refs().kind() {

tests/ui/manual_div_ceil.fixed

+11
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,14 @@ fn issue_13843() {
5050

5151
let _ = 1_000_000_u32.div_ceil(6u32);
5252
}
53+
54+
fn issue_13950() {
55+
let x = 33u32;
56+
let _ = x.div_ceil(8);
57+
let _ = x.div_ceil(8);
58+
59+
let y = -33i32;
60+
let _ = (y + -8) / -7;
61+
let _ = (-8 + y) / -7;
62+
let _ = (y - 8) / -7;
63+
}

tests/ui/manual_div_ceil.rs

+11
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,14 @@ fn issue_13843() {
5050

5151
let _ = (1_000_000 + 6u32 - 1) / 6u32;
5252
}
53+
54+
fn issue_13950() {
55+
let x = 33u32;
56+
let _ = (x + 7) / 8;
57+
let _ = (7 + x) / 8;
58+
59+
let y = -33i32;
60+
let _ = (y + -8) / -7;
61+
let _ = (-8 + y) / -7;
62+
let _ = (y - 8) / -7;
63+
}

tests/ui/manual_div_ceil.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -85,5 +85,17 @@ error: manually reimplementing `div_ceil`
8585
LL | let _ = (1_000_000 + 6u32 - 1) / 6u32;
8686
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `1_000_000_u32.div_ceil(6u32)`
8787

88-
error: aborting due to 14 previous errors
88+
error: manually reimplementing `div_ceil`
89+
--> tests/ui/manual_div_ceil.rs:56:13
90+
|
91+
LL | let _ = (x + 7) / 8;
92+
| ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
93+
94+
error: manually reimplementing `div_ceil`
95+
--> tests/ui/manual_div_ceil.rs:57:13
96+
|
97+
LL | let _ = (7 + x) / 8;
98+
| ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
99+
100+
error: aborting due to 16 previous errors
89101

tests/ui/manual_div_ceil_with_feature.fixed

+11
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,14 @@ fn issue_13843() {
5050

5151
let _ = 1_000_000_u32.div_ceil(6u32);
5252
}
53+
54+
fn issue_13950() {
55+
let x = 33u32;
56+
let _ = x.div_ceil(8);
57+
let _ = x.div_ceil(8);
58+
59+
let y = -33i32;
60+
let _ = y.div_ceil(-7);
61+
let _ = y.div_ceil(-7);
62+
let _ = y.div_ceil(-7);
63+
}

tests/ui/manual_div_ceil_with_feature.rs

+11
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,14 @@ fn issue_13843() {
5050

5151
let _ = (1_000_000 + 6u32 - 1) / 6u32;
5252
}
53+
54+
fn issue_13950() {
55+
let x = 33u32;
56+
let _ = (x + 7) / 8;
57+
let _ = (7 + x) / 8;
58+
59+
let y = -33i32;
60+
let _ = (y + -8) / -7;
61+
let _ = (-8 + y) / -7;
62+
let _ = (y - 8) / -7;
63+
}

tests/ui/manual_div_ceil_with_feature.stderr

+31-1
Original file line numberDiff line numberDiff line change
@@ -109,5 +109,35 @@ error: manually reimplementing `div_ceil`
109109
LL | let _ = (1_000_000 + 6u32 - 1) / 6u32;
110110
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `1_000_000_u32.div_ceil(6u32)`
111111

112-
error: aborting due to 18 previous errors
112+
error: manually reimplementing `div_ceil`
113+
--> tests/ui/manual_div_ceil_with_feature.rs:56:13
114+
|
115+
LL | let _ = (x + 7) / 8;
116+
| ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
117+
118+
error: manually reimplementing `div_ceil`
119+
--> tests/ui/manual_div_ceil_with_feature.rs:57:13
120+
|
121+
LL | let _ = (7 + x) / 8;
122+
| ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
123+
124+
error: manually reimplementing `div_ceil`
125+
--> tests/ui/manual_div_ceil_with_feature.rs:60:13
126+
|
127+
LL | let _ = (y + -8) / -7;
128+
| ^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `y.div_ceil(-7)`
129+
130+
error: manually reimplementing `div_ceil`
131+
--> tests/ui/manual_div_ceil_with_feature.rs:61:13
132+
|
133+
LL | let _ = (-8 + y) / -7;
134+
| ^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `y.div_ceil(-7)`
135+
136+
error: manually reimplementing `div_ceil`
137+
--> tests/ui/manual_div_ceil_with_feature.rs:62:13
138+
|
139+
LL | let _ = (y - 8) / -7;
140+
| ^^^^^^^^^^^^ help: consider using `.div_ceil()`: `y.div_ceil(-7)`
141+
142+
error: aborting due to 23 previous errors
113143

0 commit comments

Comments
 (0)