about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJacob Pratt <jacob@jhpratt.dev>2025-02-04 05:38:03 -0500
committerGitHub <noreply@github.com>2025-02-04 05:38:03 -0500
commitd89e98dcbfbb6d53606ed5998e6b8f509bb24000 (patch)
tree69c78742a922917f3d0b18980ced8216561f6c6e
parent8a8b4641754e9ce8a31b272dda6567727452df9e (diff)
parent670d892dc9f1b6f74b7103a6602262f383197d20 (diff)
downloadrust-d89e98dcbfbb6d53606ed5998e6b8f509bb24000.tar.gz
rust-d89e98dcbfbb6d53606ed5998e6b8f509bb24000.zip
Rollup merge of #136398 - pitaj:unsafecell_access, r=dtolnay
add UnsafeCell direct access APIs

- Implementation for ACP: https://github.com/rust-lang/libs-team/issues/521
- Tracking issue #136327
-rw-r--r--library/core/src/cell.rs84
1 files changed, 84 insertions, 0 deletions
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 20187e478aa..320d8176011 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -2118,6 +2118,35 @@ impl<T> UnsafeCell<T> {
     pub const fn into_inner(self) -> T {
         self.value
     }
+
+    /// Replace the value in this `UnsafeCell` and return the old value.
+    ///
+    /// # Safety
+    ///
+    /// The caller must take care to avoid aliasing and data races.
+    ///
+    /// - It is Undefined Behavior to allow calls to race with
+    ///   any other access to the wrapped value.
+    /// - It is Undefined Behavior to call this while any other
+    ///   reference(s) to the wrapped value are alive.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unsafe_cell_access)]
+    /// use std::cell::UnsafeCell;
+    ///
+    /// let uc = UnsafeCell::new(5);
+    ///
+    /// let old = unsafe { uc.replace(10) };
+    /// assert_eq!(old, 5);
+    /// ```
+    #[inline]
+    #[unstable(feature = "unsafe_cell_access", issue = "136327")]
+    pub const unsafe fn replace(&self, value: T) -> T {
+        // SAFETY: pointer comes from `&self` so naturally satisfies invariants.
+        unsafe { ptr::replace(self.get(), value) }
+    }
 }
 
 impl<T: ?Sized> UnsafeCell<T> {
@@ -2230,6 +2259,61 @@ impl<T: ?Sized> UnsafeCell<T> {
         // no guarantee for user code that this will work in future versions of the compiler!
         this as *const T as *mut T
     }
+
+    /// Get a shared reference to the value within the `UnsafeCell`.
+    ///
+    /// # Safety
+    ///
+    /// - It is Undefined Behavior to call this while any mutable
+    ///   reference to the wrapped value is alive.
+    /// - Mutating the wrapped value while the returned
+    ///   reference is alive is Undefined Behavior.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unsafe_cell_access)]
+    /// use std::cell::UnsafeCell;
+    ///
+    /// let uc = UnsafeCell::new(5);
+    ///
+    /// let val = unsafe { uc.as_ref_unchecked() };
+    /// assert_eq!(val, &5);
+    /// ```
+    #[inline]
+    #[unstable(feature = "unsafe_cell_access", issue = "136327")]
+    pub const unsafe fn as_ref_unchecked(&self) -> &T {
+        // SAFETY: pointer comes from `&self` so naturally satisfies ptr-to-ref invariants.
+        unsafe { self.get().as_ref_unchecked() }
+    }
+
+    /// Get an exclusive reference to the value within the `UnsafeCell`.
+    ///
+    /// # Safety
+    ///
+    /// - It is Undefined Behavior to call this while any other
+    ///   reference(s) to the wrapped value are alive.
+    /// - Mutating the wrapped value through other means while the
+    ///   returned reference is alive is Undefined Behavior.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(unsafe_cell_access)]
+    /// use std::cell::UnsafeCell;
+    ///
+    /// let uc = UnsafeCell::new(5);
+    ///
+    /// unsafe { *uc.as_mut_unchecked() += 1; }
+    /// assert_eq!(uc.into_inner(), 6);
+    /// ```
+    #[inline]
+    #[unstable(feature = "unsafe_cell_access", issue = "136327")]
+    #[allow(clippy::mut_from_ref)]
+    pub const unsafe fn as_mut_unchecked(&self) -> &mut T {
+        // SAFETY: pointer comes from `&self` so naturally satisfies ptr-to-ref invariants.
+        unsafe { self.get().as_mut_unchecked() }
+    }
 }
 
 #[stable(feature = "unsafe_cell_default", since = "1.10.0")]