243243
244244use core:: any:: Any ;
245245use core:: cell:: { Cell , CloneFromCell } ;
246- use core:: clone:: UseCloned ;
247246#[ cfg( not( no_global_oom_handling) ) ]
248- use core:: clone:: { CloneToUninit , TrivialClone } ;
247+ use core:: clone:: TrivialClone ;
248+ use core:: clone:: { CloneToUninit , UseCloned } ;
249249use core:: cmp:: Ordering ;
250250use core:: hash:: { Hash , Hasher } ;
251251use core:: intrinsics:: abort;
@@ -1290,6 +1290,104 @@ impl<T, A: Allocator> Rc<mem::MaybeUninit<T>, A> {
12901290 }
12911291}
12921292
1293+ impl < T : ?Sized + CloneToUninit > Rc < T > {
1294+ /// Constructs a new `Rc<T>` with a clone of `value`.
1295+ ///
1296+ /// # Examples
1297+ ///
1298+ /// ```
1299+ /// #![feature(clone_from_ref)]
1300+ /// use std::rc::Rc;
1301+ ///
1302+ /// let hello: Rc<str> = Rc::clone_from_ref("hello");
1303+ /// ```
1304+ #[ cfg( not( no_global_oom_handling) ) ]
1305+ #[ unstable( feature = "clone_from_ref" , issue = "149075" ) ]
1306+ pub fn clone_from_ref ( value : & T ) -> Rc < T > {
1307+ Rc :: clone_from_ref_in ( value, Global )
1308+ }
1309+
1310+ /// Constructs a new `Rc<T>` with a clone of `value`, returning an error if allocation fails
1311+ ///
1312+ /// # Examples
1313+ ///
1314+ /// ```
1315+ /// #![feature(clone_from_ref)]
1316+ /// #![feature(allocator_api)]
1317+ /// use std::rc::Rc;
1318+ ///
1319+ /// let hello: Rc<str> = Rc::try_clone_from_ref("hello")?;
1320+ /// # Ok::<(), std::alloc::AllocError>(())
1321+ /// ```
1322+ #[ unstable( feature = "clone_from_ref" , issue = "149075" ) ]
1323+ //#[unstable(feature = "allocator_api", issue = "32838")]
1324+ pub fn try_clone_from_ref ( value : & T ) -> Result < Rc < T > , AllocError > {
1325+ Rc :: try_clone_from_ref_in ( value, Global )
1326+ }
1327+ }
1328+
1329+ impl < T : ?Sized + CloneToUninit , A : Allocator > Rc < T , A > {
1330+ /// Constructs a new `Rc<T>` with a clone of `value` in the provided allocator.
1331+ ///
1332+ /// # Examples
1333+ ///
1334+ /// ```
1335+ /// #![feature(clone_from_ref)]
1336+ /// #![feature(allocator_api)]
1337+ /// use std::rc::Rc;
1338+ /// use std::alloc::System;
1339+ ///
1340+ /// let hello: Rc<str, System> = Rc::clone_from_ref_in("hello", System);
1341+ /// ```
1342+ #[ cfg( not( no_global_oom_handling) ) ]
1343+ #[ unstable( feature = "clone_from_ref" , issue = "149075" ) ]
1344+ //#[unstable(feature = "allocator_api", issue = "32838")]
1345+ pub fn clone_from_ref_in ( value : & T , alloc : A ) -> Rc < T , A > {
1346+ // `in_progress` drops the allocation if we panic before finishing initializing it.
1347+ let mut in_progress: UniqueRcUninit < T , A > = UniqueRcUninit :: new ( value, alloc) ;
1348+
1349+ // Initialize with clone of value.
1350+ let initialized_clone = unsafe {
1351+ // Clone. If the clone panics, `in_progress` will be dropped and clean up.
1352+ value. clone_to_uninit ( in_progress. data_ptr ( ) . cast ( ) ) ;
1353+ // Cast type of pointer, now that it is initialized.
1354+ in_progress. into_rc ( )
1355+ } ;
1356+
1357+ initialized_clone
1358+ }
1359+
1360+ /// Constructs a new `Rc<T>` with a clone of `value` in the provided allocator, returning an error if allocation fails
1361+ ///
1362+ /// # Examples
1363+ ///
1364+ /// ```
1365+ /// #![feature(clone_from_ref)]
1366+ /// #![feature(allocator_api)]
1367+ /// use std::rc::Rc;
1368+ /// use std::alloc::System;
1369+ ///
1370+ /// let hello: Rc<str, System> = Rc::try_clone_from_ref_in("hello", System)?;
1371+ /// # Ok::<(), std::alloc::AllocError>(())
1372+ /// ```
1373+ #[ unstable( feature = "clone_from_ref" , issue = "149075" ) ]
1374+ //#[unstable(feature = "allocator_api", issue = "32838")]
1375+ pub fn try_clone_from_ref_in ( value : & T , alloc : A ) -> Result < Rc < T , A > , AllocError > {
1376+ // `in_progress` drops the allocation if we panic before finishing initializing it.
1377+ let mut in_progress: UniqueRcUninit < T , A > = UniqueRcUninit :: try_new ( value, alloc) ?;
1378+
1379+ // Initialize with clone of value.
1380+ let initialized_clone = unsafe {
1381+ // Clone. If the clone panics, `in_progress` will be dropped and clean up.
1382+ value. clone_to_uninit ( in_progress. data_ptr ( ) . cast ( ) ) ;
1383+ // Cast type of pointer, now that it is initialized.
1384+ in_progress. into_rc ( )
1385+ } ;
1386+
1387+ Ok ( initialized_clone)
1388+ }
1389+ }
1390+
12931391impl < T , A : Allocator > Rc < [ mem:: MaybeUninit < T > ] , A > {
12941392 /// Converts to `Rc<[T]>`.
12951393 ///
@@ -4358,16 +4456,15 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueRc<T, A> {
43584456/// This is a helper for [`Rc::make_mut()`] to ensure correct cleanup on panic.
43594457/// It is nearly a duplicate of `UniqueRc<MaybeUninit<T>, A>` except that it allows `T: !Sized`,
43604458/// which `MaybeUninit` does not.
4361- #[ cfg( not( no_global_oom_handling) ) ]
43624459struct UniqueRcUninit < T : ?Sized , A : Allocator > {
43634460 ptr : NonNull < RcInner < T > > ,
43644461 layout_for_value : Layout ,
43654462 alloc : Option < A > ,
43664463}
43674464
4368- #[ cfg( not( no_global_oom_handling) ) ]
43694465impl < T : ?Sized , A : Allocator > UniqueRcUninit < T , A > {
43704466 /// Allocates a RcInner with layout suitable to contain `for_value` or a clone of it.
4467+ #[ cfg( not( no_global_oom_handling) ) ]
43714468 fn new ( for_value : & T , alloc : A ) -> UniqueRcUninit < T , A > {
43724469 let layout = Layout :: for_value ( for_value) ;
43734470 let ptr = unsafe {
@@ -4380,6 +4477,20 @@ impl<T: ?Sized, A: Allocator> UniqueRcUninit<T, A> {
43804477 Self { ptr : NonNull :: new ( ptr) . unwrap ( ) , layout_for_value : layout, alloc : Some ( alloc) }
43814478 }
43824479
4480+ /// Allocates a RcInner with layout suitable to contain `for_value` or a clone of it,
4481+ /// returning an error if allocation fails.
4482+ fn try_new ( for_value : & T , alloc : A ) -> Result < UniqueRcUninit < T , A > , AllocError > {
4483+ let layout = Layout :: for_value ( for_value) ;
4484+ let ptr = unsafe {
4485+ Rc :: try_allocate_for_layout (
4486+ layout,
4487+ |layout_for_rc_inner| alloc. allocate ( layout_for_rc_inner) ,
4488+ |mem| mem. with_metadata_of ( ptr:: from_ref ( for_value) as * const RcInner < T > ) ,
4489+ ) ?
4490+ } ;
4491+ Ok ( Self { ptr : NonNull :: new ( ptr) . unwrap ( ) , layout_for_value : layout, alloc : Some ( alloc) } )
4492+ }
4493+
43834494 /// Returns the pointer to be written into to initialize the [`Rc`].
43844495 fn data_ptr ( & mut self ) -> * mut T {
43854496 let offset = data_offset_align ( self . layout_for_value . align ( ) ) ;
@@ -4402,7 +4513,6 @@ impl<T: ?Sized, A: Allocator> UniqueRcUninit<T, A> {
44024513 }
44034514}
44044515
4405- #[ cfg( not( no_global_oom_handling) ) ]
44064516impl < T : ?Sized , A : Allocator > Drop for UniqueRcUninit < T , A > {
44074517 fn drop ( & mut self ) {
44084518 // SAFETY:
0 commit comments