From 670d892dc9f1b6f74b7103a6602262f383197d20 Mon Sep 17 00:00:00 2001
From: Peter Jaszkowiak
Date: Sat, 1 Feb 2025 13:09:28 -0700
Subject: [PATCH] add UnsafeCell direct access APIs
---
library/core/src/cell.rs | 84 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 20187e478aac5..320d8176011fd 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -2118,6 +2118,35 @@ impl UnsafeCell {
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 UnsafeCell {
@@ -2230,6 +2259,61 @@ impl UnsafeCell {
// 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")]