Fix unnecessary_min_or_max for usize (#16575)

Fixes: rust-lang/rust-clippy#16555

changelog: [unnecessary_min_or_max]: Fix false negatives for
usize::{MIN,MAX} by handling usize bit width correctly during constant
evaluation, enabling the lint to trigger on cases like n.min(0) /
n.max(usize::MAX).
This commit is contained in:
dswij
2026-02-20 15:53:19 +00:00
committed by GitHub
4 changed files with 112 additions and 2 deletions
@@ -88,7 +88,17 @@ fn detect_extrema<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<
match (cv.int_value(cx.tcx, ty)?, ty.kind()) {
(FullInt::S(i), &ty::Int(ity)) if i == i128::MIN >> (128 - ity.bit_width()?) => Some(Extrema::Minimum),
(FullInt::S(i), &ty::Int(ity)) if i == i128::MAX >> (128 - ity.bit_width()?) => Some(Extrema::Maximum),
(FullInt::U(i), &ty::Uint(uty)) if i == u128::MAX >> (128 - uty.bit_width()?) => Some(Extrema::Maximum),
(FullInt::U(i), &ty::Uint(uty))
if {
let bits = match uty {
ty::UintTy::Usize => u32::try_from(cx.tcx.data_layout.pointer_size().bits()).ok()?,
_ => u32::try_from(uty.bit_width()?).ok()?,
};
i == u128::MAX >> (128 - bits)
} =>
{
Some(Extrema::Maximum)
},
(FullInt::U(0), &ty::Uint(_)) => Some(Extrema::Minimum),
_ => None,
}
+26
View File
@@ -77,6 +77,32 @@ fn main() {
let _ = (X + 1).min(12);
let _ = 12.min(X - 1);
let _ = 12.max(X - 1);
let n: usize = 42;
let _ = 0;
//~^ unnecessary_min_or_max
let _ = 0usize;
//~^ unnecessary_min_or_max
let _ = (0usize);
//~^ unnecessary_min_or_max
let _ = usize::MIN;
//~^ unnecessary_min_or_max
let _ = usize::MAX;
//~^ unnecessary_min_or_max
let _ = (usize::MAX);
//~^ unnecessary_min_or_max
let _ = !0usize;
//~^ unnecessary_min_or_max
let _ = n;
//~^ unnecessary_min_or_max
}
fn random_u32() -> u32 {
// random number generator
+26
View File
@@ -77,6 +77,32 @@ fn main() {
let _ = (X + 1).min(12);
let _ = 12.min(X - 1);
let _ = 12.max(X - 1);
let n: usize = 42;
let _ = n.min(0);
//~^ unnecessary_min_or_max
let _ = n.min(0usize);
//~^ unnecessary_min_or_max
let _ = (0usize).min(n);
//~^ unnecessary_min_or_max
let _ = n.min(usize::MIN);
//~^ unnecessary_min_or_max
let _ = n.max(usize::MAX);
//~^ unnecessary_min_or_max
let _ = (usize::MAX).max(n);
//~^ unnecessary_min_or_max
let _ = n.max(!0usize);
//~^ unnecessary_min_or_max
let _ = n.max(0);
//~^ unnecessary_min_or_max
}
fn random_u32() -> u32 {
// random number generator
+49 -1
View File
@@ -103,5 +103,53 @@ error: `x` is never smaller than `i32::MIN - 0` and has therefore no effect
LL | let _ = x.min(i32::MIN - 0);
| ^^^^^^^^^^^^^^^^^^^ help: try: `i32::MIN - 0`
error: aborting due to 17 previous errors
error: `n` is never smaller than `0` and has therefore no effect
--> tests/ui/unnecessary_min_or_max.rs:83:13
|
LL | let _ = n.min(0);
| ^^^^^^^^ help: try: `0`
error: `n` is never smaller than `0usize` and has therefore no effect
--> tests/ui/unnecessary_min_or_max.rs:86:13
|
LL | let _ = n.min(0usize);
| ^^^^^^^^^^^^^ help: try: `0usize`
error: `(0usize)` is never greater than `n` and has therefore no effect
--> tests/ui/unnecessary_min_or_max.rs:89:13
|
LL | let _ = (0usize).min(n);
| ^^^^^^^^^^^^^^^ help: try: `(0usize)`
error: `n` is never smaller than `usize::MIN` and has therefore no effect
--> tests/ui/unnecessary_min_or_max.rs:92:13
|
LL | let _ = n.min(usize::MIN);
| ^^^^^^^^^^^^^^^^^ help: try: `usize::MIN`
error: `n` is never greater than `usize::MAX` and has therefore no effect
--> tests/ui/unnecessary_min_or_max.rs:95:13
|
LL | let _ = n.max(usize::MAX);
| ^^^^^^^^^^^^^^^^^ help: try: `usize::MAX`
error: `(usize::MAX)` is never smaller than `n` and has therefore no effect
--> tests/ui/unnecessary_min_or_max.rs:98:13
|
LL | let _ = (usize::MAX).max(n);
| ^^^^^^^^^^^^^^^^^^^ help: try: `(usize::MAX)`
error: `n` is never greater than `!0usize` and has therefore no effect
--> tests/ui/unnecessary_min_or_max.rs:101:13
|
LL | let _ = n.max(!0usize);
| ^^^^^^^^^^^^^^ help: try: `!0usize`
error: `n` is never smaller than `0` and has therefore no effect
--> tests/ui/unnecessary_min_or_max.rs:104:13
|
LL | let _ = n.max(0);
| ^^^^^^^^ help: try: `n`
error: aborting due to 25 previous errors