diff options
| author | Jacob Pratt <jacob@jhpratt.dev> | 2025-02-04 05:38:03 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-04 05:38:03 -0500 |
| commit | d89e98dcbfbb6d53606ed5998e6b8f509bb24000 (patch) | |
| tree | 69c78742a922917f3d0b18980ced8216561f6c6e | |
| parent | 8a8b4641754e9ce8a31b272dda6567727452df9e (diff) | |
| parent | 670d892dc9f1b6f74b7103a6602262f383197d20 (diff) | |
| download | rust-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.rs | 84 |
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")] |
