From d116f48788645f2b5ff5cd409f4ac8ba84f906ad Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 22 Dec 2020 12:10:18 -0800 Subject: [PATCH 1/7] Add fallible box allocator APIs (`Box::try_new_*_in()`) --- library/alloc/src/boxed.rs | 86 +++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index a6360f25eca31..bc56c7a3c4fbb 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -153,7 +153,7 @@ use core::pin::Pin; use core::ptr::{self, Unique}; use core::task::{Context, Poll}; -use crate::alloc::{handle_alloc_error, Allocator, Global, Layout}; +use crate::alloc::{handle_alloc_error, AllocError, Allocator, Global, Layout}; use crate::borrow::Cow; use crate::raw_vec::RawVec; use crate::str::from_boxed_utf8_unchecked; @@ -267,6 +267,31 @@ impl Box { } } + /// Allocates memory in the given allocator then places `x` into it, + /// returning an error if the allocation fails + /// + /// This doesn't actually allocate if `T` is zero-sized. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let five = Box::try_new_in(5, System)?; + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new_in(x: T, alloc: A) -> Result { + let mut boxed = Self::try_new_uninit_in(alloc)?; + unsafe { + boxed.as_mut_ptr().write(x); + Ok(boxed.assume_init()) + } + } + /// Constructs a new box with uninitialized contents in the provided allocator. /// /// # Examples @@ -295,6 +320,36 @@ impl Box { unsafe { Box::from_raw_in(ptr.as_ptr(), alloc) } } + /// Constructs a new box with uninitialized contents in the provided allocator, + /// returning an error if the allocation fails + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// use std::alloc::System; + /// + /// let mut five = Box::::try_new_uninit_in(System)?; + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> { + let layout = Layout::new::>(); + let ptr = alloc.allocate(layout)?.cast(); + unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) } + } + /// Constructs a new `Box` with uninitialized contents, with the memory /// being filled with `0` bytes in the provided allocator. /// @@ -324,6 +379,35 @@ impl Box { unsafe { Box::from_raw_in(ptr.as_ptr(), alloc) } } + /// Constructs a new `Box` with uninitialized contents, with the memory + /// being filled with `0` bytes in the provided allocator. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// use std::alloc::System; + /// + /// let zero = Box::::try_new_zeroed_in(System)?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> { + let layout = Layout::new::>(); + let ptr = alloc.allocate_zeroed(layout)?.cast(); + unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) } + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `x` will be pinned in memory and unable to be moved. #[unstable(feature = "allocator_api", issue = "32838")] From dd2c6c318bfe3191e936f4500d60b5089db1ef60 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 31 Dec 2020 06:40:17 +0000 Subject: [PATCH 2/7] Add fallible box APIs (`Box::try_new_*`) --- library/alloc/src/boxed.rs | 74 +++++++++++++++++++++++++++++++++++++- library/alloc/src/rc.rs | 22 ++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index bc56c7a3c4fbb..eb00d1a8b47f1 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -241,6 +241,77 @@ impl Box { pub fn pin(x: T) -> Pin> { (box x).into() } + + /// Allocates memory on the heap then places `x` into it, + /// returning an error if the allocation fails + /// + /// This doesn't actually allocate if `T` is zero-sized. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// let five = Box::try_new(5)?; + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new(x: T) -> Result { + Self::try_new_in(x, Global) + } + + /// Constructs a new box with uninitialized contents on the heap, + /// returning an error if the allocation fails + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// + /// let mut five = Box::::try_new_uninit()?; + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_uninit() -> Result>, AllocError> { + Box::try_new_uninit_in(Global) + } + + /// Constructs a new `Box` with uninitialized contents, with the memory + /// being filled with `0` bytes on the heap + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// let zero = Box::::try_new_zeroed()?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_zeroed() -> Result>, AllocError> { + Box::try_new_zeroed_in(Global) + } } impl Box { @@ -380,7 +451,8 @@ impl Box { } /// Constructs a new `Box` with uninitialized contents, with the memory - /// being filled with `0` bytes in the provided allocator. + /// being filled with `0` bytes in the provided allocator, + /// returning an error if the allocation fails, /// /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage /// of this method. diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index a96be57143d38..739ffd31f60b5 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -346,6 +346,28 @@ impl Rc { ) } + /// Constructs a new `Rc`. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn try_new(value: T) -> Result, AllocError> { + // There is an implicit weak pointer owned by all the strong + // pointers, which ensures that the weak destructor never frees + // the allocation while the strong destructor is running, even + // if the weak pointer is stored inside the strong one. + Ok(Self::from_inner( + Box::leak(Box::try_new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })?) + .into(), + )) + } + /// Constructs a new `Rc` using a weak reference to itself. Attempting /// to upgrade the weak reference before this function returns will result /// in a `None` value. However, the weak reference may be cloned freely and From 973fa8e30eb2f699db4337624e193d0994666c7c Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 31 Dec 2020 08:14:16 +0000 Subject: [PATCH 3/7] Add fallible Rc APIs (`Rc::try_new_*`) --- library/alloc/src/rc.rs | 143 +++++++++++++++++++++++++++++++++------- 1 file changed, 121 insertions(+), 22 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 739ffd31f60b5..afaefaa2565e8 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -346,28 +346,6 @@ impl Rc { ) } - /// Constructs a new `Rc`. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_api, new_uninit)] - /// use std::rc::Rc; - /// - /// let five = Rc::new(5); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn try_new(value: T) -> Result, AllocError> { - // There is an implicit weak pointer owned by all the strong - // pointers, which ensures that the weak destructor never frees - // the allocation while the strong destructor is running, even - // if the weak pointer is stored inside the strong one. - Ok(Self::from_inner( - Box::leak(Box::try_new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })?) - .into(), - )) - } - /// Constructs a new `Rc` using a weak reference to itself. Attempting /// to upgrade the weak reference before this function returns will result /// in a `None` value. However, the weak reference may be cloned freely and @@ -475,6 +453,95 @@ impl Rc { } } + /// Constructs a new `Rc`, returning an error if the allocation fails + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::rc::Rc; + /// + /// let five = Rc::try_new(5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn try_new(value: T) -> Result, AllocError> { + // There is an implicit weak pointer owned by all the strong + // pointers, which ensures that the weak destructor never frees + // the allocation while the strong destructor is running, even + // if the weak pointer is stored inside the strong one. + Ok(Self::from_inner( + Box::leak(Box::try_new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })?) + .into(), + )) + } + + /// Constructs a new `Rc` with uninitialized contents, returning an error if the allocation fails + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::::try_new_uninit()?; + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_uninit() -> Result>, AllocError> { + unsafe { + Ok(Rc::from_ptr(Rc::try_allocate_for_layout( + Layout::new::(), + |layout| Global.allocate(layout), + |mem| mem as *mut RcBox>, + )?)) + } + } + + /// Constructs a new `Rc` with uninitialized contents, with the memory + /// being filled with `0` bytes, returning an error if the allocation fails + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// use std::rc::Rc; + /// + /// let zero = Rc::::try_new_zeroed()?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + //#[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_zeroed() -> Result>, AllocError> { + unsafe { + Ok(Rc::from_ptr(Rc::try_allocate_for_layout( + Layout::new::(), + |layout| Global.allocate_zeroed(layout), + |mem| mem as *mut RcBox>, + )?)) + } + } /// 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")] @@ -1056,6 +1123,38 @@ impl Rc { inner } + /// Allocates an `RcBox` with sufficient space for + /// a possibly-unsized inner value where the value has the layout provided, + /// returning an error if allocation fails. + /// + /// The function `mem_to_rcbox` is called with the data pointer + /// and must return back a (potentially fat)-pointer for the `RcBox`. + unsafe fn try_allocate_for_layout( + value_layout: Layout, + allocate: impl FnOnce(Layout) -> Result, AllocError>, + mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox, + ) -> Result<*mut RcBox, AllocError> { + // Calculate layout using the given value layout. + // Previously, layout was calculated on the expression + // `&*(ptr as *const RcBox)`, but this created a misaligned + // reference (see #54908). + let layout = Layout::new::>().extend(value_layout).unwrap().0.pad_to_align(); + + // Allocate for the layout. + let ptr = allocate(layout)?; + + // Initialize the RcBox + let inner = mem_to_rcbox(ptr.as_non_null_ptr().as_ptr()); + unsafe { + debug_assert_eq!(Layout::for_value(&*inner), layout); + + ptr::write(&mut (*inner).strong, Cell::new(1)); + ptr::write(&mut (*inner).weak, Cell::new(1)); + } + + Ok(inner) + } + /// Allocates an `RcBox` with sufficient space for an unsized inner value unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox { // Allocate for the `RcBox` using the given value. From bb15fa1da0501324783d901ddb7d9d7e1ba53080 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 31 Dec 2020 08:30:23 +0000 Subject: [PATCH 4/7] Add fallible Arc APIs (`Arc::try_new_*`) --- library/alloc/src/sync.rs | 122 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 9d478a302e96c..e8c3d1293e7b1 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -478,6 +478,97 @@ impl Arc { unsafe { Pin::new_unchecked(Arc::new(data)) } } + /// Constructs a new `Arc`, returning an error if allocation fails. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::sync::Arc; + /// + /// let five = Arc::try_new(5)?; + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new(data: T) -> Result, AllocError> { + // Start the weak pointer count as 1 which is the weak pointer that's + // held by all the strong pointers (kinda), see std/rc.rs for more info + let x: Box<_> = Box::try_new(ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data, + })?; + Ok(Self::from_inner(Box::leak(x).into())) + } + + /// Constructs a new `Arc` with uninitialized contents, returning an error + /// if allocation fails. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit, allocator_api)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::::try_new_uninit()?; + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_uninit() -> Result>, AllocError> { + unsafe { + Ok(Arc::from_ptr(Arc::try_allocate_for_layout( + Layout::new::(), + |layout| Global.allocate(layout), + |mem| mem as *mut ArcInner>, + )?)) + } + } + + /// Constructs a new `Arc` with uninitialized contents, with the memory + /// being filled with `0` bytes, returning an error if allocation fails. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit, allocator_api)] + /// + /// use std::sync::Arc; + /// + /// let zero = Arc::::try_new_zeroed()?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_zeroed() -> Result>, AllocError> { + unsafe { + Ok(Arc::from_ptr(Arc::try_allocate_for_layout( + Layout::new::(), + |layout| Global.allocate_zeroed(layout), + |mem| mem as *mut ArcInner>, + )?)) + } + } /// Returns the inner value, if the `Arc` has exactly one strong reference. /// /// Otherwise, an [`Err`] is returned with the same `Arc` that was @@ -1009,6 +1100,37 @@ impl Arc { inner } + /// Allocates an `ArcInner` with sufficient space for + /// a possibly-unsized inner value where the value has the layout provided, + /// returning an error if allocation fails. + /// + /// The function `mem_to_arcinner` is called with the data pointer + /// and must return back a (potentially fat)-pointer for the `ArcInner`. + unsafe fn try_allocate_for_layout( + value_layout: Layout, + allocate: impl FnOnce(Layout) -> Result, AllocError>, + mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, + ) -> Result<*mut ArcInner, AllocError> { + // Calculate layout using the given value layout. + // Previously, layout was calculated on the expression + // `&*(ptr as *const ArcInner)`, but this created a misaligned + // reference (see #54908). + let layout = Layout::new::>().extend(value_layout).unwrap().0.pad_to_align(); + + let ptr = allocate(layout)?; + + // Initialize the ArcInner + let inner = mem_to_arcinner(ptr.as_non_null_ptr().as_ptr()); + debug_assert_eq!(unsafe { Layout::for_value(&*inner) }, layout); + + unsafe { + ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1)); + ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1)); + } + + Ok(inner) + } + /// Allocates an `ArcInner` with sufficient space for an unsized inner value. unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner { // Allocate for the `ArcInner` using the given value. From 589aa8e29c8b21a450ea6a78a387f6c0ac060fa4 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 31 Dec 2020 08:43:30 +0000 Subject: [PATCH 5/7] Reuse Box::try_new_*_in() in Box::new_*_in() --- library/alloc/src/boxed.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index eb00d1a8b47f1..4391176c8bee0 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -387,8 +387,7 @@ impl Box { // #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_in(alloc: A) -> Box, A> { let layout = Layout::new::>(); - let ptr = alloc.allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout)).cast(); - unsafe { Box::from_raw_in(ptr.as_ptr(), alloc) } + Box::try_new_uninit_in(alloc).unwrap_or_else(|_| handle_alloc_error(layout)) } /// Constructs a new box with uninitialized contents in the provided allocator, @@ -445,9 +444,7 @@ impl Box { // #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_zeroed_in(alloc: A) -> Box, A> { let layout = Layout::new::>(); - let ptr = - alloc.allocate_zeroed(layout).unwrap_or_else(|_| handle_alloc_error(layout)).cast(); - unsafe { Box::from_raw_in(ptr.as_ptr(), alloc) } + Box::try_new_zeroed_in(alloc).unwrap_or_else(|_| handle_alloc_error(layout)) } /// Constructs a new `Box` with uninitialized contents, with the memory From 8f3cb7d75d0271066a11502d331333dc804e5d14 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 31 Dec 2020 16:36:28 +0000 Subject: [PATCH 6/7] Make [A]Rc::allocate_for_layout() use try_allocate_for_layout() --- library/alloc/src/rc.rs | 15 +++------------ library/alloc/src/sync.rs | 13 ++----------- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index afaefaa2565e8..5f5c3c19a8115 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1107,20 +1107,10 @@ impl Rc { // `&*(ptr as *const RcBox)`, but this created a misaligned // reference (see #54908). let layout = Layout::new::>().extend(value_layout).unwrap().0.pad_to_align(); - - // Allocate for the layout. - let ptr = allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout)); - - // Initialize the RcBox - let inner = mem_to_rcbox(ptr.as_non_null_ptr().as_ptr()); unsafe { - debug_assert_eq!(Layout::for_value(&*inner), layout); - - ptr::write(&mut (*inner).strong, Cell::new(1)); - ptr::write(&mut (*inner).weak, Cell::new(1)); + Rc::try_allocate_for_layout(value_layout, allocate, mem_to_rcbox) + .unwrap_or_else(|_| handle_alloc_error(layout)) } - - inner } /// Allocates an `RcBox` with sufficient space for @@ -1129,6 +1119,7 @@ impl Rc { /// /// The function `mem_to_rcbox` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `RcBox`. + #[inline] unsafe fn try_allocate_for_layout( value_layout: Layout, allocate: impl FnOnce(Layout) -> Result, AllocError>, diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index e8c3d1293e7b1..83032f7feeedd 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1085,19 +1085,10 @@ impl Arc { // `&*(ptr as *const ArcInner)`, but this created a misaligned // reference (see #54908). let layout = Layout::new::>().extend(value_layout).unwrap().0.pad_to_align(); - - let ptr = allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout)); - - // Initialize the ArcInner - let inner = mem_to_arcinner(ptr.as_non_null_ptr().as_ptr()); - debug_assert_eq!(unsafe { Layout::for_value(&*inner) }, layout); - unsafe { - ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1)); - ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1)); + Arc::try_allocate_for_layout(value_layout, allocate, mem_to_arcinner) + .unwrap_or_else(|_| handle_alloc_error(layout)) } - - inner } /// Allocates an `ArcInner` with sufficient space for From 375e7c58644d1f7959bfd33caf455d6aa34cc326 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 31 Dec 2020 16:48:51 +0000 Subject: [PATCH 7/7] More inline, doc fixes --- library/alloc/src/boxed.rs | 3 ++- library/alloc/src/sync.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 4391176c8bee0..8eb2caa60b126 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -269,7 +269,6 @@ impl Box { /// ``` /// #![feature(allocator_api, new_uninit)] /// - /// /// let mut five = Box::::try_new_uninit()?; /// /// let five = unsafe { @@ -284,6 +283,7 @@ impl Box { /// ``` #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] pub fn try_new_uninit() -> Result>, AllocError> { Box::try_new_uninit_in(Global) } @@ -309,6 +309,7 @@ impl Box { /// [zeroed]: mem::MaybeUninit::zeroed #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] pub fn try_new_zeroed() -> Result>, AllocError> { Box::try_new_zeroed_in(Global) } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 83032f7feeedd..5aaf521b4e0d5 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -557,7 +557,7 @@ impl Arc { /// # Ok::<(), std::alloc::AllocError>(()) /// ``` /// - /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed + /// [zeroed]: mem::MaybeUninit::zeroed #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] pub fn try_new_zeroed() -> Result>, AllocError> {