From f05b63b8531291dd8b57da38a7bde99cab11ee55 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Mon, 29 Apr 2024 18:08:43 -0500 Subject: [PATCH 1/6] Make `Rc` `allocator_api` APIs more consistent. * Add `into_raw_with_allocator` on `Rc`/`Weak` * Remove `where A: Clone` from `Rc::assume_init`s, `Rc::unwrap_or_clone`, and `Rc::downcast(_unchecked)` * Add `fn allocator(&self)` to `Rc`/`Weak` for all `T: ?Sized` * Make `TryFrom> for Rc<[T; N]>` allocator-aware --- library/alloc/src/rc.rs | 131 +++++++++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 49 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index c245b42c3e880..d0f02e9d7d782 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -661,16 +661,6 @@ impl Rc { } impl Rc { - /// Returns a reference to the underlying allocator. - /// - /// Note: this is an associated function, which means that you have - /// to call it as `Rc::allocator(&r)` instead of `r.allocator()`. This - /// is so that there is no conflict with a method on the inner type. - #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] - pub fn allocator(this: &Self) -> &A { - &this.alloc - } /// Constructs a new `Rc` in the provided allocator. /// /// # Examples @@ -1145,12 +1135,9 @@ impl Rc, A> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] #[inline] - pub unsafe fn assume_init(self) -> Rc - where - A: Clone, - { - let md_self = mem::ManuallyDrop::new(self); - unsafe { Rc::from_inner_in(md_self.ptr.cast(), md_self.alloc.clone()) } + pub unsafe fn assume_init(self) -> Rc { + let (ptr, alloc) = Self::into_raw_with_allocator(self); + unsafe { Rc::from_raw_in(ptr.cast(), alloc) } } } @@ -1189,12 +1176,9 @@ impl Rc<[mem::MaybeUninit], A> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] #[inline] - pub unsafe fn assume_init(self) -> Rc<[T], A> - where - A: Clone, - { - let md_self = mem::ManuallyDrop::new(self); - unsafe { Rc::from_ptr_in(md_self.ptr.as_ptr() as _, md_self.alloc.clone()) } + pub unsafe fn assume_init(self) -> Rc<[T], A> { + let (ptr, alloc) = Self::into_raw_with_allocator(self); + unsafe { Rc::from_raw_in(ptr as *const [T], alloc) } } } @@ -1333,6 +1317,17 @@ impl Rc { } impl Rc { + /// Returns a reference to the underlying allocator. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Rc::allocator(&r)` instead of `r.allocator()`. This + /// is so that there is no conflict with a method on the inner type. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn allocator(this: &Self) -> &A { + &this.alloc + } + /// Consumes the `Rc`, returning the wrapped pointer. /// /// To avoid a memory leak the pointer must be converted back to an `Rc` using @@ -1356,6 +1351,33 @@ impl Rc { ptr } + /// Consumes the `Rc`, returning the wrapped pointer and allocator. + /// + /// To avoid a memory leak the pointer must be converted back to an `Rc` using + /// [`Rc::from_raw_in`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::rc::Rc; + /// use std::alloc::System; + /// + /// let x = Rc::new_in("hello".to_owned(), System); + /// let (ptr, alloc) = Rc::into_raw_with_allocator(x); + /// assert_eq!(unsafe { &*ptr }, "hello"); + /// let x = unsafe { Rc::from_raw_in(ptr, alloc) }; + /// assert_eq!(&*x, "hello"); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn into_raw_with_allocator(this: Self) -> (*const T, A) { + let this = mem::ManuallyDrop::new(this); + let ptr = Self::as_ptr(&this); + // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped + let alloc = unsafe { ptr::read(Self::allocator(&this)) }; + (ptr, alloc) + } + /// Provides a raw pointer to the data. /// /// The counts are not affected in any way and the `Rc` is not consumed. The pointer is valid @@ -1809,7 +1831,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. /// @@ -1845,7 +1869,7 @@ impl Rc { } } -impl Rc { +impl Rc { /// Attempt to downcast the `Rc` to a concrete type. /// /// # Examples @@ -1868,12 +1892,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) } @@ -1908,12 +1931,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) } } } @@ -2661,12 +2683,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) } @@ -2923,6 +2946,13 @@ impl Weak { } impl Weak { + /// Returns a reference to the underlying allocator. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn allocator(&self) -> &A { + &self.alloc + } + /// Returns a raw pointer to the object `T` pointed to by this `Weak`. /// /// The pointer is valid only if there are some strong references. The pointer may be dangling, @@ -3000,11 +3030,11 @@ impl Weak { result } - /// Consumes the `Weak` and turns it into a raw pointer. + /// Consumes the `Weak`, returning the wrapped pointer and allocator. /// /// This converts the weak pointer into a raw pointer, while still preserving the ownership of /// one weak reference (the weak count is not modified by this operation). It can be turned - /// back into the `Weak` with [`from_raw`]. + /// back into the `Weak` with [`from_raw_in`]. /// /// The same restrictions of accessing the target of the pointer as with /// [`as_ptr`] apply. @@ -3012,27 +3042,30 @@ impl Weak { /// # Examples /// /// ``` + /// #![feature(allocator_api)] /// use std::rc::{Rc, Weak}; + /// use std::alloc::System; /// - /// let strong = Rc::new("hello".to_owned()); + /// let strong = Rc::new_in("hello".to_owned(), System); /// let weak = Rc::downgrade(&strong); - /// let raw = weak.into_raw(); + /// let (raw, alloc) = weak.into_raw_with_allocator(); /// /// assert_eq!(1, Rc::weak_count(&strong)); /// assert_eq!("hello", unsafe { &*raw }); /// - /// drop(unsafe { Weak::from_raw(raw) }); + /// drop(unsafe { Weak::from_raw_in(raw, alloc) }); /// assert_eq!(0, Rc::weak_count(&strong)); /// ``` /// - /// [`from_raw`]: Weak::from_raw + /// [`from_raw_in`]: Weak::from_raw_in /// [`as_ptr`]: Weak::as_ptr #[inline] #[unstable(feature = "allocator_api", issue = "32838")] - pub fn into_raw_and_alloc(self) -> (*const T, A) { - let rc = mem::ManuallyDrop::new(self); - let result = rc.as_ptr(); - let alloc = unsafe { ptr::read(&rc.alloc) }; + pub fn into_raw_with_allocator(self) -> (*const T, A) { + let this = mem::ManuallyDrop::new(self); + let result = this.as_ptr(); + // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped + let alloc = unsafe { ptr::read(this.allocator()) }; (result, alloc) } From f9d73078e40773962b707f1b5f4791ba113f2ea1 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sun, 18 Feb 2024 21:36:41 -0600 Subject: [PATCH 2/6] make internal_into_inner_with_allocator an associated fn to prevent name collisions --- library/alloc/src/sync.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 297a273d274bf..2b8efdc400bd9 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -280,8 +280,8 @@ impl Arc { impl Arc { #[inline] - fn internal_into_inner_with_allocator(self) -> (NonNull>, A) { - let this = mem::ManuallyDrop::new(self); + fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { + let this = mem::ManuallyDrop::new(this); (this.ptr, unsafe { ptr::read(&this.alloc) }) } @@ -1290,7 +1290,7 @@ impl Arc, A> { #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub unsafe fn assume_init(self) -> Arc { - let (ptr, alloc) = self.internal_into_inner_with_allocator(); + let (ptr, alloc) = Arc::into_inner_with_allocator(self); unsafe { Arc::from_inner_in(ptr.cast(), alloc) } } } @@ -1332,7 +1332,7 @@ impl Arc<[mem::MaybeUninit], A> { #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub unsafe fn assume_init(self) -> Arc<[T], A> { - let (ptr, alloc) = self.internal_into_inner_with_allocator(); + let (ptr, alloc) = Arc::into_inner_with_allocator(self); unsafe { Arc::from_ptr_in(ptr.as_ptr() as _, alloc) } } } @@ -2499,7 +2499,7 @@ impl Arc { { if (*self).is::() { unsafe { - let (ptr, alloc) = self.internal_into_inner_with_allocator(); + let (ptr, alloc) = Arc::into_inner_with_allocator(self); Ok(Arc::from_inner_in(ptr.cast(), alloc)) } } else { @@ -2540,7 +2540,7 @@ impl Arc { T: Any + Send + Sync, { unsafe { - let (ptr, alloc) = self.internal_into_inner_with_allocator(); + let (ptr, alloc) = Arc::into_inner_with_allocator(self); Arc::from_inner_in(ptr.cast(), alloc) } } @@ -3506,7 +3506,7 @@ impl TryFrom> for Arc<[T; N], A> { fn try_from(boxed_slice: Arc<[T], A>) -> Result { if boxed_slice.len() == N { - let (ptr, alloc) = boxed_slice.internal_into_inner_with_allocator(); + let (ptr, alloc) = Arc::into_inner_with_allocator(boxed_slice); Ok(unsafe { Arc::from_inner_in(ptr.cast(), alloc) }) } else { Err(boxed_slice) From a2002eca054a376c071042c56c7b50504b7e4898 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sun, 18 Feb 2024 21:37:49 -0600 Subject: [PATCH 3/6] Move Arc::allocator to T: ?Sized --- library/alloc/src/sync.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 2b8efdc400bd9..0cc62d9fafb7a 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -683,16 +683,6 @@ impl Arc { } impl Arc { - /// Returns a reference to the underlying allocator. - /// - /// Note: this is an associated function, which means that you have - /// to call it as `Arc::allocator(&a)` instead of `a.allocator()`. This - /// is so that there is no conflict with a method on the inner type. - #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] - pub fn allocator(this: &Self) -> &A { - &this.alloc - } /// Constructs a new `Arc` in the provided allocator. /// /// # Examples @@ -1473,6 +1463,17 @@ impl Arc { } impl Arc { + /// Returns a reference to the underlying allocator. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Arc::allocator(&a)` instead of `a.allocator()`. This + /// is so that there is no conflict with a method on the inner type. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn allocator(this: &Self) -> &A { + &this.alloc + } + /// Consumes the `Arc`, returning the wrapped pointer. /// /// To avoid a memory leak the pointer must be converted back to an `Arc` using From 052a14091c9b8b7636574f3c4f18e93a36ad2e3d Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sun, 18 Feb 2024 23:26:11 -0600 Subject: [PATCH 4/6] Add {Arc,Weak}::into_raw_with_allocator --- library/alloc/src/sync.rs | 67 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 0cc62d9fafb7a..b7d242eb53ebc 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1497,6 +1497,34 @@ impl Arc { ptr } + /// Consumes the `Arc`, returning the wrapped pointer and allocator. + /// + /// To avoid a memory leak the pointer must be converted back to an `Arc` using + /// [`Arc::from_raw_in`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let x = Arc::new_in("hello".to_owned(), System); + /// let (ptr, alloc) = Arc::into_raw_with_allocator(x); + /// assert_eq!(unsafe { &*ptr }, "hello"); + /// let x = unsafe { Arc::from_raw_in(ptr, alloc) }; + /// assert_eq!(&*x, "hello"); + /// ``` + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn into_raw_with_allocator(this: Self) -> (*const T, A) { + let this = mem::ManuallyDrop::new(this); + let ptr = Self::as_ptr(&this); + // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped + let alloc = unsafe { ptr::read(Self::allocator(&this)) }; + (ptr, alloc) + } + /// Provides a raw pointer to the data. /// /// The counts are not affected in any way and the `Arc` is not consumed. The pointer is valid for @@ -2739,6 +2767,45 @@ impl Weak { result } + /// Consumes the `Weak`, returning the wrapped pointer and allocator. + /// + /// This converts the weak pointer into a raw pointer, while still preserving the ownership of + /// one weak reference (the weak count is not modified by this operation). It can be turned + /// back into the `Weak` with [`from_raw_in`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_ptr`] apply. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::sync::{Arc, Weak}; + /// use std::alloc::System; + /// + /// let strong = Arc::new_in("hello".to_owned(), System); + /// let weak = Arc::downgrade(&strong); + /// let (raw, alloc) = weak.into_raw_with_allocator(); + /// + /// assert_eq!(1, Arc::weak_count(&strong)); + /// assert_eq!("hello", unsafe { &*raw }); + /// + /// drop(unsafe { Weak::from_raw_in(raw, alloc) }); + /// assert_eq!(0, Arc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw_in`]: Weak::from_raw_in + /// [`as_ptr`]: Weak::as_ptr + #[must_use = "losing the pointer will leak memory"] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn into_raw_with_allocator(self) -> (*const T, A) { + let this = mem::ManuallyDrop::new(self); + let result = this.as_ptr(); + // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped + let alloc = unsafe { ptr::read(Self::allocator(&this)) }; + (result, alloc) + } + /// Converts a raw pointer previously created by [`into_raw`] back into `Weak` in the provided /// allocator. /// From f23292a26b2f7072b32219ef15461cb38f442f5a Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sun, 18 Feb 2024 23:40:04 -0600 Subject: [PATCH 5/6] Add fn sync::Weak::allocator, remove A: Clone bound on Arc::unwrap_or_clone and From> for Arc<[T], A> --- library/alloc/src/sync.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index b7d242eb53ebc..ca76d93f3924a 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2256,7 +2256,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. /// @@ -2690,6 +2692,13 @@ impl Weak { } impl Weak { + /// Returns a reference to the underlying allocator. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn allocator(&self) -> &A { + &self.alloc + } + /// Returns a raw pointer to the object `T` pointed to by this `Weak`. /// /// The pointer is valid only if there are some strong references. The pointer may be dangling, @@ -3494,7 +3503,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 From 9f3dc91425eb2b87f316b656f28d8f2869ed0133 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Fri, 12 Apr 2024 12:39:18 -0500 Subject: [PATCH 6/6] add (private) Rc::into_inner_with_allocator, and use it where Arc does --- library/alloc/src/rc.rs | 32 ++++++++++++++++---------------- library/alloc/src/sync.rs | 12 ++++-------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index d0f02e9d7d782..e491d4d91aa9c 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -365,6 +365,12 @@ impl Rc { unsafe { self.ptr.as_ref() } } + #[inline] + fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { + let this = mem::ManuallyDrop::new(this); + (this.ptr, unsafe { ptr::read(&this.alloc) }) + } + #[inline] unsafe fn from_inner_in(ptr: NonNull>, alloc: A) -> Self { Self { ptr, phantom: PhantomData, alloc } @@ -1136,8 +1142,8 @@ impl Rc, A> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Rc { - let (ptr, alloc) = Self::into_raw_with_allocator(self); - unsafe { Rc::from_raw_in(ptr.cast(), alloc) } + let (ptr, alloc) = Self::into_inner_with_allocator(self); + unsafe { Rc::from_inner_in(ptr.cast(), alloc) } } } @@ -1177,8 +1183,8 @@ impl Rc<[mem::MaybeUninit], A> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Rc<[T], A> { - let (ptr, alloc) = Self::into_raw_with_allocator(self); - unsafe { Rc::from_raw_in(ptr as *const [T], alloc) } + let (ptr, alloc) = Self::into_inner_with_allocator(self); + unsafe { Rc::from_ptr_in(ptr.as_ptr() as _, alloc) } } } @@ -1892,11 +1898,8 @@ impl Rc { #[stable(feature = "rc_downcast", since = "1.29.0")] pub fn downcast(self) -> Result, Self> { if (*self).is::() { - 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)) } + let (ptr, alloc) = Rc::into_inner_with_allocator(self); + unsafe { Ok(Rc::from_inner_in(ptr.cast(), alloc)) } } else { Err(self) } @@ -1931,11 +1934,8 @@ impl Rc { #[inline] #[unstable(feature = "downcast_unchecked", issue = "90850")] pub unsafe fn downcast_unchecked(self) -> Rc { - 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) } + let (ptr, alloc) = Rc::into_inner_with_allocator(self); + unsafe { Rc::from_inner_in(ptr.cast(), alloc) } } } @@ -2688,8 +2688,8 @@ impl TryFrom> for Rc<[T; N], A> { fn try_from(boxed_slice: Rc<[T], A>) -> Result { if boxed_slice.len() == N { - let (ptr, alloc) = Rc::into_raw_with_allocator(boxed_slice); - Ok(unsafe { Rc::from_raw_in(ptr as *mut [T; N], alloc) }) + let (ptr, alloc) = Rc::into_inner_with_allocator(boxed_slice); + Ok(unsafe { Rc::from_inner_in(ptr.cast(), alloc) }) } else { Err(boxed_slice) } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index ca76d93f3924a..43cd3f6f92578 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2529,10 +2529,8 @@ impl Arc { T: Any + Send + Sync, { if (*self).is::() { - unsafe { - let (ptr, alloc) = Arc::into_inner_with_allocator(self); - Ok(Arc::from_inner_in(ptr.cast(), alloc)) - } + let (ptr, alloc) = Arc::into_inner_with_allocator(self); + unsafe { Ok(Arc::from_inner_in(ptr.cast(), alloc)) } } else { Err(self) } @@ -2570,10 +2568,8 @@ impl Arc { where T: Any + Send + Sync, { - unsafe { - let (ptr, alloc) = Arc::into_inner_with_allocator(self); - Arc::from_inner_in(ptr.cast(), alloc) - } + let (ptr, alloc) = Arc::into_inner_with_allocator(self); + unsafe { Arc::from_inner_in(ptr.cast(), alloc) } } }