@@ -192,11 +192,15 @@ use core::fmt;
192
192
use core:: future:: Future ;
193
193
use core:: hash:: { Hash , Hasher } ;
194
194
use core:: marker:: { Tuple , Unsize } ;
195
+ #[ cfg( not( no_global_oom_handling) ) ]
196
+ use core:: mem:: MaybeUninit ;
195
197
use core:: mem:: { self , SizedTypeProperties } ;
196
198
use core:: ops:: {
197
199
AsyncFn , AsyncFnMut , AsyncFnOnce , CoerceUnsized , Coroutine , CoroutineState , Deref , DerefMut ,
198
200
DerefPure , DispatchFromDyn , LegacyReceiver ,
199
201
} ;
202
+ #[ cfg( not( no_global_oom_handling) ) ]
203
+ use core:: ops:: { Residual , Try } ;
200
204
use core:: pin:: { Pin , PinCoerceUnsized } ;
201
205
use core:: ptr:: { self , NonNull , Unique } ;
202
206
use core:: task:: { Context , Poll } ;
@@ -389,6 +393,84 @@ impl<T> Box<T> {
389
393
pub fn try_new_zeroed ( ) -> Result < Box < mem:: MaybeUninit < T > > , AllocError > {
390
394
Box :: try_new_zeroed_in ( Global )
391
395
}
396
+
397
+ /// Maps the value in a box, reusing the allocation if possible.
398
+ ///
399
+ /// `f` is called on the value in the box, and the result is returned, also boxed.
400
+ ///
401
+ /// Note: this is an associated function, which means that you have
402
+ /// to call it as `Box::map(b, f)` instead of `b.map(f)`. This
403
+ /// is so that there is no conflict with a method on the inner type.
404
+ ///
405
+ /// # Examples
406
+ ///
407
+ /// ```
408
+ /// #![feature(smart_pointer_try_map)]
409
+ ///
410
+ /// let b = Box::new(7);
411
+ /// let new = Box::map(b, |i| i + 7);
412
+ /// assert_eq!(*new, 14);
413
+ /// ```
414
+ #[ cfg( not( no_global_oom_handling) ) ]
415
+ #[ unstable( feature = "smart_pointer_try_map" , issue = "144419" ) ]
416
+ pub fn map < U > ( this : Self , f : impl FnOnce ( T ) -> U ) -> Box < U > {
417
+ if size_of :: < T > ( ) == size_of :: < U > ( ) && align_of :: < T > ( ) == align_of :: < U > ( ) {
418
+ let ( allocation, value) = unsafe {
419
+ let ptr = Box :: into_raw ( this) ;
420
+ let value = ptr. read ( ) ;
421
+ let allocation = Box :: from_raw ( ptr. cast :: < MaybeUninit < U > > ( ) ) ;
422
+ ( allocation, value)
423
+ } ;
424
+
425
+ Box :: write ( allocation, f ( value) )
426
+ } else {
427
+ Box :: new ( f ( * this) )
428
+ }
429
+ }
430
+
431
+ /// Attempts to map the value in a box, reusing the allocation if possible.
432
+ ///
433
+ /// `f` is called on the value in the box, and if the operation succeeds, the result is
434
+ /// returned, also boxed.
435
+ ///
436
+ /// Note: this is an associated function, which means that you have
437
+ /// to call it as `Box::try_map(b, f)` instead of `b.try_map(f)`. This
438
+ /// is so that there is no conflict with a method on the inner type.
439
+ ///
440
+ /// # Examples
441
+ ///
442
+ /// ```
443
+ /// #![feature(smart_pointer_try_map)]
444
+ ///
445
+ /// let b = Box::new(7);
446
+ /// let new = Box::try_map(b, u32::try_from).unwrap();
447
+ /// assert_eq!(*new, 7);
448
+ /// ```
449
+ #[ cfg( not( no_global_oom_handling) ) ]
450
+ #[ unstable( feature = "smart_pointer_try_map" , issue = "144419" ) ]
451
+ pub fn try_map < R > (
452
+ this : Self ,
453
+ f : impl FnOnce ( T ) -> R ,
454
+ ) -> <R :: Residual as Residual < Box < R :: Output > > >:: TryType
455
+ where
456
+ R : Try ,
457
+ R :: Residual : Residual < Box < R :: Output > > ,
458
+ {
459
+ if size_of :: < T > ( ) == size_of :: < R :: Output > ( ) && align_of :: < T > ( ) == align_of :: < R :: Output > ( ) {
460
+ let ( allocation, value) = unsafe {
461
+ let ptr = Box :: into_raw ( this) ;
462
+ let value = ptr. read ( ) ;
463
+ let allocation = Box :: from_raw ( ptr. cast :: < MaybeUninit < R :: Output > > ( ) ) ;
464
+ ( allocation, value)
465
+ } ;
466
+ <R :: Residual as Residual < Box < R :: Output > > >:: TryType :: from_output ( Box :: write (
467
+ allocation,
468
+ f ( value) ?,
469
+ ) )
470
+ } else {
471
+ <R :: Residual as Residual < Box < R :: Output > > >:: TryType :: from_output ( Box :: new ( f ( * this) ?) )
472
+ }
473
+ }
392
474
}
393
475
394
476
impl < T , A : Allocator > Box < T , A > {
0 commit comments