diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs index 421bd6f53f7..64f87c80f8d 100644 --- a/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/clippy_lints/src/casts/cast_possible_truncation.rs @@ -29,21 +29,19 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b ExprKind::Block(block, _) => block.expr.map_or(nbits, |e| apply_reductions(cx, nbits, e, signed)), ExprKind::Binary(op, left, right) => match op.node { BinOpKind::Div => { - apply_reductions(cx, nbits, left, signed) - - (if signed { - 0 // let's be conservative here - } else { - // by dividing by 1, we remove 0 bits, etc. - get_constant_bits(cx, right).map_or(0, |b| b.saturating_sub(1)) - }) + apply_reductions(cx, nbits, left, signed).saturating_sub(if signed { + // let's be conservative here + 0 + } else { + // by dividing by 1, we remove 0 bits, etc. + get_constant_bits(cx, right).map_or(0, |b| b.saturating_sub(1)) + }) }, BinOpKind::Rem | BinOpKind::BitAnd => get_constant_bits(cx, right) .unwrap_or(u64::max_value()) .min(apply_reductions(cx, nbits, left, signed)), - BinOpKind::Shr => { - apply_reductions(cx, nbits, left, signed) - - constant_int(cx, right).map_or(0, |s| u64::try_from(s).expect("shift too high")) - }, + BinOpKind::Shr => apply_reductions(cx, nbits, left, signed) + .saturating_sub(constant_int(cx, right).map_or(0, |s| u64::try_from(s).expect("shift too high"))), _ => nbits, }, ExprKind::MethodCall(method, [left, right], _) => { diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index cf85a5ca931..e6031e9adae 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -1,13 +1,13 @@ #![feature(repr128)] #![allow(incomplete_features)] - -#[warn( +#![warn( clippy::cast_precision_loss, clippy::cast_possible_truncation, clippy::cast_sign_loss, clippy::cast_possible_wrap )] -#[allow(clippy::cast_abs_to_unsigned, clippy::no_effect, clippy::unnecessary_operation)] +#![allow(clippy::cast_abs_to_unsigned, clippy::no_effect, clippy::unnecessary_operation)] + fn main() { // Test clippy::cast_precision_loss let x0 = 1i32; @@ -252,3 +252,11 @@ fn main() { } } } + +fn avoid_subtract_overflow(q: u32) { + let c = (q >> 16) as u8; + c as usize; + + let c = (q / 1000) as u8; + c as usize; +} diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 7a68c0984f1..0c63b4af308 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -194,5 +194,17 @@ error: casting `main::E10` to `u16` may truncate the value LL | let _ = self as u16; | ^^^^^^^^^^^ -error: aborting due to 31 previous errors +error: casting `u32` to `u8` may truncate the value + --> $DIR/cast.rs:257:13 + | +LL | let c = (q >> 16) as u8; + | ^^^^^^^^^^^^^^^ + +error: casting `u32` to `u8` may truncate the value + --> $DIR/cast.rs:260:13 + | +LL | let c = (q / 1000) as u8; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 33 previous errors