6363) ] 
6464#![ allow( missing_docs) ]  
6565
66- use  safety:: { ensures,  requires} ; 
6766use  crate :: marker:: DiscriminantKind ; 
6867use  crate :: marker:: Tuple ; 
6968use  crate :: ptr; 
7069use  crate :: ub_checks; 
70+ use  safety:: { ensures,  requires} ; 
7171
7272#[ cfg( kani) ]  
7373use  crate :: kani; 
@@ -77,12 +77,19 @@ pub mod simd;
7777
7878// These imports are used for simplifying intra-doc links 
7979#[ allow( unused_imports) ]  
80- #[ cfg( all( target_has_atomic = "8" ,  target_has_atomic = "32" ,  target_has_atomic = "ptr" ) ) ]  
80+ #[ cfg( all(  
81+     target_has_atomic = "8" ,  
82+     target_has_atomic = "32" ,  
83+     target_has_atomic = "ptr"  
84+ ) ) ] 
8185use  crate :: sync:: atomic:: { self ,  AtomicBool ,  AtomicI32 ,  AtomicIsize ,  AtomicU32 ,  Ordering } ; 
8286
8387#[ stable( feature = "drop_in_place" ,  since = "1.8.0" ) ]  
8488#[ rustc_allowed_through_unstable_modules]  
85- #[ deprecated( note = "no longer an intrinsic - use `ptr::drop_in_place` directly" ,  since = "1.52.0" ) ]  
89+ #[ deprecated(  
90+     note = "no longer an intrinsic - use `ptr::drop_in_place` directly" ,  
91+     since = "1.52.0"  
92+ ) ] 
8693#[ inline]  
8794pub  unsafe  fn  drop_in_place < T :  ?Sized > ( to_drop :  * mut  T )  { 
8895    // SAFETY: see `ptr::drop_in_place` 
@@ -1032,7 +1039,11 @@ pub const fn unlikely(b: bool) -> bool {
10321039#[ miri:: intrinsic_fallback_is_spec]  
10331040#[ inline]  
10341041pub  fn  select_unpredictable < T > ( b :  bool ,  true_val :  T ,  false_val :  T )  -> T  { 
1035-     if  b {  true_val }  else  {  false_val } 
1042+     if  b { 
1043+         true_val
1044+     }  else  { 
1045+         false_val
1046+     } 
10361047} 
10371048
10381049extern  "rust-intrinsic"  { 
@@ -2937,7 +2948,7 @@ pub const fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
29372948#[ requires( ub_checks:: can_dereference( x)  && ub_checks:: can_write( x) ) ]  
29382949#[ requires( ub_checks:: can_dereference( y)  && ub_checks:: can_write( y) ) ]  
29392950#[ requires( x. addr( )  != y. addr( )  || core:: mem:: size_of:: <T >( )  == 0 ) ]  
2940- #[ requires( ub_checks:: is_nonoverlapping( x as  * const  ( ) ,  x  as  * const  ( ) ,  size_of:: <T >( ) ,  1 ) ) ]  
2951+ #[ requires( ub_checks:: is_nonoverlapping( x as  * const  ( ) ,  y  as  * const  ( ) ,  size_of:: <T >( ) ,  1 ) ) ]  
29412952#[ ensures( |_| ub_checks:: can_dereference( x)  && ub_checks:: can_dereference( y) ) ]  
29422953pub  const  unsafe  fn  typed_swap < T > ( x :  * mut  T ,  y :  * mut  T )  { 
29432954    // SAFETY: The caller provided single non-overlapping items behind 
@@ -3013,9 +3024,9 @@ pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize)
30133024#[ unstable( feature = "core_intrinsics" ,  issue = "none" ) ]  
30143025#[ rustc_intrinsic]  
30153026#[ rustc_intrinsic_must_be_overridden]  
3016- // FIXME(kani): Cannot verify intrinsics contract yet.  
3017- // <https://github.com/model-checking/kani /issues/3345 > 
3018- #[ requires( ub_checks:: can_dereference( _ptr as  * const  crate :: ptr :: DynMetadata <dyn  crate :: any :: Any > ) ) ]  
3027+ // VTable pointers must be valid for dereferencing at least 3 `usize` (size, alignment and drop):  
3028+ // <https://github.com/rust-lang/unsafe-code-guidelines /issues/166 > 
3029+ #[ requires( ub_checks:: can_dereference( _ptr as  * const  [ usize ;   3 ] ) ) ]  
30193030pub  unsafe  fn  vtable_size ( _ptr :  * const  ( ) )  -> usize  { 
30203031    unreachable ! ( ) 
30213032} 
@@ -3029,9 +3040,9 @@ pub unsafe fn vtable_size(_ptr: *const ()) -> usize {
30293040#[ unstable( feature = "core_intrinsics" ,  issue = "none" ) ]  
30303041#[ rustc_intrinsic]  
30313042#[ rustc_intrinsic_must_be_overridden]  
3032- // FIXME(kani): Cannot verify intrinsics contract yet.  
3033- // <https://github.com/model-checking/kani /issues/3345 > 
3034- #[ requires( ub_checks:: can_dereference( _ptr as  * const  crate :: ptr :: DynMetadata <dyn  crate :: any :: Any > ) ) ]  
3043+ // VTable pointers must be valid for dereferencing at least 3 `usize` (size, alignment and drop):  
3044+ // <https://github.com/rust-lang/unsafe-code-guidelines /issues/166 > 
3045+ #[ requires( ub_checks:: can_dereference( _ptr as  * const  [ usize ;   3 ] ) ) ]  
30353046pub  unsafe  fn  vtable_align ( _ptr :  * const  ( ) )  -> usize  { 
30363047    unreachable ! ( ) 
30373048} 
@@ -3116,14 +3127,6 @@ pub const fn variant_count<T>() -> usize {
31163127#[ rustc_const_unstable( feature = "const_size_of_val" ,  issue = "46571" ) ]  
31173128#[ rustc_intrinsic]  
31183129#[ 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 ) ) ) ) ]  
31273130pub  const  unsafe  fn  size_of_val < T :  ?Sized > ( _ptr :  * const  T )  -> usize  { 
31283131    unreachable ! ( ) 
31293132} 
@@ -3324,7 +3327,6 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons
33243327  && ub_checks:: can_write( core:: ptr:: slice_from_raw_parts_mut( dst,  count) )  
33253328  && ub_checks:: is_nonoverlapping( src as  * const  ( ) ,  dst as  * const  ( ) ,  size_of:: <T >( ) ,  count) ) ]  
33263329#[ ensures( |_| {  check_copy_untyped( src,  dst,  count) } ) ]  
3327- #[ cfg_attr( kani,  kani:: modifies( crate :: ptr:: slice_from_raw_parts( dst,  count) ) ) ]  
33283330pub  const  unsafe  fn  copy_nonoverlapping < T > ( src :  * const  T ,  dst :  * mut  T ,  count :  usize )  { 
33293331    extern  "rust-intrinsic"  { 
33303332        #[ rustc_const_unstable( feature = "const_intrinsic_copy" ,  issue = "80697" ) ]  
@@ -3517,7 +3519,7 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
35173519#[ rustc_diagnostic_item = "ptr_write_bytes" ]  
35183520#[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1  
35193521  && ub_checks:: can_write( core:: ptr:: slice_from_raw_parts_mut( dst,  count) ) ) ]  
3520- #[ requires( count >  0  ||  ub_checks:: is_aligned_and_not_null( dst as  * const  ( ) ,  align_of:: <T >( ) ) ) ]  
3522+ #[ requires( ub_checks:: is_aligned_and_not_null( dst as  * const  ( ) ,  align_of:: <T >( ) ) ) ]  
35213523#[ ensures( |_| 
35223524    ub_checks:: can_dereference( crate :: ptr:: slice_from_raw_parts( dst as  * const  u8 ,  count *  size_of:: <T >( ) ) ) ) ]  
35233525#[ cfg_attr( kani,  kani:: modifies( crate :: ptr:: slice_from_raw_parts( dst,  count) ) ) ]  
@@ -3551,10 +3553,10 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
35513553fn  check_copy_untyped < T > ( src :  * const  T ,  dst :  * mut  T ,  count :  usize )  -> bool  { 
35523554    #[ cfg( kani) ]  
35533555    if  count > 0  { 
3554-         let  byte = kani:: any_where ( |  sz :  & usize   | * sz < size_of :: <   T   > ( ) ) ; 
3555-         let  elem = kani:: any_where ( |  val :  & usize   | * val < count) ; 
3556-         let  src_data = src as  *   const  u8 ; 
3557-         let  dst_data = unsafe  {  dst. add ( elem)  }  as  *   const  u8 ; 
3556+         let  byte = kani:: any_where ( |sz :  & usize | * sz < size_of :: < T > ( ) ) ; 
3557+         let  elem = kani:: any_where ( |val :  & usize | * val < count) ; 
3558+         let  src_data = src as  * const  u8 ; 
3559+         let  dst_data = unsafe  {  dst. add ( elem)  }  as  * const  u8 ; 
35583560        ub_checks:: can_dereference ( unsafe  {  src_data. add ( byte)  } ) 
35593561            == ub_checks:: can_dereference ( unsafe  {  dst_data. add ( byte)  } ) 
35603562    }  else  { 
@@ -3587,163 +3589,81 @@ pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize
35873589} 
35883590
35893591#[ cfg( kani) ]  
3590- #[ unstable( feature= "kani" ,  issue= "none" ) ]  
3592+ #[ unstable( feature =  "kani" ,  issue =  "none" ) ]  
35913593mod  verify { 
3592-     use  core:: { cmp,  fmt} ; 
3593-     use  core:: ptr:: addr_of_mut; 
3594-     use  core:: mem:: MaybeUninit ; 
35953594    use  super :: * ; 
35963595    use  crate :: kani; 
3596+     use  core:: mem:: MaybeUninit ; 
3597+     use  core:: ptr:: addr_of_mut; 
3598+     use  core:: { cmp,  fmt} ; 
3599+     use  kani:: { AllocationStatus ,  Arbitrary ,  ArbitraryPointer ,  PointerGenerator } ; 
35973600
35983601    #[ kani:: proof_for_contract( typed_swap) ]  
35993602    pub  fn  check_typed_swap_u8 ( )  { 
3600-         check_swap :: < u8 > ( ) 
3603+         run_with_arbitrary_ptrs :: < u8 > ( |x ,  y|  unsafe   {   typed_swap ( x ,  y )   } ) ; 
36013604    } 
36023605
36033606    #[ kani:: proof_for_contract( typed_swap) ]  
36043607    pub  fn  check_typed_swap_char ( )  { 
3605-         check_swap :: < char > ( ) 
3608+         run_with_arbitrary_ptrs :: < char > ( |x ,  y|  unsafe   {   typed_swap ( x ,  y )   } ) ; 
36063609    } 
36073610
36083611    #[ kani:: proof_for_contract( typed_swap) ]  
36093612    pub  fn  check_typed_swap_non_zero ( )  { 
3610-         check_swap :: < core:: num:: NonZeroI32 > ( ) 
3611-     } 
3612- 
3613-     pub  fn  check_swap < T :  kani:: Arbitrary  + Copy  + cmp:: PartialEq  + fmt:: Debug > ( )  { 
3614-         let  mut  x = kani:: any :: < T > ( ) ; 
3615-         let  old_x = x; 
3616-         let  mut  y = kani:: any :: < T > ( ) ; 
3617-         let  old_y = y; 
3618- 
3619-         unsafe  {  typed_swap ( & mut  x,  & mut  y)  } ; 
3620-         assert_eq ! ( y,  old_x) ; 
3621-         assert_eq ! ( x,  old_y) ; 
3613+         run_with_arbitrary_ptrs :: < core:: num:: NonZeroI32 > ( |x,  y| unsafe  {  typed_swap ( x,  y)  } ) ; 
36223614    } 
36233615
3624-     #[ derive( Copy ,  Clone ,  Debug ,  PartialEq ,  Eq ,  kani:: Arbitrary ) ]  
3625-     enum  AllocationStatus  { 
3626-         /// Dangling pointers 
3627- Dangling , 
3628-         /// Pointer to dead object 
3629- DeadObj , 
3630-         /// Null pointers 
3631- Null , 
3632-         /// In bounds pointer (it may be unaligned) 
3633- InBounds , 
3634-         /// Out of bounds 
3635- OutBounds , 
3636-     } 
3637- 
3638-     struct  PointerGenerator < T ,  const  BUF_LEN :  usize >  { 
3639-         // Internal allocation that may be used to generate valid pointers. 
3640-         buf :  MaybeUninit < [ T ;  BUF_LEN ] > , 
3641-     } 
3642- 
3643-     struct  ArbitraryPointer < T >  { 
3644-         pub  ptr :  * mut  T , 
3645-         pub  status :  AllocationStatus , 
3646-         pub  is_initialized :  bool , 
3647-     } 
3648- 
3649-     impl < T :  kani:: Arbitrary ,  const  BUF_LEN :  usize >  PointerGenerator < T ,  BUF_LEN >  { 
3650-         const  SZ  :  usize  = BUF_LEN  *  size_of :: < T > ( ) ; 
3651- 
3652-         pub  fn  new ( )  -> Self  { 
3653-             PointerGenerator  { 
3654-                 buf :  MaybeUninit :: uninit ( ) 
3655-             } 
3656-         } 
3657- 
3658-         /// Create another ArbitraryPointer that may have the same precedence as the `other` pointer. 
3659- /// 
3660- /// I.e.: Non-deterministically derive a pointer from the given pointer or create a new 
3661- /// arbitrary pointer. 
3662- pub  fn  generate_ptr ( & mut  self )  -> ArbitraryPointer < T >  { 
3663-             // Create an arbitrary pointer, but leave `ptr` as unset for now. 
3664-             let  mut  arbitrary = ArbitraryPointer  { 
3665-                 ptr :  ptr:: null_mut :: < T > ( ) , 
3666-                 is_initialized :  false , 
3667-                 status :  kani:: any ( ) , 
3668-             } ; 
3669- 
3670-             let  buf_ptr = addr_of_mut ! ( self . buf)  as  * mut  T ; 
3671- 
3672-             // Offset is used to potentially generate unaligned pointer. 
3673-             let  offset = kani:: any_where ( |b :  & usize | * b < size_of :: < T > ( ) ) ; 
3674-             let  ptr = match  arbitrary. status  { 
3675-                 AllocationStatus :: Dangling  => { 
3676-                     crate :: ptr:: dangling_mut :: < T > ( ) . wrapping_add ( offset) 
3677-                 } 
3678-                 AllocationStatus :: DeadObj  => { 
3679-                     let  mut  obj:  T  = kani:: any ( ) ; 
3680-                     & mut  obj as  * mut  _ 
3681-                 } 
3682-                 AllocationStatus :: Null  => { 
3683-                     crate :: ptr:: null_mut :: < T > ( ) 
3684-                 } 
3685-                 AllocationStatus :: InBounds  => { 
3686-                     let  pos = kani:: any_where ( |i :  & usize | * i < ( BUF_LEN  - 1 ) ) ; 
3687-                     let  ptr:  * mut  T  = buf_ptr. wrapping_add ( pos) . wrapping_byte_add ( offset) ; 
3688-                     if  kani:: any ( )  { 
3689-                         arbitrary. is_initialized  = true ; 
3690-                         // This should be in bounds of arbitrary.alloc. 
3691-                         unsafe  {  ptr. write_unaligned ( kani:: any ( ) )  } ; 
3692-                     } 
3693-                     ptr
3694-                 } 
3695-                 AllocationStatus :: OutBounds  => { 
3696-                     if  kani:: any ( )  { 
3697-                         buf_ptr. wrapping_add ( BUF_LEN ) . wrapping_byte_sub ( offset) 
3698-                     }  else  { 
3699-                         buf_ptr. wrapping_add ( BUF_LEN ) . wrapping_byte_add ( offset) 
3700-                     } 
3701-                 } 
3702-             } ; 
3703- 
3704-             arbitrary
3705-         } 
3706-     } 
3707- 
3708- 
37093616    #[ kani:: proof_for_contract( copy) ]  
37103617    fn  check_copy ( )  { 
3711-         let  mut  generator = PointerGenerator :: < char ,  10 > :: new ( ) ; 
3712-         let  src = generator. generate_ptr ( ) ; 
3713-         let  dst = if  kani:: any ( )  { 
3714-             generator. generate_ptr ( ) 
3715-         }  else  { 
3716-             PointerGenerator :: < char ,  10 > :: new ( ) . generate_ptr ( ) 
3717-         } ; 
3718-         // Skip dangling for now since it makes Kani contract panic. 
3719-         kani:: assume ( src. status  != AllocationStatus :: Dangling ) ; 
3720-         kani:: assume ( dst. status  != AllocationStatus :: Dangling ) ; 
3721-         unsafe  {  copy ( src. ptr ,  dst. ptr ,  kani:: any ( ) )  } 
3618+         run_with_arbitrary_ptrs :: < char > ( |src,  dst| unsafe  {  copy ( src,  dst,  kani:: any ( ) )  } ) ; 
37223619    } 
37233620
37243621    #[ kani:: proof_for_contract( copy_nonoverlapping) ]  
37253622    fn  check_copy_nonoverlapping ( )  { 
3726-         let  mut  generator = PointerGenerator :: < char ,  10 > :: new ( ) ; 
3727-         let  src = generator. generate_ptr ( ) ; 
3728-         // Destination may or may not have the same provenance as src. 
3729-         let  dst = if  kani:: any ( )  { 
3730-             generator. generate_ptr ( ) 
3731-         }  else  { 
3732-             PointerGenerator :: < char ,  10 > :: new ( ) . generate_ptr ( ) 
3733-         } ; 
3734-         // Skip dangling for now since it makes Kani contract panic. 
3735-         kani:: assume ( src. status  != AllocationStatus :: Dangling ) ; 
3736-         kani:: assume ( dst. status  != AllocationStatus :: Dangling ) ; 
3737-         unsafe  {  copy_nonoverlapping ( src. ptr ,  dst. ptr ,  kani:: any ( ) )  } 
3623+         run_with_arbitrary_ptrs :: < char > ( |src,  dst| unsafe  { 
3624+             copy_nonoverlapping ( src,  dst,  kani:: any ( ) ) 
3625+         } ) ; 
37383626    } 
37393627
37403628    #[ kani:: proof_for_contract( write_bytes) ]  
37413629    fn  check_write_bytes ( )  { 
3742-         let  mut  generator = PointerGenerator :: < char ,  10 > :: new ( ) ; 
3743-         let  src = generator. generate_ptr ( ) ; 
3744-         kani:: assume ( src. status  != AllocationStatus :: Dangling ) ; 
3745-         // Skip dangling for now since it makes Kani contract panic. 
3746-         // Verify this case in a separate harness. 
3747-         unsafe  {  write_bytes ( src. ptr ,  kani:: any ( ) ,  kani:: any ( ) )  } 
3630+         let  mut  generator = PointerGenerator :: < 100 > :: new ( ) ; 
3631+         let  ArbitraryPointer  { 
3632+             ptr :  src, 
3633+             status :  src_status, 
3634+             ..
3635+         }  = generator. any_alloc_status :: < char > ( ) ; 
3636+         kani:: assume ( supported_status ( src_status) ) ; 
3637+         unsafe  {  write_bytes ( src,  kani:: any ( ) ,  kani:: any ( ) )  } ; 
3638+     } 
3639+ 
3640+     fn  run_with_arbitrary_ptrs < T :  Arbitrary > ( harness :  impl  Fn ( * mut  T ,  * mut  T ) )  { 
3641+         let  mut  generator1 = PointerGenerator :: < 100 > :: new ( ) ; 
3642+         let  mut  generator2 = PointerGenerator :: < 100 > :: new ( ) ; 
3643+         let  ArbitraryPointer  { 
3644+             ptr :  src, 
3645+             status :  src_status, 
3646+             ..
3647+         }  = generator1. any_alloc_status :: < T > ( ) ; 
3648+         let  ArbitraryPointer  { 
3649+             ptr :  dst, 
3650+             status :  dst_status, 
3651+             ..
3652+         }  = if  kani:: any ( )  { 
3653+             generator1. any_alloc_status :: < T > ( ) 
3654+         }  else  { 
3655+             generator2. any_alloc_status :: < T > ( ) 
3656+         } ; 
3657+         kani:: assume ( supported_status ( src_status) ) ; 
3658+         kani:: assume ( supported_status ( dst_status) ) ; 
3659+         harness ( src,  dst) ; 
3660+     } 
3661+ 
3662+     /// Return whether the current status is supported by Kani's contract. 
3663+ /// 
3664+ /// Kani memory predicates currently doesn't support pointers to dangling or dead allocations. 
3665+ /// Thus, we have to explicitly exclude those cases. 
3666+ fn  supported_status ( status :  AllocationStatus )  -> bool  { 
3667+         status != AllocationStatus :: Dangling  && status != AllocationStatus :: DeadObject 
37483668    } 
37493669} 
0 commit comments