@@ -1042,56 +1042,6 @@ extern "rust-intrinsic" {
1042
1042
#[ rustc_nounwind]
1043
1043
pub fn breakpoint ( ) ;
1044
1044
1045
- /// Executes a breakpoint trap, for inspection by a debugger.
1046
- ///
1047
- /// This intrinsic does not have a stable counterpart.
1048
- #[ rustc_nounwind]
1049
- // FIXME: Kani currently does not support annotating intrinsics.
1050
- // See https://github.com/model-checking/kani/issues/3325
1051
- #[ cfg_attr( not( kani) , requires( matches!(
1052
- <T as Pointee >:: Metadata :: map_dyn( crate :: ptr:: metadata( _val) :: metadata( ) ,
1053
- |dyn_meta| { ub_checks:: can_dereference( dyn_meta) } ) ,
1054
- None | Some ( true ) ) ) ) ]
1055
- #[ cfg_attr( not( kani) , requires( matches!(
1056
- <T as Pointee >:: Metadata :: map_len( crate :: ptr:: metadata( _val) :: metadata( ) ,
1057
- |_| { ub_checks:: can_dereference( _val) } ) ,
1058
- None | Some ( true ) ) ) ) ]
1059
- pub fn size_of_val < T : ?Sized > ( _val : * const T ) -> usize ;
1060
- /// The required alignment of the referenced value.
1061
- ///
1062
- /// The stabilized version of this intrinsic is [`core::mem::align_of_val`].
1063
- #[ rustc_const_unstable( feature = "const_align_of_val" , issue = "46571" ) ]
1064
- #[ rustc_nounwind]
1065
- pub fn min_align_of_val < T : ?Sized > ( _: * const T ) -> usize ;
1066
-
1067
- /// Gets a static string slice containing the name of a type.
1068
- ///
1069
- /// Note that, unlike most intrinsics, this is safe to call;
1070
- /// it does not require an `unsafe` block.
1071
- /// Therefore, implementations must not require the user to uphold
1072
- /// any safety invariants.
1073
- ///
1074
- /// The stabilized version of this intrinsic is [`core::any::type_name`].
1075
- #[ rustc_const_unstable( feature = "const_type_name" , issue = "63084" ) ]
1076
- #[ rustc_safe_intrinsic]
1077
- #[ rustc_nounwind]
1078
- pub fn type_name < T : ?Sized > ( ) -> & ' static str ;
1079
-
1080
- /// Gets an identifier which is globally unique to the specified type. This
1081
- /// function will return the same value for a type regardless of whichever
1082
- /// crate it is invoked in.
1083
- ///
1084
- /// Note that, unlike most intrinsics, this is safe to call;
1085
- /// it does not require an `unsafe` block.
1086
- /// Therefore, implementations must not require the user to uphold
1087
- /// any safety invariants.
1088
- ///
1089
- /// The stabilized version of this intrinsic is [`core::any::TypeId::of`].
1090
- #[ rustc_const_unstable( feature = "const_type_id" , issue = "77125" ) ]
1091
- #[ rustc_safe_intrinsic]
1092
- #[ rustc_nounwind]
1093
- pub fn type_id < T : ?Sized + ' static > ( ) -> u128 ;
1094
-
1095
1045
/// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
1096
1046
/// This will statically either panic, or do nothing.
1097
1047
///
@@ -3166,6 +3116,14 @@ pub const fn variant_count<T>() -> usize {
3166
3116
#[ rustc_const_unstable( feature = "const_size_of_val" , issue = "46571" ) ]
3167
3117
#[ rustc_intrinsic]
3168
3118
#[ rustc_intrinsic_must_be_overridden]
3119
+ #[ cfg_attr( not( kani) , requires( matches!(
3120
+ <T as Pointee >:: Metadata :: map_dyn( crate :: ptr:: metadata( _val) :: metadata( ) ,
3121
+ |dyn_meta| { ub_checks:: can_dereference( dyn_meta) } ) ,
3122
+ None | Some ( true ) ) ) ) ]
3123
+ #[ cfg_attr( not( kani) , requires( matches!(
3124
+ <T as Pointee >:: Metadata :: map_len( crate :: ptr:: metadata( _val) :: metadata( ) ,
3125
+ |_| { ub_checks:: can_dereference( _val) } ) ,
3126
+ None | Some ( true ) ) ) ) ]
3169
3127
pub const unsafe fn size_of_val < T : ?Sized > ( _ptr : * const T ) -> usize {
3170
3128
unreachable ! ( )
3171
3129
}
@@ -3363,20 +3321,10 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons
3363
3321
#[ cfg_attr( kani, kani:: modifies( crate :: ptr:: slice_from_raw_parts( dst, count) ) ) ]
3364
3322
#[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
3365
3323
&& ub_checks:: can_dereference( core:: ptr:: slice_from_raw_parts( src as * const crate :: mem:: MaybeUninit <T >, count) )
3366
- && ub_checks:: can_write( core:: ptr:: slice_from_raw_parts_mut( dst, count) ) ) ]
3367
- #[ requires( ub_checks:: is_nonoverlapping( src as * const ( ) , dst as * const ( ) , size_of:: <T >( ) , count) ) ]
3368
- // TODO: Use quantifiers once it's available.
3369
- // Ensures the initialization state is preserved.
3370
- #[ ensures( |_| {
3371
- if count > 0 {
3372
- let byte = kani:: any_where( | sz: & usize | * sz < size_of:: < T >) ;
3373
- let elem = kani:: any_where( | val: & usize | * val < count) ;
3374
- let src_data = src as * const u8 ;
3375
- let dst_data = unsafe { dst. offset( elem) } as * const u8 ;
3376
- ub_checks:: can_dereference( unsafe { src_data. offset( byte) } )
3377
- == ub_checks:: can_dereference( unsafe { dst_data. offset( byte) } )
3378
- }
3379
- } ) ]
3324
+ && ub_checks:: can_write( core:: ptr:: slice_from_raw_parts_mut( dst, count) )
3325
+ && ub_checks:: is_nonoverlapping( src as * const ( ) , dst as * const ( ) , size_of:: <T >( ) , count) ) ]
3326
+ #[ ensures( |_| { check_copy_untyped( src, dst, count) } ) ]
3327
+ #[ cfg_attr( kani, kani:: modifies( crate :: ptr:: slice_from_raw_parts( dst, count) ) ) ]
3380
3328
pub const unsafe fn copy_nonoverlapping < T > ( src : * const T , dst : * mut T , count : usize ) {
3381
3329
extern "rust-intrinsic" {
3382
3330
#[ rustc_const_unstable( feature = "const_intrinsic_copy" , issue = "80697" ) ]
@@ -3483,16 +3431,8 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
3483
3431
#[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
3484
3432
&& ub_checks:: can_dereference( core:: ptr:: slice_from_raw_parts( src as * const crate :: mem:: MaybeUninit <T >, count) )
3485
3433
&& ub_checks:: can_write( core:: ptr:: slice_from_raw_parts_mut( dst, count) ) ) ]
3486
- #[ ensures( |_| {
3487
- if count > 0 {
3488
- let byte = kani:: any_where( | sz: & usize | * sz < size_of:: < T >) ;
3489
- let elem = kani:: any_where( | val: & usize | * val < count) ;
3490
- let src_data = src as * const u8 ;
3491
- let dst_data = unsafe { dst. offset( elem) } as * const u8 ;
3492
- ub_checks:: can_dereference( unsafe { src_data. offset( byte) } )
3493
- == ub_checks:: can_dereference( unsafe { dst_data. offset( byte) } )
3494
- }
3495
- } ) ]
3434
+ #[ ensures( |_| { check_copy_untyped( src, dst, count) } ) ]
3435
+ #[ cfg_attr( kani, kani:: modifies( crate :: ptr:: slice_from_raw_parts( dst, count) ) ) ]
3496
3436
pub const unsafe fn copy < T > ( src : * const T , dst : * mut T , count : usize ) {
3497
3437
extern "rust-intrinsic" {
3498
3438
#[ rustc_const_unstable( feature = "const_intrinsic_copy" , issue = "80697" ) ]
@@ -3576,14 +3516,12 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
3576
3516
#[ inline( always) ]
3577
3517
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
3578
3518
#[ rustc_diagnostic_item = "ptr_write_bytes" ]
3579
- #[ cfg_attr( kani, kani:: modifies( crate :: ptr:: slice_from_raw_parts( dst, count) ) ) ]
3580
3519
#[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
3581
- && ub_checks:: can_write( core:: ptr:: slice_from_raw_parts_mut( dst as * mut u8 , count) ) ) ]
3582
- // TODO: Change this to quantifiers when available.
3583
- #[ ensures( |_| {
3584
- let idx = kani:: any_where( |idx: & usize | * idx < count) ;
3585
- ub_checks:: can_dereference( dst. offset( idx) as * const u8 )
3586
- } ) ]
3520
+ && ub_checks:: can_write( core:: ptr:: slice_from_raw_parts_mut( dst, count) ) ) ]
3521
+ #[ requires( count > 0 || ub_checks:: is_aligned_and_not_null( dst as * const ( ) , align_of:: <T >( ) ) ) ]
3522
+ #[ ensures( |_|
3523
+ ub_checks:: can_dereference( crate :: ptr:: slice_from_raw_parts( dst as * const u8 , count * size_of:: <T >( ) ) ) ) ]
3524
+ #[ cfg_attr( kani, kani:: modifies( crate :: ptr:: slice_from_raw_parts( dst, count) ) ) ]
3587
3525
pub const unsafe fn write_bytes < T > ( dst : * mut T , val : u8 , count : usize ) {
3588
3526
extern "rust-intrinsic" {
3589
3527
#[ rustc_const_unstable( feature = "const_ptr_write" , issue = "86302" ) ]
@@ -3605,6 +3543,21 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
3605
3543
}
3606
3544
}
3607
3545
3546
+ // Ensures the initialization state is preserved.
3547
+ // This is used for contracts only.
3548
+ fn check_copy_untyped < T > ( src : * const T , dst : * mut T , count : usize ) -> bool {
3549
+ if count > 0 {
3550
+ let byte = kani:: any_where ( | sz : & usize | * sz < size_of :: < T > ( ) ) ;
3551
+ let elem = kani:: any_where ( | val : & usize | * val < count) ;
3552
+ let src_data = src as * const u8 ;
3553
+ let dst_data = unsafe { dst. add ( elem) } as * const u8 ;
3554
+ ub_checks:: can_dereference ( unsafe { src_data. add ( byte) } )
3555
+ == ub_checks:: can_dereference ( unsafe { dst_data. add ( byte) } )
3556
+ } else {
3557
+ true
3558
+ }
3559
+ }
3560
+
3608
3561
/// Inform Miri that a given pointer definitely has a certain alignment.
3609
3562
#[ cfg( miri) ]
3610
3563
pub ( crate ) const fn miri_promise_symbolic_alignment ( ptr : * const ( ) , align : usize ) {
@@ -3632,6 +3585,7 @@ pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize
3632
3585
mod verify {
3633
3586
use core:: { cmp, fmt} ;
3634
3587
use core:: ptr:: addr_of_mut;
3588
+ use core:: mem:: MaybeUninit ;
3635
3589
use super :: * ;
3636
3590
use crate :: kani;
3637
3591
@@ -3686,28 +3640,44 @@ mod verify {
3686
3640
}
3687
3641
3688
3642
impl < T : kani:: Arbitrary > ArbitraryPointers < T > {
3689
- fn with_arbitrary < F > ( harness : F ) where F : FnOnce ( ArbitraryPointers < u32 > ) {
3643
+ const MAX_SIZE_T : usize = 100 ;
3644
+ const SIZE_T : usize = size_of :: < T > ( ) ;
3645
+
3646
+ const IS_VALID : ( ) = assert ! ( Self :: SIZE_T < Self :: MAX_SIZE_T , "Exceeded supported type size" ) ;
3647
+
3648
+ fn with_arbitrary < F > ( harness : F ) where F : FnOnce ( ArbitraryPointers < T > ) {
3649
+
3650
+ #[ repr( C ) ]
3651
+ struct WithUninit < const SIZE : usize > {
3652
+ bytes : [ MaybeUninit < u8 > ; SIZE ] ,
3653
+ }
3654
+
3690
3655
#[ repr( C ) ]
3691
- struct WithPadding {
3692
- byte : u8 ,
3693
- // padding in the middle.
3694
- bytes : u64 ,
3656
+ #[ repr( packed) ]
3657
+ #[ derive( kani:: Arbitrary ) ]
3658
+ struct Unaligned < T > {
3659
+ first : u8 ,
3660
+ val : T , // If alignment of T > 1, this value will be unaligned but valid otherwise.
3695
3661
}
3696
- let mut single = kani:: any :: < u32 > ( ) ;
3697
- let ptr1 = addr_of_mut ! ( single) ;
3698
3662
3699
- // FIXME(kani) this should be but this is not available in `kani_core` yet:
3700
- // let mut array: [u8; 100] = kani::any();
3701
- let mut array = [ kani:: any :: < u32 > ( ) , 100 ] ;
3702
- let ptr2 = addr_of_mut ! ( array) as * mut u32 ;
3663
+ let mut single = kani:: any :: < T > ( ) ;
3664
+ let single_ptr = addr_of_mut ! ( single) ;
3703
3665
3704
- let mut buffer = [ 0u8 ; 6 ] ;
3705
- let unaligned = unsafe { addr_of_mut ! ( buffer ) . byte_offset ( 1 ) } as * mut u32 ;
3666
+ let mut array : [ T ; 100 ] = kani :: any ( ) ;
3667
+ let array_ptr = addr_of_mut ! ( array ) as * mut T ;
3706
3668
3707
- let mut padding = WithPadding { byte : kani:: any ( ) , bytes : kani:: any ( ) } ;
3708
- let uninit = unsafe { addr_of_mut ! ( padding. byte) . byte_offset ( 4 ) } as * mut u32 ;
3669
+ let mut unaligned: Unaligned < T > = kani:: any ( ) ;
3670
+ let unaligned_ptr = addr_of_mut ! ( unaligned. val) as * mut T ;
3671
+
3672
+ let mut uninit = WithUninit { bytes : [ MaybeUninit :: zeroed ( ) ; Self :: MAX_SIZE_T ] } ;
3673
+ for i in 0 ..Self :: SIZE_T {
3674
+ if kani:: any ( ) {
3675
+ uninit. bytes [ i] = MaybeUninit :: uninit ( ) ;
3676
+ }
3677
+ }
3678
+ let uninit_ptr = & mut uninit as * mut _ as * mut T ;
3709
3679
3710
- let arbitrary = ArbitraryPointers :: from ( ptr1 , ptr2 , unaligned , uninit ) ;
3680
+ let arbitrary = ArbitraryPointers :: from ( single_ptr , array_ptr , unaligned_ptr , uninit_ptr ) ;
3711
3681
harness ( arbitrary) ;
3712
3682
}
3713
3683
@@ -3748,7 +3718,6 @@ mod verify {
3748
3718
}
3749
3719
}
3750
3720
3751
- /// This harness currently fails because we cannot define the modifies clause for slices.
3752
3721
#[ kani:: proof_for_contract( copy) ]
3753
3722
fn check_copy ( ) {
3754
3723
ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
@@ -3774,7 +3743,6 @@ mod verify {
3774
3743
} ) ;
3775
3744
}
3776
3745
3777
- /// FIXME(kani): This harness currently fails because we cannot define the modifies clause for slices.
3778
3746
#[ kani:: proof_for_contract( copy_nonoverlapping) ]
3779
3747
fn check_copy_nonoverlapping ( ) {
3780
3748
ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
@@ -3786,7 +3754,6 @@ mod verify {
3786
3754
} ) ;
3787
3755
}
3788
3756
3789
- /// FIXME(kani): This harness currently fails because we cannot define the modifies clause for slices.
3790
3757
#[ kani:: proof_for_contract( write_bytes) ]
3791
3758
fn check_write_bytes ( ) {
3792
3759
ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
0 commit comments