@@ -1112,6 +1112,12 @@ macro_rules! nonzero_integer {
1112
1112
#[ must_use = "this returns the result of the operation, \
1113
1113
without modifying the original"]
1114
1114
#[ inline]
1115
+ #[ requires( {
1116
+ self . get( ) . checked_mul( other. get( ) ) . is_some( )
1117
+ } ) ]
1118
+ #[ ensures( |result: & Self | {
1119
+ self . get( ) . checked_mul( other. get( ) ) . is_some_and( |product| product == result. get( ) )
1120
+ } ) ]
1115
1121
pub const unsafe fn unchecked_mul( self , other: Self ) -> Self {
1116
1122
// SAFETY: The caller ensures there is no overflow.
1117
1123
unsafe { Self :: new_unchecked( self . get( ) . unchecked_mul( other. get( ) ) ) }
@@ -1514,6 +1520,13 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
1514
1520
#[ must_use = "this returns the result of the operation, \
1515
1521
without modifying the original"]
1516
1522
#[ inline]
1523
+ #[ requires( {
1524
+ self . get( ) . checked_add( other) . is_some( )
1525
+ } ) ]
1526
+ #[ ensures( |result: & Self | {
1527
+ // Postcondition: the result matches the expected addition
1528
+ self . get( ) . checked_add( other) . is_some_and( |sum| sum == result. get( ) )
1529
+ } ) ]
1517
1530
pub const unsafe fn unchecked_add( self , other: $Int) -> Self {
1518
1531
// SAFETY: The caller ensures there is no overflow.
1519
1532
unsafe { Self :: new_unchecked( self . get( ) . unchecked_add( other) ) }
@@ -2575,4 +2588,306 @@ mod verify {
2575
2588
nonzero_check_clamp_panic ! ( core:: num:: NonZeroU64 , nonzero_check_clamp_panic_for_u64) ;
2576
2589
nonzero_check_clamp_panic ! ( core:: num:: NonZeroU128 , nonzero_check_clamp_panic_for_u128) ;
2577
2590
nonzero_check_clamp_panic ! ( core:: num:: NonZeroUsize , nonzero_check_clamp_panic_for_usize) ;
2591
+
2592
+ macro_rules! check_mul_unchecked_small {
2593
+ ( $t: ty, $nonzero_type: ty, $nonzero_check_unchecked_mul_for: ident) => {
2594
+ #[ kani:: proof_for_contract( NonZero :: <$t>:: unchecked_mul) ]
2595
+ pub fn $nonzero_check_unchecked_mul_for( ) {
2596
+ let x: $nonzero_type = kani:: any( ) ;
2597
+ let y: $nonzero_type = kani:: any( ) ;
2598
+
2599
+ unsafe {
2600
+ x. unchecked_mul( y) ;
2601
+ }
2602
+ }
2603
+ } ;
2604
+ }
2605
+
2606
+ // Use for NonZero what already worked well for general numeric types (see num/mod.rs)
2607
+ macro_rules! check_mul_unchecked_intervals {
2608
+ ( $t: ty, $nonzero_type: ty, $nonzero_check_mul_for: ident, $min: expr, $max: expr) => {
2609
+ #[ kani:: proof_for_contract( NonZero :: <$t>:: unchecked_mul) ]
2610
+ pub fn $nonzero_check_mul_for( ) {
2611
+ let x = kani:: any:: <$t>( ) ;
2612
+ let y = kani:: any:: <$t>( ) ;
2613
+
2614
+ kani:: assume( x != 0 && x >= $min && x <= $max) ;
2615
+ kani:: assume( y != 0 && y >= $min && y <= $max) ;
2616
+
2617
+ let x = <$nonzero_type>:: new( x) . unwrap( ) ;
2618
+ let y = <$nonzero_type>:: new( y) . unwrap( ) ;
2619
+
2620
+ unsafe {
2621
+ x. unchecked_mul( y) ;
2622
+ }
2623
+ }
2624
+ } ;
2625
+ }
2626
+
2627
+ //Calls for i32
2628
+ check_mul_unchecked_intervals ! (
2629
+ i32 ,
2630
+ NonZeroI32 ,
2631
+ check_mul_i32_small,
2632
+ NonZeroI32 :: new( -10i32 ) . unwrap( ) . into( ) ,
2633
+ NonZeroI32 :: new( 10i32 ) . unwrap( ) . into( )
2634
+ ) ;
2635
+ check_mul_unchecked_intervals ! (
2636
+ i32 ,
2637
+ NonZeroI32 ,
2638
+ check_mul_i32_large_pos,
2639
+ NonZeroI32 :: new( i32 :: MAX - 1000i32 ) . unwrap( ) . into( ) ,
2640
+ NonZeroI32 :: new( i32 :: MAX ) . unwrap( ) . into( )
2641
+ ) ;
2642
+ check_mul_unchecked_intervals ! (
2643
+ i32 ,
2644
+ NonZeroI32 ,
2645
+ check_mul_i32_large_neg,
2646
+ NonZeroI32 :: new( i32 :: MIN + 1000i32 ) . unwrap( ) . into( ) ,
2647
+ NonZeroI32 :: new( i32 :: MIN + 1 ) . unwrap( ) . into( )
2648
+ ) ;
2649
+ check_mul_unchecked_intervals ! (
2650
+ i32 ,
2651
+ NonZeroI32 ,
2652
+ check_mul_i32_edge_pos,
2653
+ NonZeroI32 :: new( i32 :: MAX / 2 ) . unwrap( ) . into( ) ,
2654
+ NonZeroI32 :: new( i32 :: MAX ) . unwrap( ) . into( )
2655
+ ) ;
2656
+ check_mul_unchecked_intervals ! (
2657
+ i32 ,
2658
+ NonZeroI32 ,
2659
+ check_mul_i32_edge_neg,
2660
+ NonZeroI32 :: new( i32 :: MIN / 2 ) . unwrap( ) . into( ) ,
2661
+ NonZeroI32 :: new( i32 :: MIN + 1 ) . unwrap( ) . into( )
2662
+ ) ;
2663
+
2664
+ //Calls for i64
2665
+ check_mul_unchecked_intervals ! (
2666
+ i64 ,
2667
+ NonZeroI64 ,
2668
+ check_mul_i64_small,
2669
+ NonZeroI64 :: new( -10i64 ) . unwrap( ) . into( ) ,
2670
+ NonZeroI64 :: new( 10i64 ) . unwrap( ) . into( )
2671
+ ) ;
2672
+ check_mul_unchecked_intervals ! (
2673
+ i64 ,
2674
+ NonZeroI64 ,
2675
+ check_mul_i64_large_pos,
2676
+ NonZeroI64 :: new( i64 :: MAX - 1000i64 ) . unwrap( ) . into( ) ,
2677
+ NonZeroI64 :: new( i64 :: MAX ) . unwrap( ) . into( )
2678
+ ) ;
2679
+ check_mul_unchecked_intervals ! (
2680
+ i64 ,
2681
+ NonZeroI64 ,
2682
+ check_mul_i64_large_neg,
2683
+ NonZeroI64 :: new( i64 :: MIN + 1000i64 ) . unwrap( ) . into( ) ,
2684
+ NonZeroI64 :: new( i64 :: MIN + 1 ) . unwrap( ) . into( )
2685
+ ) ;
2686
+ check_mul_unchecked_intervals ! (
2687
+ i64 ,
2688
+ NonZeroI64 ,
2689
+ check_mul_i64_edge_pos,
2690
+ NonZeroI64 :: new( i64 :: MAX / 2 ) . unwrap( ) . into( ) ,
2691
+ NonZeroI64 :: new( i64 :: MAX ) . unwrap( ) . into( )
2692
+ ) ;
2693
+ check_mul_unchecked_intervals ! (
2694
+ i64 ,
2695
+ NonZeroI64 ,
2696
+ check_mul_i64_edge_neg,
2697
+ NonZeroI64 :: new( i64 :: MIN / 2 ) . unwrap( ) . into( ) ,
2698
+ NonZeroI64 :: new( i64 :: MIN + 1 ) . unwrap( ) . into( )
2699
+ ) ;
2700
+
2701
+ //calls for i128
2702
+ check_mul_unchecked_intervals ! (
2703
+ i128 ,
2704
+ NonZeroI128 ,
2705
+ check_mul_i128_small,
2706
+ NonZeroI128 :: new( -10i128 ) . unwrap( ) . into( ) ,
2707
+ NonZeroI128 :: new( 10i128 ) . unwrap( ) . into( )
2708
+ ) ;
2709
+ check_mul_unchecked_intervals ! (
2710
+ i128 ,
2711
+ NonZeroI128 ,
2712
+ check_mul_i128_large_pos,
2713
+ NonZeroI128 :: new( i128 :: MAX - 1000i128 ) . unwrap( ) . into( ) ,
2714
+ NonZeroI128 :: new( i128 :: MAX ) . unwrap( ) . into( )
2715
+ ) ;
2716
+ check_mul_unchecked_intervals ! (
2717
+ i128 ,
2718
+ NonZeroI128 ,
2719
+ check_mul_i128_large_neg,
2720
+ NonZeroI128 :: new( i128 :: MIN + 1000i128 ) . unwrap( ) . into( ) ,
2721
+ NonZeroI128 :: new( i128 :: MIN + 1 ) . unwrap( ) . into( )
2722
+ ) ;
2723
+ check_mul_unchecked_intervals ! (
2724
+ i128 ,
2725
+ NonZeroI128 ,
2726
+ check_mul_i128_edge_pos,
2727
+ NonZeroI128 :: new( i128 :: MAX / 2 ) . unwrap( ) . into( ) ,
2728
+ NonZeroI128 :: new( i128 :: MAX ) . unwrap( ) . into( )
2729
+ ) ;
2730
+ check_mul_unchecked_intervals ! (
2731
+ i128 ,
2732
+ NonZeroI128 ,
2733
+ check_mul_i128_edge_neg,
2734
+ NonZeroI128 :: new( i128 :: MIN / 2 ) . unwrap( ) . into( ) ,
2735
+ NonZeroI128 :: new( i128 :: MIN + 1 ) . unwrap( ) . into( )
2736
+ ) ;
2737
+
2738
+ //calls for isize
2739
+ check_mul_unchecked_intervals ! (
2740
+ isize ,
2741
+ NonZeroIsize ,
2742
+ check_mul_isize_small,
2743
+ NonZeroIsize :: new( -10isize ) . unwrap( ) . into( ) ,
2744
+ NonZeroIsize :: new( 10isize ) . unwrap( ) . into( )
2745
+ ) ;
2746
+ check_mul_unchecked_intervals ! (
2747
+ isize ,
2748
+ NonZeroIsize ,
2749
+ check_mul_isize_large_pos,
2750
+ NonZeroIsize :: new( isize :: MAX - 1000isize ) . unwrap( ) . into( ) ,
2751
+ NonZeroIsize :: new( isize :: MAX ) . unwrap( ) . into( )
2752
+ ) ;
2753
+ check_mul_unchecked_intervals ! (
2754
+ isize ,
2755
+ NonZeroIsize ,
2756
+ check_mul_isize_large_neg,
2757
+ NonZeroIsize :: new( isize :: MIN + 1000isize ) . unwrap( ) . into( ) ,
2758
+ NonZeroIsize :: new( isize :: MIN + 1 ) . unwrap( ) . into( )
2759
+ ) ;
2760
+ check_mul_unchecked_intervals ! (
2761
+ isize ,
2762
+ NonZeroIsize ,
2763
+ check_mul_isize_edge_pos,
2764
+ NonZeroIsize :: new( isize :: MAX / 2 ) . unwrap( ) . into( ) ,
2765
+ NonZeroIsize :: new( isize :: MAX ) . unwrap( ) . into( )
2766
+ ) ;
2767
+ check_mul_unchecked_intervals ! (
2768
+ isize ,
2769
+ NonZeroIsize ,
2770
+ check_mul_isize_edge_neg,
2771
+ NonZeroIsize :: new( isize :: MIN / 2 ) . unwrap( ) . into( ) ,
2772
+ NonZeroIsize :: new( isize :: MIN + 1 ) . unwrap( ) . into( )
2773
+ ) ;
2774
+
2775
+ //calls for u32
2776
+ check_mul_unchecked_intervals ! (
2777
+ u32 ,
2778
+ NonZeroU32 ,
2779
+ check_mul_u32_small,
2780
+ NonZeroU32 :: new( 1u32 ) . unwrap( ) . into( ) ,
2781
+ NonZeroU32 :: new( 10u32 ) . unwrap( ) . into( )
2782
+ ) ;
2783
+ check_mul_unchecked_intervals ! (
2784
+ u32 ,
2785
+ NonZeroU32 ,
2786
+ check_mul_u32_large,
2787
+ NonZeroU32 :: new( u32 :: MAX - 1000u32 ) . unwrap( ) . into( ) ,
2788
+ NonZeroU32 :: new( u32 :: MAX ) . unwrap( ) . into( )
2789
+ ) ;
2790
+ check_mul_unchecked_intervals ! (
2791
+ u32 ,
2792
+ NonZeroU32 ,
2793
+ check_mul_u32_edge,
2794
+ NonZeroU32 :: new( u32 :: MAX / 2 ) . unwrap( ) . into( ) ,
2795
+ NonZeroU32 :: new( u32 :: MAX ) . unwrap( ) . into( )
2796
+ ) ;
2797
+
2798
+ //calls for u64
2799
+ check_mul_unchecked_intervals ! (
2800
+ u64 ,
2801
+ NonZeroU64 ,
2802
+ check_mul_u64_small,
2803
+ NonZeroU64 :: new( 1u64 ) . unwrap( ) . into( ) ,
2804
+ NonZeroU64 :: new( 10u64 ) . unwrap( ) . into( )
2805
+ ) ;
2806
+ check_mul_unchecked_intervals ! (
2807
+ u64 ,
2808
+ NonZeroU64 ,
2809
+ check_mul_u64_large,
2810
+ NonZeroU64 :: new( u64 :: MAX - 1000u64 ) . unwrap( ) . into( ) ,
2811
+ NonZeroU64 :: new( u64 :: MAX ) . unwrap( ) . into( )
2812
+ ) ;
2813
+ check_mul_unchecked_intervals ! (
2814
+ u64 ,
2815
+ NonZeroU64 ,
2816
+ check_mul_u64_edge,
2817
+ NonZeroU64 :: new( u64 :: MAX / 2 ) . unwrap( ) . into( ) ,
2818
+ NonZeroU64 :: new( u64 :: MAX ) . unwrap( ) . into( )
2819
+ ) ;
2820
+
2821
+ //calls for u128
2822
+ check_mul_unchecked_intervals ! (
2823
+ u128 ,
2824
+ NonZeroU128 ,
2825
+ check_mul_u128_small,
2826
+ NonZeroU128 :: new( 1u128 ) . unwrap( ) . into( ) ,
2827
+ NonZeroU128 :: new( 10u128 ) . unwrap( ) . into( )
2828
+ ) ;
2829
+ check_mul_unchecked_intervals ! (
2830
+ u128 ,
2831
+ NonZeroU128 ,
2832
+ check_mul_u128_large,
2833
+ NonZeroU128 :: new( u128 :: MAX - 1000u128 ) . unwrap( ) . into( ) ,
2834
+ NonZeroU128 :: new( u128 :: MAX ) . unwrap( ) . into( )
2835
+ ) ;
2836
+ check_mul_unchecked_intervals ! (
2837
+ u128 ,
2838
+ NonZeroU128 ,
2839
+ check_mul_u128_edge,
2840
+ NonZeroU128 :: new( u128 :: MAX / 2 ) . unwrap( ) . into( ) ,
2841
+ NonZeroU128 :: new( u128 :: MAX ) . unwrap( ) . into( )
2842
+ ) ;
2843
+
2844
+ //calls for usize
2845
+ check_mul_unchecked_intervals ! (
2846
+ usize ,
2847
+ NonZeroUsize ,
2848
+ check_mul_usize_small,
2849
+ NonZeroUsize :: new( 1usize ) . unwrap( ) . into( ) ,
2850
+ NonZeroUsize :: new( 10usize ) . unwrap( ) . into( )
2851
+ ) ;
2852
+ check_mul_unchecked_intervals ! (
2853
+ usize ,
2854
+ NonZeroUsize ,
2855
+ check_mul_usize_large,
2856
+ NonZeroUsize :: new( usize :: MAX - 1000usize ) . unwrap( ) . into( ) ,
2857
+ NonZeroUsize :: new( usize :: MAX ) . unwrap( ) . into( )
2858
+ ) ;
2859
+ check_mul_unchecked_intervals ! (
2860
+ usize ,
2861
+ NonZeroUsize ,
2862
+ check_mul_usize_edge,
2863
+ NonZeroUsize :: new( usize :: MAX / 2 ) . unwrap( ) . into( ) ,
2864
+ NonZeroUsize :: new( usize :: MAX ) . unwrap( ) . into( )
2865
+ ) ;
2866
+
2867
+ //calls for i8, i16, u8, u16
2868
+ check_mul_unchecked_small ! ( i8 , NonZeroI8 , nonzero_check_mul_for_i8) ;
2869
+ check_mul_unchecked_small ! ( i16 , NonZeroI16 , nonzero_check_mul_for_i16) ;
2870
+ check_mul_unchecked_small ! ( u8 , NonZeroU8 , nonzero_check_mul_for_u8) ;
2871
+ check_mul_unchecked_small ! ( u16 , NonZeroU16 , nonzero_check_mul_for_u16) ;
2872
+
2873
+ macro_rules! nonzero_check_add {
2874
+ ( $t: ty, $nonzero_type: ty, $nonzero_check_unchecked_add_for: ident) => {
2875
+ #[ kani:: proof_for_contract( NonZero :: <$t>:: unchecked_add) ]
2876
+ pub fn $nonzero_check_unchecked_add_for( ) {
2877
+ let x: $nonzero_type = kani:: any( ) ;
2878
+ let y: $t = kani:: any( ) ;
2879
+
2880
+ unsafe {
2881
+ x. unchecked_add( y) ;
2882
+ }
2883
+ }
2884
+ } ;
2885
+ }
2886
+
2887
+ nonzero_check_add ! ( u8 , core:: num:: NonZeroU8 , nonzero_check_unchecked_add_for_u8) ;
2888
+ nonzero_check_add ! ( u16 , core:: num:: NonZeroU16 , nonzero_check_unchecked_add_for_u16) ;
2889
+ nonzero_check_add ! ( u32 , core:: num:: NonZeroU32 , nonzero_check_unchecked_add_for_u32) ;
2890
+ nonzero_check_add ! ( u64 , core:: num:: NonZeroU64 , nonzero_check_unchecked_add_for_u64) ;
2891
+ nonzero_check_add ! ( u128 , core:: num:: NonZeroU128 , nonzero_check_unchecked_add_for_u128) ;
2892
+ nonzero_check_add ! ( usize , core:: num:: NonZeroUsize , nonzero_check_unchecked_add_for_usize) ;
2578
2893
}
0 commit comments