From 2134c8e8c5a0b0a2ccaac52e45eaa70b691ca2fa Mon Sep 17 00:00:00 2001 From: Zachary S Date: Fri, 19 Jan 2024 18:41:02 -0600 Subject: [PATCH] Relax allocator bounds on more Arc/Rc methods/impls. Remove `A: Clone` bound from: * `downcast`, `downcast_unchecked`, `unwrap_or_clone` for both. * `From> for Arc<[T], A>` (Rc's already didn't require A: Clone) * `TryFrom> for Arc<[T; N], A>` Make existing `TryFrom> for Rc<[T; N]>` allocator-aware. --- library/alloc/src/rc.rs | 35 ++++++++++++++++++----------------- library/alloc/src/sync.rs | 34 +++++++++++++++++----------------- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 45e66fe82ce5a..a7ea167055e0b 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1760,7 +1760,9 @@ impl Rc { // reference to the allocation. unsafe { &mut this.ptr.as_mut().value } } +} +impl Rc { /// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the /// clone. /// @@ -1796,7 +1798,7 @@ impl Rc { } } -impl Rc { +impl Rc { /// Attempt to downcast the `Rc` to a concrete type. /// /// # Examples @@ -1819,12 +1821,11 @@ impl Rc { #[stable(feature = "rc_downcast", since = "1.29.0")] pub fn downcast(self) -> Result, Self> { if (*self).is::() { - unsafe { - let ptr = self.ptr.cast::>(); - let alloc = self.alloc.clone(); - forget(self); - Ok(Rc::from_inner_in(ptr, alloc)) - } + let this = mem::ManuallyDrop::new(self); + let ptr = this.ptr.cast::>(); + // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped + let alloc = unsafe { ptr::read(&this.alloc) }; + unsafe { Ok(Rc::from_inner_in(ptr, alloc)) } } else { Err(self) } @@ -1859,12 +1860,11 @@ impl Rc { #[inline] #[unstable(feature = "downcast_unchecked", issue = "90850")] pub unsafe fn downcast_unchecked(self) -> Rc { - unsafe { - let ptr = self.ptr.cast::>(); - let alloc = self.alloc.clone(); - mem::forget(self); - Rc::from_inner_in(ptr, alloc) - } + let this = mem::ManuallyDrop::new(self); + let ptr = this.ptr.cast::>(); + // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped + let alloc = unsafe { ptr::read(&this.alloc) }; + unsafe { Rc::from_inner_in(ptr, alloc) } } } @@ -2604,12 +2604,13 @@ impl From> for Rc<[u8]> { } #[stable(feature = "boxed_slice_try_from", since = "1.43.0")] -impl TryFrom> for Rc<[T; N]> { - type Error = Rc<[T]>; +impl TryFrom> for Rc<[T; N], A> { + type Error = Rc<[T], A>; - fn try_from(boxed_slice: Rc<[T]>) -> Result { + fn try_from(boxed_slice: Rc<[T], A>) -> Result { if boxed_slice.len() == N { - Ok(unsafe { Rc::from_raw(Rc::into_raw(boxed_slice) as *mut [T; N]) }) + let (ptr, alloc) = Rc::into_raw_with_allocator(boxed_slice); + Ok(unsafe { Rc::from_raw_in(ptr as *mut [T; N], alloc) }) } else { Err(boxed_slice) } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 3f703b8b2e841..ec55befbd0d43 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2187,7 +2187,9 @@ impl Arc { // either unique to begin with, or became one upon cloning the contents. unsafe { Self::get_mut_unchecked(this) } } +} +impl Arc { /// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the /// clone. /// @@ -2432,7 +2434,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Arc { } } -impl Arc { +impl Arc { /// Attempt to downcast the `Arc` to a concrete type. /// /// # Examples @@ -2458,12 +2460,11 @@ impl Arc { T: Any + Send + Sync, { if (*self).is::() { - unsafe { - let ptr = self.ptr.cast::>(); - let alloc = self.alloc.clone(); - mem::forget(self); - Ok(Arc::from_inner_in(ptr, alloc)) - } + let this = mem::ManuallyDrop::new(self); + let ptr = this.ptr.cast::>(); + // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped + let alloc = unsafe { ptr::read(&this.alloc) }; + unsafe { Ok(Arc::from_inner_in(ptr, alloc)) } } else { Err(self) } @@ -2501,12 +2502,11 @@ impl Arc { where T: Any + Send + Sync, { - unsafe { - let ptr = self.ptr.cast::>(); - let alloc = self.alloc.clone(); - mem::forget(self); - Arc::from_inner_in(ptr, alloc) - } + let this = mem::ManuallyDrop::new(self); + let ptr = this.ptr.cast::>(); + // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped + let alloc = unsafe { ptr::read(&this.alloc) }; + unsafe { Arc::from_inner_in(ptr, alloc) } } } @@ -3432,7 +3432,7 @@ impl From> for Arc { #[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] -impl From> for Arc<[T], A> { +impl From> for Arc<[T], A> { /// Allocate a reference-counted slice and move `v`'s items into it. /// /// # Example @@ -3507,13 +3507,13 @@ impl From> for Arc<[u8]> { } #[stable(feature = "boxed_slice_try_from", since = "1.43.0")] -impl TryFrom> for Arc<[T; N], A> { +impl TryFrom> for Arc<[T; N], A> { type Error = Arc<[T], A>; fn try_from(boxed_slice: Arc<[T], A>) -> Result { if boxed_slice.len() == N { - let alloc = boxed_slice.alloc.clone(); - Ok(unsafe { Arc::from_raw_in(Arc::into_raw(boxed_slice) as *mut [T; N], alloc) }) + let (ptr, alloc) = Arc::into_raw_with_allocator(boxed_slice); + Ok(unsafe { Arc::from_raw_in(ptr as *mut [T; N], alloc) }) } else { Err(boxed_slice) }