@@ -12,7 +12,8 @@ use crate::fmt;
1212use  crate :: hash:: { self ,  Hash } ; 
1313use  crate :: intrinsics:: transmute_unchecked; 
1414use  crate :: iter:: { UncheckedIterator ,  repeat_n} ; 
15- use  crate :: mem:: { self ,  MaybeUninit } ; 
15+ use  crate :: marker:: Destruct ; 
16+ use  crate :: mem:: { self ,  ManuallyDrop ,  MaybeUninit } ; 
1617use  crate :: ops:: { 
1718    ChangeOutputType ,  ControlFlow ,  FromResidual ,  Index ,  IndexMut ,  NeverShortCircuit ,  Residual ,  Try , 
1819} ; 
@@ -24,7 +25,6 @@ mod drain;
2425mod  equality; 
2526mod  iter; 
2627
27- pub ( crate )  use  drain:: drain_array_with; 
2828#[ stable( feature = "array_value_iter" ,  since = "1.51.0" ) ]  
2929pub  use  iter:: IntoIter ; 
3030
@@ -104,9 +104,10 @@ pub fn repeat<T: Clone, const N: usize>(val: T) -> [T; N] {
104104/// ``` 
105105#[ inline]  
106106#[ stable( feature = "array_from_fn" ,  since = "1.63.0" ) ]  
107- pub  fn  from_fn < T ,  const  N :  usize ,  F > ( f :  F )  -> [ T ;  N ] 
107+ #[ rustc_const_unstable( feature = "const_array" ,  issue = "none" ) ]  
108+ pub  const  fn  from_fn< T ,  const  N :  usize ,  F > ( f :  F )  -> [ T ;  N ] 
108109where 
109-     F :  FnMut ( usize )  -> T , 
110+     F :  [ const ]   FnMut ( usize )  -> T  +  [ const ]   Destruct , 
110111{ 
111112    try_from_fn ( NeverShortCircuit :: wrap_mut_1 ( f ) ) . 0 
112113} 
@@ -142,11 +143,12 @@ where
142143/// ``` 
143144#[ inline]  
144145#[ unstable( feature = "array_try_from_fn" ,  issue = "89379" ) ]  
145- pub  fn  try_from_fn < R ,  const  N :  usize ,  F > ( cb :  F )  -> ChangeOutputType < R ,  [ R :: Output ;  N ] > 
146+ #[ rustc_const_unstable( feature = "array_try_from_fn" ,  issue = "89379" ) ]  
147+ pub  const  fn  try_from_fn< R ,  const  N :  usize ,  F > ( cb :  F )  -> ChangeOutputType < R ,  [ R :: Output ;  N ] > 
146148where 
147-     F :  FnMut ( usize )  -> R , 
148-     R :  Try , 
149-     R :: Residual :   Residual < [ R :: Output ;  N ] > , 
149+     F :  [ const ]   FnMut ( usize )  -> R  +  [ const ]   Destruct , 
150+     R :  [ const ]   Try < Residual :   Residual < [ R :: Output ;   N ] > > , 
151+     < R :: Residual   as   Residual < [ R :: Output ;  N ] > > :: TryType :   [ const ]   Try , 
150152{ 
151153    let  mut  array  = [ const  {  MaybeUninit :: uninit ( )  } ;  N ] ; 
152154    match  try_from_fn_erased ( & mut  array,  cb)  { 
@@ -542,9 +544,10 @@ impl<T, const N: usize> [T; N] {
542544/// ``` 
543545#[ must_use]  
544546    #[ stable( feature = "array_map" ,  since = "1.55.0" ) ]  
545-     pub  fn  map < F ,  U > ( self ,  f :  F )  -> [ U ;  N ] 
547+     #[ rustc_const_unstable( feature = "const_array" ,  issue = "none" ) ]  
548+     pub  const  fn  map< F ,  U > ( self ,  f :  F )  -> [ U ;  N ] 
546549    where 
547-         F :  FnMut ( T )  -> U , 
550+         F :  [ const ]   FnMut ( T )  -> U  +  [ const ]   Destruct , 
548551    { 
549552        self . try_map ( NeverShortCircuit :: wrap_mut_1 ( f ) ) . 0 
550553    } 
@@ -580,11 +583,60 @@ impl<T, const N: usize> [T; N] {
580583/// assert_eq!(c, Some(a)); 
581584/// ``` 
582585#[ unstable( feature = "array_try_map" ,  issue = "79711" ) ]  
583-     pub  fn  try_map < R > ( self ,  f :  impl  FnMut ( T )  -> R )  -> ChangeOutputType < R ,  [ R :: Output ;  N ] > 
586+     #[ rustc_const_unstable( feature = "array_try_map" ,  issue = "79711" ) ]  
587+     pub const  fn  try_map < R ,  F > ( self ,  mut  f :  F )  -> ChangeOutputType < R ,  [ R :: Output ;  N ] > 
584588    where 
585-         R :  Try < Residual :  Residual < [ R :: Output ;  N ] > > , 
589+         F :  [ const ]  FnMut ( T )  -> R  + [ const ]  Destruct , 
590+         R :  [ const ]  Try < Residual :  Residual < [ R :: Output ;  N ] > > , 
591+         <R :: Residual  as  Residual < [ R :: Output ;  N ] > >:: TryType :  [ const ]  Try , 
586592    { 
587-         drain_array_with ( self ,  |iter| try_from_trusted_iterator ( iter. map ( f) ) ) 
593+         #[ rustc_const_unstable ( feature = "array_try_map" ,  issue = "79711" ) ] 
594+         struct Guardian < ' a ,  T ,  U ,  const  N :  usize ,  F :  FnMut ( T )  -> U >  { 
595+             array :  ManuallyDrop < [ T ;  N ] > , 
596+             moved :  usize , 
597+             f :  & ' a  mut  F , 
598+         } 
599+         #[ rustc_const_unstable ( feature = "array_try_map" ,  issue = "79711" ) ] 
600+         impl <T ,  U ,  const  N :  usize ,  F > const FnOnce < ( usize , ) >  for  & mut  Guardian < ' _ ,  T ,  U ,  N ,  F > 
601+         where 
602+             F :  [ const ]  FnMut ( T )  -> U , 
603+         { 
604+             type  Output  = U ; 
605+ 
606+             extern "rust-call"  fn call_once ( mut self ,  args :  ( usize, ) )  -> Self :: Output  { 
607+                 self. call_mut ( args) 
608+             } 
609+         } 
610+         #[ rustc_const_unstable ( feature = "array_try_map" ,  issue = "79711" ) ] 
611+         impl<T ,  U ,  const  N :  usize,  F > const  FnMut <( usize, ) > for  & mut  Guardian < ' _ ,  T ,  U ,  N ,  F > 
612+         where 
613+             F :  [ const ]  FnMut ( T )  -> U , 
614+         { 
615+             extern  "rust-call"  fn  call_mut( & mut  self ,  ( x, ) :  ( usize, ) )  -> Self :: Output  { 
616+                 // SAFETY: increment moved before moving. if `f` panics, we drop the rest. 
617+                 self. moved += 1 ; 
618+                 // SAFETY: caller guarantees never called with number >= N 
619+                 ( self . f) ( unsafe {  self. array. as_ptr( ) . add( x) . read( )  } ) 
620+             } 
621+         } 
622+         #[ rustc_const_unstable( feature = "array_try_map" ,  issue = "79711" ) ] 
623+         impl < T :  [ const ]  Destruct ,  U ,  const  N :  usize ,  F :  FnMut ( T )  -> U >  const Drop 
624+             for Guardian < ' _ ,  T ,  U ,  N ,  F > 
625+         { 
626+             fn  drop( & mut  self )  { 
627+                 let  mut  n = self . moved; 
628+                 while  n != N  { 
629+                     // SAFETY: moved must always be < N 
630+                     unsafe {  self . array. as_mut_ptr( ) . add( n) . drop_in_place( )  } ; 
631+                     n += 1 ; 
632+                 } 
633+             } 
634+         } 
635+         let  mut  f = Guardian  {  array :  ManuallyDrop :: new( self ) ,  moved :  0 ,  f :  & mut  f } ; 
636+         // SAFETY: try_from_fn calls `f` with 0..N. 
637+         let  out = try_from_fn( & mut  f) ; 
638+         mem:: forget( f) ;  // it doesnt like being remembered 
639+         out
588640    } 
589641
590642    /// Returns a slice containing the entire array. Equivalent to `&s[..]`. 
@@ -878,12 +930,14 @@ where
878930.   So  if  you give it a shot,  make sure to watch what
879931/// happens in the codegen tests. 
880932[ inline] 
881- fn  try_from_fn_erased < T ,  R > ( 
933+ #[ rustc_const_unstable( feature = "array_try_from_fn",  issue = "89379 ") ] 
934+ const  fn  try_from_fn_erased<T ,  R ,  F >( 
882935    buffer:  & mut  [ MaybeUninit <T >] , 
883-     mut  generator :  impl   FnMut ( usize )  ->  R , 
936+     mut  generator:  F , 
884937)  -> ControlFlow <R :: Residual >
885938where 
886-     R :  Try < Output  = T > , 
939+     R :  [ const ]  Try <Output  = T >, 
940+     F :  [ const ]  FnMut ( usize )  -> R  + [ const ]  Destruct , 
887941{ 
888942    let  mut  guard = Guard  {  array_mut:  buffer,  initialized:  0  } ; 
889943
@@ -923,7 +977,8 @@ impl<T> Guard<'_, T> {
923977/// 
924978/// No more than N elements must be initialized. 
925979[ inline] 
926-     pub ( crate )  unsafe  fn  push_unchecked ( & mut  self ,  item :  T )  { 
980+     #[ rustc_const_unstable( feature = "array_try_from_fn",  issue = "89379 ") ] 
981+     pub ( crate )  const  unsafe  fn  push_unchecked( & mut  self ,  item:  T )  { 
927982        // SAFETY: If `initialized` was correct before and the caller does not 
928983        // invoke this method more than N times then writes will be in-bounds 
929984        // and slots will not be initialized more than once. 
@@ -934,15 +989,21 @@ impl<T> Guard<'_, T> {
934989    } 
935990} 
936991
937- impl < T >  Drop  for  Guard < ' _ ,  T >  { 
992+ #[ rustc_const_unstable( feature = "array_try_from_fn",  issue = "89379 ") ] 
993+ impl <T > const  Drop  for  Guard <' _,  T > { 
938994    #[ inline] 
939995    fn  drop( & mut  self )  { 
940996        debug_assert!( self . initialized <= self . array_mut. len( ) ) ; 
941- 
942-         // SAFETY: this slice will contain only initialized objects. 
943-         unsafe  { 
944-             self . array_mut . get_unchecked_mut ( ..self . initialized ) . assume_init_drop ( ) ; 
945-         } 
997+         crate :: intrinsics:: const_eval_select!( 
998+             @capture [ T ]  {  x:  & mut  Guard <' _,  T > = self  }  -> ( ) : 
999+             if  const  { } 
1000+             else  { 
1001+                 // SAFETY: this slice will contain only initialized objects. 
1002+                 unsafe  { 
1003+                     x. array_mut. get_unchecked_mut( ..x. initialized) . assume_init_drop( ) ; 
1004+                 } 
1005+             } 
1006+         ) ; 
9461007    } 
9471008} 
9481009
0 commit comments