| #![allow(clippy::assign_op_pattern)] | |
| #![warn(clippy::implicit_saturating_sub)] | |
| use std::cmp::PartialEq; | |
| use std::ops::SubAssign; | |
| // Mock type | |
| struct Mock; | |
| impl PartialEq<u32> for Mock { | |
| fn eq(&self, _: &u32) -> bool { | |
| true | |
| } | |
| } | |
| impl SubAssign<u32> for Mock { | |
| fn sub_assign(&mut self, _: u32) {} | |
| } | |
| fn main() { | |
| // Tests for unsigned integers | |
| let end_8: u8 = 10; | |
| let start_8: u8 = 5; | |
| let mut u_8: u8 = end_8 - start_8; | |
| // Lint | |
| u_8 = u_8.saturating_sub(1); | |
| match end_8 { | |
| 10 => { | |
| // Lint | |
| u_8 = u_8.saturating_sub(1); | |
| }, | |
| 11 => u_8 += 1, | |
| _ => u_8 = 0, | |
| } | |
| let end_16: u16 = 40; | |
| let start_16: u16 = 35; | |
| let mut u_16: u16 = end_16 - start_16; | |
| // Lint | |
| u_16 = u_16.saturating_sub(1); | |
| let mut end_32: u32 = 7010; | |
| let mut start_32: u32 = 7000; | |
| let mut u_32: u32 = end_32 - start_32; | |
| // Lint | |
| u_32 = u_32.saturating_sub(1); | |
| // No Lint | |
| if u_32 > 0 { | |
| u_16 += 1; | |
| } | |
| // No Lint | |
| if u_32 != 0 { | |
| end_32 -= 1; | |
| start_32 += 1; | |
| } | |
| let mut end_64: u64 = 75001; | |
| let mut start_64: u64 = 75000; | |
| let mut u_64: u64 = end_64 - start_64; | |
| // Lint | |
| u_64 = u_64.saturating_sub(1); | |
| // Lint | |
| u_64 = u_64.saturating_sub(1); | |
| // Lint | |
| u_64 = u_64.saturating_sub(1); | |
| // No Lint | |
| if u_64 >= 1 { | |
| u_64 -= 1; | |
| } | |
| // No Lint | |
| if u_64 > 0 { | |
| end_64 -= 1; | |
| } | |
| // Tests for usize | |
| let end_usize: usize = 8054; | |
| let start_usize: usize = 8050; | |
| let mut u_usize: usize = end_usize - start_usize; | |
| // Lint | |
| u_usize = u_usize.saturating_sub(1); | |
| // Tests for signed integers | |
| let endi_8: i8 = 10; | |
| let starti_8: i8 = 50; | |
| let mut i_8: i8 = endi_8 - starti_8; | |
| // Lint | |
| i_8 = i_8.saturating_sub(1); | |
| // Lint | |
| i_8 = i_8.saturating_sub(1); | |
| // Lint | |
| i_8 = i_8.saturating_sub(1); | |
| // Lint | |
| i_8 = i_8.saturating_sub(1); | |
| let endi_16: i16 = 45; | |
| let starti_16: i16 = 44; | |
| let mut i_16: i16 = endi_16 - starti_16; | |
| // Lint | |
| i_16 = i_16.saturating_sub(1); | |
| // Lint | |
| i_16 = i_16.saturating_sub(1); | |
| // Lint | |
| i_16 = i_16.saturating_sub(1); | |
| // Lint | |
| i_16 = i_16.saturating_sub(1); | |
| let endi_32: i32 = 45; | |
| let starti_32: i32 = 44; | |
| let mut i_32: i32 = endi_32 - starti_32; | |
| // Lint | |
| i_32 = i_32.saturating_sub(1); | |
| // Lint | |
| i_32 = i_32.saturating_sub(1); | |
| // Lint | |
| i_32 = i_32.saturating_sub(1); | |
| // Lint | |
| i_32 = i_32.saturating_sub(1); | |
| let endi_64: i64 = 45; | |
| let starti_64: i64 = 44; | |
| let mut i_64: i64 = endi_64 - starti_64; | |
| // Lint | |
| i_64 = i_64.saturating_sub(1); | |
| // Lint | |
| i_64 = i_64.saturating_sub(1); | |
| // Lint | |
| i_64 = i_64.saturating_sub(1); | |
| // No Lint | |
| if i_64 > 0 { | |
| i_64 -= 1; | |
| } | |
| // No Lint | |
| if i_64 != 0 { | |
| i_64 -= 1; | |
| } | |
| // issue #7831 | |
| // No Lint | |
| if u_32 > 0 { | |
| u_32 -= 1; | |
| } else { | |
| println!("side effect"); | |
| } | |
| // Extended tests | |
| let mut m = Mock; | |
| let mut u_32 = 3000; | |
| let a = 200; | |
| let mut b = 8; | |
| if m != 0 { | |
| m -= 1; | |
| } | |
| if a > 0 { | |
| b -= 1; | |
| } | |
| if 0 > a { | |
| b -= 1; | |
| } | |
| if u_32 > 0 { | |
| u_32 -= 1; | |
| } else { | |
| println!("don't lint this"); | |
| } | |
| if u_32 > 0 { | |
| println!("don't lint this"); | |
| u_32 -= 1; | |
| } | |
| if u_32 > 42 { | |
| println!("brace yourself!"); | |
| } else if u_32 > 0 { | |
| u_32 -= 1; | |
| } | |
| let result = if a < b { | |
| println!("we shouldn't remove this"); | |
| 0 | |
| } else { | |
| a - b | |
| }; | |
| } | |
| fn regression_13524(a: usize, b: usize, c: bool) -> usize { | |
| if c { | |
| 123 | |
| } else { b.saturating_sub(a) } | |
| } | |
| fn with_side_effect(a: u64) -> u64 { | |
| println!("a = {a}"); | |
| a | |
| } | |
| fn arbitrary_expression() { | |
| let (a, b) = (15u64, 20u64); | |
| let _ = (a * 2).saturating_sub(b); | |
| //~^ implicit_saturating_sub | |
| let _ = a.saturating_sub(b * 2); | |
| //~^ implicit_saturating_sub | |
| let _ = a.saturating_sub(b * 2); | |
| //~^ implicit_saturating_sub | |
| let _ = if with_side_effect(a) > a { | |
| with_side_effect(a) - a | |
| } else { | |
| 0 | |
| }; | |
| } | |
| fn issue16307() { | |
| let x: u8 = 100; | |
| let y = 100_u8.saturating_sub(x); | |
| //~^ implicit_saturating_sub | |
| println!("{y}"); | |
| } | |
| fn wrongly_unmangled_macros() { | |
| macro_rules! test_big { | |
| ($val:expr) => { | |
| ($val * 2 + 1) | |
| }; | |
| } | |
| macro_rules! test_little { | |
| ($val:expr) => { | |
| ($val * 2 + 0) | |
| }; | |
| } | |
| let a = 15u64; | |
| let b = 20u64; | |
| let _ = test_big!(a).saturating_sub(test_little!(b)); | |
| } | |
| #[clippy::msrv = "1.46.0"] | |
| pub const fn const_msrv_too_low(mut x: u32) -> u32 { | |
| if x != 0 { | |
| x -= 1; | |
| } | |
| x | |
| } | |
| #[clippy::msrv = "1.47.0"] | |
| pub const fn const_msrv_ok(mut x: u32) -> u32 { | |
| x = x.saturating_sub(1); | |
| x | |
| } | |
| #[clippy::msrv = "1.46.0"] | |
| pub fn nonconst_msrv_low(mut x: u32) -> u32 { | |
| x = x.saturating_sub(1); | |
| x | |
| } |