From 1613fdae37df044f2c254d25d356b3a57eb61a50 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 6 Jul 2019 18:17:24 +0200 Subject: [PATCH 01/14] Add Rc::get_mut_unchecked, Arc::get_mut_unchecked --- src/liballoc/rc.rs | 31 ++++++++++++++++++++++++++++++- src/liballoc/sync.rs | 31 ++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 0c406a92029a7..22d06180d8d55 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -560,13 +560,42 @@ impl Rc { pub fn get_mut(this: &mut Self) -> Option<&mut T> { if Rc::is_unique(this) { unsafe { - Some(&mut this.ptr.as_mut().value) + Some(Rc::get_mut_unchecked(this)) } } else { None } } + /// Returns a mutable reference to the inner value, + /// without any check. + /// + /// See also [`get_mut`], which is safe and does appropriate checks. + /// + /// [`get_mut`]: struct.Rc.html#method.get_mut + /// + /// # Safety + /// + /// There must be no other `Rc` or [`Weak`][weak] pointers to the same value. + /// This is the case for example immediately after `Rc::new`. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let mut x = Rc::new(String::new()); + /// unsafe { + /// Rc::get_mut_unchecked(&mut x).push_str("foo") + /// } + /// assert_eq!(*x, "foo"); + /// ``` + #[inline] + #[unstable(feature = "get_mut_unchecked", issue = "0")] + pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { + &mut this.ptr.as_mut().value + } + #[inline] #[stable(feature = "ptr_eq", since = "1.17.0")] /// Returns `true` if the two `Rc`s point to the same value (not diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 7d3b2656a7b90..4cd8e1fd4dd23 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -945,13 +945,42 @@ impl Arc { // the Arc itself to be `mut`, so we're returning the only possible // reference to the inner data. unsafe { - Some(&mut this.ptr.as_mut().data) + Some(Arc::get_mut_unchecked(this)) } } else { None } } + /// Returns a mutable reference to the inner value, + /// without any check. + /// + /// See also [`get_mut`], which is safe and does appropriate checks. + /// + /// [`get_mut`]: struct.Arc.html#method.get_mut + /// + /// # Safety + /// + /// There must be no other `Arc` or [`Weak`][weak] pointers to the same value. + /// This is the case for example immediately after `Rc::new`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut x = Arc::new(String::new()); + /// unsafe { + /// Arc::get_mut_unchecked(&mut x).push_str("foo") + /// } + /// assert_eq!(*x, "foo"); + /// ``` + #[inline] + #[unstable(feature = "get_mut_unchecked", issue = "0")] + pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { + &mut this.ptr.as_mut().data + } + /// Determine whether this is the unique reference (including weak refs) to /// the underlying data. /// From 7b02b9f8ec2850ac687ee5c7d869a626e09d22cb Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 6 Jul 2019 17:19:58 +0200 Subject: [PATCH 02/14] Add new_uninit and assume_init on Box, Rc, and Arc --- src/liballoc/boxed.rs | 61 +++++++++++++++++++++++++++++ src/liballoc/rc.rs | 81 +++++++++++++++++++++++++++++++++++++++ src/liballoc/sync.rs | 81 +++++++++++++++++++++++++++++++++++++++ src/libcore/ptr/unique.rs | 8 ++++ 4 files changed, 231 insertions(+) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index c92db517cad36..5ea7847ca45a6 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -93,6 +93,7 @@ use core::ops::{ use core::ptr::{self, NonNull, Unique}; use core::task::{Context, Poll}; +use crate::alloc; use crate::vec::Vec; use crate::raw_vec::RawVec; use crate::str::from_boxed_utf8_unchecked; @@ -121,6 +122,32 @@ impl Box { box x } + /// Construct a new box with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut five = Box::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// Box::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit() -> Box> { + let layout = alloc::Layout::new::>(); + let ptr = unsafe { alloc::alloc(layout) }; + let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout)); + Box(unique.cast()) + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `x` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -130,6 +157,40 @@ impl Box { } } +impl Box> { + /// Convert to `Box`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut five = Box::::new_uninit(); + /// + /// let five: Box = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// Box::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + #[inline] + pub unsafe fn assume_init(this: Self) -> Box { + Box(Box::into_unique(this).cast()) + } +} + impl Box { /// Constructs a box from a raw pointer. /// diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 22d06180d8d55..c902580354dae 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -327,6 +327,43 @@ impl Rc { })) } + /// Construct a new Rc with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// Rc::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit() -> Rc> { + let layout = Layout::new::>>(); + unsafe { + let mut ptr = Global.alloc(layout) + .unwrap_or_else(|_| handle_alloc_error(layout)) + .cast::>>(); + ptr::write(&mut ptr.as_mut().strong, Cell::new(1)); + ptr::write(&mut ptr.as_mut().weak, Cell::new(1)); + Rc { + ptr, + phantom: PhantomData, + } + } + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `value` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -377,6 +414,48 @@ impl Rc { } } +impl Rc> { + /// Convert to `Rc`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// Rc::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + #[inline] + pub unsafe fn assume_init(this: Self) -> Rc { + let ptr = this.ptr.cast(); + mem::forget(this); + Rc { + ptr, + phantom: PhantomData, + } + } +} + impl Rc { /// Consumes the `Rc`, returning the wrapped pointer. /// @@ -582,6 +661,8 @@ impl Rc { /// # Examples /// /// ``` + /// #![feature(get_mut_unchecked)] + /// /// use std::rc::Rc; /// /// let mut x = Rc::new(String::new()); diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 4cd8e1fd4dd23..8c63c81ee2741 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -311,6 +311,43 @@ impl Arc { Self::from_inner(Box::into_raw_non_null(x)) } + /// Construct a Arc box with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// Arc::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit() -> Arc> { + let layout = Layout::new::>>(); + unsafe { + let mut ptr = Global.alloc(layout) + .unwrap_or_else(|_| handle_alloc_error(layout)) + .cast::>>(); + ptr::write(&mut ptr.as_mut().strong, atomic::AtomicUsize::new(1)); + ptr::write(&mut ptr.as_mut().weak, atomic::AtomicUsize::new(1)); + Arc { + ptr, + phantom: PhantomData, + } + } + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `data` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -361,6 +398,48 @@ impl Arc { } } +impl Arc> { + /// Convert to `Arc`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// Arc::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + #[inline] + pub unsafe fn assume_init(this: Self) -> Arc { + let ptr = this.ptr.cast(); + mem::forget(this); + Arc { + ptr, + phantom: PhantomData, + } + } +} + impl Arc { /// Consumes the `Arc`, returning the wrapped pointer. /// @@ -967,6 +1046,8 @@ impl Arc { /// # Examples /// /// ``` + /// #![feature(get_mut_unchecked)] + /// /// use std::sync::Arc; /// /// let mut x = Arc::new(String::new()); diff --git a/src/libcore/ptr/unique.rs b/src/libcore/ptr/unique.rs index f0d011fe6b2c0..a739f3b6022db 100644 --- a/src/libcore/ptr/unique.rs +++ b/src/libcore/ptr/unique.rs @@ -122,6 +122,14 @@ impl Unique { pub unsafe fn as_mut(&mut self) -> &mut T { &mut *self.as_ptr() } + + /// Cast to a pointer of another type + #[inline] + pub const fn cast(self) -> Unique { + unsafe { + Unique::new_unchecked(self.as_ptr() as *mut U) + } + } } #[unstable(feature = "ptr_internals", issue = "0")] From bde19240594c229a19ac928b823101965f4a0cd8 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 6 Jul 2019 21:27:55 +0200 Subject: [PATCH 03/14] Add new_uninit_slice and assume_init on Box, Rc, and Arc of [T] --- src/liballoc/boxed.rs | 74 ++++++++++++++++++++++++++++++-- src/liballoc/rc.rs | 98 ++++++++++++++++++++++++++++++++++++++++--- src/liballoc/sync.rs | 98 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 256 insertions(+), 14 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 5ea7847ca45a6..a759260bd8f78 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -91,6 +91,7 @@ use core::ops::{ CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Receiver, Generator, GeneratorState }; use core::ptr::{self, NonNull, Unique}; +use core::slice; use core::task::{Context, Poll}; use crate::alloc; @@ -135,7 +136,7 @@ impl Box { /// // Deferred initialization: /// five.as_mut_ptr().write(5); /// - /// Box::assume_init(five) + /// five.assume_init() /// }; /// /// assert_eq!(*five, 5) @@ -148,6 +149,35 @@ impl Box { Box(unique.cast()) } + /// Construct a new boxed slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut values = Box::::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { + let layout = alloc::Layout::array::>(len).unwrap(); + let ptr = unsafe { alloc::alloc(layout) }; + let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout)); + let slice = unsafe { slice::from_raw_parts_mut(unique.cast().as_ptr(), len) }; + Box(Unique::from(slice)) + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `x` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -179,15 +209,51 @@ impl Box> { /// // Deferred initialization: /// five.as_mut_ptr().write(5); /// - /// Box::assume_init(five) + /// five.assume_init() /// }; /// /// assert_eq!(*five, 5) /// ``` #[unstable(feature = "new_uninit", issue = "0")] #[inline] - pub unsafe fn assume_init(this: Self) -> Box { - Box(Box::into_unique(this).cast()) + pub unsafe fn assume_init(self) -> Box { + Box(Box::into_unique(self).cast()) + } +} + +impl Box<[mem::MaybeUninit]> { + /// Convert to `Box<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the values + /// really are in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut values = Box::::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + #[inline] + pub unsafe fn assume_init(self) -> Box<[T]> { + Box(Unique::new_unchecked(Box::into_raw(self) as _)) } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index c902580354dae..404c86a24da7b 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -343,7 +343,7 @@ impl Rc { /// // Deferred initialization: /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); /// - /// Rc::assume_init(five) + /// five.assume_init() /// }; /// /// assert_eq!(*five, 5) @@ -364,6 +364,50 @@ impl Rc { } } + /// Construct a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut values = Rc::::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { + let data_layout = Layout::array::>(len).unwrap(); + let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); + unsafe { + let allocated_ptr = Global.alloc(layout) + .unwrap_or_else(|_| handle_alloc_error(layout)) + .as_ptr(); + let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit; + let slice: *mut [mem::MaybeUninit] = from_raw_parts_mut(data_ptr, len); + let wide_ptr = slice as *mut RcBox<[mem::MaybeUninit]>; + let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr); + ptr::write(&mut (*wide_ptr).strong, Cell::new(1)); + ptr::write(&mut (*wide_ptr).weak, Cell::new(1)); + Rc { + ptr: NonNull::new_unchecked(wide_ptr), + phantom: PhantomData, + } + } + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `value` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -439,16 +483,60 @@ impl Rc> { /// // Deferred initialization: /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); /// - /// Rc::assume_init(five) + /// five.assume_init() /// }; /// /// assert_eq!(*five, 5) /// ``` #[unstable(feature = "new_uninit", issue = "0")] #[inline] - pub unsafe fn assume_init(this: Self) -> Rc { - let ptr = this.ptr.cast(); - mem::forget(this); + pub unsafe fn assume_init(self) -> Rc { + let ptr = self.ptr.cast(); + mem::forget(self); + Rc { + ptr, + phantom: PhantomData, + } + } +} + +impl Rc<[mem::MaybeUninit]> { + /// Convert to `Rc<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut values = Rc::::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + #[inline] + pub unsafe fn assume_init(self) -> Rc<[T]> { + let ptr = NonNull::new_unchecked(self.ptr.as_ptr() as _); + mem::forget(self); Rc { ptr, phantom: PhantomData, diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 8c63c81ee2741..3f47b9e6c7dae 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -327,7 +327,7 @@ impl Arc { /// // Deferred initialization: /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); /// - /// Arc::assume_init(five) + /// five.assume_init() /// }; /// /// assert_eq!(*five, 5) @@ -348,6 +348,50 @@ impl Arc { } } + /// Construct a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut values = Arc::::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { + let data_layout = Layout::array::>(len).unwrap(); + let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); + unsafe { + let allocated_ptr = Global.alloc(layout) + .unwrap_or_else(|_| handle_alloc_error(layout)) + .as_ptr(); + let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit; + let slice: *mut [mem::MaybeUninit] = from_raw_parts_mut(data_ptr, len); + let wide_ptr = slice as *mut ArcInner<[mem::MaybeUninit]>; + let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr); + ptr::write(&mut (*wide_ptr).strong, atomic::AtomicUsize::new(1)); + ptr::write(&mut (*wide_ptr).weak, atomic::AtomicUsize::new(1)); + Arc { + ptr: NonNull::new_unchecked(wide_ptr), + phantom: PhantomData, + } + } + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `data` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -423,16 +467,60 @@ impl Arc> { /// // Deferred initialization: /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); /// - /// Arc::assume_init(five) + /// five.assume_init() /// }; /// /// assert_eq!(*five, 5) /// ``` #[unstable(feature = "new_uninit", issue = "0")] #[inline] - pub unsafe fn assume_init(this: Self) -> Arc { - let ptr = this.ptr.cast(); - mem::forget(this); + pub unsafe fn assume_init(self) -> Arc { + let ptr = self.ptr.cast(); + mem::forget(self); + Arc { + ptr, + phantom: PhantomData, + } + } +} + +impl Arc<[mem::MaybeUninit]> { + /// Convert to `Arc<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut values = Arc::::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + #[inline] + pub unsafe fn assume_init(self) -> Arc<[T]> { + let ptr = NonNull::new_unchecked(self.ptr.as_ptr() as _); + mem::forget(self); Arc { ptr, phantom: PhantomData, From 170d933d2f8a7d4787355a86136093af86b03077 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 6 Jul 2019 21:52:15 +0200 Subject: [PATCH 04/14] =?UTF-8?q?Move=20constructors=20of=20boxed/rc?= =?UTF-8?q?=E2=80=99ed=20slices=20to=20matching=20`impl`=20blocks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/liballoc/boxed.rs | 22 ++++++----- src/liballoc/rc.rs | 92 ++++++++++++++++++++++--------------------- src/liballoc/sync.rs | 92 ++++++++++++++++++++++--------------------- 3 files changed, 106 insertions(+), 100 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index a759260bd8f78..6e296907ce8ae 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -149,6 +149,16 @@ impl Box { Box(unique.cast()) } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `x` will be pinned in memory and unable to be moved. + #[stable(feature = "pin", since = "1.33.0")] + #[inline(always)] + pub fn pin(x: T) -> Pin> { + (box x).into() + } +} + +impl Box<[T]> { /// Construct a new boxed slice with uninitialized contents. /// /// # Examples @@ -156,7 +166,7 @@ impl Box { /// ``` /// #![feature(new_uninit)] /// - /// let mut values = Box::::new_uninit_slice(3); + /// let mut values = Box::<[u32]>::new_uninit_slice(3); /// /// let values = unsafe { /// // Deferred initialization: @@ -177,14 +187,6 @@ impl Box { let slice = unsafe { slice::from_raw_parts_mut(unique.cast().as_ptr(), len) }; Box(Unique::from(slice)) } - - /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then - /// `x` will be pinned in memory and unable to be moved. - #[stable(feature = "pin", since = "1.33.0")] - #[inline(always)] - pub fn pin(x: T) -> Pin> { - (box x).into() - } } impl Box> { @@ -237,7 +239,7 @@ impl Box<[mem::MaybeUninit]> { /// ``` /// #![feature(new_uninit)] /// - /// let mut values = Box::::new_uninit_slice(3); + /// let mut values = Box::<[u32]>::new_uninit_slice(3); /// /// let values = unsafe { /// // Deferred initialization: diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 404c86a24da7b..aa1268ec05116 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -364,50 +364,6 @@ impl Rc { } } - /// Construct a new reference-counted slice with uninitialized contents. - /// - /// # Examples - /// - /// ``` - /// #![feature(new_uninit)] - /// #![feature(get_mut_unchecked)] - /// - /// use std::rc::Rc; - /// - /// let mut values = Rc::::new_uninit_slice(3); - /// - /// let values = unsafe { - /// // Deferred initialization: - /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); - /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); - /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); - /// - /// values.assume_init() - /// }; - /// - /// assert_eq!(*values, [1, 2, 3]) - /// ``` - #[unstable(feature = "new_uninit", issue = "0")] - pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { - let data_layout = Layout::array::>(len).unwrap(); - let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); - unsafe { - let allocated_ptr = Global.alloc(layout) - .unwrap_or_else(|_| handle_alloc_error(layout)) - .as_ptr(); - let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit; - let slice: *mut [mem::MaybeUninit] = from_raw_parts_mut(data_ptr, len); - let wide_ptr = slice as *mut RcBox<[mem::MaybeUninit]>; - let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr); - ptr::write(&mut (*wide_ptr).strong, Cell::new(1)); - ptr::write(&mut (*wide_ptr).weak, Cell::new(1)); - Rc { - ptr: NonNull::new_unchecked(wide_ptr), - phantom: PhantomData, - } - } - } - /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `value` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -458,6 +414,52 @@ impl Rc { } } +impl Rc<[T]> { + /// Construct a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut values = Rc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { + let data_layout = Layout::array::>(len).unwrap(); + let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); + unsafe { + let allocated_ptr = Global.alloc(layout) + .unwrap_or_else(|_| handle_alloc_error(layout)) + .as_ptr(); + let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit; + let slice: *mut [mem::MaybeUninit] = from_raw_parts_mut(data_ptr, len); + let wide_ptr = slice as *mut RcBox<[mem::MaybeUninit]>; + let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr); + ptr::write(&mut (*wide_ptr).strong, Cell::new(1)); + ptr::write(&mut (*wide_ptr).weak, Cell::new(1)); + Rc { + ptr: NonNull::new_unchecked(wide_ptr), + phantom: PhantomData, + } + } + } +} + impl Rc> { /// Convert to `Rc`. /// @@ -519,7 +521,7 @@ impl Rc<[mem::MaybeUninit]> { /// /// use std::rc::Rc; /// - /// let mut values = Rc::::new_uninit_slice(3); + /// let mut values = Rc::<[u32]>::new_uninit_slice(3); /// /// let values = unsafe { /// // Deferred initialization: diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 3f47b9e6c7dae..93441437e45f5 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -348,50 +348,6 @@ impl Arc { } } - /// Construct a new reference-counted slice with uninitialized contents. - /// - /// # Examples - /// - /// ``` - /// #![feature(new_uninit)] - /// #![feature(get_mut_unchecked)] - /// - /// use std::sync::Arc; - /// - /// let mut values = Arc::::new_uninit_slice(3); - /// - /// let values = unsafe { - /// // Deferred initialization: - /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); - /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); - /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); - /// - /// values.assume_init() - /// }; - /// - /// assert_eq!(*values, [1, 2, 3]) - /// ``` - #[unstable(feature = "new_uninit", issue = "0")] - pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { - let data_layout = Layout::array::>(len).unwrap(); - let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); - unsafe { - let allocated_ptr = Global.alloc(layout) - .unwrap_or_else(|_| handle_alloc_error(layout)) - .as_ptr(); - let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit; - let slice: *mut [mem::MaybeUninit] = from_raw_parts_mut(data_ptr, len); - let wide_ptr = slice as *mut ArcInner<[mem::MaybeUninit]>; - let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr); - ptr::write(&mut (*wide_ptr).strong, atomic::AtomicUsize::new(1)); - ptr::write(&mut (*wide_ptr).weak, atomic::AtomicUsize::new(1)); - Arc { - ptr: NonNull::new_unchecked(wide_ptr), - phantom: PhantomData, - } - } - } - /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `data` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -442,6 +398,52 @@ impl Arc { } } +impl Arc<[T]> { + /// Construct a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut values = Arc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { + let data_layout = Layout::array::>(len).unwrap(); + let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); + unsafe { + let allocated_ptr = Global.alloc(layout) + .unwrap_or_else(|_| handle_alloc_error(layout)) + .as_ptr(); + let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit; + let slice: *mut [mem::MaybeUninit] = from_raw_parts_mut(data_ptr, len); + let wide_ptr = slice as *mut ArcInner<[mem::MaybeUninit]>; + let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr); + ptr::write(&mut (*wide_ptr).strong, atomic::AtomicUsize::new(1)); + ptr::write(&mut (*wide_ptr).weak, atomic::AtomicUsize::new(1)); + Arc { + ptr: NonNull::new_unchecked(wide_ptr), + phantom: PhantomData, + } + } + } +} + impl Arc> { /// Convert to `Arc`. /// @@ -503,7 +505,7 @@ impl Arc<[mem::MaybeUninit]> { /// /// use std::sync::Arc; /// - /// let mut values = Arc::::new_uninit_slice(3); + /// let mut values = Arc::<[u32]>::new_uninit_slice(3); /// /// let values = unsafe { /// // Deferred initialization: From 4eeb623e9ee35db03ec3281dcfd1c61194312404 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 6 Jul 2019 23:30:32 +0200 Subject: [PATCH 05/14] Fix intra-rustdoc links --- src/liballoc/boxed.rs | 4 ++++ src/liballoc/rc.rs | 6 +++++- src/liballoc/sync.rs | 6 +++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 6e296907ce8ae..3442fce467a70 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -200,6 +200,8 @@ impl Box> { /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// /// # Examples /// /// ``` @@ -234,6 +236,8 @@ impl Box<[mem::MaybeUninit]> { /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// /// # Examples /// /// ``` diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index aa1268ec05116..70911790be24e 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -471,6 +471,8 @@ impl Rc> { /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// /// # Examples /// /// ``` @@ -513,6 +515,8 @@ impl Rc<[mem::MaybeUninit]> { /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// /// # Examples /// /// ``` @@ -745,7 +749,7 @@ impl Rc { /// /// # Safety /// - /// There must be no other `Rc` or [`Weak`][weak] pointers to the same value. + /// There must be no other `Rc` or [`Weak`] pointers to the same value. /// This is the case for example immediately after `Rc::new`. /// /// # Examples diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 93441437e45f5..901d2d831d16b 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -455,6 +455,8 @@ impl Arc> { /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// /// # Examples /// /// ``` @@ -497,6 +499,8 @@ impl Arc<[mem::MaybeUninit]> { /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// /// # Examples /// /// ``` @@ -1130,7 +1134,7 @@ impl Arc { /// /// # Safety /// - /// There must be no other `Arc` or [`Weak`][weak] pointers to the same value. + /// There must be no other `Arc` or [`Weak`] pointers to the same value. /// This is the case for example immediately after `Rc::new`. /// /// # Examples From dab967afdc76904c971d5ac5f5f46e31272a9827 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 16 Jul 2019 09:02:36 +0200 Subject: [PATCH 06/14] Use `alloc::Global` in `Box::new_uninit` --- src/liballoc/boxed.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 3442fce467a70..9f6b16bbef33c 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -94,7 +94,7 @@ use core::ptr::{self, NonNull, Unique}; use core::slice; use core::task::{Context, Poll}; -use crate::alloc; +use crate::alloc::{self, Global, Alloc}; use crate::vec::Vec; use crate::raw_vec::RawVec; use crate::str::from_boxed_utf8_unchecked; @@ -144,9 +144,11 @@ impl Box { #[unstable(feature = "new_uninit", issue = "0")] pub fn new_uninit() -> Box> { let layout = alloc::Layout::new::>(); - let ptr = unsafe { alloc::alloc(layout) }; - let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout)); - Box(unique.cast()) + let ptr = unsafe { + Global.alloc(layout) + .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) + }; + Box(ptr.cast().into()) } /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then From 1141136b90663cf9d5ee6325b2f9e47f02e70746 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 16 Jul 2019 09:17:35 +0200 Subject: [PATCH 07/14] Use ManuallyDrop instead of mem::forget Per https://github.com/rust-lang/rust/pull/62451#discussion_r303197278 --- src/liballoc/rc.rs | 8 ++------ src/liballoc/sync.rs | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 70911790be24e..c76c4b50c64fa 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -495,10 +495,8 @@ impl Rc> { #[unstable(feature = "new_uninit", issue = "0")] #[inline] pub unsafe fn assume_init(self) -> Rc { - let ptr = self.ptr.cast(); - mem::forget(self); Rc { - ptr, + ptr: mem::ManuallyDrop::new(self).ptr.cast(), phantom: PhantomData, } } @@ -541,10 +539,8 @@ impl Rc<[mem::MaybeUninit]> { #[unstable(feature = "new_uninit", issue = "0")] #[inline] pub unsafe fn assume_init(self) -> Rc<[T]> { - let ptr = NonNull::new_unchecked(self.ptr.as_ptr() as _); - mem::forget(self); Rc { - ptr, + ptr: NonNull::new_unchecked(mem::ManuallyDrop::new(self).ptr.as_ptr() as _), phantom: PhantomData, } } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 901d2d831d16b..bc3acd27e8b4d 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -479,10 +479,8 @@ impl Arc> { #[unstable(feature = "new_uninit", issue = "0")] #[inline] pub unsafe fn assume_init(self) -> Arc { - let ptr = self.ptr.cast(); - mem::forget(self); Arc { - ptr, + ptr: mem::ManuallyDrop::new(self).ptr.cast(), phantom: PhantomData, } } @@ -525,10 +523,8 @@ impl Arc<[mem::MaybeUninit]> { #[unstable(feature = "new_uninit", issue = "0")] #[inline] pub unsafe fn assume_init(self) -> Arc<[T]> { - let ptr = NonNull::new_unchecked(self.ptr.as_ptr() as _); - mem::forget(self); Arc { - ptr, + ptr: NonNull::new_unchecked(mem::ManuallyDrop::new(self).ptr.as_ptr() as _), phantom: PhantomData, } } From 78264f5e3c94592ff64aab831499f48497083a91 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 5 Aug 2019 17:45:30 +0200 Subject: [PATCH 08/14] Add tracking issue numbers --- src/liballoc/boxed.rs | 8 ++++---- src/liballoc/rc.rs | 10 +++++----- src/liballoc/sync.rs | 10 +++++----- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 9f6b16bbef33c..e315b9f3417af 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -141,7 +141,7 @@ impl Box { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Box> { let layout = alloc::Layout::new::>(); let ptr = unsafe { @@ -181,7 +181,7 @@ impl Box<[T]> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { let layout = alloc::Layout::array::>(len).unwrap(); let ptr = unsafe { alloc::alloc(layout) }; @@ -220,7 +220,7 @@ impl Box> { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Box { Box(Box::into_unique(self).cast()) @@ -258,7 +258,7 @@ impl Box<[mem::MaybeUninit]> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Box<[T]> { Box(Unique::new_unchecked(Box::into_raw(self) as _)) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index c76c4b50c64fa..a9aa822173fdc 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -348,7 +348,7 @@ impl Rc { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Rc> { let layout = Layout::new::>>(); unsafe { @@ -438,7 +438,7 @@ impl Rc<[T]> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { let data_layout = Layout::array::>(len).unwrap(); let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); @@ -492,7 +492,7 @@ impl Rc> { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Rc { Rc { @@ -536,7 +536,7 @@ impl Rc<[mem::MaybeUninit]> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Rc<[T]> { Rc { @@ -762,7 +762,7 @@ impl Rc { /// assert_eq!(*x, "foo"); /// ``` #[inline] - #[unstable(feature = "get_mut_unchecked", issue = "0")] + #[unstable(feature = "get_mut_unchecked", issue = "63292")] pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { &mut this.ptr.as_mut().value } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index bc3acd27e8b4d..50fd98508930f 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -332,7 +332,7 @@ impl Arc { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Arc> { let layout = Layout::new::>>(); unsafe { @@ -422,7 +422,7 @@ impl Arc<[T]> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { let data_layout = Layout::array::>(len).unwrap(); let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); @@ -476,7 +476,7 @@ impl Arc> { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Arc { Arc { @@ -520,7 +520,7 @@ impl Arc<[mem::MaybeUninit]> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Arc<[T]> { Arc { @@ -1147,7 +1147,7 @@ impl Arc { /// assert_eq!(*x, "foo"); /// ``` #[inline] - #[unstable(feature = "get_mut_unchecked", issue = "0")] + #[unstable(feature = "get_mut_unchecked", issue = "63292")] pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { &mut this.ptr.as_mut().data } From ae1e201a0cd37a48bd3dabf1c643ccd5f53f7680 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 5 Aug 2019 17:50:44 +0200 Subject: [PATCH 09/14] Add a comment on the usage of Layout::new::>() --- src/liballoc/rc.rs | 2 ++ src/liballoc/sync.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index a9aa822173fdc..9d608c886b88e 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -441,6 +441,8 @@ impl Rc<[T]> { #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { let data_layout = Layout::array::>(len).unwrap(); + // This relies on `value` being the last field of `RcBox` in memory, + // so that the layout of `RcBox` is the same as that of `RcBox<()>` followed by `T`. let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); unsafe { let allocated_ptr = Global.alloc(layout) diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 50fd98508930f..1bd177be0d543 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -425,6 +425,8 @@ impl Arc<[T]> { #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { let data_layout = Layout::array::>(len).unwrap(); + // This relies on `value` being the last field of `RcBox` in memory, + // so that the layout of `RcBox` is the same as that of `RcBox<()>` followed by `T`. let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); unsafe { let allocated_ptr = Global.alloc(layout) From 810dfd7cd451c370d0c47d6aa9e62b16292a29e0 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 16 Aug 2019 17:44:24 +0200 Subject: [PATCH 10/14] Reuse more internal Rc and Arc methods --- src/liballoc/rc.rs | 42 +++++++----------------------------------- src/liballoc/sync.rs | 42 +++++++----------------------------------- 2 files changed, 14 insertions(+), 70 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 9d608c886b88e..abb09684260d0 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -350,17 +350,11 @@ impl Rc { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Rc> { - let layout = Layout::new::>>(); unsafe { - let mut ptr = Global.alloc(layout) - .unwrap_or_else(|_| handle_alloc_error(layout)) - .cast::>>(); - ptr::write(&mut ptr.as_mut().strong, Cell::new(1)); - ptr::write(&mut ptr.as_mut().weak, Cell::new(1)); - Rc { - ptr, - phantom: PhantomData, - } + Rc::from_ptr(Rc::allocate_for_unsized( + Layout::new::(), + |mem| mem as *mut RcBox>, + )) } } @@ -440,24 +434,8 @@ impl Rc<[T]> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { - let data_layout = Layout::array::>(len).unwrap(); - // This relies on `value` being the last field of `RcBox` in memory, - // so that the layout of `RcBox` is the same as that of `RcBox<()>` followed by `T`. - let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); unsafe { - let allocated_ptr = Global.alloc(layout) - .unwrap_or_else(|_| handle_alloc_error(layout)) - .as_ptr(); - let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit; - let slice: *mut [mem::MaybeUninit] = from_raw_parts_mut(data_ptr, len); - let wide_ptr = slice as *mut RcBox<[mem::MaybeUninit]>; - let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr); - ptr::write(&mut (*wide_ptr).strong, Cell::new(1)); - ptr::write(&mut (*wide_ptr).weak, Cell::new(1)); - Rc { - ptr: NonNull::new_unchecked(wide_ptr), - phantom: PhantomData, - } + Rc::from_ptr(Rc::allocate_for_slice(len)) } } } @@ -497,10 +475,7 @@ impl Rc> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Rc { - Rc { - ptr: mem::ManuallyDrop::new(self).ptr.cast(), - phantom: PhantomData, - } + Rc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) } } @@ -541,10 +516,7 @@ impl Rc<[mem::MaybeUninit]> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Rc<[T]> { - Rc { - ptr: NonNull::new_unchecked(mem::ManuallyDrop::new(self).ptr.as_ptr() as _), - phantom: PhantomData, - } + Rc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) } } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 1bd177be0d543..bb4d1499014c1 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -334,17 +334,11 @@ impl Arc { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Arc> { - let layout = Layout::new::>>(); unsafe { - let mut ptr = Global.alloc(layout) - .unwrap_or_else(|_| handle_alloc_error(layout)) - .cast::>>(); - ptr::write(&mut ptr.as_mut().strong, atomic::AtomicUsize::new(1)); - ptr::write(&mut ptr.as_mut().weak, atomic::AtomicUsize::new(1)); - Arc { - ptr, - phantom: PhantomData, - } + Arc::from_ptr(Arc::allocate_for_unsized( + Layout::new::(), + |mem| mem as *mut ArcInner>, + )) } } @@ -424,24 +418,8 @@ impl Arc<[T]> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { - let data_layout = Layout::array::>(len).unwrap(); - // This relies on `value` being the last field of `RcBox` in memory, - // so that the layout of `RcBox` is the same as that of `RcBox<()>` followed by `T`. - let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); unsafe { - let allocated_ptr = Global.alloc(layout) - .unwrap_or_else(|_| handle_alloc_error(layout)) - .as_ptr(); - let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit; - let slice: *mut [mem::MaybeUninit] = from_raw_parts_mut(data_ptr, len); - let wide_ptr = slice as *mut ArcInner<[mem::MaybeUninit]>; - let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr); - ptr::write(&mut (*wide_ptr).strong, atomic::AtomicUsize::new(1)); - ptr::write(&mut (*wide_ptr).weak, atomic::AtomicUsize::new(1)); - Arc { - ptr: NonNull::new_unchecked(wide_ptr), - phantom: PhantomData, - } + Arc::from_ptr(Arc::allocate_for_slice(len)) } } } @@ -481,10 +459,7 @@ impl Arc> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Arc { - Arc { - ptr: mem::ManuallyDrop::new(self).ptr.cast(), - phantom: PhantomData, - } + Arc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) } } @@ -525,10 +500,7 @@ impl Arc<[mem::MaybeUninit]> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Arc<[T]> { - Arc { - ptr: NonNull::new_unchecked(mem::ManuallyDrop::new(self).ptr.as_ptr() as _), - phantom: PhantomData, - } + Arc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) } } From 7a641f7c516ac666c72bf9edfbec8648aa0160c7 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 16 Aug 2019 17:45:44 +0200 Subject: [PATCH 11/14] Relax the safety condition for get_mut_unchecked --- src/liballoc/rc.rs | 6 ++++-- src/liballoc/sync.rs | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index abb09684260d0..1509afa48893f 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -719,8 +719,10 @@ impl Rc { /// /// # Safety /// - /// There must be no other `Rc` or [`Weak`] pointers to the same value. - /// This is the case for example immediately after `Rc::new`. + /// Any other `Rc` or [`Weak`] pointers to the same value must not be dereferenced + /// for the duration of the returned borrow. + /// This is trivially the case if no such pointer exist, + /// for example immediately after `Rc::new`. /// /// # Examples /// diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index bb4d1499014c1..078ddc27da9b9 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -1104,8 +1104,10 @@ impl Arc { /// /// # Safety /// - /// There must be no other `Arc` or [`Weak`] pointers to the same value. - /// This is the case for example immediately after `Rc::new`. + /// Any other `Arc` or [`Weak`] pointers to the same value must not be dereferenced + /// for the duration of the returned borrow. + /// This is trivially the case if no such pointer exist, + /// for example immediately after `Arc::new`. /// /// # Examples /// From ba0328327c8ce94f7bf380223d655c70de584e93 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 17 Aug 2019 15:15:17 +0200 Subject: [PATCH 12/14] Doc nits Co-Authored-By: Ralf Jung --- src/liballoc/boxed.rs | 8 ++++---- src/liballoc/rc.rs | 10 +++++----- src/liballoc/sync.rs | 10 +++++----- src/libcore/ptr/unique.rs | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index e315b9f3417af..c61e3183409f2 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -123,7 +123,7 @@ impl Box { box x } - /// Construct a new box with uninitialized contents. + /// Constructs a new box with uninitialized contents. /// /// # Examples /// @@ -161,7 +161,7 @@ impl Box { } impl Box<[T]> { - /// Construct a new boxed slice with uninitialized contents. + /// Constructs a new boxed slice with uninitialized contents. /// /// # Examples /// @@ -192,7 +192,7 @@ impl Box<[T]> { } impl Box> { - /// Convert to `Box`. + /// Converts to `Box`. /// /// # Safety /// @@ -228,7 +228,7 @@ impl Box> { } impl Box<[mem::MaybeUninit]> { - /// Convert to `Box<[T]>`. + /// Converts to `Box<[T]>`. /// /// # Safety /// diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 1509afa48893f..7183336ba5302 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -327,7 +327,7 @@ impl Rc { })) } - /// Construct a new Rc with uninitialized contents. + /// Constructs a new `Rc` with uninitialized contents. /// /// # Examples /// @@ -409,7 +409,7 @@ impl Rc { } impl Rc<[T]> { - /// Construct a new reference-counted slice with uninitialized contents. + /// Constructs a new reference-counted slice with uninitialized contents. /// /// # Examples /// @@ -441,7 +441,7 @@ impl Rc<[T]> { } impl Rc> { - /// Convert to `Rc`. + /// Converts to `Rc`. /// /// # Safety /// @@ -480,7 +480,7 @@ impl Rc> { } impl Rc<[mem::MaybeUninit]> { - /// Convert to `Rc<[T]>`. + /// Converts to `Rc<[T]>`. /// /// # Safety /// @@ -721,7 +721,7 @@ impl Rc { /// /// Any other `Rc` or [`Weak`] pointers to the same value must not be dereferenced /// for the duration of the returned borrow. - /// This is trivially the case if no such pointer exist, + /// This is trivially the case if no such pointers exist, /// for example immediately after `Rc::new`. /// /// # Examples diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 078ddc27da9b9..ffab842c76927 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -311,7 +311,7 @@ impl Arc { Self::from_inner(Box::into_raw_non_null(x)) } - /// Construct a Arc box with uninitialized contents. + /// Constructs a new `Arc` with uninitialized contents. /// /// # Examples /// @@ -393,7 +393,7 @@ impl Arc { } impl Arc<[T]> { - /// Construct a new reference-counted slice with uninitialized contents. + /// Constructs a new reference-counted slice with uninitialized contents. /// /// # Examples /// @@ -425,7 +425,7 @@ impl Arc<[T]> { } impl Arc> { - /// Convert to `Arc`. + /// Converts to `Arc`. /// /// # Safety /// @@ -464,7 +464,7 @@ impl Arc> { } impl Arc<[mem::MaybeUninit]> { - /// Convert to `Arc<[T]>`. + /// Converts to `Arc<[T]>`. /// /// # Safety /// @@ -1106,7 +1106,7 @@ impl Arc { /// /// Any other `Arc` or [`Weak`] pointers to the same value must not be dereferenced /// for the duration of the returned borrow. - /// This is trivially the case if no such pointer exist, + /// This is trivially the case if no such pointers exist, /// for example immediately after `Arc::new`. /// /// # Examples diff --git a/src/libcore/ptr/unique.rs b/src/libcore/ptr/unique.rs index a739f3b6022db..24f45394a3bd5 100644 --- a/src/libcore/ptr/unique.rs +++ b/src/libcore/ptr/unique.rs @@ -123,7 +123,7 @@ impl Unique { &mut *self.as_ptr() } - /// Cast to a pointer of another type + /// Casts to a pointer of another type #[inline] pub const fn cast(self) -> Unique { unsafe { From b79ce1b1b10d6de1dac516d5e129f8251725ebe2 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 17 Aug 2019 15:39:21 +0200 Subject: [PATCH 13/14] Rename private helper method allocate_for_unsized to allocate_for_layout --- src/liballoc/rc.rs | 10 +++++----- src/liballoc/sync.rs | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 7183336ba5302..2b222caf13f3d 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -351,7 +351,7 @@ impl Rc { #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Rc> { unsafe { - Rc::from_ptr(Rc::allocate_for_unsized( + Rc::from_ptr(Rc::allocate_for_layout( Layout::new::(), |mem| mem as *mut RcBox>, )) @@ -880,11 +880,11 @@ impl Rc { impl Rc { /// Allocates an `RcBox` with sufficient space for - /// an unsized value where the value has the layout provided. + /// a possibly-unsized value where the value has the layout provided. /// /// The function `mem_to_rcbox` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `RcBox`. - unsafe fn allocate_for_unsized( + unsafe fn allocate_for_layout( value_layout: Layout, mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox ) -> *mut RcBox { @@ -913,7 +913,7 @@ impl Rc { /// Allocates an `RcBox` with sufficient space for an unsized value unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox { // Allocate for the `RcBox` using the given value. - Self::allocate_for_unsized( + Self::allocate_for_layout( Layout::for_value(&*ptr), |mem| set_data_ptr(ptr as *mut T, mem) as *mut RcBox, ) @@ -944,7 +944,7 @@ impl Rc { impl Rc<[T]> { /// Allocates an `RcBox<[T]>` with the given length. unsafe fn allocate_for_slice(len: usize) -> *mut RcBox<[T]> { - Self::allocate_for_unsized( + Self::allocate_for_layout( Layout::array::(len).unwrap(), |mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut RcBox<[T]>, ) diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index ffab842c76927..341172136e258 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -335,7 +335,7 @@ impl Arc { #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Arc> { unsafe { - Arc::from_ptr(Arc::allocate_for_unsized( + Arc::from_ptr(Arc::allocate_for_layout( Layout::new::(), |mem| mem as *mut ArcInner>, )) @@ -736,11 +736,11 @@ impl Arc { impl Arc { /// Allocates an `ArcInner` with sufficient space for - /// an unsized value where the value has the layout provided. + /// a possibly-unsized value where the value has the layout provided. /// /// The function `mem_to_arcinner` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `ArcInner`. - unsafe fn allocate_for_unsized( + unsafe fn allocate_for_layout( value_layout: Layout, mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner ) -> *mut ArcInner { @@ -768,7 +768,7 @@ impl Arc { /// Allocates an `ArcInner` with sufficient space for an unsized value. unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner { // Allocate for the `ArcInner` using the given value. - Self::allocate_for_unsized( + Self::allocate_for_layout( Layout::for_value(&*ptr), |mem| set_data_ptr(ptr as *mut T, mem) as *mut ArcInner, ) @@ -799,7 +799,7 @@ impl Arc { impl Arc<[T]> { /// Allocates an `ArcInner<[T]>` with the given length. unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> { - Self::allocate_for_unsized( + Self::allocate_for_layout( Layout::array::(len).unwrap(), |mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut ArcInner<[T]>, ) From 9bd70834b0084f17d622b204a22dc80835d8d962 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 17 Aug 2019 21:40:35 +0200 Subject: [PATCH 14/14] Doc nit Co-Authored-By: Ralf Jung --- src/libcore/ptr/unique.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ptr/unique.rs b/src/libcore/ptr/unique.rs index 24f45394a3bd5..3521dd7997956 100644 --- a/src/libcore/ptr/unique.rs +++ b/src/libcore/ptr/unique.rs @@ -123,7 +123,7 @@ impl Unique { &mut *self.as_ptr() } - /// Casts to a pointer of another type + /// Casts to a pointer of another type. #[inline] pub const fn cast(self) -> Unique { unsafe {