mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 07:00:55 +00:00
test cases added including some edge cases
This commit is contained in:
parent
46f8d360de
commit
73039f654e
4 changed files with 201 additions and 38 deletions
|
@ -9,16 +9,34 @@ use rustc_span::symbol::sym;
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
|
/// Checks for conversions from `NonZero` types to regular integer types,
|
||||||
|
/// and suggests using `NonZero` types for the target as well.
|
||||||
///
|
///
|
||||||
/// ### Why is this bad?
|
/// ### Why is this bad?
|
||||||
|
/// Converting from `NonZero` types to regular integer types and then back to `NonZero`
|
||||||
|
/// types is less efficient and loses the type-safety guarantees provided by `NonZero` types.
|
||||||
|
/// Using `NonZero` types consistently can lead to more optimized code and prevent
|
||||||
|
/// certain classes of errors related to zero values.
|
||||||
///
|
///
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// // example code where clippy issues a warning
|
/// use std::num::{NonZeroU32, NonZeroU64};
|
||||||
|
///
|
||||||
|
/// fn example(x: u64, y: NonZeroU32) {
|
||||||
|
/// // Bad: Converting NonZeroU32 to u64 unnecessarily
|
||||||
|
/// let r1 = x / u64::from(y.get());
|
||||||
|
/// let r2 = x % u64::from(y.get());
|
||||||
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
/// Use instead:
|
/// Use instead:
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// // example code which does not raise clippy warning
|
/// use std::num::{NonZeroU32, NonZeroU64};
|
||||||
|
///
|
||||||
|
/// fn example(x: u64, y: NonZeroU32) {
|
||||||
|
/// // Good: Preserving the NonZero property
|
||||||
|
/// let r1 = x / NonZeroU64::from(y);
|
||||||
|
/// let r2 = x % NonZeroU64::from(y);
|
||||||
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[clippy::version = "1.81.0"]
|
#[clippy::version = "1.81.0"]
|
||||||
pub NON_ZERO_SUGGESTIONS,
|
pub NON_ZERO_SUGGESTIONS,
|
||||||
|
|
69
tests/ui/non_zero_suggestions.fixed
Normal file
69
tests/ui/non_zero_suggestions.fixed
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#![warn(clippy::non_zero_suggestions)]
|
||||||
|
|
||||||
|
use std::num::{NonZeroI16, NonZeroI8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Positive test cases (lint should trigger)
|
||||||
|
|
||||||
|
// U32 -> U64
|
||||||
|
let x: u64 = 100;
|
||||||
|
let y = NonZeroU32::new(10).unwrap();
|
||||||
|
let r1 = x / NonZeroU64::from(y);
|
||||||
|
let r2 = x % NonZeroU64::from(y);
|
||||||
|
|
||||||
|
// U16 -> U32
|
||||||
|
let a: u32 = 50;
|
||||||
|
let b = NonZeroU16::new(5).unwrap();
|
||||||
|
let r3 = a / NonZeroU32::from(b);
|
||||||
|
|
||||||
|
// I8 -> I16
|
||||||
|
let c: i16 = 25;
|
||||||
|
let d = NonZeroI8::new(3).unwrap();
|
||||||
|
let r4 = NonZeroI16::from(d);
|
||||||
|
|
||||||
|
// Different operations
|
||||||
|
let m: u64 = 400;
|
||||||
|
let n = NonZeroU32::new(20).unwrap();
|
||||||
|
let r5 = m / NonZeroU64::from(n);
|
||||||
|
|
||||||
|
// Edge cases
|
||||||
|
|
||||||
|
// Using the max value of a type
|
||||||
|
let max_u32 = NonZeroU32::new(u32::MAX).unwrap();
|
||||||
|
let r6 = NonZeroU64::from(max_u32);
|
||||||
|
|
||||||
|
// Chained method calls
|
||||||
|
let _ = NonZeroU64::from(NonZeroU32::new(10).unwrap());
|
||||||
|
|
||||||
|
// Negative test cases (lint should not trigger)
|
||||||
|
|
||||||
|
// Same size types
|
||||||
|
let e: u32 = 200;
|
||||||
|
let f = NonZeroU32::new(20).unwrap();
|
||||||
|
let r10 = e / f.get();
|
||||||
|
|
||||||
|
// Smaller to larger, but not NonZero
|
||||||
|
let g: u64 = 1000;
|
||||||
|
let h: u32 = 50;
|
||||||
|
let r11 = g / u64::from(h);
|
||||||
|
|
||||||
|
// Using From correctly
|
||||||
|
let k: u64 = 300;
|
||||||
|
let l = NonZeroU32::new(15).unwrap();
|
||||||
|
let r12 = k / NonZeroU64::from(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional function to test the lint in a different context
|
||||||
|
fn divide_numbers(x: u64, y: NonZeroU32) -> u64 {
|
||||||
|
x / NonZeroU64::from(y)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Calculator {
|
||||||
|
value: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Calculator {
|
||||||
|
fn divide(&self, divisor: NonZeroU32) -> u64 {
|
||||||
|
self.value / NonZeroU64::from(divisor)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,52 +1,69 @@
|
||||||
#![warn(clippy::non_zero_suggestions)]
|
#![warn(clippy::non_zero_suggestions)]
|
||||||
|
|
||||||
use std::num::{
|
use std::num::{NonZeroI16, NonZeroI8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
|
||||||
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32,
|
|
||||||
NonZeroU64, NonZeroU8, NonZeroUsize,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Basic cases
|
// Positive test cases (lint should trigger)
|
||||||
let _ = u8::try_from(NonZeroU8::new(5).unwrap().get());
|
|
||||||
|
|
||||||
let _ = u16::from(NonZeroU16::new(10).unwrap().get());
|
// U32 -> U64
|
||||||
|
let x: u64 = 100;
|
||||||
|
let y = NonZeroU32::new(10).unwrap();
|
||||||
|
let r1 = x / u64::from(y.get());
|
||||||
|
let r2 = x % u64::from(y.get());
|
||||||
|
|
||||||
// Different integer types
|
// U16 -> U32
|
||||||
let _ = u32::from(NonZeroU32::new(15).unwrap().get());
|
let a: u32 = 50;
|
||||||
|
let b = NonZeroU16::new(5).unwrap();
|
||||||
|
let r3 = a / u32::from(b.get());
|
||||||
|
|
||||||
let _ = u64::from(NonZeroU64::new(20).unwrap().get());
|
// I8 -> I16
|
||||||
|
let c: i16 = 25;
|
||||||
|
let d = NonZeroI8::new(3).unwrap();
|
||||||
|
let r4 = i16::from(d.get());
|
||||||
|
|
||||||
let _ = u128::from(NonZeroU128::new(25).unwrap().get());
|
// Different operations
|
||||||
|
let m: u64 = 400;
|
||||||
let _ = usize::from(NonZeroUsize::new(30).unwrap().get());
|
let n = NonZeroU32::new(20).unwrap();
|
||||||
|
let r5 = m / u64::from(n.get());
|
||||||
// Signed integer types
|
|
||||||
let _ = i8::try_from(NonZeroI8::new(-5).unwrap().get());
|
|
||||||
|
|
||||||
let _ = i16::from(NonZeroI16::new(-10).unwrap().get());
|
|
||||||
|
|
||||||
let _ = i32::from(NonZeroI32::new(-15).unwrap().get());
|
|
||||||
|
|
||||||
// Edge cases
|
// Edge cases
|
||||||
|
|
||||||
// Complex expression
|
// Using the max value of a type
|
||||||
let _ = u8::from(NonZeroU8::new(5).unwrap().get() + 1);
|
let max_u32 = NonZeroU32::new(u32::MAX).unwrap();
|
||||||
|
let r6 = u64::from(max_u32.get());
|
||||||
|
|
||||||
// Function call
|
// Chained method calls
|
||||||
fn get_non_zero() -> NonZeroU8 {
|
let _ = u64::from(NonZeroU32::new(10).unwrap().get());
|
||||||
NonZeroU8::new(42).unwrap()
|
|
||||||
}
|
|
||||||
let _ = u8::from(get_non_zero().get());
|
|
||||||
|
|
||||||
// Method chaining
|
// Negative test cases (lint should not trigger)
|
||||||
let _ = u16::from(NonZeroU16::new(100).unwrap().get().checked_add(1).unwrap());
|
|
||||||
// This should not trigger the lint
|
|
||||||
|
|
||||||
// Different conversion methods
|
// Same size types
|
||||||
let _ = u32::try_from(NonZeroU32::new(200).unwrap().get()).unwrap();
|
let e: u32 = 200;
|
||||||
|
let f = NonZeroU32::new(20).unwrap();
|
||||||
|
let r10 = e / f.get();
|
||||||
|
|
||||||
// Cases that should not trigger the lint
|
// Smaller to larger, but not NonZero
|
||||||
let _ = u8::from(5);
|
let g: u64 = 1000;
|
||||||
let _ = u16::from(10u8);
|
let h: u32 = 50;
|
||||||
let _ = i32::try_from(40u32).unwrap();
|
let r11 = g / u64::from(h);
|
||||||
|
|
||||||
|
// Using From correctly
|
||||||
|
let k: u64 = 300;
|
||||||
|
let l = NonZeroU32::new(15).unwrap();
|
||||||
|
let r12 = k / NonZeroU64::from(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional function to test the lint in a different context
|
||||||
|
fn divide_numbers(x: u64, y: NonZeroU32) -> u64 {
|
||||||
|
x / u64::from(y.get())
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Calculator {
|
||||||
|
value: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Calculator {
|
||||||
|
fn divide(&self, divisor: NonZeroU32) -> u64 {
|
||||||
|
self.value / u64::from(divisor.get())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
59
tests/ui/non_zero_suggestions.stderr
Normal file
59
tests/ui/non_zero_suggestions.stderr
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
|
||||||
|
--> tests/ui/non_zero_suggestions.rs:11:18
|
||||||
|
|
|
||||||
|
LL | let r1 = x / u64::from(y.get());
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(y)`
|
||||||
|
|
|
||||||
|
= note: `-D clippy::non-zero-suggestions` implied by `-D warnings`
|
||||||
|
= help: to override `-D warnings` add `#[allow(clippy::non_zero_suggestions)]`
|
||||||
|
|
||||||
|
error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
|
||||||
|
--> tests/ui/non_zero_suggestions.rs:12:18
|
||||||
|
|
|
||||||
|
LL | let r2 = x % u64::from(y.get());
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(y)`
|
||||||
|
|
||||||
|
error: Consider using `NonZeroU32::from()` for more efficient and type-safe conversion
|
||||||
|
--> tests/ui/non_zero_suggestions.rs:17:18
|
||||||
|
|
|
||||||
|
LL | let r3 = a / u32::from(b.get());
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU32::from(b)`
|
||||||
|
|
||||||
|
error: Consider using `NonZeroI16::from()` for more efficient and type-safe conversion
|
||||||
|
--> tests/ui/non_zero_suggestions.rs:22:14
|
||||||
|
|
|
||||||
|
LL | let r4 = i16::from(d.get());
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroI16::from(d)`
|
||||||
|
|
||||||
|
error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
|
||||||
|
--> tests/ui/non_zero_suggestions.rs:27:18
|
||||||
|
|
|
||||||
|
LL | let r5 = m / u64::from(n.get());
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(n)`
|
||||||
|
|
||||||
|
error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
|
||||||
|
--> tests/ui/non_zero_suggestions.rs:33:14
|
||||||
|
|
|
||||||
|
LL | let r6 = u64::from(max_u32.get());
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(max_u32)`
|
||||||
|
|
||||||
|
error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
|
||||||
|
--> tests/ui/non_zero_suggestions.rs:36:13
|
||||||
|
|
|
||||||
|
LL | let _ = u64::from(NonZeroU32::new(10).unwrap().get());
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(NonZeroU32::new(10).unwrap())`
|
||||||
|
|
||||||
|
error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
|
||||||
|
--> tests/ui/non_zero_suggestions.rs:58:9
|
||||||
|
|
|
||||||
|
LL | x / u64::from(y.get())
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(y)`
|
||||||
|
|
||||||
|
error: Consider using `NonZeroU64::from()` for more efficient and type-safe conversion
|
||||||
|
--> tests/ui/non_zero_suggestions.rs:67:22
|
||||||
|
|
|
||||||
|
LL | self.value / u64::from(divisor.get())
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: Replace with: `NonZeroU64::from(divisor)`
|
||||||
|
|
||||||
|
error: aborting due to 9 previous errors
|
||||||
|
|
Loading…
Reference in a new issue