@@ -292,6 +292,7 @@ pub mod layout;
292
292
pub mod macro_util;
293
293
#[ doc( hidden) ]
294
294
pub mod pointer;
295
+ #[ macro_use]
295
296
mod util;
296
297
// TODO(#252): If we make this pub, come up with a better name.
297
298
mod wrappers;
@@ -314,10 +315,7 @@ use core::{
314
315
ops:: { Deref , DerefMut } ,
315
316
ptr:: { self , NonNull } ,
316
317
slice,
317
- sync:: atomic:: {
318
- AtomicBool , AtomicI16 , AtomicI32 , AtomicI8 , AtomicIsize , AtomicPtr , AtomicU16 , AtomicU32 ,
319
- AtomicU8 , AtomicUsize ,
320
- } ,
318
+ sync:: atomic:: * ,
321
319
} ;
322
320
323
321
use crate :: pointer:: invariant;
@@ -665,9 +663,7 @@ impl_known_layout!(
665
663
u8 , i8 , u16 , i16 , u32 , i32 , u64 , i64 , u128 , i128 , usize , isize , f32 , f64 ,
666
664
bool , char ,
667
665
NonZeroU8 , NonZeroI8 , NonZeroU16 , NonZeroI16 , NonZeroU32 , NonZeroI32 ,
668
- NonZeroU64 , NonZeroI64 , NonZeroU128 , NonZeroI128 , NonZeroUsize , NonZeroIsize ,
669
- AtomicBool , AtomicI16 , AtomicI32 , AtomicI8 , AtomicIsize , AtomicU16 , AtomicU32 ,
670
- AtomicU8 , AtomicUsize
666
+ NonZeroU64 , NonZeroI64 , NonZeroU128 , NonZeroI128 , NonZeroUsize , NonZeroIsize
671
667
) ;
672
668
#[ rustfmt:: skip]
673
669
impl_known_layout ! (
@@ -676,8 +672,7 @@ impl_known_layout!(
676
672
T => Wrapping <T >,
677
673
T => MaybeUninit <T >,
678
674
T : ?Sized => * const T ,
679
- T : ?Sized => * mut T ,
680
- T => AtomicPtr <T >
675
+ T : ?Sized => * mut T
681
676
) ;
682
677
impl_known_layout ! ( const N : usize , T => [ T ; N ] ) ;
683
678
@@ -3797,46 +3792,95 @@ safety_comment! {
3797
3792
unsafe_impl_for_power_set!( A , B , C , D , E , F , G , H , I , J , K , L -> M => Immutable for opt_extern_c_fn!( ...) ) ;
3798
3793
}
3799
3794
3800
- macro_rules! impl_traits_for_atomics {
3801
- ( $( $atomics: ident [ $inners: ident] ) ,* $( , ) ?) => {
3802
- $(
3803
- impl_for_transparent_wrapper!( TryFromBytes for $atomics [ UnsafeCell <$inners>] ) ;
3804
- impl_for_transparent_wrapper!( FromZeros for $atomics [ UnsafeCell <$inners>] ) ;
3805
- impl_for_transparent_wrapper!( FromBytes for $atomics [ UnsafeCell <$inners>] ) ;
3806
- impl_for_transparent_wrapper!( IntoBytes for $atomics [ UnsafeCell <$inners>] ) ;
3807
- ) *
3808
- } ;
3795
+ /// Implements the zerocopy traits for atomic integer types.
3796
+ ///
3797
+ /// Note that we only implement traits for atomics types if the corresponding
3798
+ /// [`#[cfg(target_has_atomic)]`][target_has_atomic] configuration is true.
3799
+ ///
3800
+ /// Note: On targets like `thumbv6m-none-eabi` (which has an [`AtomicU32`]
3801
+ /// type but `#[cfg(target_has_atomic = "32")]` is false), we don't implement
3802
+ /// the zerocopy traits. We will be able to handle this when Rust stabilizes
3803
+ /// [`#[cfg(target_has_atomic_load_store)]`][target_has_atomic_load_store].
3804
+ ///
3805
+ /// [target_has_atomic]: https://doc.rust-lang.org/reference/conditional-compilation.html#target_has_atomic
3806
+ /// [target_has_atomic_load_store]: https://www.github.com/rust-lang/rust/issues/94039
3807
+ ///
3808
+ /// # Safety
3809
+ ///
3810
+ /// `$atomic` must be an atomic type with corresponding native type `$native`.
3811
+ macro_rules! unsafe_impl_traits_for_atomics {
3812
+ ( $( $atomic: ident [ $native: ident] ) ,* ) => { $(
3813
+ // SAFETY: `$atomic` is an atomic type with native type `$native`.
3814
+ unsafe impl util:: Atomic for $atomic { type Native = $native; }
3815
+
3816
+ impl_for_transparent_wrapper!( TryFromBytes for $atomic) ;
3817
+ impl_for_transparent_wrapper!( FromZeros for $atomic) ;
3818
+ unsafe_impl_traits_for_atomics!( @from_bytes $atomic) ;
3819
+ impl_for_transparent_wrapper!( IntoBytes for $atomic) ;
3820
+ impl_known_layout!( $atomic) ;
3821
+ ) * } ;
3822
+ ( @from_bytes AtomicBool ) => { } ;
3823
+ ( @from_bytes $atomic: ty) => { impl_for_transparent_wrapper!( FromBytes for $atomic) ; } ;
3809
3824
}
3810
3825
3811
- #[ rustfmt:: skip]
3812
- impl_traits_for_atomics ! (
3813
- AtomicBool [ bool ] ,
3814
- AtomicI16 [ i16 ] , AtomicI32 [ i32 ] , AtomicI8 [ i8 ] , AtomicIsize [ isize ] ,
3815
- AtomicU16 [ u16 ] , AtomicU32 [ u32 ] , AtomicU8 [ u8 ] , AtomicUsize [ usize ] ,
3816
- ) ;
3826
+ #[ cfg( zerocopy_atomics) ]
3827
+ #[ cfg( target_has_atomic = "8" ) ]
3828
+ #[ cfg_attr( doc_cfg, doc( cfg( target_has_atomic = "8" ) ) ) ]
3829
+ mod atomic_8 {
3830
+ use super :: * ;
3831
+ unsafe_impl_traits_for_atomics ! ( AtomicBool [ bool ] , AtomicU8 [ u8 ] , AtomicI8 [ i8 ] ) ;
3832
+ safety_comment ! {
3833
+ /// SAFETY:
3834
+ /// Per [1], `AtomicBool`, `AtomicU8`, and `AtomicI8` have an alignment of 1.
3835
+ ///
3836
+ /// [1] Per https://doc.rust-lang.org/nightly/core/sync/atomic/struct.AtomicBool.html:
3837
+ ///
3838
+ /// This type has the same size, alignment, and bit validity as [the native type].
3839
+ unsafe_impl!( AtomicBool : Unaligned ) ;
3840
+ unsafe_impl!( AtomicU8 : Unaligned ) ;
3841
+ unsafe_impl!( AtomicI8 : Unaligned ) ;
3842
+ }
3843
+ assert_unaligned ! ( AtomicBool , AtomicU8 , AtomicI8 ) ;
3844
+ }
3845
+ #[ cfg( zerocopy_atomics) ]
3846
+ #[ cfg( target_has_atomic = "16" ) ]
3847
+ #[ cfg_attr( doc_cfg, doc( cfg( target_has_atomic = "16" ) ) ) ]
3848
+ mod atomic_16 {
3849
+ use super :: * ;
3850
+ unsafe_impl_traits_for_atomics ! ( AtomicU16 [ u16 ] , AtomicI16 [ i16 ] ) ;
3851
+ }
3852
+ #[ cfg( zerocopy_atomics) ]
3853
+ #[ cfg( target_has_atomic = "32" ) ]
3854
+ #[ cfg_attr( doc_cfg, doc( cfg( target_has_atomic = "32" ) ) ) ]
3855
+ mod atomic_32 {
3856
+ use super :: * ;
3857
+ unsafe_impl_traits_for_atomics ! ( AtomicU32 [ u32 ] , AtomicI32 [ i32 ] ) ;
3858
+ }
3859
+ #[ cfg( zerocopy_atomics) ]
3860
+ #[ cfg( target_has_atomic = "64" ) ]
3861
+ #[ cfg_attr( doc_cfg, doc( cfg( target_has_atomic = "64" ) ) ) ]
3862
+ mod atomic_64 {
3863
+ use super :: * ;
3864
+ unsafe_impl_traits_for_atomics ! ( AtomicU64 [ u64 ] , AtomicI64 [ i64 ] ) ;
3865
+ }
3866
+ #[ cfg( zerocopy_atomics) ]
3867
+ #[ cfg( target_has_atomic = "ptr" ) ]
3868
+ #[ cfg_attr( doc_cfg, doc( cfg( target_has_atomic = "ptr" ) ) ) ]
3869
+ mod atomic_ptr {
3870
+ use super :: * ;
3871
+ unsafe_impl_traits_for_atomics ! ( AtomicUsize [ usize ] , AtomicIsize [ isize ] ) ;
3817
3872
3818
- safety_comment ! {
3819
3873
/// SAFETY:
3820
- /// Per [1], `AtomicBool`, `AtomicU8`, and `AtomicI8` have the same size as
3821
- /// `bool`, `u8`, and `i8` respectively. Since a type's alignment cannot be
3822
- /// smaller than 1 [2], and since its alignment cannot be greater than its
3823
- /// size [3], the only possible value for the alignment is 1. Thus, it is
3824
- /// sound to implement `Unaligned`.
3874
+ /// `AtomicPtr<T>`` is garunteed to wrap a `*mut T`. Just like *mut T, we
3875
+ /// don't implement FromBytes/IntoBytes.
3825
3876
///
3826
- /// [1] TODO(#896), TODO(https://github.com/rust-lang/rust/pull/121943):
3827
- /// Cite docs once they've landed.
3828
- ///
3829
- /// [2] Per https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment:
3830
- ///
3831
- /// Alignment is measured in bytes, and must be at least 1.
3832
- ///
3833
- /// [3] Per https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment:
3834
- ///
3835
- /// The size of a value is always a multiple of its alignment.
3836
- unsafe_impl!( AtomicBool : Unaligned ) ;
3837
- unsafe_impl!( AtomicU8 : Unaligned ) ;
3838
- unsafe_impl!( AtomicI8 : Unaligned ) ;
3839
- assert_unaligned!( AtomicBool , AtomicU8 , AtomicI8 ) ;
3877
+ /// See the comments on the `*mut T` impls for more information.
3878
+ unsafe impl < T > util:: Atomic for AtomicPtr < T > {
3879
+ type Native = * mut T ;
3880
+ }
3881
+ impl_for_transparent_wrapper ! ( T => TryFromBytes for AtomicPtr <T >) ;
3882
+ impl_for_transparent_wrapper ! ( T => FromZeros for AtomicPtr <T >) ;
3883
+ impl_known_layout ! ( T => AtomicPtr <T >) ;
3840
3884
}
3841
3885
3842
3886
safety_comment ! {
0 commit comments