Skip to content

Commit ba06f13

Browse files
committed
test cases added including some edge cases
1 parent de59e57 commit ba06f13

File tree

4 files changed

+198
-35
lines changed

4 files changed

+198
-35
lines changed

clippy_lints/src/non_zero_suggestions.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,34 @@ use rustc_span::symbol::sym;
99

1010
declare_clippy_lint! {
1111
/// ### What it does
12+
/// Checks for conversions from `NonZero` types to regular integer types,
13+
/// and suggests using `NonZero` types for the target as well.
1214
///
1315
/// ### Why is this bad?
16+
/// Converting from `NonZero` types to regular integer types and then back to `NonZero`
17+
/// types is less efficient and loses the type-safety guarantees provided by `NonZero` types.
18+
/// Using `NonZero` types consistently can lead to more optimized code and prevent
19+
/// certain classes of errors related to zero values.
1420
///
1521
/// ### Example
1622
/// ```no_run
17-
/// // example code where clippy issues a warning
23+
/// use std::num::{NonZeroU32, NonZeroU64};
24+
///
25+
/// fn example(x: u64, y: NonZeroU32) {
26+
/// // Bad: Converting NonZeroU32 to u64 unnecessarily
27+
/// let r1 = x / u64::from(y.get());
28+
/// let r2 = x % u64::from(y.get());
29+
/// }
1830
/// ```
1931
/// Use instead:
2032
/// ```no_run
21-
/// // example code which does not raise clippy warning
33+
/// use std::num::{NonZeroU32, NonZeroU64};
34+
///
35+
/// fn example(x: u64, y: NonZeroU32) {
36+
/// // Good: Preserving the NonZero property
37+
/// let r1 = x / NonZeroU64::from(y);
38+
/// let r2 = x % NonZeroU64::from(y);
39+
/// }
2240
/// ```
2341
#[clippy::version = "1.81.0"]
2442
pub NON_ZERO_SUGGESTIONS,

tests/ui/non_zero_suggestions.fixed

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#![warn(clippy::non_zero_suggestions)]
2+
3+
use std::num::{NonZeroI16, NonZeroI8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
4+
5+
fn main() {
6+
// Positive test cases (lint should trigger)
7+
8+
// U32 -> U64
9+
let x: u64 = 100;
10+
let y = NonZeroU32::new(10).unwrap();
11+
let r1 = x / NonZeroU64::from(y);
12+
let r2 = x % NonZeroU64::from(y);
13+
14+
// U16 -> U32
15+
let a: u32 = 50;
16+
let b = NonZeroU16::new(5).unwrap();
17+
let r3 = a / NonZeroU32::from(b);
18+
19+
// I8 -> I16
20+
let c: i16 = 25;
21+
let d = NonZeroI8::new(3).unwrap();
22+
let r4 = NonZeroI16::from(d);
23+
24+
// Different operations
25+
let m: u64 = 400;
26+
let n = NonZeroU32::new(20).unwrap();
27+
let r5 = m / NonZeroU64::from(n);
28+
29+
// Edge cases
30+
31+
// Using the max value of a type
32+
let max_u32 = NonZeroU32::new(u32::MAX).unwrap();
33+
let r6 = NonZeroU64::from(max_u32);
34+
35+
// Chained method calls
36+
let _ = NonZeroU64::from(NonZeroU32::new(10).unwrap());
37+
38+
// Negative test cases (lint should not trigger)
39+
40+
// Same size types
41+
let e: u32 = 200;
42+
let f = NonZeroU32::new(20).unwrap();
43+
let r10 = e / f.get();
44+
45+
// Smaller to larger, but not NonZero
46+
let g: u64 = 1000;
47+
let h: u32 = 50;
48+
let r11 = g / u64::from(h);
49+
50+
// Using From correctly
51+
let k: u64 = 300;
52+
let l = NonZeroU32::new(15).unwrap();
53+
let r12 = k / NonZeroU64::from(l);
54+
}
55+
56+
// Additional function to test the lint in a different context
57+
fn divide_numbers(x: u64, y: NonZeroU32) -> u64 {
58+
x / NonZeroU64::from(y)
59+
}
60+
61+
struct Calculator {
62+
value: u64,
63+
}
64+
65+
impl Calculator {
66+
fn divide(&self, divisor: NonZeroU32) -> u64 {
67+
self.value / NonZeroU64::from(divisor)
68+
}
69+
}

tests/ui/non_zero_suggestions.rs

Lines changed: 50 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,69 @@
11
#![warn(clippy::non_zero_suggestions)]
22

3-
use std::num::{
4-
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32,
5-
NonZeroU64, NonZeroU8, NonZeroUsize,
6-
};
3+
use std::num::{NonZeroI16, NonZeroI8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
74

85
fn main() {
9-
// Basic cases
10-
let _ = u8::try_from(NonZeroU8::new(5).unwrap().get());
6+
// Positive test cases (lint should trigger)
117

12-
let _ = u16::from(NonZeroU16::new(10).unwrap().get());
8+
// U32 -> U64
9+
let x: u64 = 100;
10+
let y = NonZeroU32::new(10).unwrap();
11+
let r1 = x / u64::from(y.get());
12+
let r2 = x % u64::from(y.get());
1313

14-
// Different integer types
15-
let _ = u32::from(NonZeroU32::new(15).unwrap().get());
14+
// U16 -> U32
15+
let a: u32 = 50;
16+
let b = NonZeroU16::new(5).unwrap();
17+
let r3 = a / u32::from(b.get());
1618

17-
let _ = u64::from(NonZeroU64::new(20).unwrap().get());
19+
// I8 -> I16
20+
let c: i16 = 25;
21+
let d = NonZeroI8::new(3).unwrap();
22+
let r4 = i16::from(d.get());
1823

19-
let _ = u128::from(NonZeroU128::new(25).unwrap().get());
24+
// Different operations
25+
let m: u64 = 400;
26+
let n = NonZeroU32::new(20).unwrap();
27+
let r5 = m / u64::from(n.get());
2028

21-
let _ = usize::from(NonZeroUsize::new(30).unwrap().get());
29+
// Edge cases
2230

23-
// Signed integer types
24-
let _ = i8::try_from(NonZeroI8::new(-5).unwrap().get());
31+
// Using the max value of a type
32+
let max_u32 = NonZeroU32::new(u32::MAX).unwrap();
33+
let r6 = u64::from(max_u32.get());
2534

26-
let _ = i16::from(NonZeroI16::new(-10).unwrap().get());
35+
// Chained method calls
36+
let _ = u64::from(NonZeroU32::new(10).unwrap().get());
2737

28-
let _ = i32::from(NonZeroI32::new(-15).unwrap().get());
38+
// Negative test cases (lint should not trigger)
2939

30-
// Edge cases
40+
// Same size types
41+
let e: u32 = 200;
42+
let f = NonZeroU32::new(20).unwrap();
43+
let r10 = e / f.get();
3144

32-
// Complex expression
33-
let _ = u8::from(NonZeroU8::new(5).unwrap().get() + 1);
45+
// Smaller to larger, but not NonZero
46+
let g: u64 = 1000;
47+
let h: u32 = 50;
48+
let r11 = g / u64::from(h);
3449

35-
// Function call
36-
fn get_non_zero() -> NonZeroU8 {
37-
NonZeroU8::new(42).unwrap()
38-
}
39-
let _ = u8::from(get_non_zero().get());
50+
// Using From correctly
51+
let k: u64 = 300;
52+
let l = NonZeroU32::new(15).unwrap();
53+
let r12 = k / NonZeroU64::from(l);
54+
}
4055

41-
// Method chaining
42-
let _ = u16::from(NonZeroU16::new(100).unwrap().get().checked_add(1).unwrap());
43-
// This should not trigger the lint
56+
// Additional function to test the lint in a different context
57+
fn divide_numbers(x: u64, y: NonZeroU32) -> u64 {
58+
x / u64::from(y.get())
59+
}
4460

45-
// Different conversion methods
46-
let _ = u32::try_from(NonZeroU32::new(200).unwrap().get()).unwrap();
61+
struct Calculator {
62+
value: u64,
63+
}
4764

48-
// Cases that should not trigger the lint
49-
let _ = u8::from(5);
50-
let _ = u16::from(10u8);
51-
let _ = i32::try_from(40u32).unwrap();
65+
impl Calculator {
66+
fn divide(&self, divisor: NonZeroU32) -> u64 {
67+
self.value / u64::from(divisor.get())
68+
}
5269
}

tests/ui/non_zero_suggestions.stderr

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
2+
--> tests/ui/non_zero_suggestions.rs:11:18
3+
|
4+
LL | let r1 = x / u64::from(y.get());
5+
| ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(y)`
6+
|
7+
= note: `-D clippy::non-zero-suggestions` implied by `-D warnings`
8+
= help: to override `-D warnings` add `#[allow(clippy::non_zero_suggestions)]`
9+
10+
error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
11+
--> tests/ui/non_zero_suggestions.rs:12:18
12+
|
13+
LL | let r2 = x % u64::from(y.get());
14+
| ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(y)`
15+
16+
error: Consider using `NonZeroU32::from()` for more efficient and type-safe conversion
17+
--> tests/ui/non_zero_suggestions.rs:17:18
18+
|
19+
LL | let r3 = a / u32::from(b.get());
20+
| ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU32::from(b)`
21+
22+
error: Consider using `NonZeroI16::from()` for more efficient and type-safe conversion
23+
--> tests/ui/non_zero_suggestions.rs:22:14
24+
|
25+
LL | let r4 = i16::from(d.get());
26+
| ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroI16::from(d)`
27+
28+
error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
29+
--> tests/ui/non_zero_suggestions.rs:27:18
30+
|
31+
LL | let r5 = m / u64::from(n.get());
32+
| ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(n)`
33+
34+
error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
35+
--> tests/ui/non_zero_suggestions.rs:33:14
36+
|
37+
LL | let r6 = u64::from(max_u32.get());
38+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(max_u32)`
39+
40+
error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
41+
--> tests/ui/non_zero_suggestions.rs:36:13
42+
|
43+
LL | let _ = u64::from(NonZeroU32::new(10).unwrap().get());
44+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(NonZeroU32::new(10).unwrap())`
45+
46+
error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
47+
--> tests/ui/non_zero_suggestions.rs:58:9
48+
|
49+
LL | x / u64::from(y.get())
50+
| ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(y)`
51+
52+
error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
53+
--> tests/ui/non_zero_suggestions.rs:67:22
54+
|
55+
LL | self.value / u64::from(divisor.get())
56+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(divisor)`
57+
58+
error: aborting due to 9 previous errors
59+

0 commit comments

Comments
 (0)