@@ -255,6 +255,8 @@ use core::marker::{PhantomData, Unsize};
255255use core:: mem:: { self , ManuallyDrop , align_of_val_raw} ;
256256use core:: num:: NonZeroUsize ;
257257use core:: ops:: { CoerceUnsized , Deref , DerefMut , DerefPure , DispatchFromDyn , LegacyReceiver } ;
258+ #[ cfg( not( no_global_oom_handling) ) ]
259+ use core:: ops:: { Residual , Try } ;
258260use core:: panic:: { RefUnwindSafe , UnwindSafe } ;
259261#[ cfg( not( no_global_oom_handling) ) ]
260262use core:: pin:: Pin ;
@@ -639,6 +641,93 @@ impl<T> Rc<T> {
639641 pub fn pin ( value : T ) -> Pin < Rc < T > > {
640642 unsafe { Pin :: new_unchecked ( Rc :: new ( value) ) }
641643 }
644+
645+ /// Maps the value in an `Rc`, reusing the allocation if possible.
646+ ///
647+ /// `f` is called on a reference to the value in the `Rc`, and the result is returned, also in
648+ /// an `Rc`.
649+ ///
650+ /// Note: this is an associated function, which means that you have
651+ /// to call it as `Rc::map(r, f)` instead of `r.map(f)`. This
652+ /// is so that there is no conflict with a method on the inner type.
653+ ///
654+ /// # Examples
655+ ///
656+ /// ```
657+ /// #![feature(smart_pointer_try_map)]
658+ ///
659+ /// use std::rc::Rc;
660+ ///
661+ /// let r = Rc::new(7);
662+ /// let new = Rc::map(r, |i| i + 7);
663+ /// assert_eq!(*new, 14);
664+ /// ```
665+ #[ cfg( not( no_global_oom_handling) ) ]
666+ #[ unstable( feature = "smart_pointer_try_map" , issue = "144419" ) ]
667+ pub fn map < U > ( this : Self , f : impl FnOnce ( & T ) -> U ) -> Rc < U > {
668+ if size_of :: < T > ( ) == size_of :: < U > ( )
669+ && align_of :: < T > ( ) == align_of :: < U > ( )
670+ && Rc :: is_unique ( & this)
671+ {
672+ unsafe {
673+ let ptr = Rc :: into_raw ( this) ;
674+ let value = ptr. read ( ) ;
675+ let mut allocation = Rc :: from_raw ( ptr. cast :: < mem:: MaybeUninit < U > > ( ) ) ;
676+
677+ Rc :: get_mut_unchecked ( & mut allocation) . write ( f ( & value) ) ;
678+ allocation. assume_init ( )
679+ }
680+ } else {
681+ Rc :: new ( f ( & * this) )
682+ }
683+ }
684+
685+ /// Attempts to map the value in an `Rc`, reusing the allocation if possible.
686+ ///
687+ /// `f` is called on a reference to the value in the `Rc`, and if the operation succeeds, the
688+ /// result is returned, also in an `Rc`.
689+ ///
690+ /// Note: this is an associated function, which means that you have
691+ /// to call it as `Rc::try_map(r, f)` instead of `r.try_map(f)`. This
692+ /// is so that there is no conflict with a method on the inner type.
693+ ///
694+ /// # Examples
695+ ///
696+ /// ```
697+ /// #![feature(smart_pointer_try_map)]
698+ ///
699+ /// use std::rc::Rc;
700+ ///
701+ /// let b = Rc::new(7);
702+ /// let new = Rc::try_map(b, |&i| u32::try_from(i)).unwrap();
703+ /// assert_eq!(*new, 7);
704+ /// ```
705+ #[ cfg( not( no_global_oom_handling) ) ]
706+ #[ unstable( feature = "smart_pointer_try_map" , issue = "144419" ) ]
707+ pub fn try_map < R > (
708+ this : Self ,
709+ f : impl FnOnce ( & T ) -> R ,
710+ ) -> <R :: Residual as Residual < Rc < R :: Output > > >:: TryType
711+ where
712+ R : Try ,
713+ R :: Residual : Residual < Rc < R :: Output > > ,
714+ {
715+ if size_of :: < T > ( ) == size_of :: < R :: Output > ( )
716+ && align_of :: < T > ( ) == align_of :: < R :: Output > ( )
717+ && Rc :: is_unique ( & this)
718+ {
719+ unsafe {
720+ let ptr = Rc :: into_raw ( this) ;
721+ let value = ptr. read ( ) ;
722+ let mut allocation = Rc :: from_raw ( ptr. cast :: < mem:: MaybeUninit < R :: Output > > ( ) ) ;
723+
724+ Rc :: get_mut_unchecked ( & mut allocation) . write ( f ( & value) ?) ;
725+ try { allocation. assume_init ( ) }
726+ }
727+ } else {
728+ try { Rc :: new ( f ( & * this) ?) }
729+ }
730+ }
642731}
643732
644733impl < T , A : Allocator > Rc < T , A > {
@@ -3991,6 +4080,128 @@ impl<T> UniqueRc<T> {
39914080 pub fn new ( value : T ) -> Self {
39924081 Self :: new_in ( value, Global )
39934082 }
4083+
4084+ /// Maps the value in a `UniqueRc`, reusing the allocation if possible.
4085+ ///
4086+ /// `f` is called on a reference to the value in the `UniqueRc`, and the result is returned,
4087+ /// also in a `UniqueRc`.
4088+ ///
4089+ /// Note: this is an associated function, which means that you have
4090+ /// to call it as `UniqueRc::map(u, f)` instead of `u.map(f)`. This
4091+ /// is so that there is no conflict with a method on the inner type.
4092+ ///
4093+ /// # Examples
4094+ ///
4095+ /// ```
4096+ /// #![feature(smart_pointer_try_map)]
4097+ /// #![feature(unique_rc_arc)]
4098+ ///
4099+ /// use std::rc::UniqueRc;
4100+ ///
4101+ /// let r = UniqueRc::new(7);
4102+ /// let new = UniqueRc::map(r, |i| i + 7);
4103+ /// assert_eq!(*new, 14);
4104+ /// ```
4105+ #[ cfg( not( no_global_oom_handling) ) ]
4106+ #[ unstable( feature = "smart_pointer_try_map" , issue = "144419" ) ]
4107+ pub fn map < U > ( this : Self , f : impl FnOnce ( T ) -> U ) -> UniqueRc < U > {
4108+ if size_of :: < T > ( ) == size_of :: < U > ( )
4109+ && align_of :: < T > ( ) == align_of :: < U > ( )
4110+ && UniqueRc :: weak_count ( & this) == 0
4111+ {
4112+ unsafe {
4113+ let ptr = UniqueRc :: into_raw ( this) ;
4114+ let value = ptr. read ( ) ;
4115+ let mut allocation = UniqueRc :: from_raw ( ptr. cast :: < mem:: MaybeUninit < U > > ( ) ) ;
4116+
4117+ allocation. write ( f ( value) ) ;
4118+ allocation. assume_init ( )
4119+ }
4120+ } else {
4121+ UniqueRc :: new ( f ( UniqueRc :: unwrap ( this) ) )
4122+ }
4123+ }
4124+
4125+ /// Attempts to map the value in a `UniqueRc`, reusing the allocation if possible.
4126+ ///
4127+ /// `f` is called on a reference to the value in the `UniqueRc`, and if the operation succeeds,
4128+ /// the result is returned, also in a `UniqueRc`.
4129+ ///
4130+ /// Note: this is an associated function, which means that you have
4131+ /// to call it as `UniqueRc::try_map(u, f)` instead of `u.try_map(f)`. This
4132+ /// is so that there is no conflict with a method on the inner type.
4133+ ///
4134+ /// # Examples
4135+ ///
4136+ /// ```
4137+ /// #![feature(smart_pointer_try_map)]
4138+ /// #![feature(unique_rc_arc)]
4139+ ///
4140+ /// use std::rc::UniqueRc;
4141+ ///
4142+ /// let b = UniqueRc::new(7);
4143+ /// let new = UniqueRc::try_map(b, u32::try_from).unwrap();
4144+ /// assert_eq!(*new, 7);
4145+ /// ```
4146+ #[ cfg( not( no_global_oom_handling) ) ]
4147+ #[ unstable( feature = "smart_pointer_try_map" , issue = "144419" ) ]
4148+ pub fn try_map < R > (
4149+ this : Self ,
4150+ f : impl FnOnce ( T ) -> R ,
4151+ ) -> <R :: Residual as Residual < UniqueRc < R :: Output > > >:: TryType
4152+ where
4153+ R : Try ,
4154+ R :: Residual : Residual < UniqueRc < R :: Output > > ,
4155+ {
4156+ if size_of :: < T > ( ) == size_of :: < R :: Output > ( )
4157+ && align_of :: < T > ( ) == align_of :: < R :: Output > ( )
4158+ && UniqueRc :: weak_count ( & this) == 0
4159+ {
4160+ unsafe {
4161+ let ptr = UniqueRc :: into_raw ( this) ;
4162+ let value = ptr. read ( ) ;
4163+ let mut allocation = UniqueRc :: from_raw ( ptr. cast :: < mem:: MaybeUninit < R :: Output > > ( ) ) ;
4164+
4165+ allocation. write ( f ( value) ?) ;
4166+ try { allocation. assume_init ( ) }
4167+ }
4168+ } else {
4169+ try { UniqueRc :: new ( f ( UniqueRc :: unwrap ( this) ) ?) }
4170+ }
4171+ }
4172+
4173+ #[ cfg( not( no_global_oom_handling) ) ]
4174+ fn unwrap ( this : Self ) -> T {
4175+ let this = ManuallyDrop :: new ( this) ;
4176+ let val: T = unsafe { ptr:: read ( & * * this) } ;
4177+
4178+ let _weak = Weak { ptr : this. ptr , alloc : Global } ;
4179+
4180+ val
4181+ }
4182+ }
4183+
4184+ impl < T : ?Sized > UniqueRc < T > {
4185+ #[ cfg( not( no_global_oom_handling) ) ]
4186+ unsafe fn from_raw ( ptr : * const T ) -> Self {
4187+ let offset = unsafe { data_offset ( ptr) } ;
4188+
4189+ // Reverse the offset to find the original RcInner.
4190+ let rc_ptr = unsafe { ptr. byte_sub ( offset) as * mut RcInner < T > } ;
4191+
4192+ Self {
4193+ ptr : unsafe { NonNull :: new_unchecked ( rc_ptr) } ,
4194+ _marker : PhantomData ,
4195+ _marker2 : PhantomData ,
4196+ alloc : Global ,
4197+ }
4198+ }
4199+
4200+ #[ cfg( not( no_global_oom_handling) ) ]
4201+ fn into_raw ( this : Self ) -> * const T {
4202+ let this = ManuallyDrop :: new ( this) ;
4203+ Self :: as_ptr ( & * this)
4204+ }
39944205}
39954206
39964207impl < T , A : Allocator > UniqueRc < T , A > {
@@ -4041,6 +4252,40 @@ impl<T: ?Sized, A: Allocator> UniqueRc<T, A> {
40414252 Rc :: from_inner_in ( this. ptr , alloc)
40424253 }
40434254 }
4255+
4256+ #[ cfg( not( no_global_oom_handling) ) ]
4257+ fn weak_count ( this : & Self ) -> usize {
4258+ this. inner ( ) . weak ( ) - 1
4259+ }
4260+
4261+ #[ cfg( not( no_global_oom_handling) ) ]
4262+ fn inner ( & self ) -> & RcInner < T > {
4263+ // SAFETY: while this UniqueRc is alive we're guaranteed that the inner pointer is valid.
4264+ unsafe { self . ptr . as_ref ( ) }
4265+ }
4266+
4267+ #[ cfg( not( no_global_oom_handling) ) ]
4268+ fn as_ptr ( this : & Self ) -> * const T {
4269+ let ptr: * mut RcInner < T > = NonNull :: as_ptr ( this. ptr ) ;
4270+
4271+ // SAFETY: This cannot go through Deref::deref or UniqueRc::inner because
4272+ // this is required to retain raw/mut provenance such that e.g. `get_mut` can
4273+ // write through the pointer after the Rc is recovered through `from_raw`.
4274+ unsafe { & raw mut ( * ptr) . value }
4275+ }
4276+
4277+ #[ inline]
4278+ #[ cfg( not( no_global_oom_handling) ) ]
4279+ fn into_inner_with_allocator ( this : Self ) -> ( NonNull < RcInner < T > > , A ) {
4280+ let this = mem:: ManuallyDrop :: new ( this) ;
4281+ ( this. ptr , unsafe { ptr:: read ( & this. alloc ) } )
4282+ }
4283+
4284+ #[ inline]
4285+ #[ cfg( not( no_global_oom_handling) ) ]
4286+ unsafe fn from_inner_in ( ptr : NonNull < RcInner < T > > , alloc : A ) -> Self {
4287+ Self { ptr, _marker : PhantomData , _marker2 : PhantomData , alloc }
4288+ }
40444289}
40454290
40464291impl < T : ?Sized , A : Allocator + Clone > UniqueRc < T , A > {
@@ -4059,6 +4304,14 @@ impl<T: ?Sized, A: Allocator + Clone> UniqueRc<T, A> {
40594304 }
40604305}
40614306
4307+ #[ cfg( not( no_global_oom_handling) ) ]
4308+ impl < T , A : Allocator > UniqueRc < mem:: MaybeUninit < T > , A > {
4309+ unsafe fn assume_init ( self ) -> UniqueRc < T , A > {
4310+ let ( ptr, alloc) = UniqueRc :: into_inner_with_allocator ( self ) ;
4311+ unsafe { UniqueRc :: from_inner_in ( ptr. cast ( ) , alloc) }
4312+ }
4313+ }
4314+
40624315#[ unstable( feature = "unique_rc_arc" , issue = "112566" ) ]
40634316impl < T : ?Sized , A : Allocator > Deref for UniqueRc < T , A > {
40644317 type Target = T ;
0 commit comments