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