add {Box, (Unique){Rc, Arc}}::(try_)map · rust-lang/rust@9c5be67 (original) (raw)
`@@ -255,6 +255,8 @@ use core:📑:{PhantomData, Unsize};
`
255
255
`use core::mem::{self, ManuallyDrop, align_of_val_raw};
`
256
256
`use core::num::NonZeroUsize;
`
257
257
`use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver};
`
``
258
`+
#[cfg(not(no_global_oom_handling))]
`
``
259
`+
use core::ops::{Residual, Try};
`
258
260
`use core::panic::{RefUnwindSafe, UnwindSafe};
`
259
261
`#[cfg(not(no_global_oom_handling))]
`
260
262
`use core::pin::Pin;
`
`@@ -639,6 +641,93 @@ impl Rc {
`
639
641
`pub fn pin(value: T) -> Pin<Rc> {
`
640
642
`unsafe { Pin::new_unchecked(Rc::new(value)) }
`
641
643
`}
`
``
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(this: Self, f: impl FnOnce(&T) -> U) -> Rc {
`
``
668
`+
if size_of::() == size_of::()
`
``
669
`+
&& align_of::() == align_of::()
`
``
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>());
`
``
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(
`
``
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::() == size_of::<R::Output>()
`
``
716
`+
&& align_of::() == 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
`+
}
`
642
731
`}
`
643
732
``
644
733
`impl<T, A: Allocator> Rc<T, A> {
`
`@@ -3991,6 +4080,128 @@ impl UniqueRc {
`
3991
4080
`pub fn new(value: T) -> Self {
`
3992
4081
`Self::new_in(value, Global)
`
3993
4082
`}
`
``
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(this: Self, f: impl FnOnce(T) -> U) -> UniqueRc {
`
``
4108
`+
if size_of::() == size_of::()
`
``
4109
`+
&& align_of::() == align_of::()
`
``
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>());
`
``
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(
`
``
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::() == size_of::<R::Output>()
`
``
4157
`+
&& align_of::() == 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 {
`
``
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 };
`
``
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
`+
}
`
3994
4205
`}
`
3995
4206
``
3996
4207
`impl<T, A: Allocator> UniqueRc<T, A> {
`
`@@ -4041,6 +4252,40 @@ impl<T: ?Sized, A: Allocator> UniqueRc<T, A> {
`
4041
4252
`Rc::from_inner_in(this.ptr, alloc)
`
4042
4253
`}
`
4043
4254
`}
`
``
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 {
`
``
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 = 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>, 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>, alloc: A) -> Self {
`
``
4287
`+
Self { ptr, _marker: PhantomData, _marker2: PhantomData, alloc }
`
``
4288
`+
}
`
4044
4289
`}
`
4045
4290
``
4046
4291
`impl<T: ?Sized, A: Allocator + Clone> UniqueRc<T, A> {
`
`@@ -4059,6 +4304,14 @@ impl<T: ?Sized, A: Allocator + Clone> UniqueRc<T, A> {
`
4059
4304
`}
`
4060
4305
`}
`
4061
4306
``
``
4307
`+
#[cfg(not(no_global_oom_handling))]
`
``
4308
`+
impl<T, A: Allocator> UniqueRc<mem::MaybeUninit, 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
+
4062
4315
`#[unstable(feature = "unique_rc_arc", issue = "112566")]
`
4063
4316
`impl<T: ?Sized, A: Allocator> Deref for UniqueRc<T, A> {
`
4064
4317
`type Target = T;
`