@@ -1591,6 +1591,7 @@ from_str_radix_size_impl! { i64 isize, u64 usize }
15911591mod verify {
15921592 use super :: * ;
15931593
1594+ // Verify `unchecked_{add, sub, mul}`
15941595 macro_rules! generate_unchecked_math_harness {
15951596 ( $type: ty, $method: ident, $harness_name: ident) => {
15961597 #[ kani:: proof_for_contract( $type:: $method) ]
@@ -1605,6 +1606,31 @@ mod verify {
16051606 }
16061607 }
16071608
1609+ // Improve unchecked_mul performance for {32, 64, 128}-bit integer types
1610+ // by adding upper and lower limits for inputs
1611+ macro_rules! generate_unchecked_mul_intervals {
1612+ ( $type: ty, $method: ident, $( $harness_name: ident, $min: expr, $max: expr) ,+) => {
1613+ $(
1614+ #[ kani:: proof_for_contract( $type:: $method) ]
1615+ pub fn $harness_name( ) {
1616+ let num1: $type = kani:: any:: <$type>( ) ;
1617+ let num2: $type = kani:: any:: <$type>( ) ;
1618+
1619+ kani:: assume( num1 >= $min && num1 <= $max) ;
1620+ kani:: assume( num2 >= $min && num2 <= $max) ;
1621+
1622+ // Ensure that multiplication does not overflow
1623+ kani:: assume( !num1. overflowing_mul( num2) . 1 ) ;
1624+
1625+ unsafe {
1626+ num1. $method( num2) ;
1627+ }
1628+ }
1629+ ) +
1630+ }
1631+ }
1632+
1633+ // Verify `unchecked_{shl, shr}`
16081634 macro_rules! generate_unchecked_shift_harness {
16091635 ( $type: ty, $method: ident, $harness_name: ident) => {
16101636 #[ kani:: proof_for_contract( $type:: $method) ]
@@ -1635,10 +1661,11 @@ mod verify {
16351661 // `unchecked_add` proofs
16361662 //
16371663 // Target types:
1638- // i{8,16,32,64,128, size } and u{8,16,32,64,128, size } -- 12 types in total
1664+ // i{8,16,32,64,128} and u{8,16,32,64,128} -- 10 types in total
16391665 //
16401666 // Target contracts:
1641- // #[requires(!self.overflowing_add(rhs).1)]
1667+ //#[requires(!self.overflowing_sub(rhs).1)] // Preconditions: No overflow should occur
1668+ //#[ensures(|ret| *ret >= Self::MIN && *ret <= Self::MAX)] // Postconditions: Result must be within valid bounds
16421669 //
16431670 // Target function:
16441671 // pub const unsafe fn unchecked_add(self, rhs: Self) -> Self
@@ -1654,4 +1681,153 @@ mod verify {
16541681 generate_unchecked_math_harness ! ( u64 , unchecked_add, checked_unchecked_add_u64) ;
16551682 generate_unchecked_math_harness ! ( u128 , unchecked_add, checked_unchecked_add_u128) ;
16561683 generate_unchecked_math_harness ! ( usize , unchecked_add, checked_unchecked_add_usize) ;
1684+
1685+ // unchecked_mul proofs
1686+ //
1687+ // Target types:
1688+ // i{8,16,32,64,128, size} and u{8,16,32,64,128, size} -- 36 types in total
1689+ //
1690+ // Target contracts:
1691+ // #[requires(!self.overflowing_mul(rhs).1)]
1692+ //
1693+ // Target function:
1694+ // pub const unsafe fn unchecked_mul(self, rhs: Self) -> Self
1695+ // exponential state spaces for 32,64 and 128, hence provided limited range for verification.
1696+ generate_unchecked_math_harness ! ( i8 , unchecked_mul, checked_unchecked_mul_i8) ;
1697+ generate_unchecked_math_harness ! ( i16 , unchecked_mul, checked_unchecked_mul_i16) ;
1698+
1699+ // ====================== i32 Harnesses ======================
1700+ generate_unchecked_mul_intervals ! ( i32 , unchecked_mul,
1701+ unchecked_mul_i32_small, -10i32 , 10i32 ,
1702+ unchecked_mul_i32_large_pos, i32 :: MAX - 1000i32 , i32 :: MAX ,
1703+ unchecked_mul_i32_large_neg, i32 :: MIN , i32 :: MIN + 1000i32 ,
1704+ unchecked_mul_i32_edge_pos, i32 :: MAX / 2 , i32 :: MAX ,
1705+ unchecked_mul_i32_edge_neg, i32 :: MIN , i32 :: MIN / 2
1706+ ) ;
1707+ // ====================== i64 Harnesses ======================
1708+ generate_unchecked_mul_intervals ! ( i64 , unchecked_mul,
1709+ unchecked_mul_i64_small, -10i64 , 10i64 ,
1710+ unchecked_mul_i64_large_pos, i64 :: MAX - 1000i64 , i64 :: MAX ,
1711+ unchecked_mul_i64_large_neg, i64 :: MIN , i64 :: MIN + 1000i64 ,
1712+ unchecked_mul_i64_edge_pos, i64 :: MAX / 2 , i64 :: MAX ,
1713+ unchecked_mul_i64_edge_neg, i64 :: MIN , i64 :: MIN / 2
1714+ ) ;
1715+ // ====================== i128 Harnesses ======================
1716+ generate_unchecked_mul_intervals ! ( i128 , unchecked_mul,
1717+ unchecked_mul_i128_small, -10i128 , 10i128 ,
1718+ unchecked_mul_i128_large_pos, i128 :: MAX - 1000i128 , i128 :: MAX ,
1719+ unchecked_mul_i128_large_neg, i128 :: MIN , i128 :: MIN + 1000i128 ,
1720+ unchecked_mul_i128_edge_pos, i128 :: MAX / 2 , i128 :: MAX ,
1721+ unchecked_mul_i128_edge_neg, i128 :: MIN , i128 :: MIN / 2
1722+ ) ;
1723+ // ====================== isize Harnesses ======================
1724+ generate_unchecked_mul_intervals ! ( isize , unchecked_mul,
1725+ unchecked_mul_isize_small, -10isize , 10isize ,
1726+ unchecked_mul_isize_large_pos, isize :: MAX - 1000isize , isize :: MAX ,
1727+ unchecked_mul_isize_large_neg, isize :: MIN , isize :: MIN + 1000isize ,
1728+ unchecked_mul_isize_edge_pos, isize :: MAX / 2 , isize :: MAX ,
1729+ unchecked_mul_isize_edge_neg, isize :: MIN , isize :: MIN / 2
1730+ ) ;
1731+
1732+ generate_unchecked_math_harness ! ( u8 , unchecked_mul, checked_unchecked_mul_u8) ;
1733+ generate_unchecked_math_harness ! ( u16 , unchecked_mul, checked_unchecked_mul_u16) ;
1734+
1735+ // ====================== u32 Harnesses ======================
1736+ generate_unchecked_mul_intervals ! ( u32 , unchecked_mul,
1737+ unchecked_mul_u32_small, 0u32 , 10u32 ,
1738+ unchecked_mul_u32_large, u32 :: MAX - 1000u32 , u32 :: MAX ,
1739+ unchecked_mul_u32_edge, u32 :: MAX / 2 , u32 :: MAX
1740+ ) ;
1741+ // ====================== u64 Harnesses ======================
1742+ generate_unchecked_mul_intervals ! ( u64 , unchecked_mul,
1743+ unchecked_mul_u64_small, 0u64 , 10u64 ,
1744+ unchecked_mul_u64_large, u64 :: MAX - 1000u64 , u64 :: MAX ,
1745+ unchecked_mul_u64_edge, u64 :: MAX / 2 , u64 :: MAX
1746+ ) ;
1747+ // ====================== u128 Harnesses ======================
1748+ generate_unchecked_mul_intervals ! ( u128 , unchecked_mul,
1749+ unchecked_mul_u128_small, 0u128 , 10u128 ,
1750+ unchecked_mul_u128_large, u128 :: MAX - 1000u128 , u128 :: MAX ,
1751+ unchecked_mul_u128_edge, u128 :: MAX / 2 , u128 :: MAX
1752+ ) ;
1753+ // ====================== usize Harnesses ======================
1754+ generate_unchecked_mul_intervals ! ( usize , unchecked_mul,
1755+ unchecked_mul_usize_small, 0usize , 10usize ,
1756+ unchecked_mul_usize_large, usize :: MAX - 1000usize , usize :: MAX ,
1757+ unchecked_mul_usize_edge, usize :: MAX / 2 , usize :: MAX
1758+ ) ;
1759+
1760+ // unchecked_shr proofs
1761+ //
1762+ // Target types:
1763+ // i{8,16,32,64,128,size} and u{8,16,32,64,128,size} -- 12 types in total
1764+ //
1765+ // Target contracts:
1766+ // #[requires(rhs < <$ActualT>::BITS)]
1767+ //
1768+ // Target function:
1769+ // pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self
1770+ generate_unchecked_shift_harness ! ( i8 , unchecked_shr, checked_unchecked_shr_i8) ;
1771+ generate_unchecked_shift_harness ! ( i16 , unchecked_shr, checked_unchecked_shr_i16) ;
1772+ generate_unchecked_shift_harness ! ( i32 , unchecked_shr, checked_unchecked_shr_i32) ;
1773+ generate_unchecked_shift_harness ! ( i64 , unchecked_shr, checked_unchecked_shr_i64) ;
1774+ generate_unchecked_shift_harness ! ( i128 , unchecked_shr, checked_unchecked_shr_i128) ;
1775+ generate_unchecked_shift_harness ! ( isize , unchecked_shr, checked_unchecked_shr_isize) ;
1776+ generate_unchecked_shift_harness ! ( u8 , unchecked_shr, checked_unchecked_shr_u8) ;
1777+ generate_unchecked_shift_harness ! ( u16 , unchecked_shr, checked_unchecked_shr_u16) ;
1778+ generate_unchecked_shift_harness ! ( u32 , unchecked_shr, checked_unchecked_shr_u32) ;
1779+ generate_unchecked_shift_harness ! ( u64 , unchecked_shr, checked_unchecked_shr_u64) ;
1780+ generate_unchecked_shift_harness ! ( u128 , unchecked_shr, checked_unchecked_shr_u128) ;
1781+ generate_unchecked_shift_harness ! ( usize , unchecked_shr, checked_unchecked_shr_usize) ;
1782+
1783+ // `unchecked_shl` proofs
1784+ //
1785+ // Target types:
1786+ // i{8,16,32,64,128} and u{8,16,32,64,128} -- 12 types in total
1787+ //
1788+ // Target contracts:
1789+ // #[requires(shift < Self::BITS)]
1790+ // #[ensures(|ret| *ret == self << shift)]
1791+ //
1792+ // Target function:
1793+ // pub const unsafe fn unchecked_shl(self, shift: u32) -> Self
1794+ //
1795+ // This function performs an unchecked bitwise left shift operation.
1796+ generate_unchecked_shift_harness ! ( i8 , unchecked_shl, checked_unchecked_shl_i8) ;
1797+ generate_unchecked_shift_harness ! ( i16 , unchecked_shl, checked_unchecked_shl_i16) ;
1798+ generate_unchecked_shift_harness ! ( i32 , unchecked_shl, checked_unchecked_shl_i32) ;
1799+ generate_unchecked_shift_harness ! ( i64 , unchecked_shl, checked_unchecked_shl_i64) ;
1800+ generate_unchecked_shift_harness ! ( i128 , unchecked_shl, checked_unchecked_shl_i128) ;
1801+ generate_unchecked_shift_harness ! ( isize , unchecked_shl, checked_unchecked_shl_isize) ;
1802+ generate_unchecked_shift_harness ! ( u8 , unchecked_shl, checked_unchecked_shl_u8) ;
1803+ generate_unchecked_shift_harness ! ( u16 , unchecked_shl, checked_unchecked_shl_u16) ;
1804+ generate_unchecked_shift_harness ! ( u32 , unchecked_shl, checked_unchecked_shl_u32) ;
1805+ generate_unchecked_shift_harness ! ( u64 , unchecked_shl, checked_unchecked_shl_u64) ;
1806+ generate_unchecked_shift_harness ! ( u128 , unchecked_shl, checked_unchecked_shl_u128) ;
1807+ generate_unchecked_shift_harness ! ( usize , unchecked_shl, checked_unchecked_shl_usize) ;
1808+
1809+ // `unchecked_sub` proofs
1810+ //
1811+ // Target types:
1812+ // i{8,16,32,64,128} and u{8,16,32,64,128} -- 12 types in total
1813+ //
1814+ // Target contracts:
1815+ // #[requires(!self.overflowing_sub(rhs).1)] // Preconditions: No overflow should occur
1816+ //
1817+ // Target function:
1818+ // pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self
1819+ //
1820+ // This function performs an unchecked subtraction operation.
1821+ generate_unchecked_math_harness ! ( i8 , unchecked_sub, checked_unchecked_sub_i8) ;
1822+ generate_unchecked_math_harness ! ( i16 , unchecked_sub, checked_unchecked_sub_i16) ;
1823+ generate_unchecked_math_harness ! ( i32 , unchecked_sub, checked_unchecked_sub_i32) ;
1824+ generate_unchecked_math_harness ! ( i64 , unchecked_sub, checked_unchecked_sub_i64) ;
1825+ generate_unchecked_math_harness ! ( i128 , unchecked_sub, checked_unchecked_sub_i128) ;
1826+ generate_unchecked_math_harness ! ( isize , unchecked_sub, checked_unchecked_sub_isize) ;
1827+ generate_unchecked_math_harness ! ( u8 , unchecked_sub, checked_unchecked_sub_u8) ;
1828+ generate_unchecked_math_harness ! ( u16 , unchecked_sub, checked_unchecked_sub_u16) ;
1829+ generate_unchecked_math_harness ! ( u32 , unchecked_sub, checked_unchecked_sub_u32) ;
1830+ generate_unchecked_math_harness ! ( u64 , unchecked_sub, checked_unchecked_sub_u64) ;
1831+ generate_unchecked_math_harness ! ( u128 , unchecked_sub, checked_unchecked_sub_u128) ;
1832+ generate_unchecked_math_harness ! ( usize , unchecked_sub, checked_unchecked_sub_usize) ;
16571833}
0 commit comments