@@ -1042,56 +1042,6 @@ extern "rust-intrinsic" {
10421042 #[ rustc_nounwind]
10431043 pub fn breakpoint ( ) ;
10441044
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-
10951045 /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
10961046 /// This will statically either panic, or do nothing.
10971047 ///
@@ -3166,6 +3116,14 @@ pub const fn variant_count<T>() -> usize {
31663116#[ rustc_const_unstable( feature = "const_size_of_val" , issue = "46571" ) ]
31673117#[ rustc_intrinsic]
31683118#[ 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 ) ) ) ) ]
31693127pub const unsafe fn size_of_val < T : ?Sized > ( _ptr : * const T ) -> usize {
31703128 unreachable ! ( )
31713129}
@@ -3363,20 +3321,10 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons
33633321#[ cfg_attr( kani, kani:: modifies( crate :: ptr:: slice_from_raw_parts( dst, count) ) ) ]
33643322#[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
33653323 && 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) ) ) ]
33803328pub const unsafe fn copy_nonoverlapping < T > ( src : * const T , dst : * mut T , count : usize ) {
33813329 extern "rust-intrinsic" {
33823330 #[ 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
34833431#[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
34843432 && ub_checks:: can_dereference( core:: ptr:: slice_from_raw_parts( src as * const crate :: mem:: MaybeUninit <T >, count) )
34853433 && 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) ) ) ]
34963436pub const unsafe fn copy < T > ( src : * const T , dst : * mut T , count : usize ) {
34973437 extern "rust-intrinsic" {
34983438 #[ 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) {
35763516#[ inline( always) ]
35773517#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
35783518#[ rustc_diagnostic_item = "ptr_write_bytes" ]
3579- #[ cfg_attr( kani, kani:: modifies( crate :: ptr:: slice_from_raw_parts( dst, count) ) ) ]
35803519#[ 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) ) ) ]
35873525pub const unsafe fn write_bytes < T > ( dst : * mut T , val : u8 , count : usize ) {
35883526 extern "rust-intrinsic" {
35893527 #[ rustc_const_unstable( feature = "const_ptr_write" , issue = "86302" ) ]
@@ -3605,6 +3543,22 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
36053543 }
36063544}
36073545
3546+ // Ensures the initialization state is preserved.
3547+ // This is used for contracts only.
3548+ #[ allow( dead_code) ]
3549+ fn check_copy_untyped < T > ( src : * const T , dst : * mut T , count : usize ) -> bool {
3550+ if count > 0 {
3551+ let byte = kani:: any_where ( | sz : & usize | * sz < size_of :: < T > ( ) ) ;
3552+ let elem = kani:: any_where ( | val : & usize | * val < count) ;
3553+ let src_data = src as * const u8 ;
3554+ let dst_data = unsafe { dst. add ( elem) } as * const u8 ;
3555+ ub_checks:: can_dereference ( unsafe { src_data. add ( byte) } )
3556+ == ub_checks:: can_dereference ( unsafe { dst_data. add ( byte) } )
3557+ } else {
3558+ true
3559+ }
3560+ }
3561+
36083562/// Inform Miri that a given pointer definitely has a certain alignment.
36093563#[ cfg( miri) ]
36103564pub ( crate ) const fn miri_promise_symbolic_alignment ( ptr : * const ( ) , align : usize ) {
@@ -3632,6 +3586,7 @@ pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize
36323586mod verify {
36333587 use core:: { cmp, fmt} ;
36343588 use core:: ptr:: addr_of_mut;
3589+ use core:: mem:: MaybeUninit ;
36353590 use super :: * ;
36363591 use crate :: kani;
36373592
@@ -3686,28 +3641,44 @@ mod verify {
36863641 }
36873642
36883643 impl < T : kani:: Arbitrary > ArbitraryPointers < T > {
3689- fn with_arbitrary < F > ( harness : F ) where F : FnOnce ( ArbitraryPointers < u32 > ) {
3644+ const MAX_SIZE_T : usize = 100 ;
3645+ const SIZE_T : usize = size_of :: < T > ( ) ;
3646+
3647+ const IS_VALID : ( ) = assert ! ( Self :: SIZE_T < Self :: MAX_SIZE_T , "Exceeded supported type size" ) ;
3648+
3649+ fn with_arbitrary < F > ( harness : F ) where F : FnOnce ( ArbitraryPointers < T > ) {
3650+
3651+ #[ repr( C ) ]
3652+ struct WithUninit < const SIZE : usize > {
3653+ bytes : [ MaybeUninit < u8 > ; SIZE ] ,
3654+ }
3655+
36903656 #[ repr( C ) ]
3691- struct WithPadding {
3692- byte : u8 ,
3693- // padding in the middle.
3694- bytes : u64 ,
3657+ #[ repr( packed) ]
3658+ #[ derive( kani:: Arbitrary ) ]
3659+ struct Unaligned < T > {
3660+ first : u8 ,
3661+ val : T , // If alignment of T > 1, this value will be unaligned but valid otherwise.
36953662 }
3696- let mut single = kani:: any :: < u32 > ( ) ;
3697- let ptr1 = addr_of_mut ! ( single) ;
36983663
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 ;
3664+ let mut single = kani:: any :: < T > ( ) ;
3665+ let single_ptr = addr_of_mut ! ( single) ;
37033666
3704- let mut buffer = [ 0u8 ; 6 ] ;
3705- let unaligned = unsafe { addr_of_mut ! ( buffer ) . byte_offset ( 1 ) } as * mut u32 ;
3667+ let mut array : [ T ; 100 ] = kani :: any ( ) ;
3668+ let array_ptr = addr_of_mut ! ( array ) as * mut T ;
37063669
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 ;
3670+ let mut unaligned: Unaligned < T > = kani:: any ( ) ;
3671+ let unaligned_ptr = addr_of_mut ! ( unaligned. val) as * mut T ;
3672+
3673+ let mut uninit = WithUninit { bytes : [ MaybeUninit :: zeroed ( ) ; Self :: MAX_SIZE_T ] } ;
3674+ for i in 0 ..Self :: SIZE_T {
3675+ if kani:: any ( ) {
3676+ uninit. bytes [ i] = MaybeUninit :: uninit ( ) ;
3677+ }
3678+ }
3679+ let uninit_ptr = & mut uninit as * mut _ as * mut T ;
37093680
3710- let arbitrary = ArbitraryPointers :: from ( ptr1 , ptr2 , unaligned , uninit ) ;
3681+ let arbitrary = ArbitraryPointers :: from ( single_ptr , array_ptr , unaligned_ptr , uninit_ptr ) ;
37113682 harness ( arbitrary) ;
37123683 }
37133684
@@ -3748,7 +3719,6 @@ mod verify {
37483719 }
37493720 }
37503721
3751- /// This harness currently fails because we cannot define the modifies clause for slices.
37523722 #[ kani:: proof_for_contract( copy) ]
37533723 fn check_copy ( ) {
37543724 ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
@@ -3774,7 +3744,6 @@ mod verify {
37743744 } ) ;
37753745 }
37763746
3777- /// FIXME(kani): This harness currently fails because we cannot define the modifies clause for slices.
37783747 #[ kani:: proof_for_contract( copy_nonoverlapping) ]
37793748 fn check_copy_nonoverlapping ( ) {
37803749 ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
@@ -3786,7 +3755,6 @@ mod verify {
37863755 } ) ;
37873756 }
37883757
3789- /// FIXME(kani): This harness currently fails because we cannot define the modifies clause for slices.
37903758 #[ kani:: proof_for_contract( write_bytes) ]
37913759 fn check_write_bytes ( ) {
37923760 ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
0 commit comments