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
This commit is contained in:
Jacob Pratt 2025-02-04 05:38:03 -05:00 committed by GitHub
commit d89e98dcbf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -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")]