Skip to content

Commit

Permalink
correct suggestion for manual_div_ceil lint
Browse files Browse the repository at this point in the history
  • Loading branch information
lapla-cogito committed Dec 22, 2024
1 parent 0f9cc8d commit 13e5caf
Show file tree
Hide file tree
Showing 7 changed files with 259 additions and 5 deletions.
42 changes: 39 additions & 3 deletions clippy_lints/src/manual_div_ceil.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use clippy_utils::SpanlessEq;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::Sugg;
use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::sugg::{Sugg, has_enclosing_paren};
use rustc_ast::{BinOpKind, LitKind};
use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability;
Expand Down Expand Up @@ -130,6 +130,22 @@ fn check_eq_expr(cx: &LateContext<'_>, lhs: &Expr<'_>, rhs: &Expr<'_>) -> bool {
SpanlessEq::new(cx).eq_expr(lhs, rhs)
}

// Check if the literal contains type suffix like `7_i32` or `7u32`
fn is_include_type_suffix(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
let snip = snippet(cx, expr.span, "..");
let numeric_types = [
"i8", "i16", "i32", "i64", "i128", "isize", "u8", "u16", "u32", "u64", "u128", "usize",
];

for ty in numeric_types {
if snip.ends_with(ty) {
return true;
}
}

false
}

