From 1c8033f77fc9e394bbc4ba28b29e0be081341b17 Mon Sep 17 00:00:00 2001 From: est31 Date: Wed, 16 Jun 2021 02:47:05 +0200 Subject: [PATCH 1/4] Split MaybeUninit::write into new feature gate and stabilize it --- library/core/src/mem/maybe_uninit.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index de3367e5e5297..ab8d6ace29bc2 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -426,7 +426,6 @@ impl MaybeUninit { /// Correct usage of this method: /// /// ```rust - /// #![feature(maybe_uninit_extra)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::>::uninit(); @@ -445,7 +444,6 @@ impl MaybeUninit { /// This usage of the method causes a leak: /// /// ```rust - /// #![feature(maybe_uninit_extra)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::::uninit(); @@ -456,8 +454,8 @@ impl MaybeUninit { /// // x is initialized now: /// let s = unsafe { x.assume_init() }; /// ``` - #[unstable(feature = "maybe_uninit_extra", issue = "63567")] - #[rustc_const_unstable(feature = "maybe_uninit_extra", issue = "63567")] + #[stable(feature = "maybe_uninit_write", since = "1.55.0")] + #[rustc_const_unstable(feature = "const_maybe_uninit_write", issue = "63567")] #[inline(always)] pub const fn write(&mut self, val: T) -> &mut T { *self = MaybeUninit::new(val); @@ -478,7 +476,7 @@ impl MaybeUninit { /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::>::uninit(); - /// unsafe { x.as_mut_ptr().write(vec![0, 1, 2]); } + /// x.write(vec![0, 1, 2]); /// // Create a reference into the `MaybeUninit`. This is okay because we initialized it. /// let x_vec = unsafe { &*x.as_ptr() }; /// assert_eq!(x_vec.len(), 3); @@ -897,9 +895,9 @@ impl MaybeUninit { /// use std::mem::MaybeUninit; /// /// let mut array: [MaybeUninit; 3] = MaybeUninit::uninit_array(); - /// array[0] = MaybeUninit::new(0); - /// array[1] = MaybeUninit::new(1); - /// array[2] = MaybeUninit::new(2); + /// array[0].write(0); + /// array[1].write(1); + /// array[2].write(2); /// /// // SAFETY: Now safe as we initialised all elements /// let array = unsafe { From 5585cce06c19524b5e8f44dcbe8de80af5083cf8 Mon Sep 17 00:00:00 2001 From: est31 Date: Fri, 25 Jun 2021 00:02:44 +0200 Subject: [PATCH 2/4] Add another example --- library/core/src/mem/maybe_uninit.rs | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index ab8d6ace29bc2..e797227c85b73 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -454,6 +454,36 @@ impl MaybeUninit { /// // x is initialized now: /// let s = unsafe { x.assume_init() }; /// ``` + /// + /// This method can be used to avoid unsafe in some cases. The example below + /// shows a part of an implementation of a fixed sized arena that lends out + /// pinned references. + /// With `write`, we can avoid the need to write through a raw pointer: + /// + /// ```rust + /// #![feature(maybe_uninit_extra)] + /// use core::pin::Pin; + /// use core::mem::MaybeUninit; + /// + /// struct PinArena { + /// memory: Box<[MaybeUninit]>, + /// len: usize, + /// } + /// + /// impl PinArena { + /// pub fn capacity(&self) -> usize { + /// self.memory.len() + /// } + /// pub fn push(&mut self, val: T) -> Pin<&mut T> { + /// if self.len >= self.capacity() { + /// panic!("Attempted to push to a full pin arena!"); + /// } + /// let ref_ = self.memory[self.len].write(val); + /// self.len += 1; + /// unsafe { Pin::new_unchecked(ref_) } + /// } + /// } + /// ``` #[stable(feature = "maybe_uninit_write", since = "1.55.0")] #[rustc_const_unstable(feature = "const_maybe_uninit_write", issue = "63567")] #[inline(always)] From 8e328be73d44c1d027de1abc1aab6819fda78c54 Mon Sep 17 00:00:00 2001 From: est31 Date: Fri, 25 Jun 2021 00:22:17 +0200 Subject: [PATCH 3/4] Fix grammar mistake present perfect passive constructions need to use the past participle form, which for run is "run". --- library/core/src/mem/maybe_uninit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index e797227c85b73..75e07fc531253 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -410,7 +410,7 @@ impl MaybeUninit { /// (now safely initialized) contents of `self`. /// /// As the content is stored inside a `MaybeUninit`, the destructor is not - /// ran for the inner data if the MaybeUninit leaves scope without a call to + /// run for the inner data if the MaybeUninit leaves scope without a call to /// [`assume_init`], [`assume_init_drop`], or similar. Code that receives /// the mutable reference returned by this function needs to keep this in /// mind. The safety model of Rust regards leaks as safe, but they are From 848a6215914e7396172e7a3895bbdbbd6a6e3247 Mon Sep 17 00:00:00 2001 From: est31 Date: Mon, 12 Jul 2021 20:32:23 +0200 Subject: [PATCH 4/4] Use the write function in some more places --- library/core/src/mem/maybe_uninit.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 75e07fc531253..b58d3ed4ae5cd 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -79,7 +79,7 @@ use crate::ptr; /// // a `MaybeUninit` may be invalid, and hence this is not UB: /// let mut x = MaybeUninit::<&i32>::uninit(); /// // Set it to a valid value. -/// unsafe { x.as_mut_ptr().write(&0); } +/// x.write(&0); /// // Extract the initialized data -- this is only allowed *after* properly /// // initializing `x`! /// let x = unsafe { x.assume_init() }; @@ -135,7 +135,7 @@ use crate::ptr; /// // this loop, we have a memory leak, but there is no memory safety /// // issue. /// for elem in &mut data[..] { -/// *elem = MaybeUninit::new(vec![42]); +/// elem.write(vec![42]); /// } /// /// // Everything is initialized. Transmute the array to the @@ -161,7 +161,7 @@ use crate::ptr; /// let mut data_len: usize = 0; /// /// for elem in &mut data[0..500] { -/// *elem = MaybeUninit::new(String::from("hello")); +/// elem.write(String::from("hello")); /// data_len += 1; /// } /// @@ -543,7 +543,7 @@ impl MaybeUninit { /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::>::uninit(); - /// unsafe { x.as_mut_ptr().write(vec![0, 1, 2]); } + /// x.write(vec![0, 1, 2]); /// // Create a reference into the `MaybeUninit>`. /// // This is okay because we initialized it. /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; @@ -602,7 +602,7 @@ impl MaybeUninit { /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::::uninit(); - /// unsafe { x.as_mut_ptr().write(true); } + /// x.write(true); /// let x_init = unsafe { x.assume_init() }; /// assert_eq!(x_init, true); /// ``` @@ -751,7 +751,7 @@ impl MaybeUninit { /// /// let mut x = MaybeUninit::>::uninit(); /// // Initialize `x`: - /// unsafe { x.as_mut_ptr().write(vec![1, 2, 3]); } + /// x.write(vec![1, 2, 3]); /// // Now that our `MaybeUninit<_>` is known to be initialized, it is okay to /// // create a shared reference to it: /// let x: &Vec = unsafe {