Skip to content

Commit 0310708

Browse files
authored
Rollup merge of rust-lang#66248 - RalfJung:unsafe_cell_raw_get, r=SimonSapin
add raw ptr variant of UnsafeCell::get This has come up recently in rust-lang#66051 (Cc @Centril @pitdicker) as well as in discussion with @nikomatsakis and in unrelated discussion with @withoutboats.
2 parents 7c3562c + 861698a commit 0310708

File tree

1 file changed

+38
-1
lines changed

1 file changed

+38
-1
lines changed

src/libcore/cell.rs

+38-1
Original file line numberDiff line numberDiff line change
@@ -1545,9 +1545,46 @@ impl<T: ?Sized> UnsafeCell<T> {
15451545
#[stable(feature = "rust1", since = "1.0.0")]
15461546
pub const fn get(&self) -> *mut T {
15471547
// We can just cast the pointer from `UnsafeCell<T>` to `T` because of
1548-
// #[repr(transparent)]
1548+
// #[repr(transparent)]. This exploits libstd's special status, there is
1549+
// no guarantee for user code that this will work in future versions of the compiler!
15491550
self as *const UnsafeCell<T> as *const T as *mut T
15501551
}
1552+
1553+
/// Gets a mutable pointer to the wrapped value.
1554+
/// The difference to [`get`] is that this function accepts a raw pointer,
1555+
/// which is useful to avoid the creation of temporary references.
1556+
///
1557+
/// The result can be cast to a pointer of any kind.
1558+
/// Ensure that the access is unique (no active references, mutable or not)
1559+
/// when casting to `&mut T`, and ensure that there are no mutations
1560+
/// or mutable aliases going on when casting to `&T`.
1561+
///
1562+
/// [`get`]: #method.get
1563+
///
1564+
/// # Examples
1565+
///
1566+
/// Gradual initialization of an `UnsafeCell` requires `raw_get`, as
1567+
/// calling `get` would require creating a reference to uninitialized data:
1568+
///
1569+
/// ```
1570+
/// #![feature(unsafe_cell_raw_get)]
1571+
/// use std::cell::UnsafeCell;
1572+
/// use std::mem::MaybeUninit;
1573+
///
1574+
/// let m = MaybeUninit::<UnsafeCell<i32>>::uninit();
1575+
/// unsafe { UnsafeCell::raw_get(m.as_ptr()).write(5); }
1576+
/// let uc = unsafe { m.assume_init() };
1577+
///
1578+
/// assert_eq!(uc.into_inner(), 5);
1579+
/// ```
1580+
#[inline]
1581+
#[unstable(feature = "unsafe_cell_raw_get", issue = "66358")]
1582+
pub const fn raw_get(this: *const Self) -> *mut T {
1583+
// We can just cast the pointer from `UnsafeCell<T>` to `T` because of
1584+
// #[repr(transparent)]. This exploits libstd's special status, there is
1585+
// no guarantee for user code that this will work in future versions of the compiler!
1586+
this as *const T as *mut T
1587+
}
15511588
}
15521589

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

0 commit comments

Comments
 (0)