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