From 1b8b2ee6f9e9e1fe109f40be4c756619d5c9aa3f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 Nov 2019 12:34:29 +0100 Subject: [PATCH 1/5] add raw ptr variant of UnsafeCell::get --- src/libcore/cell.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 87d8e7aff058d..0860d9c0cfa8b 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1548,6 +1548,36 @@ impl UnsafeCell { // #[repr(transparent)] self as *const UnsafeCell as *const T as *mut T } + + /// Gets a mutable pointer to the wrapped value. + /// + /// This 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` + /// + /// # Examples + /// + /// Gradual initialization of an `UnsafeCell`: + /// + /// ``` + /// #![feature(unsafe_cell_raw_get)] + /// use std::cell::UnsafeCell; + /// use std::mem::MaybeUninit; + /// + /// let m = MaybeUninit::>::uninit(); + /// unsafe { m.as_ptr().raw_get().write(5); } + /// let uc = unsafe { m.assume_init() }; + /// + /// assert_eq!(uc.into_inner(), 5); + /// ``` + #[inline] + #[unstable(feature = "unsafe_cell_raw_get", issue = "0")] + pub const fn raw_get(self: *const Self) -> *mut T { + // We can just cast the pointer from `UnsafeCell` to `T` because of + // #[repr(transparent)] + self as *const T as *mut T + } } #[stable(feature = "unsafe_cell_default", since = "1.10.0")] From aba385abbd69146387893c84951a06ec283f4d10 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 13 Nov 2019 09:05:57 +0100 Subject: [PATCH 2/5] Trailing full stop Co-Authored-By: Mazdak Farrokhzad --- src/libcore/cell.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 0860d9c0cfa8b..e3292ecc1d187 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1554,7 +1554,7 @@ impl UnsafeCell { /// This 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` + /// or mutable aliases going on when casting to `&T`. /// /// # Examples /// From 19ebe2fb6d7de19de155e70938fafcca6f9b5003 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 13 Nov 2019 09:07:52 +0100 Subject: [PATCH 3/5] clarify why we can do the ptr cast --- src/libcore/cell.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index e3292ecc1d187..4afeec6675865 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1545,7 +1545,8 @@ impl UnsafeCell { #[stable(feature = "rust1", since = "1.0.0")] pub const fn get(&self) -> *mut T { // We can just cast the pointer from `UnsafeCell` 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 as *const T as *mut T } @@ -1572,10 +1573,11 @@ impl UnsafeCell { /// assert_eq!(uc.into_inner(), 5); /// ``` #[inline] - #[unstable(feature = "unsafe_cell_raw_get", issue = "0")] + #[unstable(feature = "unsafe_cell_raw_get", issue = "66358")] pub const fn raw_get(self: *const Self) -> *mut T { // We can just cast the pointer from `UnsafeCell` 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 T as *mut T } } From 5b5ae01340fdbb31f56453655472b783e5719eb9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 13 Nov 2019 09:11:09 +0100 Subject: [PATCH 4/5] expand docs --- src/libcore/cell.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 4afeec6675865..7b7be8f3d2ff6 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1551,15 +1551,20 @@ impl UnsafeCell { } /// 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. /// - /// This can be cast to a pointer of any kind. + /// 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`: + /// Gradual initialization of an `UnsafeCell` requires `raw_get`, as + /// calling `get` would require creating a reference to uninitialized data: /// /// ``` /// #![feature(unsafe_cell_raw_get)] From 861698a493fc547254e61dc23a43dfb0683df91a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 13 Nov 2019 09:31:08 +0100 Subject: [PATCH 5/5] make things ugly --- src/libcore/cell.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 7b7be8f3d2ff6..03f32e726187b 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1572,18 +1572,18 @@ impl UnsafeCell { /// use std::mem::MaybeUninit; /// /// let m = MaybeUninit::>::uninit(); - /// unsafe { m.as_ptr().raw_get().write(5); } + /// 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(self: *const Self) -> *mut T { + pub const fn raw_get(this: *const Self) -> *mut T { // We can just cast the pointer from `UnsafeCell` 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! - self as *const T as *mut T + this as *const T as *mut T } }