fn build_suggestion(
cx: &LateContext<'_>,
expr: &Expr<'_>,
Expand All @@ -138,9 +154,29 @@ fn build_suggestion(
applicability: &mut Applicability,
) {
let dividend_sugg = Sugg::hir_with_applicability(cx, lhs, "..", applicability).maybe_par();
let mut type_suffix = String::new();
if cx.typeck_results().expr_ty(lhs).is_numeric()
&& !is_include_type_suffix(cx, lhs)
&& matches!(lhs.kind, ExprKind::Lit(_) | ExprKind::Unary(_, _))
{
type_suffix = format!("_{}", cx.typeck_results().expr_ty(rhs));
}
let dividend_sugg_str = dividend_sugg.into_string();
// If `dividend_sugg` has enclosing paren like `(-2048)` and we need to add type suffix in the
// suggestion message, we want to make a suggestion string before `div_ceil` like
// `(-2048_{type_suffix})`.
let suggestion_before_div_ceil = if has_enclosing_paren(&dividend_sugg_str) {
format!(
"{}{})",
&dividend_sugg_str[..dividend_sugg_str.len() - 1].to_string(),
type_suffix
)
} else {
format!("{dividend_sugg_str}{type_suffix}")
};
let divisor_snippet = snippet_with_applicability(cx, rhs.span.source_callsite(), "..", applicability);

let sugg = format!("{dividend_sugg}.div_ceil({divisor_snippet})");
let sugg = format!("{suggestion_before_div_ceil}.div_ceil({divisor_snippet})");

span_lint_and_sugg(
cx,
Expand Down
22 changes: 22 additions & 0 deletions tests/ui/manual_div_ceil.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,25 @@ fn main() {
let _ = (7_u32 as i32 + (y_i - 1)) / y_i;
let _ = (7_u32 as i32 + (4 - 1)) / 4;
}

fn issue_13843() {
let x = 3usize;
let _ = 2048_usize.div_ceil(x);

let x = 5usize;
let _ = 2048usize.div_ceil(x);

let x = 5usize;
let _ = 2048_usize.div_ceil(x);

let x = 2048usize;
let _ = x.div_ceil(4);

let _: u32 = 2048_u32.div_ceil(6);
let _: usize = 2048_usize.div_ceil(6);
let _: u32 = 0x2048_u32.div_ceil(0x6);

let _ = 2048_u32.div_ceil(6u32);

let _ = 1_000_000_u32.div_ceil(6u32);
}
22 changes: 22 additions & 0 deletions tests/ui/manual_div_ceil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,25 @@ fn main() {
let _ = (7_u32 as i32 + (y_i - 1)) / y_i;
let _ = (7_u32 as i32 + (4 - 1)) / 4;
}

fn issue_13843() {
let x = 3usize;
let _ = (2048 + x - 1) / x;

let x = 5usize;
let _ = (2048usize + x - 1) / x;

let x = 5usize;
let _ = (2048_usize + x - 1) / x;

let x = 2048usize;
let _ = (x + 4 - 1) / 4;

let _: u32 = (2048 + 6 - 1) / 6;
let _: usize = (2048 + 6 - 1) / 6;
let _: u32 = (0x2048 + 0x6 - 1) / 0x6;

let _ = (2048 + 6u32 - 1) / 6u32;

let _ = (1_000_000 + 6u32 - 1) / 6u32;
}
56 changes: 55 additions & 1 deletion tests/ui/manual_div_ceil.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,59 @@ error: manually reimplementing `div_ceil`
LL | let _ = (7_i32 as u32 + (4 - 1)) / 4;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `(7_i32 as u32).div_ceil(4)`

error: aborting due to 5 previous errors
error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil.rs:34:13
|
LL | let _ = (2048 + x - 1) / x;
| ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(x)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil.rs:37:13
|
LL | let _ = (2048usize + x - 1) / x;
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048usize.div_ceil(x)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil.rs:40:13
|
LL | let _ = (2048_usize + x - 1) / x;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(x)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil.rs:43:13
|
LL | let _ = (x + 4 - 1) / 4;
| ^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(4)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil.rs:45:18
|
LL | let _: u32 = (2048 + 6 - 1) / 6;
| ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_u32.div_ceil(6)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil.rs:46:20
|
LL | let _: usize = (2048 + 6 - 1) / 6;
| ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(6)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil.rs:47:18
|
LL | let _: u32 = (0x2048 + 0x6 - 1) / 0x6;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `0x2048_u32.div_ceil(0x6)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil.rs:49:13
|
LL | let _ = (2048 + 6u32 - 1) / 6u32;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_u32.div_ceil(6u32)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil.rs:51:13
|
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

27 changes: 27 additions & 0 deletions tests/ui/manual_div_ceil_with_feature.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,30 @@ fn main() {

let _ = (x + (y - 1)) / z;
}

fn issue_13843() {
let x = 3usize;
let _ = 2048_usize.div_ceil(x);

let x = 5usize;
let _ = 2048usize.div_ceil(x);

let x = 5usize;
let _ = 2048_usize.div_ceil(x);

let x = 2048usize;
let _ = x.div_ceil(4);

let _ = 2048_i32.div_ceil(4);

let _: u32 = 2048_u32.div_ceil(6);
let _: usize = 2048_usize.div_ceil(6);
let _: u32 = 0x2048_u32.div_ceil(0x6);

let _ = 2048_u32.div_ceil(6u32);

let x = -2;
let _ = (-2048_i32).div_ceil(x);

let _ = 1_000_000_u32.div_ceil(6u32);
}
27 changes: 27 additions & 0 deletions tests/ui/manual_div_ceil_with_feature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,30 @@ fn main() {

let _ = (x + (y - 1)) / z;
}

fn issue_13843() {
let x = 3usize;
let _ = (2048 + x - 1) / x;

let x = 5usize;
let _ = (2048usize + x - 1) / x;

let x = 5usize;
let _ = (2048_usize + x - 1) / x;

let x = 2048usize;
let _ = (x + 4 - 1) / 4;

let _ = (2048 + 4 - 1) / 4;

let _: u32 = (2048 + 6 - 1) / 6;
let _: usize = (2048 + 6 - 1) / 6;
let _: u32 = (0x2048 + 0x6 - 1) / 0x6;

let _ = (2048 + 6u32 - 1) / 6u32;

let x = -2;
let _ = (-2048 + x - 1) / x;

let _ = (1_000_000 + 6u32 - 1) / 6u32;
}
68 changes: 67 additions & 1 deletion tests/ui/manual_div_ceil_with_feature.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,71 @@ error: manually reimplementing `div_ceil`
LL | let _ = (z_u + (4 - 1)) / 4;
| ^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `z_u.div_ceil(4)`

error: aborting due to 7 previous errors
error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil_with_feature.rs:29:13
|
LL | let _ = (2048 + x - 1) / x;
| ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(x)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil_with_feature.rs:32:13
|
LL | let _ = (2048usize + x - 1) / x;
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048usize.div_ceil(x)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil_with_feature.rs:35:13
|
LL | let _ = (2048_usize + x - 1) / x;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(x)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil_with_feature.rs:38:13
|
LL | let _ = (x + 4 - 1) / 4;
| ^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(4)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil_with_feature.rs:40:13
|
LL | let _ = (2048 + 4 - 1) / 4;
| ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_i32.div_ceil(4)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil_with_feature.rs:42:18
|
LL | let _: u32 = (2048 + 6 - 1) / 6;
| ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_u32.div_ceil(6)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil_with_feature.rs:43:20
|
LL | let _: usize = (2048 + 6 - 1) / 6;
| ^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_usize.div_ceil(6)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil_with_feature.rs:44:18
|
LL | let _: u32 = (0x2048 + 0x6 - 1) / 0x6;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `0x2048_u32.div_ceil(0x6)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil_with_feature.rs:46:13
|
LL | let _ = (2048 + 6u32 - 1) / 6u32;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `2048_u32.div_ceil(6u32)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil_with_feature.rs:49:13
|
LL | let _ = (-2048 + x - 1) / x;
| ^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `(-2048_i32).div_ceil(x)`

error: manually reimplementing `div_ceil`
--> tests/ui/manual_div_ceil_with_feature.rs:51:13
|
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

0 comments on commit 13e5caf

Please sign in to comment.