Skip to content

Commit

Permalink
Rollup merge of #136398 - pitaj:unsafecell_access, r=dtolnay
Browse files Browse the repository at this point in the history
add UnsafeCell direct access APIs

- Implementation for ACP: rust-lang/libs-team#521
- Tracking issue #136327
  • Loading branch information
jhpratt authored Feb 4, 2025
2 parents 8a8b464 + 670d892 commit d89e98d
Showing 1 changed file with 84 additions and 0 deletions.
84 changes: 84 additions & 0 deletions library/core/src/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -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")]
Expand Down

0 comments on commit d89e98d

Please sign in to comment.