Skip to content

Commit

Permalink
Relax allocator bounds on more Arc/Rc methods/impls.
Browse files Browse the repository at this point in the history
Remove `A: Clone` bound from:
* `downcast`, `downcast_unchecked`, `unwrap_or_clone` for both.
* `From<Vec<T, A>> for Arc<[T], A>` (Rc's already didn't require A: Clone)
* `TryFrom<Arc<[T], A>> for Arc<[T; N], A>`

Make existing `TryFrom<Rc<[T]>> for Rc<[T; N]>` allocator-aware.
  • Loading branch information
zachs18 committed Jan 20, 2024
1 parent e037761 commit 2134c8e
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 34 deletions.
35 changes: 18 additions & 17 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1760,7 +1760,9 @@ impl<T: Clone, A: Allocator + Clone> Rc<T, A> {
// reference to the allocation.
unsafe { &mut this.ptr.as_mut().value }
}
}

impl<T: Clone, A: Allocator> Rc<T, A> {
/// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the
/// clone.
///
Expand Down Expand Up @@ -1796,7 +1798,7 @@ impl<T: Clone, A: Allocator + Clone> Rc<T, A> {
}
}

impl<A: Allocator + Clone> Rc<dyn Any, A> {
impl<A: Allocator> Rc<dyn Any, A> {
/// Attempt to downcast the `Rc<dyn Any>` to a concrete type.
///
/// # Examples
Expand All @@ -1819,12 +1821,11 @@ impl<A: Allocator + Clone> Rc<dyn Any, A> {
#[stable(feature = "rc_downcast", since = "1.29.0")]
pub fn downcast<T: Any>(self) -> Result<Rc<T, A>, Self> {
if (*self).is::<T>() {
unsafe {
let ptr = self.ptr.cast::<RcBox<T>>();
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::<RcBox<T>>();
// 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)
}
Expand Down Expand Up @@ -1859,12 +1860,11 @@ impl<A: Allocator + Clone> Rc<dyn Any, A> {
#[inline]
#[unstable(feature = "downcast_unchecked", issue = "90850")]
pub unsafe fn downcast_unchecked<T: Any>(self) -> Rc<T, A> {
unsafe {
let ptr = self.ptr.cast::<RcBox<T>>();
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::<RcBox<T>>();
// 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) }
}
}

Expand Down Expand Up @@ -2604,12 +2604,13 @@ impl From<Rc<str>> for Rc<[u8]> {
}

#[stable(feature = "boxed_slice_try_from", since = "1.43.0")]
impl<T, const N: usize> TryFrom<Rc<[T]>> for Rc<[T; N]> {
type Error = Rc<[T]>;
impl<T, A: Allocator, const N: usize> TryFrom<Rc<[T], A>> for Rc<[T; N], A> {
type Error = Rc<[T], A>;

fn try_from(boxed_slice: Rc<[T]>) -> Result<Self, Self::Error> {
fn try_from(boxed_slice: Rc<[T], A>) -> Result<Self, Self::Error> {
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)
}
Expand Down
34 changes: 17 additions & 17 deletions library/alloc/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2187,7 +2187,9 @@ impl<T: Clone, A: Allocator + Clone> Arc<T, A> {
// either unique to begin with, or became one upon cloning the contents.
unsafe { Self::get_mut_unchecked(this) }
}
}

impl<T: Clone, A: Allocator> Arc<T, A> {
/// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the
/// clone.
///
Expand Down Expand Up @@ -2432,7 +2434,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Arc<T, A> {
}
}

impl<A: Allocator + Clone> Arc<dyn Any + Send + Sync, A> {
impl<A: Allocator> Arc<dyn Any + Send + Sync, A> {
/// Attempt to downcast the `Arc<dyn Any + Send + Sync>` to a concrete type.
///
/// # Examples
Expand All @@ -2458,12 +2460,11 @@ impl<A: Allocator + Clone> Arc<dyn Any + Send + Sync, A> {
T: Any + Send + Sync,
{
if (*self).is::<T>() {
unsafe {
let ptr = self.ptr.cast::<ArcInner<T>>();
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::<ArcInner<T>>();
// 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)
}
Expand Down Expand Up @@ -2501,12 +2502,11 @@ impl<A: Allocator + Clone> Arc<dyn Any + Send + Sync, A> {
where
T: Any + Send + Sync,
{
unsafe {
let ptr = self.ptr.cast::<ArcInner<T>>();
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::<ArcInner<T>>();
// 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) }
}
}

Expand Down Expand Up @@ -3432,7 +3432,7 @@ impl<T: ?Sized, A: Allocator> From<Box<T, A>> for Arc<T, A> {

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_slice", since = "1.21.0")]
impl<T, A: Allocator + Clone> From<Vec<T, A>> for Arc<[T], A> {
impl<T, A: Allocator> From<Vec<T, A>> for Arc<[T], A> {
/// Allocate a reference-counted slice and move `v`'s items into it.
///
/// # Example
Expand Down Expand Up @@ -3507,13 +3507,13 @@ impl From<Arc<str>> for Arc<[u8]> {
}

#[stable(feature = "boxed_slice_try_from", since = "1.43.0")]
impl<T, A: Allocator + Clone, const N: usize> TryFrom<Arc<[T], A>> for Arc<[T; N], A> {
impl<T, A: Allocator, const N: usize> TryFrom<Arc<[T], A>> for Arc<[T; N], A> {
type Error = Arc<[T], A>;

fn try_from(boxed_slice: Arc<[T], A>) -> Result<Self, Self::Error> {
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)
}
Expand Down

0 comments on commit 2134c8e

Please sign in to comment.