@@ -252,8 +252,6 @@ use core::intrinsics::abort;
252
252
#[ cfg( not( no_global_oom_handling) ) ]
253
253
use core:: iter;
254
254
use core:: marker:: { PhantomData , Unsize } ;
255
- #[ cfg( not( no_global_oom_handling) ) ]
256
- use core:: mem:: MaybeUninit ;
257
255
use core:: mem:: { self , ManuallyDrop , align_of_val_raw} ;
258
256
use core:: num:: NonZeroUsize ;
259
257
use core:: ops:: { CoerceUnsized , Deref , DerefMut , DerefPure , DispatchFromDyn , LegacyReceiver } ;
@@ -675,7 +673,7 @@ impl<T> Rc<T> {
675
673
unsafe {
676
674
let ptr = Rc :: into_raw ( this) ;
677
675
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 > > ( ) ) ;
679
677
680
678
Rc :: get_mut_unchecked ( & mut allocation) . write ( f ( & value) ) ;
681
679
allocation. assume_init ( )
@@ -687,7 +685,7 @@ impl<T> Rc<T> {
687
685
688
686
/// Attempts to map the value in an `Rc`, reusing the allocation if possible.
689
687
///
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
691
689
/// result is returned, also in an `Rc`.
692
690
///
693
691
/// Note: this is an associated function, which means that you have
@@ -722,7 +720,7 @@ impl<T> Rc<T> {
722
720
unsafe {
723
721
let ptr = Rc :: into_raw ( this) ;
724
722
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 > > ( ) ) ;
726
724
727
725
Rc :: get_mut_unchecked ( & mut allocation) . write ( f ( & value) ?) ;
728
726
try { allocation. assume_init ( ) }
@@ -4093,6 +4091,129 @@ impl<T> UniqueRc<T> {
4093
4091
pub fn new ( value : T ) -> Self {
4094
4092
Self :: new_in ( value, Global )
4095
4093
}
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
+ this. inner ( ) . dec_strong ( ) ;
4190
+ let _weak = Weak { ptr : this. ptr , alloc : Global } ;
4191
+
4192
+ val
4193
+ }
4194
+ }
4195
+
4196
+ impl < T : ?Sized > UniqueRc < T > {
4197
+ #[ cfg( not( no_global_oom_handling) ) ]
4198
+ unsafe fn from_raw ( ptr : * const T ) -> Self {
4199
+ let offset = unsafe { data_offset ( ptr) } ;
4200
+
4201
+ // Reverse the offset to find the original RcInner.
4202
+ let rc_ptr = unsafe { ptr. byte_sub ( offset) as * mut RcInner < T > } ;
4203
+
4204
+ Self {
4205
+ ptr : unsafe { NonNull :: new_unchecked ( rc_ptr) } ,
4206
+ _marker : PhantomData ,
4207
+ _marker2 : PhantomData ,
4208
+ alloc : Global ,
4209
+ }
4210
+ }
4211
+
4212
+ #[ cfg( not( no_global_oom_handling) ) ]
4213
+ fn into_raw ( this : Self ) -> * const T {
4214
+ let this = ManuallyDrop :: new ( this) ;
4215
+ Self :: as_ptr ( & * this)
4216
+ }
4096
4217
}
4097
4218
4098
4219
impl < T , A : Allocator > UniqueRc < T , A > {
@@ -4143,6 +4264,40 @@ impl<T: ?Sized, A: Allocator> UniqueRc<T, A> {
4143
4264
Rc :: from_inner_in ( this. ptr , alloc)
4144
4265
}
4145
4266
}
4267
+
4268
+ #[ cfg( not( no_global_oom_handling) ) ]
4269
+ fn weak_count ( this : & Self ) -> usize {
4270
+ this. inner ( ) . weak ( ) - 1
4271
+ }
4272
+
4273
+ #[ cfg( not( no_global_oom_handling) ) ]
4274
+ fn inner ( & self ) -> & RcInner < T > {
4275
+ // SAFETY: while this UniqueRc is alive we're guaranteed that the inner pointer is valid.
4276
+ unsafe { self . ptr . as_ref ( ) }
4277
+ }
4278
+
4279
+ #[ cfg( not( no_global_oom_handling) ) ]
4280
+ fn as_ptr ( this : & Self ) -> * const T {
4281
+ let ptr: * mut RcInner < T > = NonNull :: as_ptr ( this. ptr ) ;
4282
+
4283
+ // SAFETY: This cannot go through Deref::deref or UniqueRc::inner because
4284
+ // this is required to retain raw/mut provenance such that e.g. `get_mut` can
4285
+ // write through the pointer after the Rc is recovered through `from_raw`.
4286
+ unsafe { & raw mut ( * ptr) . value }
4287
+ }
4288
+
4289
+ #[ inline]
4290
+ #[ cfg( not( no_global_oom_handling) ) ]
4291
+ fn into_inner_with_allocator ( this : Self ) -> ( NonNull < RcInner < T > > , A ) {
4292
+ let this = mem:: ManuallyDrop :: new ( this) ;
4293
+ ( this. ptr , unsafe { ptr:: read ( & this. alloc ) } )
4294
+ }
4295
+
4296
+ #[ inline]
4297
+ #[ cfg( not( no_global_oom_handling) ) ]
4298
+ unsafe fn from_inner_in ( ptr : NonNull < RcInner < T > > , alloc : A ) -> Self {
4299
+ Self { ptr, _marker : PhantomData , _marker2 : PhantomData , alloc }
4300
+ }
4146
4301
}
4147
4302
4148
4303
impl < T : ?Sized , A : Allocator + Clone > UniqueRc < T , A > {
@@ -4161,6 +4316,14 @@ impl<T: ?Sized, A: Allocator + Clone> UniqueRc<T, A> {
4161
4316
}
4162
4317
}
4163
4318
4319
+ #[ cfg( not( no_global_oom_handling) ) ]
4320
+ impl < T , A : Allocator > UniqueRc < mem:: MaybeUninit < T > , A > {
4321
+ unsafe fn assume_init ( self ) -> UniqueRc < T , A > {
4322
+ let ( ptr, alloc) = UniqueRc :: into_inner_with_allocator ( self ) ;
4323
+ unsafe { UniqueRc :: from_inner_in ( ptr. cast ( ) , alloc) }
4324
+ }
4325
+ }
4326
+
4164
4327
#[ unstable( feature = "unique_rc_arc" , issue = "112566" ) ]
4165
4328
impl < T : ?Sized , A : Allocator > Deref for UniqueRc < T , A > {
4166
4329
type Target = T ;
0 commit comments