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