@@ -252,8 +252,6 @@ use core::intrinsics::abort;
252252#[ cfg( not( no_global_oom_handling) ) ]
253253use core:: iter;
254254use core:: marker:: { PhantomData , Unsize } ;
255- #[ cfg( not( no_global_oom_handling) ) ]
256- use core:: mem:: MaybeUninit ;
257255use core:: mem:: { self , ManuallyDrop , align_of_val_raw} ;
258256use core:: num:: NonZeroUsize ;
259257use core:: ops:: { CoerceUnsized , Deref , DerefMut , DerefPure , DispatchFromDyn , LegacyReceiver } ;
@@ -651,7 +649,7 @@ impl<T> Rc<T> {
651649 /// an `Rc`.
652650 ///
653651 /// Note: this is an associated function, which means that you have
654- /// to call it as `Rc::map(& r, f)` instead of `r.map(f)`. This
652+ /// to call it as `Rc::map(r, f)` instead of `r.map(f)`. This
655653 /// is so that there is no conflict with a method on the inner type.
656654 ///
657655 /// # Examples
@@ -675,7 +673,7 @@ impl<T> Rc<T> {
675673 unsafe {
676674 let ptr = Rc :: into_raw ( this) ;
677675 let value = ptr. read ( ) ;
678- let mut allocation = Rc :: from_raw ( ptr. cast :: < MaybeUninit < U > > ( ) ) ;
676+ let mut allocation = Rc :: from_raw ( ptr. cast :: < mem :: MaybeUninit < U > > ( ) ) ;
679677
680678 Rc :: get_mut_unchecked ( & mut allocation) . write ( f ( & value) ) ;
681679 allocation. assume_init ( )
@@ -687,11 +685,11 @@ impl<T> Rc<T> {
687685
688686 /// Attempts to map the value in an `Rc`, reusing the allocation if possible.
689687 ///
690- /// `f` is called on a reference to the value in the box , and if the operation succeeds, the
688+ /// `f` is called on a reference to the value in the `Rc` , and if the operation succeeds, the
691689 /// result is returned, also in an `Rc`.
692690 ///
693691 /// Note: this is an associated function, which means that you have
694- /// to call it as `Rc::try_map(& r, f)` instead of `r.try_map(f)`. This
692+ /// to call it as `Rc::try_map(r, f)` instead of `r.try_map(f)`. This
695693 /// is so that there is no conflict with a method on the inner type.
696694 ///
697695 /// # Examples
@@ -722,7 +720,7 @@ impl<T> Rc<T> {
722720 unsafe {
723721 let ptr = Rc :: into_raw ( this) ;
724722 let value = ptr. read ( ) ;
725- let mut allocation = Rc :: from_raw ( ptr. cast :: < MaybeUninit < R :: Output > > ( ) ) ;
723+ let mut allocation = Rc :: from_raw ( ptr. cast :: < mem :: MaybeUninit < R :: Output > > ( ) ) ;
726724
727725 Rc :: get_mut_unchecked ( & mut allocation) . write ( f ( & value) ?) ;
728726 try { allocation. assume_init ( ) }
@@ -4093,6 +4091,128 @@ impl<T> UniqueRc<T> {
40934091 pub fn new ( value : T ) -> Self {
40944092 Self :: new_in ( value, Global )
40954093 }
4094+
4095+ /// Maps the value in a `UniqueRc`, reusing the allocation if possible.
4096+ ///
4097+ /// `f` is called on a reference to the value in the `UniqueRc`, and the result is returned,
4098+ /// also in a `UniqueRc`.
4099+ ///
4100+ /// Note: this is an associated function, which means that you have
4101+ /// to call it as `UniqueRc::map(u, f)` instead of `u.map(f)`. This
4102+ /// is so that there is no conflict with a method on the inner type.
4103+ ///
4104+ /// # Examples
4105+ ///
4106+ /// ```
4107+ /// #![feature(smart_pointer_try_map)]
4108+ /// #![feature(unique_rc_arc)]
4109+ ///
4110+ /// use std::rc::UniqueRc;
4111+ ///
4112+ /// let r = UniqueRc::new(7);
4113+ /// let new = UniqueRc::map(r, |i| i + 7);
4114+ /// assert_eq!(*new, 14);
4115+ /// ```
4116+ #[ cfg( not( no_global_oom_handling) ) ]
4117+ #[ unstable( feature = "smart_pointer_try_map" , issue = "144419" ) ]
4118+ pub fn map < U > ( this : Self , f : impl FnOnce ( T ) -> U ) -> UniqueRc < U > {
4119+ if size_of :: < T > ( ) == size_of :: < U > ( )
4120+ && align_of :: < T > ( ) == align_of :: < U > ( )
4121+ && UniqueRc :: weak_count ( & this) == 0
4122+ {
4123+ unsafe {
4124+ let ptr = UniqueRc :: into_raw ( this) ;
4125+ let value = ptr. read ( ) ;
4126+ let mut allocation = UniqueRc :: from_raw ( ptr. cast :: < mem:: MaybeUninit < U > > ( ) ) ;
4127+
4128+ allocation. write ( f ( value) ) ;
4129+ allocation. assume_init ( )
4130+ }
4131+ } else {
4132+ UniqueRc :: new ( f ( UniqueRc :: unwrap ( this) ) )
4133+ }
4134+ }
4135+
4136+ /// Attempts to map the value in a `UniqueRc`, reusing the allocation if possible.
4137+ ///
4138+ /// `f` is called on a reference to the value in the `UniqueRc`, and if the operation succeeds,
4139+ /// the result is returned, also in a `UniqueRc`.
4140+ ///
4141+ /// Note: this is an associated function, which means that you have
4142+ /// to call it as `UniqueRc::try_map(u, f)` instead of `u.try_map(f)`. This
4143+ /// is so that there is no conflict with a method on the inner type.
4144+ ///
4145+ /// # Examples
4146+ ///
4147+ /// ```
4148+ /// #![feature(smart_pointer_try_map)]
4149+ /// #![feature(unique_rc_arc)]
4150+ ///
4151+ /// use std::rc::UniqueRc;
4152+ ///
4153+ /// let b = UniqueRc::new(7);
4154+ /// let new = UniqueRc::try_map(b, u32::try_from).unwrap();
4155+ /// assert_eq!(*new, 7);
4156+ /// ```
4157+ #[ cfg( not( no_global_oom_handling) ) ]
4158+ #[ unstable( feature = "smart_pointer_try_map" , issue = "144419" ) ]
4159+ pub fn try_map < R > (
4160+ this : Self ,
4161+ f : impl FnOnce ( T ) -> R ,
4162+ ) -> <R :: Residual as Residual < UniqueRc < R :: Output > > >:: TryType
4163+ where
4164+ R : Try ,
4165+ R :: Residual : Residual < UniqueRc < R :: Output > > ,
4166+ {
4167+ if size_of :: < T > ( ) == size_of :: < R :: Output > ( )
4168+ && align_of :: < T > ( ) == align_of :: < R :: Output > ( )
4169+ && UniqueRc :: weak_count ( & this) == 0
4170+ {
4171+ unsafe {
4172+ let ptr = UniqueRc :: into_raw ( this) ;
4173+ let value = ptr. read ( ) ;
4174+ let mut allocation = UniqueRc :: from_raw ( ptr. cast :: < mem:: MaybeUninit < R :: Output > > ( ) ) ;
4175+
4176+ allocation. write ( f ( value) ?) ;
4177+ try { allocation. assume_init ( ) }
4178+ }
4179+ } else {
4180+ try { UniqueRc :: new ( f ( UniqueRc :: unwrap ( this) ) ?) }
4181+ }
4182+ }
4183+
4184+ #[ cfg( not( no_global_oom_handling) ) ]
4185+ fn unwrap ( this : Self ) -> T {
4186+ let this = ManuallyDrop :: new ( this) ;
4187+ let val: T = unsafe { ptr:: read ( & * * this) } ;
4188+
4189+ let _weak = Weak { ptr : this. ptr , alloc : Global } ;
4190+
4191+ val
4192+ }
4193+ }
4194+
4195+ impl < T : ?Sized > UniqueRc < T > {
4196+ #[ cfg( not( no_global_oom_handling) ) ]
4197+ unsafe fn from_raw ( ptr : * const T ) -> Self {
4198+ let offset = unsafe { data_offset ( ptr) } ;
4199+
4200+ // Reverse the offset to find the original RcInner.
4201+ let rc_ptr = unsafe { ptr. byte_sub ( offset) as * mut RcInner < T > } ;
4202+
4203+ Self {
4204+ ptr : unsafe { NonNull :: new_unchecked ( rc_ptr) } ,
4205+ _marker : PhantomData ,
4206+ _marker2 : PhantomData ,
4207+ alloc : Global ,
4208+ }
4209+ }
4210+
4211+ #[ cfg( not( no_global_oom_handling) ) ]
4212+ fn into_raw ( this : Self ) -> * const T {
4213+ let this = ManuallyDrop :: new ( this) ;
4214+ Self :: as_ptr ( & * this)
4215+ }
40964216}
40974217
40984218impl < T , A : Allocator > UniqueRc < T , A > {
@@ -4143,6 +4263,40 @@ impl<T: ?Sized, A: Allocator> UniqueRc<T, A> {
41434263 Rc :: from_inner_in ( this. ptr , alloc)
41444264 }
41454265 }
4266+
4267+ #[ cfg( not( no_global_oom_handling) ) ]
4268+ fn weak_count ( this : & Self ) -> usize {
4269+ this. inner ( ) . weak ( ) - 1
4270+ }
4271+
4272+ #[ cfg( not( no_global_oom_handling) ) ]
4273+ fn inner ( & self ) -> & RcInner < T > {
4274+ // SAFETY: while this UniqueRc is alive we're guaranteed that the inner pointer is valid.
4275+ unsafe { self . ptr . as_ref ( ) }
4276+ }
4277+
4278+ #[ cfg( not( no_global_oom_handling) ) ]
4279+ fn as_ptr ( this : & Self ) -> * const T {
4280+ let ptr: * mut RcInner < T > = NonNull :: as_ptr ( this. ptr ) ;
4281+
4282+ // SAFETY: This cannot go through Deref::deref or UniqueRc::inner because
4283+ // this is required to retain raw/mut provenance such that e.g. `get_mut` can
4284+ // write through the pointer after the Rc is recovered through `from_raw`.
4285+ unsafe { & raw mut ( * ptr) . value }
4286+ }
4287+
4288+ #[ inline]
4289+ #[ cfg( not( no_global_oom_handling) ) ]
4290+ fn into_inner_with_allocator ( this : Self ) -> ( NonNull < RcInner < T > > , A ) {
4291+ let this = mem:: ManuallyDrop :: new ( this) ;
4292+ ( this. ptr , unsafe { ptr:: read ( & this. alloc ) } )
4293+ }
4294+
4295+ #[ inline]
4296+ #[ cfg( not( no_global_oom_handling) ) ]
4297+ unsafe fn from_inner_in ( ptr : NonNull < RcInner < T > > , alloc : A ) -> Self {
4298+ Self { ptr, _marker : PhantomData , _marker2 : PhantomData , alloc }
4299+ }
41464300}
41474301
41484302impl < T : ?Sized , A : Allocator + Clone > UniqueRc < T , A > {
@@ -4161,6 +4315,14 @@ impl<T: ?Sized, A: Allocator + Clone> UniqueRc<T, A> {
41614315 }
41624316}
41634317
4318+ #[ cfg( not( no_global_oom_handling) ) ]
4319+ impl < T , A : Allocator > UniqueRc < mem:: MaybeUninit < T > , A > {
4320+ unsafe fn assume_init ( self ) -> UniqueRc < T , A > {
4321+ let ( ptr, alloc) = UniqueRc :: into_inner_with_allocator ( self ) ;
4322+ unsafe { UniqueRc :: from_inner_in ( ptr. cast ( ) , alloc) }
4323+ }
4324+ }
4325+
41644326#[ unstable( feature = "unique_rc_arc" , issue = "112566" ) ]
41654327impl < T : ?Sized , A : Allocator > Deref for UniqueRc < T , A > {
41664328 type Target = T ;
0 commit comments