manual_div_ceil: detect unsigned alternate form#16941
manual_div_ceil: detect unsigned alternate form#16941cyphercodes wants to merge 1 commit intorust-lang:masterfrom
manual_div_ceil: detect unsigned alternate form#16941Conversation
|
r? @dswij rustbot has assigned @dswij. Use Why was this reviewer chosen?The reviewer was selected based on:
|
|
nice work trying to catch use std::hint::black_box;
fn main() {
let a: u32 = black_box(0);
let b: u32 = black_box(5);
// println!("{}", a.div_ceil(b));
// println!("{}", (a - 1) / b + 1);
}here |
| @@ -16,6 +16,18 @@ use super::MANUAL_DIV_CEIL; | |||
| pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, op: BinOpKind, lhs: &Expr<'_>, rhs: &Expr<'_>, msrv: Msrv) { | |||
| let mut applicability = Applicability::MachineApplicable; | |||
There was a problem hiding this comment.
if we truly want to lint on the alternate form, i think this should be at minimum MaybeIncorrect in that case.
| if op == BinOpKind::Add && msrv.meets(cx, msrvs::DIV_CEIL) { | ||
| // (x - 1) / y + 1 | ||
| if check_alternate_form(cx, expr, lhs, rhs, &mut applicability) { | ||
| return; | ||
| } | ||
|
|
||
| // 1 + (x - 1) / y | ||
| if check_alternate_form(cx, expr, rhs, lhs, &mut applicability) { | ||
| return; | ||
| } | ||
| } |
There was a problem hiding this comment.
this assumes x > 0 without proving it.
| && let ExprKind::Binary(sub_op, dividend, sub_rhs) = div_lhs.kind | ||
| && sub_op.node == BinOpKind::Sub | ||
| && check_literal(sub_rhs) | ||
| && check_uint_ty(cx.typeck_results().expr_ty(dividend)) | ||
| && check_uint_ty(cx.typeck_results().expr_ty(div_rhs)) | ||
| { | ||
| build_suggestion(cx, expr, dividend, div_rhs, applicability); | ||
| true |
There was a problem hiding this comment.
this doesn't account for dividend == 0
If you don't ignore overflow, |
|
that is not really my main point, the existing behavior already takes account for both signed and unsigned integers compared to this, linting for only a > 0 already suggests that the pattern is not a clean equivalent of |
|
I agree that It's plausible that the user could want the behavior of: if a == 0 {
panic!()
else {
a.div_ceil(b)
}But in that case it seems reasonable to recommend explicitness about that (possibly by allowing the lint). |
|
☔ The latest upstream changes (possibly #15793) made this pull request unmergeable. Please resolve the merge conflicts. |
Fixes #16940
changelog: [
manual_div_ceil]: also detect unsigned(x - 1) / y + 1formsSummary
(x - 1) / y + 1and1 + (x - 1) / yasmanual_div_ceilfor unsigned integers.Test plan
cargo fmt --checkTESTNAME=manual_div_ceil cargo uiblessTESTNAME=manual_div_ceil cargo uitestgit diff --check