Skip to content

Commit 36e75be

Browse files
committed
Unchecked Mul and Add: Adding Macros & cleanup
1 parent d67be7e commit 36e75be

File tree

1 file changed

+55
-30
lines changed

1 file changed

+55
-30
lines changed

library/core/src/num/nonzero.rs

Lines changed: 55 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,13 +1010,10 @@ macro_rules! nonzero_integer {
10101010
without modifying the original"]
10111011
#[inline]
10121012
#[requires({
1013-
let (result, overflow) = self.get().overflowing_mul(other.get());
1014-
!overflow // Precondition to ensure no overflow occurs during multiplication
1013+
!self.get().checked_mul(other.get()).is_some()
10151014
})]
10161015
#[ensures(|result: &Self| {
1017-
// Ensure the resulting value is the expected product
1018-
let (expected_result, _) = self.get().overflowing_mul(other.get());
1019-
result.get() == expected_result
1016+
self.get().checked_mul(other.get()).unwrap() == result.get()
10201017
})]
10211018
pub const unsafe fn unchecked_mul(self, other: Self) -> Self {
10221019
// SAFETY: The caller ensures there is no overflow.
@@ -1381,13 +1378,11 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
13811378
without modifying the original"]
13821379
#[inline]
13831380
#[requires({
1384-
let (result, overflow) = self.get().overflowing_add(other);
1385-
!overflow // Precondition: no overflow can occur
1381+
!self.get().checked_add(other).is_some()
13861382
})]
13871383
#[ensures(|result: &Self| {
13881384
// Postcondition: the result matches the expected addition
1389-
let (expected_result, _) = self.get().overflowing_add(other);
1390-
result.get() == expected_result
1385+
self.get().checked_add(other).unwrap() == result.get()
13911386
})]
13921387
pub const unsafe fn unchecked_add(self, other: $Int) -> Self {
13931388
// SAFETY: The caller ensures there is no overflow.
@@ -2233,27 +2228,57 @@ mod verify {
22332228
nonzero_check!(u128, core::num::NonZeroU128, nonzero_check_new_unchecked_for_u128);
22342229
nonzero_check!(usize, core::num::NonZeroUsize, nonzero_check_new_unchecked_for_usize);
22352230

2236-
#[kani::proof_for_contract(i8::unchecked_mul)]
2237-
fn nonzero_unchecked_mul() {
2238-
let x: NonZeroI8 = kani::any();
2239-
let y: NonZeroI8 = kani::any();
2240-
2241-
// Check the precondition to assume no overflow
2242-
let (result, overflow) = x.get().overflowing_mul(y.get());
2243-
kani::assume(!overflow); // Ensure the multiplication does not overflow
2244-
2245-
unsafe {
2246-
let _ = x.unchecked_mul(y);
2247-
}
2231+
macro_rules! nonzero_check_mul {
2232+
($t:ty, $nonzero_type:ty, $nonzero_unchecked_mul:ident) => {
2233+
#[kani::proof_for_contract(NonZero::unchecked_mul)]
2234+
pub fn $nonzero_unchecked_mul_for() {
2235+
let x: NonZeroI8 = kani::any();
2236+
let y: NonZeroI8 = kani::any();
2237+
unsafe {
2238+
let _ = x.unchecked_mul(y);
2239+
}
2240+
}
2241+
};
22482242
}
2249-
2250-
#[kani::proof_for_contract(i8::unchecked_add)]
2251-
fn nonzero_unchecked_add() {
2252-
let x: i8 = kani::any();
2253-
let y: i8 = kani::any();
2254-
unsafe {
2255-
let _ = x.unchecked_add(y); // Call the unchecked function
2256-
}
2243+
2244+
// Use the macro to generate different versions of the function for multiple types
2245+
nonzero_check!(i8, core::num::NonZeroI8, nonzero_unchecked_mul_for_i8);
2246+
nonzero_check!(i16, core::num::NonZeroI16, nonzero_unchecked_mul_for_16);
2247+
nonzero_check!(i32, core::num::NonZeroI32, nonzero_unchecked_mul_for_32);
2248+
nonzero_check!(i64, core::num::NonZeroI64, nonzero_unchecked_mul_for_64);
2249+
nonzero_check!(i128, core::num::NonZeroI128, nonzero_unchecked_mul_for_128);
2250+
nonzero_check!(isize, core::num::NonZeroIsize, nonzero_unchecked_mul_for_isize);
2251+
nonzero_check!(u8, core::num::NonZeroU8, nonzero_unchecked_mul_for_u8);
2252+
nonzero_check!(u16, core::num::NonZeroU16, nonzero_unchecked_mul_for_u16);
2253+
nonzero_check!(u32, core::num::NonZeroU32, nonzero_unchecked_mul_for_u32);
2254+
nonzero_check!(u64, core::num::NonZeroU64, nonzero_unchecked_mul_for_u64);
2255+
nonzero_check!(u128, core::num::NonZeroU128, nonzero_unchecked_mul_for_u128);
2256+
nonzero_check!(usize, core::num::NonZeroUsize, nonzero_unchecked_mul_for_usize);
2257+
2258+
macro_rules! nonzero_check_add {
2259+
($t:ty, $nonzero_type:ty, $nonzero_unchecked_add:ident) => {
2260+
#[kani::proof_for_contract(NonZero::unchecked_add)]
2261+
pub fn $nonzero_unchecked_add_for() {
2262+
let x: i8 = kani::any();
2263+
let y: i8 = kani::any();
2264+
unsafe {
2265+
let _ = x.unchecked_add(y); // Call the unchecked function
2266+
}
2267+
}
2268+
};
22572269
}
2258-
2270+
2271+
// Use the macro to generate different versions of the function for multiple types
2272+
nonzero_check!(i8, core::num::NonZeroI8, nonzero_unchecked_add_for_i8);
2273+
nonzero_check!(i16, core::num::NonZeroI16, nonzero_unchecked_add_for_16);
2274+
nonzero_check!(i32, core::num::NonZeroI32, nonzero_unchecked_add_for_32);
2275+
nonzero_check!(i64, core::num::NonZeroI64, nonzero_unchecked_add_for_64);
2276+
nonzero_check!(i128, core::num::NonZeroI128, nonzero_unchecked_add_for_128);
2277+
nonzero_check!(isize, core::num::NonZeroIsize, nonzero_unchecked_add_for_isize);
2278+
nonzero_check!(u8, core::num::NonZeroU8, nonzero_unchecked_add_for_u8);
2279+
nonzero_check!(u16, core::num::NonZeroU16, nonzero_unchecked_add_for_u16);
2280+
nonzero_check!(u32, core::num::NonZeroU32, nonzero_unchecked_add_for_u32);
2281+
nonzero_check!(u64, core::num::NonZeroU64, nonzero_unchecked_add_for_u64);
2282+
nonzero_check!(u128, core::num::NonZeroU128, nonzero_unchecked_add_for_u128);
2283+
nonzero_check!(usize, core::num::NonZeroUsize, nonzero_unchecked_add_for_usize);
22592284
}

0 commit comments

Comments
 (0)