Skip to content

Commit 18e5b2d

Browse files
authored
Fix unnecessary_min_or_max for usize (rust-lang#16575)
Fixes: rust-lang#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).
2 parents 7064751 + 4916d95 commit 18e5b2d

File tree

4 files changed

+112
-2
lines changed

4 files changed

+112
-2
lines changed

clippy_lints/src/methods/unnecessary_min_or_max.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,17 @@ fn detect_extrema<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<
8888
match (cv.int_value(cx.tcx, ty)?, ty.kind()) {
8989
(FullInt::S(i), &ty::Int(ity)) if i == i128::MIN >> (128 - ity.bit_width()?) => Some(Extrema::Minimum),
9090
(FullInt::S(i), &ty::Int(ity)) if i == i128::MAX >> (128 - ity.bit_width()?) => Some(Extrema::Maximum),
91-
(FullInt::U(i), &ty::Uint(uty)) if i == u128::MAX >> (128 - uty.bit_width()?) => Some(Extrema::Maximum),
91+
(FullInt::U(i), &ty::Uint(uty))
92+
if {
93+
let bits = match uty {
94+
ty::UintTy::Usize => u32::try_from(cx.tcx.data_layout.pointer_size().bits()).ok()?,
95+
_ => u32::try_from(uty.bit_width()?).ok()?,
96+
};
97+
i == u128::MAX >> (128 - bits)
98+
} =>
99+
{
100+
Some(Extrema::Maximum)
101+
},
92102
(FullInt::U(0), &ty::Uint(_)) => Some(Extrema::Minimum),
93103
_ => None,
94104
}

tests/ui/unnecessary_min_or_max.fixed

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,32 @@ fn main() {
7777
let _ = (X + 1).min(12);
7878
let _ = 12.min(X - 1);
7979
let _ = 12.max(X - 1);
80+
81+
let n: usize = 42;
82+
83+
let _ = 0;
84+
//~^ unnecessary_min_or_max
85+
86+
let _ = 0usize;
87+
//~^ unnecessary_min_or_max
88+
89+
let _ = (0usize);
90+
//~^ unnecessary_min_or_max
91+
92+
let _ = usize::MIN;
93+
//~^ unnecessary_min_or_max
94+
95+
let _ = usize::MAX;
96+
//~^ unnecessary_min_or_max
97+
98+
let _ = (usize::MAX);
99+
//~^ unnecessary_min_or_max
100+
101+
let _ = !0usize;
102+
//~^ unnecessary_min_or_max
103+
104+
let _ = n;
105+
//~^ unnecessary_min_or_max
80106
}
81107
fn random_u32() -> u32 {
82108
// random number generator

tests/ui/unnecessary_min_or_max.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,32 @@ fn main() {
7777
let _ = (X + 1).min(12);
7878
let _ = 12.min(X - 1);
7979
let _ = 12.max(X - 1);
80+
81+
let n: usize = 42;
82+
83+
let _ = n.min(0);
84+
//~^ unnecessary_min_or_max
85+
86+
let _ = n.min(0usize);
87+
//~^ unnecessary_min_or_max
88+
89+
let _ = (0usize).min(n);
90+
//~^ unnecessary_min_or_max
91+
92+
let _ = n.min(usize::MIN);
93+
//~^ unnecessary_min_or_max
94+
95+
let _ = n.max(usize::MAX);
96+
//~^ unnecessary_min_or_max
97+
98+
let _ = (usize::MAX).max(n);
99+
//~^ unnecessary_min_or_max
100+
101+
let _ = n.max(!0usize);
102+
//~^ unnecessary_min_or_max
103+
104+
let _ = n.max(0);
105+
//~^ unnecessary_min_or_max
80106
}
81107
fn random_u32() -> u32 {
82108
// random number generator

tests/ui/unnecessary_min_or_max.stderr

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,53 @@ error: `x` is never smaller than `i32::MIN - 0` and has therefore no effect
103103
LL | let _ = x.min(i32::MIN - 0);
104104
| ^^^^^^^^^^^^^^^^^^^ help: try: `i32::MIN - 0`
105105

106-
error: aborting due to 17 previous errors
106+
error: `n` is never smaller than `0` and has therefore no effect
107+
--> tests/ui/unnecessary_min_or_max.rs:83:13
108+
|
109+
LL | let _ = n.min(0);
110+
| ^^^^^^^^ help: try: `0`
111+
112+
error: `n` is never smaller than `0usize` and has therefore no effect
113+
--> tests/ui/unnecessary_min_or_max.rs:86:13
114+
|
115+
LL | let _ = n.min(0usize);
116+
| ^^^^^^^^^^^^^ help: try: `0usize`
117+
118+
error: `(0usize)` is never greater than `n` and has therefore no effect
119+
--> tests/ui/unnecessary_min_or_max.rs:89:13
120+
|
121+
LL | let _ = (0usize).min(n);
122+
| ^^^^^^^^^^^^^^^ help: try: `(0usize)`
123+
124+
error: `n` is never smaller than `usize::MIN` and has therefore no effect
125+
--> tests/ui/unnecessary_min_or_max.rs:92:13
126+
|
127+
LL | let _ = n.min(usize::MIN);
128+
| ^^^^^^^^^^^^^^^^^ help: try: `usize::MIN`
129+
130+
error: `n` is never greater than `usize::MAX` and has therefore no effect
131+
--> tests/ui/unnecessary_min_or_max.rs:95:13
132+
|
133+
LL | let _ = n.max(usize::MAX);
134+
| ^^^^^^^^^^^^^^^^^ help: try: `usize::MAX`
135+
136+
error: `(usize::MAX)` is never smaller than `n` and has therefore no effect
137+
--> tests/ui/unnecessary_min_or_max.rs:98:13
138+
|
139+
LL | let _ = (usize::MAX).max(n);
140+
| ^^^^^^^^^^^^^^^^^^^ help: try: `(usize::MAX)`
141+
142+
error: `n` is never greater than `!0usize` and has therefore no effect
143+
--> tests/ui/unnecessary_min_or_max.rs:101:13
144+
|
145+
LL | let _ = n.max(!0usize);
146+
| ^^^^^^^^^^^^^^ help: try: `!0usize`
147+
148+
error: `n` is never smaller than `0` and has therefore no effect
149+
--> tests/ui/unnecessary_min_or_max.rs:104:13
150+
|
151+
LL | let _ = n.max(0);
152+
| ^^^^^^^^ help: try: `n`
153+
154+
error: aborting due to 25 previous errors
107155

0 commit comments

Comments
 (0)