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