Skip to content

Commit 76ec0aa

Browse files
committed
Added check for next_multiple_of in manual_div_ceil
1 parent 9e3e964 commit 76ec0aa

File tree

8 files changed

+186
-45
lines changed

8 files changed

+186
-45
lines changed

clippy_lints/src/operators/manual_div_ceil.rs

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -18,57 +18,65 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, op: BinOpKind, lhs: &
1818
if op == BinOpKind::Div
1919
&& check_int_ty_and_feature(cx, lhs)
2020
&& check_int_ty_and_feature(cx, rhs)
21-
&& let ExprKind::Binary(inner_op, inner_lhs, inner_rhs) = lhs.kind
2221
&& msrv.meets(cx, msrvs::DIV_CEIL)
2322
{
24-
// (x + (y - 1)) / y
25-
if let ExprKind::Binary(sub_op, sub_lhs, sub_rhs) = inner_rhs.kind
26-
&& inner_op.node == BinOpKind::Add
27-
&& sub_op.node == BinOpKind::Sub
28-
&& check_literal(sub_rhs)
29-
&& check_eq_expr(cx, sub_lhs, rhs)
30-
{
31-
build_suggestion(cx, expr, inner_lhs, rhs, &mut applicability);
32-
return;
33-
}
23+
if let ExprKind::Binary(inner_op, inner_lhs, inner_rhs) = lhs.kind {
24+
// (x + (y - 1)) / y
25+
if let ExprKind::Binary(sub_op, sub_lhs, sub_rhs) = inner_rhs.kind
26+
&& inner_op.node == BinOpKind::Add
27+
&& sub_op.node == BinOpKind::Sub
28+
&& check_literal(sub_rhs)
29+
&& check_eq_expr(cx, sub_lhs, rhs)
30+
{
31+
build_suggestion(cx, expr, inner_lhs, rhs, &mut applicability);
32+
return;
33+
}
3434

35-
// ((y - 1) + x) / y
36-
if let ExprKind::Binary(sub_op, sub_lhs, sub_rhs) = inner_lhs.kind
37-
&& inner_op.node == BinOpKind::Add
38-
&& sub_op.node == BinOpKind::Sub
39-
&& check_literal(sub_rhs)
40-
&& check_eq_expr(cx, sub_lhs, rhs)
41-
{
42-
build_suggestion(cx, expr, inner_rhs, rhs, &mut applicability);
43-
return;
44-
}
35+
// ((y - 1) + x) / y
36+
if let ExprKind::Binary(sub_op, sub_lhs, sub_rhs) = inner_lhs.kind
37+
&& inner_op.node == BinOpKind::Add
38+
&& sub_op.node == BinOpKind::Sub
39+
&& check_literal(sub_rhs)
40+
&& check_eq_expr(cx, sub_lhs, rhs)
41+
{
42+
build_suggestion(cx, expr, inner_rhs, rhs, &mut applicability);
43+
return;
44+
}
4545

46-
// (x + y - 1) / y
47-
if let ExprKind::Binary(add_op, add_lhs, add_rhs) = inner_lhs.kind
48-
&& inner_op.node == BinOpKind::Sub
49-
&& add_op.node == BinOpKind::Add
50-
&& check_literal(inner_rhs)
51-
&& check_eq_expr(cx, add_rhs, rhs)
52-
{
53-
build_suggestion(cx, expr, add_lhs, rhs, &mut applicability);
54-
}
46+
// (x + y - 1) / y
47+
if let ExprKind::Binary(add_op, add_lhs, add_rhs) = inner_lhs.kind
48+
&& inner_op.node == BinOpKind::Sub
49+
&& add_op.node == BinOpKind::Add
50+
&& check_literal(inner_rhs)
51+
&& check_eq_expr(cx, add_rhs, rhs)
52+
{
53+
build_suggestion(cx, expr, add_lhs, rhs, &mut applicability);
54+
}
5555

56-
// (x + (Y - 1)) / Y
57-
if inner_op.node == BinOpKind::Add && differ_by_one(inner_rhs, rhs) {
58-
build_suggestion(cx, expr, inner_lhs, rhs, &mut applicability);
59-
}
56+
// (x + (Y - 1)) / Y
57+
if inner_op.node == BinOpKind::Add && differ_by_one(inner_rhs, rhs) {
58+
build_suggestion(cx, expr, inner_lhs, rhs, &mut applicability);
59+
}
6060

61-
// ((Y - 1) + x) / Y
62-
if inner_op.node == BinOpKind::Add && differ_by_one(inner_lhs, rhs) {
63-
build_suggestion(cx, expr, inner_rhs, rhs, &mut applicability);
64-
}
61+
// ((Y - 1) + x) / Y
62+
if inner_op.node == BinOpKind::Add && differ_by_one(inner_lhs, rhs) {
63+
build_suggestion(cx, expr, inner_rhs, rhs, &mut applicability);
64+
}
6565

66-
// (x - (-Y - 1)) / Y
67-
if inner_op.node == BinOpKind::Sub
68-
&& let ExprKind::Unary(UnOp::Neg, abs_div_rhs) = rhs.kind
69-
&& differ_by_one(abs_div_rhs, inner_rhs)
66+
// (x - (-Y - 1)) / Y
67+
if inner_op.node == BinOpKind::Sub
68+
&& let ExprKind::Unary(UnOp::Neg, abs_div_rhs) = rhs.kind
69+
&& differ_by_one(abs_div_rhs, inner_rhs)
70+
{
71+
build_suggestion(cx, expr, inner_lhs, rhs, &mut applicability);
72+
}
73+
} else if let ExprKind::MethodCall(method, receiver, [next_multiple_of_arg], _) = lhs.kind
74+
&& method.ident.name == sym::next_multiple_of
75+
&& check_int_ty_and_feature(cx, receiver)
76+
&& check_eq_expr(cx, next_multiple_of_arg, rhs)
7077
{
71-
build_suggestion(cx, expr, inner_lhs, rhs, &mut applicability);
78+
// x.next_multiple_of(Y) / Y
79+
build_suggestion(cx, expr, receiver, rhs, &mut applicability);
7280
}
7381
}
7482
}

