@@ -227,6 +227,100 @@ use crate::cell::UnsafeCell;
227227use crate :: hint:: spin_loop;
228228use crate :: { fmt, intrinsics} ;
229229
230+ trait Sealed { }
231+
232+ /// A marker trait for primitive types which can be modified atomically.
233+ ///
234+ /// This is an implementation detail for <code>[Atomic]\<T></code> which may disappear or be replaced at any time.
235+ ///
236+ /// # Safety
237+ ///
238+ /// Types implementing this trait must be primitives that can be modified atomically.
239+ ///
240+ /// The associated `Self::AtomicInner` type must have the same size and bit validity as `Self`,
241+ /// but may have a higher alignment requirement, so the following `transmute`s are sound:
242+ ///
243+ /// - `&mut Self::AtomicInner` as `&mut Self`
244+ /// - `Self` as `Self::AtomicInner` or the reverse
245+ #[ unstable(
246+ feature = "atomic_internals" ,
247+ reason = "implementation detail which may disappear or be replaced at any time" ,
248+ issue = "none"
249+ ) ]
250+ #[ allow( private_bounds) ]
251+ pub unsafe trait AtomicPrimitive : Sized + Copy + Sealed {
252+ #[ doc( hidden) ]
253+ type AtomicInner : Sized ;
254+ }
255+
256+ macro impl_atomic_primitive (
257+ $Atom: ident $( <$T: ident>) ? ( $Primitive: ty) ,
258+ size ( $size: literal) ,
259+ align ( $align: literal) $( , ) ?
260+ ) {
261+ impl $( <$T>) ? Sealed for $Primitive { }
262+
263+ #[ unstable(
264+ feature = "atomic_internals" ,
265+ reason = "implementation detail which may disappear or be replaced at any time" ,
266+ issue = "none"
267+ ) ]
268+ #[ cfg( target_has_atomic_load_store = $size) ]
269+ unsafe impl $( <$T>) ? AtomicPrimitive for $Primitive {
270+ type AtomicInner = $Atom $( <$T>) ?;
271+ }
272+ }
273+
274+ impl_atomic_primitive ! ( AtomicBool ( bool ) , size( "8" ) , align( 1 ) ) ;
275+ impl_atomic_primitive ! ( AtomicI8 ( i8 ) , size( "8" ) , align( 1 ) ) ;
276+ impl_atomic_primitive ! ( AtomicU8 ( u8 ) , size( "8" ) , align( 1 ) ) ;
277+ impl_atomic_primitive ! ( AtomicI16 ( i16 ) , size( "16" ) , align( 2 ) ) ;
278+ impl_atomic_primitive ! ( AtomicU16 ( u16 ) , size( "16" ) , align( 2 ) ) ;
279+ impl_atomic_primitive ! ( AtomicI32 ( i32 ) , size( "32" ) , align( 4 ) ) ;
280+ impl_atomic_primitive ! ( AtomicU32 ( u32 ) , size( "32" ) , align( 4 ) ) ;
281+ impl_atomic_primitive ! ( AtomicI64 ( i64 ) , size( "64" ) , align( 8 ) ) ;
282+ impl_atomic_primitive ! ( AtomicU64 ( u64 ) , size( "64" ) , align( 8 ) ) ;
283+ impl_atomic_primitive ! ( AtomicI128 ( i128 ) , size( "128" ) , align( 16 ) ) ;
284+ impl_atomic_primitive ! ( AtomicU128 ( u128 ) , size( "128" ) , align( 16 ) ) ;
285+
286+ #[ cfg( target_pointer_width = "16" ) ]
287+ impl_atomic_primitive ! ( AtomicIsize ( isize ) , size( "ptr" ) , align( 2 ) ) ;
288+ #[ cfg( target_pointer_width = "32" ) ]
289+ impl_atomic_primitive ! ( AtomicIsize ( isize ) , size( "ptr" ) , align( 4 ) ) ;
290+ #[ cfg( target_pointer_width = "64" ) ]
291+ impl_atomic_primitive ! ( AtomicIsize ( isize ) , size( "ptr" ) , align( 8 ) ) ;
292+
293+ #[ cfg( target_pointer_width = "16" ) ]
294+ impl_atomic_primitive ! ( AtomicUsize ( usize ) , size( "ptr" ) , align( 2 ) ) ;
295+ #[ cfg( target_pointer_width = "32" ) ]
296+ impl_atomic_primitive ! ( AtomicUsize ( usize ) , size( "ptr" ) , align( 4 ) ) ;
297+ #[ cfg( target_pointer_width = "64" ) ]
298+ impl_atomic_primitive ! ( AtomicUsize ( usize ) , size( "ptr" ) , align( 8 ) ) ;
299+
300+ #[ cfg( target_pointer_width = "16" ) ]
301+ impl_atomic_primitive ! ( AtomicPtr <T >( * mut T ) , size( "ptr" ) , align( 2 ) ) ;
302+ #[ cfg( target_pointer_width = "32" ) ]
303+ impl_atomic_primitive ! ( AtomicPtr <T >( * mut T ) , size( "ptr" ) , align( 4 ) ) ;
304+ #[ cfg( target_pointer_width = "64" ) ]
305+ impl_atomic_primitive ! ( AtomicPtr <T >( * mut T ) , size( "ptr" ) , align( 8 ) ) ;
306+
307+ /// A memory location which can be safely modified from multiple threads.
308+ ///
309+ /// This has the same size and bit validity as the underlying type `T`. However,
310+ /// the alignment of this type is always equal to its size, even on targets where
311+ /// `T` has alignment less than its size.
312+ ///
313+ /// For more about the differences between atomic types and non-atomic types as
314+ /// well as information about the portability of this type, please see the
315+ /// [module-level documentation].
316+ ///
317+ /// **Note:** This type is only available on platforms that support atomic loads
318+ /// and stores of `T`.
319+ ///
320+ /// [module-level documentation]: crate::sync::atomic
321+ #[ unstable( feature = "generic_atomic" , issue = "130539" ) ]
322+ pub type Atomic < T > = <T as AtomicPrimitive >:: AtomicInner ;
323+
230324// Some architectures don't have byte-sized atomics, which results in LLVM
231325// emulating them using a LL/SC loop. However for AtomicBool we can take
232326// advantage of the fact that it only ever contains 0 or 1 and use atomic OR/AND
0 commit comments