@@ -246,7 +246,9 @@ use self::Ordering::*;
246246use crate :: cell:: UnsafeCell ;
247247use crate :: hint:: spin_loop;
248248use crate :: intrinsics:: AtomicOrdering as AO ;
249- use crate :: { fmt, intrinsics} ;
249+ use crate :: { fmt, intrinsics, ub_checks} ;
250+ #[ cfg( kani) ]
251+ use crate :: kani;
250252
251253trait Sealed { }
252254
@@ -571,6 +573,7 @@ impl AtomicBool {
571573 #[ inline]
572574 #[ stable( feature = "atomic_from_ptr" , since = "1.75.0" ) ]
573575 #[ rustc_const_stable( feature = "const_atomic_from_ptr" , since = "1.84.0" ) ]
576+ #[ safety:: requires( ub_checks:: can_dereference( ptr as * const AtomicBool ) ) ]
574577 pub const unsafe fn from_ptr < ' a > ( ptr : * mut bool ) -> & ' a AtomicBool {
575578 // SAFETY: guaranteed by the caller
576579 unsafe { & * ptr. cast ( ) }
@@ -1529,6 +1532,7 @@ impl<T> AtomicPtr<T> {
15291532 #[ inline]
15301533 #[ stable( feature = "atomic_from_ptr" , since = "1.75.0" ) ]
15311534 #[ rustc_const_stable( feature = "const_atomic_from_ptr" , since = "1.84.0" ) ]
1535+ #[ safety:: requires( ub_checks:: can_dereference( ptr as * const AtomicPtr <T >) ) ]
15321536 pub const unsafe fn from_ptr < ' a > ( ptr : * mut * mut T ) -> & ' a AtomicPtr < T > {
15331537 // SAFETY: guaranteed by the caller
15341538 unsafe { & * ptr. cast ( ) }
@@ -2705,6 +2709,7 @@ macro_rules! atomic_int {
27052709 #[ inline]
27062710 #[ stable( feature = "atomic_from_ptr" , since = "1.75.0" ) ]
27072711 #[ rustc_const_stable( feature = "const_atomic_from_ptr" , since = "1.84.0" ) ]
2712+ #[ safety:: requires( ub_checks:: can_dereference( ptr as * const $atomic_type) ) ]
27082713 pub const unsafe fn from_ptr<' a>( ptr: * mut $int_type) -> & ' a $atomic_type {
27092714 // SAFETY: guaranteed by the caller
27102715 unsafe { & * ptr. cast( ) }
@@ -3928,6 +3933,7 @@ fn strongest_failure_ordering(order: Ordering) -> Ordering {
39283933
39293934#[ inline]
39303935#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
3936+ #[ safety:: requires( ub_checks:: can_write( dst) ) ]
39313937unsafe fn atomic_store < T : Copy > ( dst : * mut T , val : T , order : Ordering ) {
39323938 // SAFETY: the caller must uphold the safety contract for `atomic_store`.
39333939 unsafe {
@@ -3943,6 +3949,7 @@ unsafe fn atomic_store<T: Copy>(dst: *mut T, val: T, order: Ordering) {
39433949
39443950#[ inline]
39453951#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
3952+ #[ safety:: requires( ub_checks:: can_dereference( dst) ) ]
39463953unsafe fn atomic_load < T : Copy > ( dst : * const T , order : Ordering ) -> T {
39473954 // SAFETY: the caller must uphold the safety contract for `atomic_load`.
39483955 unsafe {
@@ -3959,6 +3966,7 @@ unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
39593966#[ inline]
39603967#[ cfg( target_has_atomic) ]
39613968#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
3969+ #[ safety:: requires( ub_checks:: can_write( dst) && ub_checks:: can_dereference( dst as * const T ) ) ]
39623970unsafe fn atomic_swap < T : Copy > ( dst : * mut T , val : T , order : Ordering ) -> T {
39633971 // SAFETY: the caller must uphold the safety contract for `atomic_swap`.
39643972 unsafe {
@@ -3976,6 +3984,7 @@ unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
39763984#[ inline]
39773985#[ cfg( target_has_atomic) ]
39783986#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
3987+ #[ safety:: requires( ub_checks:: can_write( dst) && ub_checks:: can_dereference( dst as * const T ) ) ]
39793988unsafe fn atomic_add < T : Copy , U : Copy > ( dst : * mut T , val : U , order : Ordering ) -> T {
39803989 // SAFETY: the caller must uphold the safety contract for `atomic_add`.
39813990 unsafe {
@@ -3993,6 +4002,7 @@ unsafe fn atomic_add<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) ->
39934002#[ inline]
39944003#[ cfg( target_has_atomic) ]
39954004#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
4005+ #[ safety:: requires( ub_checks:: can_write( dst) && ub_checks:: can_dereference( dst as * const T ) ) ]
39964006unsafe fn atomic_sub < T : Copy , U : Copy > ( dst : * mut T , val : U , order : Ordering ) -> T {
39974007 // SAFETY: the caller must uphold the safety contract for `atomic_sub`.
39984008 unsafe {
@@ -4012,6 +4022,7 @@ unsafe fn atomic_sub<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) ->
40124022#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
40134023#[ unstable( feature = "core_intrinsics" , issue = "none" ) ]
40144024#[ doc( hidden) ]
4025+ #[ safety:: requires( ub_checks:: can_write( dst) && ub_checks:: can_dereference( dst as * const T ) ) ]
40154026pub unsafe fn atomic_compare_exchange < T : Copy > (
40164027 dst : * mut T ,
40174028 old : T ,
@@ -4077,6 +4088,7 @@ pub unsafe fn atomic_compare_exchange<T: Copy>(
40774088#[ inline]
40784089#[ cfg( target_has_atomic) ]
40794090#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
4091+ #[ safety:: requires( ub_checks:: can_write( dst) && ub_checks:: can_dereference( dst as * const T ) ) ]
40804092unsafe fn atomic_compare_exchange_weak < T : Copy > (
40814093 dst : * mut T ,
40824094 old : T ,
@@ -4142,6 +4154,7 @@ unsafe fn atomic_compare_exchange_weak<T: Copy>(
41424154#[ inline]
41434155#[ cfg( target_has_atomic) ]
41444156#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
4157+ #[ safety:: requires( ub_checks:: can_write( dst) && ub_checks:: can_dereference( dst as * const T ) ) ]
41454158unsafe fn atomic_and < T : Copy , U : Copy > ( dst : * mut T , val : U , order : Ordering ) -> T {
41464159 // SAFETY: the caller must uphold the safety contract for `atomic_and`
41474160 unsafe {
@@ -4158,6 +4171,7 @@ unsafe fn atomic_and<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) ->
41584171#[ inline]
41594172#[ cfg( target_has_atomic) ]
41604173#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
4174+ #[ safety:: requires( ub_checks:: can_write( dst) && ub_checks:: can_dereference( dst as * const T ) ) ]
41614175unsafe fn atomic_nand < T : Copy , U : Copy > ( dst : * mut T , val : U , order : Ordering ) -> T {
41624176 // SAFETY: the caller must uphold the safety contract for `atomic_nand`
41634177 unsafe {
@@ -4174,6 +4188,7 @@ unsafe fn atomic_nand<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) ->
41744188#[ inline]
41754189#[ cfg( target_has_atomic) ]
41764190#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
4191+ #[ safety:: requires( ub_checks:: can_write( dst) && ub_checks:: can_dereference( dst as * const T ) ) ]
41774192unsafe fn atomic_or < T : Copy , U : Copy > ( dst : * mut T , val : U , order : Ordering ) -> T {
41784193 // SAFETY: the caller must uphold the safety contract for `atomic_or`
41794194 unsafe {
@@ -4190,6 +4205,7 @@ unsafe fn atomic_or<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T
41904205#[ inline]
41914206#[ cfg( target_has_atomic) ]
41924207#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
4208+ #[ safety:: requires( ub_checks:: can_write( dst) && ub_checks:: can_dereference( dst as * const T ) ) ]
41934209unsafe fn atomic_xor < T : Copy , U : Copy > ( dst : * mut T , val : U , order : Ordering ) -> T {
41944210 // SAFETY: the caller must uphold the safety contract for `atomic_xor`
41954211 unsafe {
@@ -4207,6 +4223,7 @@ unsafe fn atomic_xor<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) ->
42074223#[ inline]
42084224#[ cfg( target_has_atomic) ]
42094225#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
4226+ #[ safety:: requires( ub_checks:: can_write( dst) && ub_checks:: can_dereference( dst as * const T ) ) ]
42104227unsafe fn atomic_max < T : Copy > ( dst : * mut T , val : T , order : Ordering ) -> T {
42114228 // SAFETY: the caller must uphold the safety contract for `atomic_max`
42124229 unsafe {
@@ -4224,6 +4241,7 @@ unsafe fn atomic_max<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
42244241#[ inline]
42254242#[ cfg( target_has_atomic) ]
42264243#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
4244+ #[ safety:: requires( ub_checks:: can_write( dst) && ub_checks:: can_dereference( dst as * const T ) ) ]
42274245unsafe fn atomic_min < T : Copy > ( dst : * mut T , val : T , order : Ordering ) -> T {
42284246 // SAFETY: the caller must uphold the safety contract for `atomic_min`
42294247 unsafe {
@@ -4241,6 +4259,7 @@ unsafe fn atomic_min<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
42414259#[ inline]
42424260#[ cfg( target_has_atomic) ]
42434261#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
4262+ #[ safety:: requires( ub_checks:: can_write( dst) && ub_checks:: can_dereference( dst as * const T ) ) ]
42444263unsafe fn atomic_umax < T : Copy > ( dst : * mut T , val : T , order : Ordering ) -> T {
42454264 // SAFETY: the caller must uphold the safety contract for `atomic_umax`
42464265 unsafe {
@@ -4258,6 +4277,7 @@ unsafe fn atomic_umax<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
42584277#[ inline]
42594278#[ cfg( target_has_atomic) ]
42604279#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
4280+ #[ safety:: requires( ub_checks:: can_write( dst) && ub_checks:: can_dereference( dst as * const T ) ) ]
42614281unsafe fn atomic_umin < T : Copy > ( dst : * mut T , val : T , order : Ordering ) -> T {
42624282 // SAFETY: the caller must uphold the safety contract for `atomic_umin`
42634283 unsafe {
@@ -4559,11 +4579,150 @@ mod verify {
45594579 let _ = atomic. load ( Ordering :: Relaxed ) ;
45604580 }
45614581
4582+ // --- AtomicPtr: multiple T sizes per spec ---
4583+
45624584 #[ kani:: proof]
4563- fn verify_atomic_ptr_from_ptr ( ) {
4585+ fn verify_atomic_ptr_from_ptr_size0 ( ) {
4586+ let mut val: * mut ( ) = core:: ptr:: null_mut ( ) ;
4587+ let ptr = & mut val as * mut * mut ( ) ;
4588+ let atomic = unsafe { AtomicPtr :: from_ptr ( ptr) } ;
4589+ let _ = atomic. load ( Ordering :: Relaxed ) ;
4590+ }
4591+
4592+ #[ kani:: proof]
4593+ fn verify_atomic_ptr_from_ptr_size1 ( ) {
45644594 let mut val: * mut u8 = core:: ptr:: null_mut ( ) ;
45654595 let ptr = & mut val as * mut * mut u8 ;
45664596 let atomic = unsafe { AtomicPtr :: from_ptr ( ptr) } ;
45674597 let _ = atomic. load ( Ordering :: Relaxed ) ;
45684598 }
4599+
4600+ #[ kani:: proof]
4601+ fn verify_atomic_ptr_from_ptr_size2 ( ) {
4602+ let mut val: * mut u16 = core:: ptr:: null_mut ( ) ;
4603+ let ptr = & mut val as * mut * mut u16 ;
4604+ let atomic = unsafe { AtomicPtr :: from_ptr ( ptr) } ;
4605+ let _ = atomic. load ( Ordering :: Relaxed ) ;
4606+ }
4607+
4608+ #[ kani:: proof]
4609+ fn verify_atomic_ptr_from_ptr_size4 ( ) {
4610+ let mut val: * mut u32 = core:: ptr:: null_mut ( ) ;
4611+ let ptr = & mut val as * mut * mut u32 ;
4612+ let atomic = unsafe { AtomicPtr :: from_ptr ( ptr) } ;
4613+ let _ = atomic. load ( Ordering :: Relaxed ) ;
4614+ }
4615+
4616+ #[ kani:: proof]
4617+ fn verify_atomic_ptr_from_ptr_size3 ( ) {
4618+ let mut val: * mut [ u8 ; 3 ] = core:: ptr:: null_mut ( ) ;
4619+ let ptr = & mut val as * mut * mut [ u8 ; 3 ] ;
4620+ let atomic = unsafe { AtomicPtr :: from_ptr ( ptr) } ;
4621+ let _ = atomic. load ( Ordering :: Relaxed ) ;
4622+ }
4623+
4624+ // --- Part 2: Verify atomic helper functions ---
4625+
4626+ #[ kani:: proof]
4627+ fn verify_atomic_store ( ) {
4628+ let mut val: i32 = kani:: any ( ) ;
4629+ let new_val: i32 = kani:: any ( ) ;
4630+ unsafe { atomic_store ( & mut val as * mut i32 , new_val, Ordering :: SeqCst ) } ;
4631+ assert ! ( val == new_val) ;
4632+ }
4633+
4634+ #[ kani:: proof]
4635+ fn verify_atomic_load ( ) {
4636+ let val: i32 = kani:: any ( ) ;
4637+ let loaded = unsafe { atomic_load ( & val as * const i32 , Ordering :: SeqCst ) } ;
4638+ assert ! ( loaded == val) ;
4639+ }
4640+
4641+ #[ kani:: proof]
4642+ fn verify_atomic_swap ( ) {
4643+ let mut val: i32 = kani:: any ( ) ;
4644+ let new_val: i32 = kani:: any ( ) ;
4645+ let old = unsafe { atomic_swap ( & mut val as * mut i32 , new_val, Ordering :: SeqCst ) } ;
4646+ let _ = old;
4647+ }
4648+
4649+ #[ kani:: proof]
4650+ fn verify_atomic_add ( ) {
4651+ let mut val: i32 = 10 ;
4652+ let old = unsafe { atomic_add ( & mut val as * mut i32 , 5i32 , Ordering :: SeqCst ) } ;
4653+ assert ! ( old == 10 ) ;
4654+ }
4655+
4656+ #[ kani:: proof]
4657+ fn verify_atomic_sub ( ) {
4658+ let mut val: i32 = 10 ;
4659+ let old = unsafe { atomic_sub ( & mut val as * mut i32 , 3i32 , Ordering :: SeqCst ) } ;
4660+ assert ! ( old == 10 ) ;
4661+ }
4662+
4663+ #[ kani:: proof]
4664+ fn verify_atomic_compare_exchange ( ) {
4665+ let mut val: i32 = 10 ;
4666+ let result = unsafe {
4667+ atomic_compare_exchange ( & mut val as * mut i32 , 10 , 20 , Ordering :: SeqCst , Ordering :: SeqCst )
4668+ } ;
4669+ assert ! ( result == Ok ( 10 ) ) ;
4670+ }
4671+
4672+ #[ kani:: proof]
4673+ fn verify_atomic_compare_exchange_weak ( ) {
4674+ let mut val: i32 = 10 ;
4675+ let _ = unsafe {
4676+ atomic_compare_exchange_weak ( & mut val as * mut i32 , 10 , 20 , Ordering :: SeqCst , Ordering :: SeqCst )
4677+ } ;
4678+ }
4679+
4680+ #[ kani:: proof]
4681+ fn verify_atomic_and ( ) {
4682+ let mut val: i32 = 0b1111 ;
4683+ let old = unsafe { atomic_and ( & mut val as * mut i32 , 0b1010i32 , Ordering :: SeqCst ) } ;
4684+ assert ! ( old == 0b1111 ) ;
4685+ }
4686+
4687+ #[ kani:: proof]
4688+ fn verify_atomic_nand ( ) {
4689+ let mut val: i32 = 0b1111 ;
4690+ let old = unsafe { atomic_nand ( & mut val as * mut i32 , 0b1010i32 , Ordering :: SeqCst ) } ;
4691+ assert ! ( old == 0b1111 ) ;
4692+ }
4693+
4694+ #[ kani:: proof]
4695+ fn verify_atomic_or ( ) {
4696+ let mut val: i32 = 0b1010 ;
4697+ let old = unsafe { atomic_or ( & mut val as * mut i32 , 0b0101i32 , Ordering :: SeqCst ) } ;
4698+ assert ! ( old == 0b1010 ) ;
4699+ }
4700+
4701+ #[ kani:: proof]
4702+ fn verify_atomic_xor ( ) {
4703+ let mut val: i32 = 0b1111 ;
4704+ let old = unsafe { atomic_xor ( & mut val as * mut i32 , 0b1010i32 , Ordering :: SeqCst ) } ;
4705+ assert ! ( old == 0b1111 ) ;
4706+ }
4707+
4708+ #[ kani:: proof]
4709+ fn verify_atomic_max ( ) {
4710+ let mut val: i32 = 10 ;
4711+ let old = unsafe { atomic_max ( & mut val as * mut i32 , 20 , Ordering :: SeqCst ) } ;
4712+ assert ! ( old == 10 ) ;
4713+ }
4714+
4715+ #[ kani:: proof]
4716+ fn verify_atomic_umax ( ) {
4717+ let mut val: u32 = 10 ;
4718+ let old = unsafe { atomic_umax ( & mut val as * mut u32 , 20 , Ordering :: SeqCst ) } ;
4719+ assert ! ( old == 10 ) ;
4720+ }
4721+
4722+ #[ kani:: proof]
4723+ fn verify_atomic_umin ( ) {
4724+ let mut val: u32 = 20 ;
4725+ let old = unsafe { atomic_umin ( & mut val as * mut u32 , 10 , Ordering :: SeqCst ) } ;
4726+ assert ! ( old == 20 ) ;
4727+ }
45694728}
0 commit comments