Skip to content

Commit

Permalink
Rollup merge of rust-lang#124981 - zachs18:rc-allocator-generalize-1,…
Browse files Browse the repository at this point in the history
… r=Mark-Simulacrum

Relax allocator requirements on some Rc/Arc APIs.

Split out from rust-lang#119761

* Remove `A: Clone` bound from `Rc::assume_init`(s), `Rc::downcast`, and `Rc::downcast_unchecked` (`Arc` methods were already relaxed by rust-lang#120445)
* Make `From<Rc<[T; N]>> for Rc<[T]>` allocator-aware (`Arc`'s already is).
* Remove `A: Clone` from `Rc/Arc::unwrap_or_clone`

Internal changes:

* Made `Arc::internal_into_inner_with_allocator` method into `Arc::into_inner_with_allocator` associated fn.
* Add private `Rc::into_inner_with_allocator` (to match Arc), so other fns don't have to juggle `ManuallyDrop`.
  • Loading branch information
GuillaumeGomez authored May 11, 2024
2 parents f313399 + 8d8eb50 commit c3ecdb3
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 32 deletions.
49 changes: 24 additions & 25 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,12 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
unsafe { self.ptr.as_ref() }
}

#[inline]
fn into_inner_with_allocator(this: Self) -> (NonNull<RcBox<T>>, A) {
let this = mem::ManuallyDrop::new(this);
(this.ptr, unsafe { ptr::read(&this.alloc) })
}

#[inline]
unsafe fn from_inner_in(ptr: NonNull<RcBox<T>>, alloc: A) -> Self {
Self { ptr, phantom: PhantomData, alloc }
Expand Down Expand Up @@ -1145,12 +1151,9 @@ impl<T, A: Allocator> Rc<mem::MaybeUninit<T>, 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_inner_in(md_self.ptr.cast(), md_self.alloc.clone()) }
pub unsafe fn assume_init(self) -> Rc<T, A> {
let (ptr, alloc) = Rc::into_inner_with_allocator(self);
unsafe { Rc::from_inner_in(ptr.cast(), alloc) }
}
}

Expand Down Expand Up @@ -1189,12 +1192,9 @@ impl<T, A: Allocator> Rc<[mem::MaybeUninit<T>], 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) = Rc::into_inner_with_allocator(self);
unsafe { Rc::from_ptr_in(ptr.as_ptr() as _, alloc) }
}
}

Expand Down Expand Up @@ -1809,7 +1809,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 @@ -1845,7 +1847,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 @@ -1869,10 +1871,8 @@ impl<A: Allocator + Clone> Rc<dyn Any, A> {
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 (ptr, alloc) = Rc::into_inner_with_allocator(self);
Ok(Rc::from_inner_in(ptr.cast(), alloc))
}
} else {
Err(self)
Expand Down Expand Up @@ -1909,10 +1909,8 @@ impl<A: Allocator + Clone> Rc<dyn Any, A> {
#[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 (ptr, alloc) = Rc::into_inner_with_allocator(self);
Rc::from_inner_in(ptr.cast(), alloc)
}
}
}
Expand Down Expand Up @@ -2661,12 +2659,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_inner_with_allocator(boxed_slice);
Ok(unsafe { Rc::from_inner_in(ptr.cast(), alloc) })
} else {
Err(boxed_slice)
}
Expand Down
16 changes: 9 additions & 7 deletions library/alloc/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,8 @@ impl<T: ?Sized> Arc<T> {

impl<T: ?Sized, A: Allocator> Arc<T, A> {
#[inline]
fn internal_into_inner_with_allocator(self) -> (NonNull<ArcInner<T>>, A) {
let this = mem::ManuallyDrop::new(self);
fn into_inner_with_allocator(this: Self) -> (NonNull<ArcInner<T>>, A) {
let this = mem::ManuallyDrop::new(this);
(this.ptr, unsafe { ptr::read(&this.alloc) })
}

Expand Down Expand Up @@ -1290,7 +1290,7 @@ impl<T, A: Allocator> Arc<mem::MaybeUninit<T>, 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_inner_in(ptr.cast(), alloc) }
}
}
Expand Down Expand Up @@ -1332,7 +1332,7 @@ impl<T, A: Allocator> Arc<[mem::MaybeUninit<T>], 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) }
}
}
Expand Down Expand Up @@ -2227,7 +2227,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 @@ -2499,7 +2501,7 @@ impl<A: Allocator> Arc<dyn Any + Send + Sync, A> {
{
if (*self).is::<T>() {
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 {
Expand Down Expand Up @@ -2540,7 +2542,7 @@ impl<A: Allocator> Arc<dyn Any + Send + Sync, A> {
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)
}
}
Expand Down Expand Up @@ -3506,7 +3508,7 @@ impl<T, A: Allocator, const N: usize> TryFrom<Arc<[T], A>> for Arc<[T; N], A> {

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

0 comments on commit c3ecdb3

Please sign in to comment.