@@ -1591,6 +1591,7 @@ from_str_radix_size_impl! { i64 isize, u64 usize }
1591
1591
mod verify {
1592
1592
use super :: * ;
1593
1593
1594
+ // Verify `unchecked_{add, sub, mul}`
1594
1595
macro_rules! generate_unchecked_math_harness {
1595
1596
( $type: ty, $method: ident, $harness_name: ident) => {
1596
1597
#[ kani:: proof_for_contract( $type:: $method) ]
@@ -1605,6 +1606,31 @@ mod verify {
1605
1606
}
1606
1607
}
1607
1608
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}`
1608
1634
macro_rules! generate_unchecked_shift_harness {
1609
1635
( $type: ty, $method: ident, $harness_name: ident) => {
1610
1636
#[ kani:: proof_for_contract( $type:: $method) ]
@@ -1635,10 +1661,11 @@ mod verify {
1635
1661
// `unchecked_add` proofs
1636
1662
//
1637
1663
// 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
1639
1665
//
1640
1666
// 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
1642
1669
//
1643
1670
// Target function:
1644
1671
// pub const unsafe fn unchecked_add(self, rhs: Self) -> Self
@@ -1654,4 +1681,153 @@ mod verify {
1654
1681
generate_unchecked_math_harness ! ( u64 , unchecked_add, checked_unchecked_add_u64) ;
1655
1682
generate_unchecked_math_harness ! ( u128 , unchecked_add, checked_unchecked_add_u128) ;
1656
1683
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) ;
1657
1833
}
0 commit comments