clippy_utils/src/sym.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ generate! {
244244
next_back,
245245
next_if,
246246
next_if_eq,
247+
next_multiple_of,
247248
next_tuple,
248249
nth,
249250
ok,

tests/ui/manual_div_ceil.fixed

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,30 @@ fn issue_15705(size: u64, c: &u64) {
105105
let _ = size.div_ceil(*c);
106106
//~^ manual_div_ceil
107107
}
108+
109+
struct MyStruct(u32);
110+
impl MyStruct {
111+
// Method matching name on different type should not trigger lint
112+
fn next_multiple_of(self, y: u32) -> u32 {
113+
self.0.next_multiple_of(y)
114+
}
115+
}
116+
117+
fn issue_16219() {
118+
let x = 33u32;
119+
120+
// Lint.
121+
let _ = x.div_ceil(8);
122+
//~^ manual_div_ceil
123+
124+
let y = &x;
125+
let _ = y.div_ceil(8);
126+
//~^ manual_div_ceil
127+
128+
// No lint.
129+
let _ = x.next_multiple_of(8) / 7;
130+
let _ = x.next_multiple_of(7) / 8;
131+
132+
let z = MyStruct(x);
133+
let _ = z.next_multiple_of(8) / 8;
134+
}

tests/ui/manual_div_ceil.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,30 @@ fn issue_15705(size: u64, c: &u64) {
105105
let _ = (size + c - 1) / c;
106106
//~^ manual_div_ceil
107107
}
108+
109+
struct MyStruct(u32);
110+
impl MyStruct {
111+
// Method matching name on different type should not trigger lint
112+
fn next_multiple_of(self, y: u32) -> u32 {
113+
self.0.next_multiple_of(y)
114+
}
115+
}
116+
117+
fn issue_16219() {
118+
let x = 33u32;
119+
120+
// Lint.
121+
let _ = x.next_multiple_of(8) / 8;
122+
//~^ manual_div_ceil
123+
124+
let y = &x;
125+
let _ = y.next_multiple_of(8) / 8;
126+
//~^ manual_div_ceil
127+
128+
// No lint.
129+
let _ = x.next_multiple_of(8) / 7;
130+
let _ = x.next_multiple_of(7) / 8;
131+
132+
let z = MyStruct(x);
133+
let _ = z.next_multiple_of(8) / 8;
134+
}

tests/ui/manual_div_ceil.stderr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,5 +131,17 @@ error: manually reimplementing `div_ceil`
131131
LL | let _ = (size + c - 1) / c;
132132
| ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `size.div_ceil(*c)`
133133

134-
error: aborting due to 20 previous errors
134+
error: manually reimplementing `div_ceil`
135+
--> tests/ui/manual_div_ceil.rs:121:13
136+
|
137+
LL | let _ = x.next_multiple_of(8) / 8;
138+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
139+
140+
error: manually reimplementing `div_ceil`
141+
--> tests/ui/manual_div_ceil.rs:125:13
142+
|
143+
LL | let _ = y.next_multiple_of(8) / 8;
144+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `y.div_ceil(8)`
145+
146+
error: aborting due to 22 previous errors
135147

tests/ui/manual_div_ceil_with_feature.fixed

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,30 @@ fn issue_13950() {
8484
let _ = y.div_ceil(-7);
8585
//~^ manual_div_ceil
8686
}
87+
88+
struct MyStruct(i32);
89+
impl MyStruct {
90+
// Method matching name on different type should not trigger lint
91+
fn next_multiple_of(self, y: i32) -> i32 {
92+
self.0.next_multiple_of(y)
93+
}
94+
}
95+
96+
fn issue_16219() {
97+
let x = 33i32;
98+
99+
// Lint.
100+
let _ = x.div_ceil(8);
101+
//~^ manual_div_ceil
102+
103+
let y = &x;
104+
let _ = y.div_ceil(8);
105+
//~^ manual_div_ceil
106+
107+
// No lint.
108+
let _ = x.next_multiple_of(8) / 7;
109+
let _ = x.next_multiple_of(7) / 8;
110+
111+
let z = MyStruct(x);
112+
let _ = z.next_multiple_of(8) / 8;
113+
}

tests/ui/manual_div_ceil_with_feature.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,30 @@ fn issue_13950() {
8484
let _ = (y - 8) / -7;
8585
//~^ manual_div_ceil
8686
}
87+
88+
struct MyStruct(i32);
89+
impl MyStruct {
90+
// Method matching name on different type should not trigger lint
91+
fn next_multiple_of(self, y: i32) -> i32 {
92+
self.0.next_multiple_of(y)
93+
}
94+
}
95+
96+
fn issue_16219() {
97+
let x = 33i32;
98+
99+
// Lint.
100+
let _ = x.next_multiple_of(8) / 8;
101+
//~^ manual_div_ceil
102+
103+
let y = &x;
104+
let _ = y.next_multiple_of(8) / 8;
105+
//~^ manual_div_ceil
106+
107+
// No lint.
108+
let _ = x.next_multiple_of(8) / 7;
109+
let _ = x.next_multiple_of(7) / 8;
110+
111+
let z = MyStruct(x);
112+
let _ = z.next_multiple_of(8) / 8;
113+
}

tests/ui/manual_div_ceil_with_feature.stderr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,17 @@ error: manually reimplementing `div_ceil`
139139
LL | let _ = (y - 8) / -7;
140140
| ^^^^^^^^^^^^ help: consider using `.div_ceil()`: `y.div_ceil(-7)`
141141

142-
error: aborting due to 23 previous errors
142+
error: manually reimplementing `div_ceil`
143+
--> tests/ui/manual_div_ceil_with_feature.rs:100:13
144+
|
145+
LL | let _ = x.next_multiple_of(8) / 8;
146+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)`
147+
148+
error: manually reimplementing `div_ceil`
149+
--> tests/ui/manual_div_ceil_with_feature.rs:104:13
150+
|
151+
LL | let _ = y.next_multiple_of(8) / 8;
152+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `y.div_ceil(8)`
153+
154+
error: aborting due to 25 previous errors
143155

0 commit comments

Comments
 (0)