From 0320eeea4c20eb3b6e858da3ba7e6c986af33a17 Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 4 Mar 2026 16:16:09 +0100 Subject: [PATCH 1/2] core: make some fundamental atomic functions generic --- library/core/src/sync/atomic.rs | 639 ++++++++------------------------ 1 file changed, 161 insertions(+), 478 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 18b05c36fd441..05db1105443ae 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -246,8 +246,7 @@ use self::Ordering::*; use crate::cell::UnsafeCell; use crate::hint::spin_loop; -use crate::intrinsics::AtomicOrdering as AO; -use crate::mem::transmute; +use crate::intrinsics::{AtomicOrdering as AO, transmute_unchecked}; use crate::{fmt, intrinsics}; #[unstable( @@ -372,6 +371,166 @@ unsafe impl Send for Atomic {} #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Sync for Atomic {} +impl Atomic { + /// Creates a new `Atomic`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicBool, AtomicI32, AtomicPtr}; + /// + /// let atomic_bool = AtomicBool::new(true); + /// + /// let atomic_i32 = AtomicI32::new(42); + /// + /// let ptr = &mut 42; + /// let atomic_ptr = AtomicPtr::new(ptr); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_atomic_new", since = "1.24.0")] + #[must_use] + pub const fn new(v: T) -> Atomic { + // SAFETY: + // `Atomic` is essentially a transparent wrapper around `T`. + unsafe { transmute_unchecked(v) } + } + + /// Creates a new `Atomic` from a pointer. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::{AtomicI32, Ordering}; + /// + /// // Get a pointer to an allocated value + /// let ptr: *mut i32 = Box::into_raw(Box::new(42)); + /// + /// assert!(ptr.cast::().is_aligned()); + /// + /// { + /// // Create an atomic view of the allocated value + /// let atomic = unsafe { AtomicI32::from_ptr(ptr) }; + /// + /// // Use `atomic` for atomic operations, possibly share it with other threads + /// atomic.store(0, Ordering::Relaxed); + /// } + /// + /// // It's ok to non-atomically access the value behind `ptr`, + /// // since the reference to the atomic ended its lifetime in the block above + /// assert_eq!(unsafe { *ptr }, 0); + /// + /// // Deallocate the value + /// unsafe { drop(Box::from_raw(ptr)) } + /// ``` + /// + /// # Safety + /// + /// * `ptr` must be aligned to `align_of::>()` + /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. + /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not + /// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different + /// sizes, without synchronization. + /// + /// [valid]: crate::ptr#safety + /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses + #[inline] + #[stable(feature = "atomic_from_ptr", since = "1.75.0")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")] + pub const unsafe fn from_ptr<'a>(ptr: *mut T) -> &'a Atomic { + // SAFETY: guaranteed by the caller + unsafe { &*ptr.cast() } + } + + /// Returns a mutable pointer to the underlying value. + /// + /// Doing non-atomic reads and writes on the resulting boolean can be a data race. + /// This method is mostly useful for FFI, where the function signature may use + /// `*mut T` instead of `&Atomic`. + /// + /// Returning an `*mut` pointer from a shared reference to this atomic is safe because `Atomic` + /// works with interior mutability. All modifications of an atomic change the value + /// through a shared reference, and can do so safely as long as they use atomic operations. Any + /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the + /// requirements of the [memory model]. + /// + /// # Examples + /// + /// ```ignore (extern-declaration) + /// # fn main() { + /// use std::sync::atomic::AtomicU32; + /// + /// extern "C" { + /// fn my_atomic_op(arg: *mut u32); + /// } + /// + /// let mut atomic = AtomicU32::new(42); + /// unsafe { + /// my_atomic_op(atomic.as_ptr()); + /// } + /// # } + /// ``` + /// + /// [memory model]: self#memory-model-for-atomic-accesses + #[inline] + #[stable(feature = "atomic_as_ptr", since = "1.70.0")] + #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] + #[rustc_never_returns_null_ptr] + #[rustc_should_not_be_called_on_const_items] + pub const fn as_ptr(&self) -> *mut T { + self.v.get().cast() + } + + /// Consumes the atomic and returns the contained value. + /// + /// This is safe because passing `self` by value guarantees that no other threads are + /// concurrently accessing the atomic data. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::AtomicI32; + /// + /// let atomic = AtomicI32::new(42); + /// assert_eq!(atomic.into_inner(), 42); + /// ``` + #[inline] + #[stable(feature = "atomic_access", since = "1.15.0")] + #[rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0")] + pub const fn into_inner(self) -> T { + // SAFETY: + // * `Atomic` is essentially a transparent wrapper around `T`. + unsafe { transmute_unchecked(self) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Atomic { + /// Creates an `Atomic` wrapping the default value of `T`. + #[inline] + fn default() -> Self { + Self::new(T::default()) + } +} + +#[stable(feature = "atomic_from", since = "1.23.0")] +#[rustc_const_unstable(feature = "const_convert", issue = "143773")] +impl const From for Atomic { + /// Converts a `T` into an `Atomic`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::atomic::AtomicI32; + /// let atomic = AtomicI32::from(42); + /// assert_eq!(format!("{atomic:?}"), "42") + /// ``` + #[inline] + fn from(v: T) -> Self { + Self::new(v) + } +} + // Some architectures don't have byte-sized atomics, which results in LLVM // emulating them using a LL/SC loop. However for AtomicBool we can take // advantage of the fact that it only ever contains 0 or 1 and use atomic OR/AND @@ -397,16 +556,6 @@ const EMULATE_ATOMIC_BOOL: bool = cfg!(any( #[stable(feature = "rust1", since = "1.0.0")] pub type AtomicBool = Atomic; -#[cfg(target_has_atomic_load_store = "8")] -#[stable(feature = "rust1", since = "1.0.0")] -impl Default for AtomicBool { - /// Creates an `AtomicBool` initialized to `false`. - #[inline] - fn default() -> Self { - Self::new(false) - } -} - /// A raw pointer type which can be safely shared between threads. /// /// This type has the same size and bit validity as a `*mut T`. @@ -417,15 +566,6 @@ impl Default for AtomicBool { #[stable(feature = "rust1", since = "1.0.0")] pub type AtomicPtr = Atomic<*mut T>; -#[cfg(target_has_atomic_load_store = "ptr")] -#[stable(feature = "rust1", since = "1.0.0")] -impl Default for AtomicPtr { - /// Creates a null `AtomicPtr`. - fn default() -> AtomicPtr { - AtomicPtr::new(crate::ptr::null_mut()) - } -} - /// Atomic memory orderings /// /// Memory orderings specify the way atomic operations synchronize memory. @@ -519,73 +659,6 @@ pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false); #[cfg(target_has_atomic_load_store = "8")] impl AtomicBool { - /// Creates a new `AtomicBool`. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::AtomicBool; - /// - /// let atomic_true = AtomicBool::new(true); - /// let atomic_false = AtomicBool::new(false); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_atomic_new", since = "1.24.0")] - #[must_use] - pub const fn new(v: bool) -> AtomicBool { - // SAFETY: - // `Atomic` is essentially a transparent wrapper around `T`. - unsafe { transmute(v) } - } - - /// Creates a new `AtomicBool` from a pointer. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{self, AtomicBool}; - /// - /// // Get a pointer to an allocated value - /// let ptr: *mut bool = Box::into_raw(Box::new(false)); - /// - /// assert!(ptr.cast::().is_aligned()); - /// - /// { - /// // Create an atomic view of the allocated value - /// let atomic = unsafe { AtomicBool::from_ptr(ptr) }; - /// - /// // Use `atomic` for atomic operations, possibly share it with other threads - /// atomic.store(true, atomic::Ordering::Relaxed); - /// } - /// - /// // It's ok to non-atomically access the value behind `ptr`, - /// // since the reference to the atomic ended its lifetime in the block above - /// assert_eq!(unsafe { *ptr }, true); - /// - /// // Deallocate the value - /// unsafe { drop(Box::from_raw(ptr)) } - /// ``` - /// - /// # Safety - /// - /// * `ptr` must be aligned to `align_of::()` (note that this is always true, since - /// `align_of::() == 1`). - /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. - /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not - /// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different - /// sizes, without synchronization. - /// - /// [valid]: crate::ptr#safety - /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses - #[inline] - #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")] - pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool { - // SAFETY: guaranteed by the caller - unsafe { &*ptr.cast() } - } - /// Returns a mutable reference to the underlying [`bool`]. /// /// This is safe because the mutable reference guarantees that no other threads are @@ -690,30 +763,6 @@ impl AtomicBool { unsafe { &mut *(v as *mut [bool] as *mut [Self]) } } - /// Consumes the atomic and returns the contained value. - /// - /// This is safe because passing `self` by value guarantees that no other threads are - /// concurrently accessing the atomic data. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::AtomicBool; - /// - /// let some_bool = AtomicBool::new(true); - /// assert_eq!(some_bool.into_inner(), true); - /// ``` - #[inline] - #[stable(feature = "atomic_access", since = "1.15.0")] - #[rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0")] - pub const fn into_inner(self) -> bool { - // SAFETY: - // * `Atomic` is essentially a transparent wrapper around `T`. - // * all operations on `Atomic` ensure that `T::Storage` remains - // a valid `bool`. - unsafe { transmute(self) } - } - /// Loads a value from the bool. /// /// `load` takes an [`Ordering`] argument which describes the memory ordering @@ -1272,45 +1321,6 @@ impl AtomicBool { self.fetch_xor(true, order) } - /// Returns a mutable pointer to the underlying [`bool`]. - /// - /// Doing non-atomic reads and writes on the resulting boolean can be a data race. - /// This method is mostly useful for FFI, where the function signature may use - /// `*mut bool` instead of `&AtomicBool`. - /// - /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the - /// atomic types work with interior mutability. All modifications of an atomic change the value - /// through a shared reference, and can do so safely as long as they use atomic operations. Any - /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the - /// requirements of the [memory model]. - /// - /// # Examples - /// - /// ```ignore (extern-declaration) - /// # fn main() { - /// use std::sync::atomic::AtomicBool; - /// - /// extern "C" { - /// fn my_atomic_op(arg: *mut bool); - /// } - /// - /// let mut atomic = AtomicBool::new(true); - /// unsafe { - /// my_atomic_op(atomic.as_ptr()); - /// } - /// # } - /// ``` - /// - /// [memory model]: self#memory-model-for-atomic-accesses - #[inline] - #[stable(feature = "atomic_as_ptr", since = "1.70.0")] - #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] - #[rustc_never_returns_null_ptr] - #[rustc_should_not_be_called_on_const_items] - pub const fn as_ptr(&self) -> *mut bool { - self.v.get().cast() - } - /// An alias for [`AtomicBool::try_update`]. #[inline] #[stable(feature = "atomic_fetch_update", since = "1.53.0")] @@ -1467,72 +1477,6 @@ impl AtomicBool { #[cfg(target_has_atomic_load_store = "ptr")] impl AtomicPtr { - /// Creates a new `AtomicPtr`. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::AtomicPtr; - /// - /// let ptr = &mut 5; - /// let atomic_ptr = AtomicPtr::new(ptr); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_atomic_new", since = "1.24.0")] - pub const fn new(p: *mut T) -> AtomicPtr { - // SAFETY: - // `Atomic` is essentially a transparent wrapper around `T`. - unsafe { transmute(p) } - } - - /// Creates a new `AtomicPtr` from a pointer. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::{self, AtomicPtr}; - /// - /// // Get a pointer to an allocated value - /// let ptr: *mut *mut u8 = Box::into_raw(Box::new(std::ptr::null_mut())); - /// - /// assert!(ptr.cast::>().is_aligned()); - /// - /// { - /// // Create an atomic view of the allocated value - /// let atomic = unsafe { AtomicPtr::from_ptr(ptr) }; - /// - /// // Use `atomic` for atomic operations, possibly share it with other threads - /// atomic.store(std::ptr::NonNull::dangling().as_ptr(), atomic::Ordering::Relaxed); - /// } - /// - /// // It's ok to non-atomically access the value behind `ptr`, - /// // since the reference to the atomic ended its lifetime in the block above - /// assert!(!unsafe { *ptr }.is_null()); - /// - /// // Deallocate the value - /// unsafe { drop(Box::from_raw(ptr)) } - /// ``` - /// - /// # Safety - /// - /// * `ptr` must be aligned to `align_of::>()` (note that on some platforms this - /// can be bigger than `align_of::<*mut T>()`). - /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. - /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not - /// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different - /// sizes, without synchronization. - /// - /// [valid]: crate::ptr#safety - /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses - #[inline] - #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")] - pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr { - // SAFETY: guaranteed by the caller - unsafe { &*ptr.cast() } - } - /// Creates a new `AtomicPtr` initialized with a null pointer. /// /// # Examples @@ -1682,29 +1626,6 @@ impl AtomicPtr { unsafe { &mut *(v as *mut [*mut T] as *mut [Self]) } } - /// Consumes the atomic and returns the contained value. - /// - /// This is safe because passing `self` by value guarantees that no other threads are - /// concurrently accessing the atomic data. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::AtomicPtr; - /// - /// let mut data = 5; - /// let atomic_ptr = AtomicPtr::new(&mut data); - /// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5); - /// ``` - #[inline] - #[stable(feature = "atomic_access", since = "1.15.0")] - #[rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0")] - pub const fn into_inner(self) -> *mut T { - // SAFETY: - // `Atomic` is essentially a transparent wrapper around `T`. - unsafe { transmute(self) } - } - /// Loads a value from the pointer. /// /// `load` takes an [`Ordering`] argument which describes the memory ordering @@ -2460,75 +2381,6 @@ impl AtomicPtr { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_xor(self.as_ptr(), val, order).cast() } } - - /// Returns a mutable pointer to the underlying pointer. - /// - /// Doing non-atomic reads and writes on the resulting pointer can be a data race. - /// This method is mostly useful for FFI, where the function signature may use - /// `*mut *mut T` instead of `&AtomicPtr`. - /// - /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the - /// atomic types work with interior mutability. All modifications of an atomic change the value - /// through a shared reference, and can do so safely as long as they use atomic operations. Any - /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the - /// requirements of the [memory model]. - /// - /// # Examples - /// - /// ```ignore (extern-declaration) - /// use std::sync::atomic::AtomicPtr; - /// - /// extern "C" { - /// fn my_atomic_op(arg: *mut *mut u32); - /// } - /// - /// let mut value = 17; - /// let atomic = AtomicPtr::new(&mut value); - /// - /// // SAFETY: Safe as long as `my_atomic_op` is atomic. - /// unsafe { - /// my_atomic_op(atomic.as_ptr()); - /// } - /// ``` - /// - /// [memory model]: self#memory-model-for-atomic-accesses - #[inline] - #[stable(feature = "atomic_as_ptr", since = "1.70.0")] - #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] - #[rustc_never_returns_null_ptr] - pub const fn as_ptr(&self) -> *mut *mut T { - self.v.get().cast() - } -} - -#[cfg(target_has_atomic_load_store = "8")] -#[stable(feature = "atomic_bool_from", since = "1.24.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl const From for AtomicBool { - /// Converts a `bool` into an `AtomicBool`. - /// - /// # Examples - /// - /// ``` - /// use std::sync::atomic::AtomicBool; - /// let atomic_bool = AtomicBool::from(true); - /// assert_eq!(format!("{atomic_bool:?}"), "true") - /// ``` - #[inline] - fn from(b: bool) -> Self { - Self::new(b) - } -} - -#[cfg(target_has_atomic_load_store = "ptr")] -#[stable(feature = "atomic_from", since = "1.23.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl const From<*mut T> for AtomicPtr { - /// Converts a `*mut T` into an `AtomicPtr`. - #[inline] - fn from(p: *mut T) -> Self { - Self::new(p) - } } #[allow(unused_macros)] // This macro ends up being unused on some architectures. @@ -2546,7 +2398,6 @@ macro_rules! atomic_int { $stable_cxchg:meta, $stable_debug:meta, $stable_access:meta, - $stable_from:meta, $stable_nand:meta, $const_stable_new:meta, $const_stable_into_inner:meta, @@ -2588,22 +2439,6 @@ macro_rules! atomic_int { #[$stable] pub type $atomic_type = Atomic<$int_type>; - #[$stable] - impl Default for $atomic_type { - #[inline] - fn default() -> Self { - Self::new(Default::default()) - } - } - - #[$stable_from] - #[rustc_const_unstable(feature = "const_convert", issue = "143773")] - impl const From<$int_type> for $atomic_type { - #[doc = concat!("Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`.")] - #[inline] - fn from(v: $int_type) -> Self { Self::new(v) } - } - #[$stable_debug] impl fmt::Debug for $atomic_type { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -2612,84 +2447,6 @@ macro_rules! atomic_int { } impl $atomic_type { - /// Creates a new atomic integer. - /// - /// # Examples - /// - /// ``` - #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")] - /// - #[doc = concat!("let atomic_forty_two = ", stringify!($atomic_type), "::new(42);")] - /// ``` - #[inline] - #[$stable] - #[$const_stable_new] - #[must_use] - pub const fn new(v: $int_type) -> Self { - // SAFETY: - // `Atomic` is essentially a transparent wrapper around `T`. - unsafe { transmute(v) } - } - - /// Creates a new reference to an atomic integer from a pointer. - /// - /// # Examples - /// - /// ``` - #[doc = concat!($extra_feature, "use std::sync::atomic::{self, ", stringify!($atomic_type), "};")] - /// - /// // Get a pointer to an allocated value - #[doc = concat!("let ptr: *mut ", stringify!($int_type), " = Box::into_raw(Box::new(0));")] - /// - #[doc = concat!("assert!(ptr.cast::<", stringify!($atomic_type), ">().is_aligned());")] - /// - /// { - /// // Create an atomic view of the allocated value - // SAFETY: this is a doc comment, tidy, it can't hurt you (also guaranteed by the construction of `ptr` and the assert above) - #[doc = concat!(" let atomic = unsafe {", stringify!($atomic_type), "::from_ptr(ptr) };")] - /// - /// // Use `atomic` for atomic operations, possibly share it with other threads - /// atomic.store(1, atomic::Ordering::Relaxed); - /// } - /// - /// // It's ok to non-atomically access the value behind `ptr`, - /// // since the reference to the atomic ended its lifetime in the block above - /// assert_eq!(unsafe { *ptr }, 1); - /// - /// // Deallocate the value - /// unsafe { drop(Box::from_raw(ptr)) } - /// ``` - /// - /// # Safety - /// - /// * `ptr` must be aligned to - #[doc = concat!(" `align_of::<", stringify!($atomic_type), ">()`")] - #[doc = if_8_bit!{ - $int_type, - yes = [ - " (note that this is always true, since `align_of::<", - stringify!($atomic_type), ">() == 1`)." - ], - no = [ - " (note that on some platforms this can be bigger than `align_of::<", - stringify!($int_type), ">()`)." - ], - }] - /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. - /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not - /// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different - /// sizes, without synchronization. - /// - /// [valid]: crate::ptr#safety - /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses - #[inline] - #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")] - pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type { - // SAFETY: guaranteed by the caller - unsafe { &*ptr.cast() } - } - /// Returns a mutable reference to the underlying integer. /// /// This is safe because the mutable reference guarantees that no other threads are @@ -2822,28 +2579,6 @@ macro_rules! atomic_int { unsafe { &mut *(v as *mut [$int_type] as *mut [Self]) } } - /// Consumes the atomic and returns the contained value. - /// - /// This is safe because passing `self` by value guarantees that no other threads are - /// concurrently accessing the atomic data. - /// - /// # Examples - /// - /// ``` - #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")] - /// - #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")] - /// assert_eq!(some_var.into_inner(), 5); - /// ``` - #[inline] - #[$stable_access] - #[$const_stable_into_inner] - pub const fn into_inner(self) -> $int_type { - // SAFETY: - // `Atomic` is essentially a transparent wrapper around `T`. - unsafe { transmute(self) } - } - /// Loads a value from the atomic integer. /// /// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation. @@ -3574,46 +3309,6 @@ macro_rules! atomic_int { // SAFETY: data races are prevented by atomic intrinsics. unsafe { $min_fn(self.as_ptr(), val, order) } } - - /// Returns a mutable pointer to the underlying integer. - /// - /// Doing non-atomic reads and writes on the resulting integer can be a data race. - /// This method is mostly useful for FFI, where the function signature may use - #[doc = concat!("`*mut ", stringify!($int_type), "` instead of `&", stringify!($atomic_type), "`.")] - /// - /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the - /// atomic types work with interior mutability. All modifications of an atomic change the value - /// through a shared reference, and can do so safely as long as they use atomic operations. Any - /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the - /// requirements of the [memory model]. - /// - /// # Examples - /// - /// ```ignore (extern-declaration) - /// # fn main() { - #[doc = concat!($extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";")] - /// - /// extern "C" { - #[doc = concat!(" fn my_atomic_op(arg: *mut ", stringify!($int_type), ");")] - /// } - /// - #[doc = concat!("let atomic = ", stringify!($atomic_type), "::new(1);")] - /// - /// // SAFETY: Safe as long as `my_atomic_op` is atomic. - /// unsafe { - /// my_atomic_op(atomic.as_ptr()); - /// } - /// # } - /// ``` - /// - /// [memory model]: self#memory-model-for-atomic-accesses - #[inline] - #[stable(feature = "atomic_as_ptr", since = "1.70.0")] - #[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")] - #[rustc_never_returns_null_ptr] - pub const fn as_ptr(&self) -> *mut $int_type { - self.v.get().cast() - } } } } @@ -3627,7 +3322,6 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), - stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), "i8", @@ -3645,7 +3339,6 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), - stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), "u8", @@ -3663,7 +3356,6 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), - stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), "i16", @@ -3681,7 +3373,6 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), - stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), "u16", @@ -3699,7 +3390,6 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), - stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), "i32", @@ -3717,7 +3407,6 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), - stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), "u32", @@ -3735,7 +3424,6 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), - stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), "i64", @@ -3753,7 +3441,6 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), - stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), "u64", @@ -3771,7 +3458,6 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "99069"), unstable(feature = "integer_atomics", issue = "99069"), unstable(feature = "integer_atomics", issue = "99069"), - unstable(feature = "integer_atomics", issue = "99069"), rustc_const_unstable(feature = "integer_atomics", issue = "99069"), rustc_const_unstable(feature = "integer_atomics", issue = "99069"), "i128", @@ -3789,7 +3475,6 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "99069"), unstable(feature = "integer_atomics", issue = "99069"), unstable(feature = "integer_atomics", issue = "99069"), - unstable(feature = "integer_atomics", issue = "99069"), rustc_const_unstable(feature = "integer_atomics", issue = "99069"), rustc_const_unstable(feature = "integer_atomics", issue = "99069"), "u128", @@ -3810,7 +3495,6 @@ macro_rules! atomic_int_ptr_sized { stable(feature = "extended_compare_and_swap", since = "1.10.0"), stable(feature = "atomic_debug", since = "1.3.0"), stable(feature = "atomic_access", since = "1.15.0"), - stable(feature = "atomic_from", since = "1.23.0"), stable(feature = "atomic_nand", since = "1.27.0"), rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), @@ -3828,7 +3512,6 @@ macro_rules! atomic_int_ptr_sized { stable(feature = "extended_compare_and_swap", since = "1.10.0"), stable(feature = "atomic_debug", since = "1.3.0"), stable(feature = "atomic_access", since = "1.15.0"), - stable(feature = "atomic_from", since = "1.23.0"), stable(feature = "atomic_nand", since = "1.27.0"), rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), From a6a05f85748de9043a0bddb1b3402adf9e7766bc Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 4 Mar 2026 17:54:42 +0100 Subject: [PATCH 2/2] bless UI test --- .../atomic-from-mut-not-available.alignment_mismatch.stderr | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/ui/stdlib-unit-tests/atomic-from-mut-not-available.alignment_mismatch.stderr b/tests/ui/stdlib-unit-tests/atomic-from-mut-not-available.alignment_mismatch.stderr index 4b1cd8a5a1256..45be8e162af05 100644 --- a/tests/ui/stdlib-unit-tests/atomic-from-mut-not-available.alignment_mismatch.stderr +++ b/tests/ui/stdlib-unit-tests/atomic-from-mut-not-available.alignment_mismatch.stderr @@ -4,18 +4,14 @@ error[E0599]: no function or associated item named `from_mut` found for struct ` LL | core::sync::atomic::AtomicU64::from_mut(&mut 0u64); | ^^^^^^^^ function or associated item not found in `Atomic` | -note: if you're trying to build a new `Atomic`, consider using `Atomic::::new` which returns `Atomic` +note: if you're trying to build a new `Atomic`, consider using `Atomic::::new` which returns `Atomic<_>` --> $SRC_DIR/core/src/sync/atomic.rs:LL:COL - ::: $SRC_DIR/core/src/sync/atomic.rs:LL:COL - | - = note: in this macro invocation = note: the function or associated item was found for - `Atomic<*mut T>` - `Atomic` - `Atomic` - `Atomic` and 6 more types - = note: this error originates in the macro `atomic_int` (in Nightly builds, run with -Z macro-backtrace for more info) help: there is an associated function `from` with a similar name | LL - core::sync::atomic::AtomicU64::from_mut(&mut 0u64);