about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2019-11-13 22:09:19 +0900
committerGitHub <noreply@github.com>2019-11-13 22:09:19 +0900
commit689cc046146faa7a8b0970614c84a3d9ca00ae84 (patch)
tree7213648ff4b501d1a2b1a03ca4ef672ae6436b9e
parentfac098291eea5a993542141e681ed9be0a4513d0 (diff)
parent861698a493fc547254e61dc23a43dfb0683df91a (diff)
downloadrust-689cc046146faa7a8b0970614c84a3d9ca00ae84.tar.gz
rust-689cc046146faa7a8b0970614c84a3d9ca00ae84.zip
Rollup merge of #66248 - RalfJung:unsafe_cell_raw_get, r=SimonSapin
add raw ptr variant of UnsafeCell::get

This has come up recently in https://github.com/rust-lang/rust/pull/66051 (Cc @Centril @pitdicker) as well as in discussion with @nikomatsakis and in unrelated discussion with @withoutboats.
-rw-r--r--src/libcore/cell.rs39
1 files changed, 38 insertions, 1 deletions
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 87d8e7aff05..03f32e72618 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -1545,9 +1545,46 @@ impl<T: ?Sized> UnsafeCell<T> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn get(&self) -> *mut T {
         // We can just cast the pointer from `UnsafeCell<T>` to `T` because of
-        // #[repr(transparent)]
+        // #[repr(transparent)]. This exploits libstd's special status, there is
+        // no guarantee for user code that this will work in future versions of the compiler!
         self as *const UnsafeCell<T> as *const T as *mut T
     }
+
+    /// Gets a mutable pointer to the wrapped value.
+    /// The difference to [`get`] is that this function accepts a raw pointer,
+    /// which is useful to avoid the creation of temporary references.
+    ///
+    /// The result can be cast to a pointer of any kind.
+    /// Ensure that the access is unique (no active references, mutable or not)
+    /// when casting to `&mut T`, and ensure that there are no mutations
+    /// or mutable aliases going on when casting to `&T`.
+    ///
+    /// [`get`]: #method.get
+    ///
+    /// # Examples
+    ///
+    /// Gradual initialization of an `UnsafeCell` requires `raw_get`, as
+    /// calling `get` would require creating a reference to uninitialized data:
+    ///
+    /// ```
+    /// #![feature(unsafe_cell_raw_get)]
+    /// use std::cell::UnsafeCell;
+    /// use std::mem::MaybeUninit;
+    ///
+    /// let m = MaybeUninit::<UnsafeCell<i32>>::uninit();
+    /// unsafe { UnsafeCell::raw_get(m.as_ptr()).write(5); }
+    /// let uc = unsafe { m.assume_init() };
+    ///
+    /// assert_eq!(uc.into_inner(), 5);
+    /// ```
+    #[inline]
+    #[unstable(feature = "unsafe_cell_raw_get", issue = "66358")]
+    pub const fn raw_get(this: *const Self) -> *mut T {
+        // We can just cast the pointer from `UnsafeCell<T>` to `T` because of
+        // #[repr(transparent)]. This exploits libstd's special status, there is
+        // no guarantee for user code that this will work in future versions of the compiler!
+        this as *const T as *mut T
+    }
 }
 
 #[stable(feature = "unsafe_cell_default", since = "1.10.0")]