Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d5d5fea

Browse files
committed
add Box::(try_)map
1 parent fc5af18 commit d5d5fea

File tree

2 files changed

+90
-2
lines changed

2 files changed

+90
-2
lines changed

‎library/alloc/src/boxed.rs

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,8 @@ use core::hash::{Hash, Hasher};
194194
use core::marker::{Tuple, Unsize};
195195
use core::mem::{self, SizedTypeProperties};
196196
use core::ops::{
197-
AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref,DerefMut,
198-
DerefPure, DispatchFromDyn, LegacyReceiver,
197+
AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, ControlFlow,Coroutine, CoroutineState, Deref,
198+
DerefMut,DerefPure, DispatchFromDyn, FromResidual,LegacyReceiver,Residual,Try,
199199
};
200200
use core::pin::{Pin, PinCoerceUnsized};
201201
use core::ptr::{self, NonNull, Unique};
@@ -389,6 +389,93 @@ impl<T> Box<T> {
389389
pub fn try_new_zeroed() -> Result<Box<mem::MaybeUninit<T>>, AllocError> {
390390
Box::try_new_zeroed_in(Global)
391391
}
392+
393+
/// Maps the value in a box, reusing the allocation if possible.
394+
///
395+
/// `f` is called on the value in the box, and the result is returned, also boxed.
396+
///
397+
/// Note: this is an associated function, which means that you have
398+
/// to call it as `Box::map(b, f)` instead of `b.map(f)`. This
399+
/// is so that there is no conflict with a method on the inner type.
400+
///
401+
/// # Examples
402+
///
403+
/// ```
404+
/// #![feature(smart_pointer_try_map)]
405+
///
406+
/// let b = Box::new(7);
407+
/// let new = Box::map(b, |i| i + 7);
408+
/// assert_eq!(*new, 14);
409+
/// ```
410+
#[unstable(feature = "smart_pointer_try_map", issue = "144419")]
411+
pub fn map<U>(this: Self, f: impl FnOnce(T) -> U) -> Box<U> {
412+
if size_of::<T>() == size_of::<U>() && align_of::<U>().is_multiple_of(align_of::<T>()) {
413+
let ptr = Box::into_raw(this);
414+
unsafe {
415+
ptr.cast::<U>().write(f(ptr.read()));
416+
Box::from_raw(ptr.cast::<U>())
417+
}
418+
} else {
419+
Box::new(f(*this))
420+
}
421+
}
422+
423+
/// Attempts to map the value in a box, reusing the allocation if possible.
424+
///
425+
/// `f` is called on the value in the box, and if the operation succeeds, the result is
426+
/// returned, also boxed.
427+
///
428+
/// Note: this is an associated function, which means that you have
429+
/// to call it as `Box::try_map(b, f)` instead of `b.try_map(f)`. This
430+
/// is so that there is no conflict with a method on the inner type.
431+
///
432+
/// # Examples
433+
///
434+
/// ```
435+
/// #![feature(smart_pointer_try_map)]
436+
///
437+
/// let b = Box::new(7);
438+
/// let new = Box::try_map(b, u32::try_from).unwrap();
439+
/// assert_eq!(*new, 7);
440+
/// ```
441+
#[unstable(feature = "smart_pointer_try_map", issue = "144419")]
442+
pub fn try_map<R>(
443+
this: Self,
444+
f: impl FnOnce(T) -> R,
445+
) -> <R::Residual as Residual<Box<R::Output>>>::TryType
446+
where
447+
R: Try,
448+
R::Residual: Residual<Box<R::Output>>,
449+
{
450+
if size_of::<T>() == size_of::<R::Output>()
451+
&& align_of::<R::Output>().is_multiple_of(align_of::<T>())
452+
{
453+
let ptr = Box::into_raw(this);
454+
unsafe {
455+
match f(ptr.read()).branch() {
456+
ControlFlow::Continue(c) => {
457+
ptr.cast::<R::Output>().write(c);
458+
<R::Residual as Residual<Box<R::Output>>>::TryType::from_output(
459+
Box::from_raw(ptr.cast::<R::Output>()),
460+
)
461+
}
462+
ControlFlow::Break(b) => {
463+
drop(Box::from_raw(ptr));
464+
<R::Residual as Residual<Box<R::Output>>>::TryType::from_residual(b)
465+
}
466+
}
467+
}
468+
} else {
469+
match f(*this).branch() {
470+
ControlFlow::Continue(c) => {
471+
<R::Residual as Residual<Box<R::Output>>>::TryType::from_output(Box::new(c))
472+
}
473+
ControlFlow::Break(b) => {
474+
<R::Residual as Residual<Box<R::Output>>>::TryType::from_residual(b)
475+
}
476+
}
477+
}
478+
}
392479
}
393480

394481
impl<T, A: Allocator> Box<T, A> {

‎library/alloc/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
#![feature(trusted_len)]
154154
#![feature(trusted_random_access)]
155155
#![feature(try_trait_v2)]
156+
#![feature(try_trait_v2_residual)]
156157
#![feature(try_with_capacity)]
157158
#![feature(tuple_trait)]
158159
#![feature(ub_checks)]

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /