1111use core:: any:: Any ;
1212use core:: cell:: CloneFromCell ;
1313#[ cfg( not( no_global_oom_handling) ) ]
14- use core:: clone:: CloneToUninit ;
15- #[ cfg( not( no_global_oom_handling) ) ]
1614use core:: clone:: TrivialClone ;
17- use core:: clone:: UseCloned ;
15+ use core:: clone:: { CloneToUninit , UseCloned } ;
1816use core:: cmp:: Ordering ;
1917use core:: hash:: { Hash , Hasher } ;
2018use core:: intrinsics:: abort;
@@ -1442,6 +1440,104 @@ impl<T, A: Allocator> Arc<mem::MaybeUninit<T>, A> {
14421440 }
14431441}
14441442
1443+ impl < T : ?Sized + CloneToUninit > Arc < T > {
1444+ /// Constructs a new `Arc<T>` with a clone of `value`.
1445+ ///
1446+ /// # Examples
1447+ ///
1448+ /// ```
1449+ /// #![feature(clone_from_ref)]
1450+ /// use std::sync::Arc;
1451+ ///
1452+ /// let hello: Arc<str> = Arc::clone_from_ref("hello");
1453+ /// ```
1454+ #[ cfg( not( no_global_oom_handling) ) ]
1455+ #[ unstable( feature = "clone_from_ref" , issue = "149075" ) ]
1456+ pub fn clone_from_ref ( value : & T ) -> Arc < T > {
1457+ Arc :: clone_from_ref_in ( value, Global )
1458+ }
1459+
1460+ /// Constructs a new `Arc<T>` with a clone of `value`, returning an error if allocation fails
1461+ ///
1462+ /// # Examples
1463+ ///
1464+ /// ```
1465+ /// #![feature(clone_from_ref)]
1466+ /// #![feature(allocator_api)]
1467+ /// use std::sync::Arc;
1468+ ///
1469+ /// let hello: Arc<str> = Arc::try_clone_from_ref("hello")?;
1470+ /// # Ok::<(), std::alloc::AllocError>(())
1471+ /// ```
1472+ #[ unstable( feature = "clone_from_ref" , issue = "149075" ) ]
1473+ //#[unstable(feature = "allocator_api", issue = "32838")]
1474+ pub fn try_clone_from_ref ( value : & T ) -> Result < Arc < T > , AllocError > {
1475+ Arc :: try_clone_from_ref_in ( value, Global )
1476+ }
1477+ }
1478+
1479+ impl < T : ?Sized + CloneToUninit , A : Allocator > Arc < T , A > {
1480+ /// Constructs a new `Arc<T>` with a clone of `value` in the provided allocator.
1481+ ///
1482+ /// # Examples
1483+ ///
1484+ /// ```
1485+ /// #![feature(clone_from_ref)]
1486+ /// #![feature(allocator_api)]
1487+ /// use std::sync::Arc;
1488+ /// use std::alloc::System;
1489+ ///
1490+ /// let hello: Arc<str, System> = Arc::clone_from_ref_in("hello", System);
1491+ /// ```
1492+ #[ cfg( not( no_global_oom_handling) ) ]
1493+ #[ unstable( feature = "clone_from_ref" , issue = "149075" ) ]
1494+ //#[unstable(feature = "allocator_api", issue = "32838")]
1495+ pub fn clone_from_ref_in ( value : & T , alloc : A ) -> Arc < T , A > {
1496+ // `in_progress` drops the allocation if we panic before finishing initializing it.
1497+ let mut in_progress: UniqueArcUninit < T , A > = UniqueArcUninit :: new ( value, alloc) ;
1498+
1499+ // Initialize with clone of value.
1500+ let initialized_clone = unsafe {
1501+ // Clone. If the clone panics, `in_progress` will be dropped and clean up.
1502+ value. clone_to_uninit ( in_progress. data_ptr ( ) . cast ( ) ) ;
1503+ // Cast type of pointer, now that it is initialized.
1504+ in_progress. into_arc ( )
1505+ } ;
1506+
1507+ initialized_clone
1508+ }
1509+
1510+ /// Constructs a new `Arc<T>` with a clone of `value` in the provided allocator, returning an error if allocation fails
1511+ ///
1512+ /// # Examples
1513+ ///
1514+ /// ```
1515+ /// #![feature(clone_from_ref)]
1516+ /// #![feature(allocator_api)]
1517+ /// use std::sync::Arc;
1518+ /// use std::alloc::System;
1519+ ///
1520+ /// let hello: Arc<str, System> = Arc::try_clone_from_ref_in("hello", System)?;
1521+ /// # Ok::<(), std::alloc::AllocError>(())
1522+ /// ```
1523+ #[ unstable( feature = "clone_from_ref" , issue = "149075" ) ]
1524+ //#[unstable(feature = "allocator_api", issue = "32838")]
1525+ pub fn try_clone_from_ref_in ( value : & T , alloc : A ) -> Result < Arc < T , A > , AllocError > {
1526+ // `in_progress` drops the allocation if we panic before finishing initializing it.
1527+ let mut in_progress: UniqueArcUninit < T , A > = UniqueArcUninit :: try_new ( value, alloc) ?;
1528+
1529+ // Initialize with clone of value.
1530+ let initialized_clone = unsafe {
1531+ // Clone. If the clone panics, `in_progress` will be dropped and clean up.
1532+ value. clone_to_uninit ( in_progress. data_ptr ( ) . cast ( ) ) ;
1533+ // Cast type of pointer, now that it is initialized.
1534+ in_progress. into_arc ( )
1535+ } ;
1536+
1537+ Ok ( initialized_clone)
1538+ }
1539+ }
1540+
14451541impl < T , A : Allocator > Arc < [ mem:: MaybeUninit < T > ] , A > {
14461542 /// Converts to `Arc<[T]>`.
14471543 ///
@@ -4137,16 +4233,15 @@ fn data_offset_align(align: usize) -> usize {
41374233/// but will deallocate it (without dropping the value) when dropped.
41384234///
41394235/// This is a helper for [`Arc::make_mut()`] to ensure correct cleanup on panic.
4140- #[ cfg( not( no_global_oom_handling) ) ]
41414236struct UniqueArcUninit < T : ?Sized , A : Allocator > {
41424237 ptr : NonNull < ArcInner < T > > ,
41434238 layout_for_value : Layout ,
41444239 alloc : Option < A > ,
41454240}
41464241
4147- #[ cfg( not( no_global_oom_handling) ) ]
41484242impl < T : ?Sized , A : Allocator > UniqueArcUninit < T , A > {
41494243 /// Allocates an ArcInner with layout suitable to contain `for_value` or a clone of it.
4244+ #[ cfg( not( no_global_oom_handling) ) ]
41504245 fn new ( for_value : & T , alloc : A ) -> UniqueArcUninit < T , A > {
41514246 let layout = Layout :: for_value ( for_value) ;
41524247 let ptr = unsafe {
@@ -4159,6 +4254,20 @@ impl<T: ?Sized, A: Allocator> UniqueArcUninit<T, A> {
41594254 Self { ptr : NonNull :: new ( ptr) . unwrap ( ) , layout_for_value : layout, alloc : Some ( alloc) }
41604255 }
41614256
4257+ /// Allocates an ArcInner with layout suitable to contain `for_value` or a clone of it,
4258+ /// returning an error if allocation fails.
4259+ fn try_new ( for_value : & T , alloc : A ) -> Result < UniqueArcUninit < T , A > , AllocError > {
4260+ let layout = Layout :: for_value ( for_value) ;
4261+ let ptr = unsafe {
4262+ Arc :: try_allocate_for_layout (
4263+ layout,
4264+ |layout_for_arcinner| alloc. allocate ( layout_for_arcinner) ,
4265+ |mem| mem. with_metadata_of ( ptr:: from_ref ( for_value) as * const ArcInner < T > ) ,
4266+ ) ?
4267+ } ;
4268+ Ok ( Self { ptr : NonNull :: new ( ptr) . unwrap ( ) , layout_for_value : layout, alloc : Some ( alloc) } )
4269+ }
4270+
41624271 /// Returns the pointer to be written into to initialize the [`Arc`].
41634272 fn data_ptr ( & mut self ) -> * mut T {
41644273 let offset = data_offset_align ( self . layout_for_value . align ( ) ) ;
0 commit comments