Skip to content

Commit d89e98d

Browse files
authored
Rollup merge of #136398 - pitaj:unsafecell_access, r=dtolnay
add UnsafeCell direct access APIs - Implementation for ACP: rust-lang/libs-team#521 - Tracking issue #136327
2 parents 8a8b464 + 670d892 commit d89e98d

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

library/core/src/cell.rs

+84
Original file line numberDiff line numberDiff line change
@@ -2118,6 +2118,35 @@ impl<T> UnsafeCell<T> {
21182118
pub const fn into_inner(self) -> T {
21192119
self.value
21202120
}
2121+
2122+
/// Replace the value in this `UnsafeCell` and return the old value.
2123+
///
2124+
/// # Safety
2125+
///
2126+
/// The caller must take care to avoid aliasing and data races.
2127+
///
2128+
/// - It is Undefined Behavior to allow calls to race with
2129+
/// any other access to the wrapped value.
2130+
/// - It is Undefined Behavior to call this while any other
2131+
/// reference(s) to the wrapped value are alive.
2132+
///
2133+
/// # Examples
2134+
///
2135+
/// ```
2136+
/// #![feature(unsafe_cell_access)]
2137+
/// use std::cell::UnsafeCell;
2138+
///
2139+
/// let uc = UnsafeCell::new(5);
2140+
///
2141+
/// let old = unsafe { uc.replace(10) };
2142+
/// assert_eq!(old, 5);
2143+
/// ```
2144+
#[inline]
2145+
#[unstable(feature = "unsafe_cell_access", issue = "136327")]
2146+
pub const unsafe fn replace(&self, value: T) -> T {
2147+
// SAFETY: pointer comes from `&self` so naturally satisfies invariants.
2148+
unsafe { ptr::replace(self.get(), value) }
2149+
}
21212150
}
21222151

21232152
impl<T: ?Sized> UnsafeCell<T> {
@@ -2230,6 +2259,61 @@ impl<T: ?Sized> UnsafeCell<T> {
22302259
// no guarantee for user code that this will work in future versions of the compiler!
22312260
this as *const T as *mut T
22322261
}
2262+
2263+
/// Get a shared reference to the value within the `UnsafeCell`.
2264+
///
2265+
/// # Safety
2266+
///
2267+
/// - It is Undefined Behavior to call this while any mutable
2268+
/// reference to the wrapped value is alive.
2269+
/// - Mutating the wrapped value while the returned
2270+
/// reference is alive is Undefined Behavior.
2271+
///
2272+
/// # Examples
2273+
///
2274+
/// ```
2275+
/// #![feature(unsafe_cell_access)]
2276+
/// use std::cell::UnsafeCell;
2277+
///
2278+
/// let uc = UnsafeCell::new(5);
2279+
///
2280+
/// let val = unsafe { uc.as_ref_unchecked() };
2281+
/// assert_eq!(val, &5);
2282+
/// ```
2283+
#[inline]
2284+
#[unstable(feature = "unsafe_cell_access", issue = "136327")]
2285+
pub const unsafe fn as_ref_unchecked(&self) -> &T {
2286+
// SAFETY: pointer comes from `&self` so naturally satisfies ptr-to-ref invariants.
2287+
unsafe { self.get().as_ref_unchecked() }
2288+
}
2289+
2290+
/// Get an exclusive reference to the value within the `UnsafeCell`.
2291+
///
2292+
/// # Safety
2293+
///
2294+
/// - It is Undefined Behavior to call this while any other
2295+
/// reference(s) to the wrapped value are alive.
2296+
/// - Mutating the wrapped value through other means while the
2297+
/// returned reference is alive is Undefined Behavior.
2298+
///
2299+
/// # Examples
2300+
///
2301+
/// ```
2302+
/// #![feature(unsafe_cell_access)]
2303+
/// use std::cell::UnsafeCell;
2304+
///
2305+
/// let uc = UnsafeCell::new(5);
2306+
///
2307+
/// unsafe { *uc.as_mut_unchecked() += 1; }
2308+
/// assert_eq!(uc.into_inner(), 6);
2309+
/// ```
2310+
#[inline]
2311+
#[unstable(feature = "unsafe_cell_access", issue = "136327")]
2312+
#[allow(clippy::mut_from_ref)]
2313+
pub const unsafe fn as_mut_unchecked(&self) -> &mut T {
2314+
// SAFETY: pointer comes from `&self` so naturally satisfies ptr-to-ref invariants.
2315+
unsafe { self.get().as_mut_unchecked() }
2316+
}
22332317
}
22342318

22352319
#[stable(feature = "unsafe_cell_default", since = "1.10.0")]

0 commit comments

Comments
 (0)