@@ -12,6 +12,7 @@ use crate::fmt;
1212use crate :: hash:: { self , Hash } ;
1313use crate :: intrinsics:: transmute_unchecked;
1414use crate :: iter:: { UncheckedIterator , repeat_n} ;
15+ use crate :: marker:: Destruct ;
1516use crate :: mem:: { self , MaybeUninit } ;
1617use crate :: ops:: {
1718 ChangeOutputType , ControlFlow , FromResidual , Index , IndexMut , NeverShortCircuit , Residual , Try ,
@@ -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 = "147606" ) ]
108+ pub const fn from_fn< T : [ const ] Destruct , 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,13 @@ 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 :: Output : [ const ] Destruct ,
152+ <R :: Residual as Residual < [ R :: Output ; N ] > >:: TryType : [ const ] Try ,
150153{
151154 let mut array = [ const { MaybeUninit :: uninit ( ) } ; N ] ;
152155 match try_from_fn_erased ( & mut array, cb) {
@@ -542,9 +545,11 @@ impl<T, const N: usize> [T; N] {
542545 /// ```
543546 #[ must_use]
544547 #[ stable( feature = "array_map" , since = "1.55.0" ) ]
545- pub fn map < F , U > ( self , f : F ) -> [ U ; N ]
548+ #[ rustc_const_unstable( feature = "const_array" , issue = "147606" ) ]
549+ pub const fn map< F , U > ( self , f : F ) -> [ U ; N ]
546550 where
547- F : FnMut ( T ) -> U ,
551+ F : [ const ] FnMut ( T ) -> U + [ const ] Destruct ,
552+ U : [ const ] Destruct ,
548553 {
549554 self . try_map ( NeverShortCircuit :: wrap_mut_1 ( f ) ) . 0
550555 }
@@ -580,11 +585,19 @@ impl<T, const N: usize> [T; N] {
580585 /// assert_eq!(c, Some(a));
581586 /// ```
582587 #[ unstable( feature = "array_try_map" , issue = "79711" ) ]
583- pub fn try_map < R > ( self , f : impl FnMut ( T ) -> R ) -> ChangeOutputType < R , [ R :: Output ; N ] >
588+ #[ rustc_const_unstable( feature = "array_try_map" , issue = "79711" ) ]
589+ pub const fn try_map < R , F > ( self , mut f : F ) -> ChangeOutputType < R , [ R :: Output ; N ] >
584590 where
585- R : Try < Residual : Residual < [ R :: Output ; N ] > > ,
591+ F : [ const ] FnMut ( T ) -> R + [ const ] Destruct ,
592+ R : [ const ] Try < Residual : Residual < [ R :: Output ; N ] > > ,
593+ R :: Output : [ const ] Destruct ,
594+ <R :: Residual as Residual < [ R :: Output ; N ] > >:: TryType : [ const ] Try ,
586595 {
587- drain_array_with ( self , |iter| try_from_trusted_iterator ( iter. map ( f) ) )
596+ // SAFETY: try_from_fn calls `f` with 0..N.
597+ let mut f = unsafe { drain:: Drain :: new ( self , & mut f ) } ;
598+ let out = try_from_fn ( & mut f) ;
599+ mem:: forget ( f) ; // it doesnt like being remembered
600+ out
588601 }
589602
590603 /// Returns a slice containing the entire array. Equivalent to `&s[..]`.
@@ -878,12 +891,15 @@ where
878891/// not optimizing away. So if you give it a shot, make sure to watch what
879892/// happens in the codegen tests.
880893#[ inline]
881- fn try_from_fn_erased < T , R > (
894+ #[ rustc_const_unstable( feature = "array_try_from_fn" , issue = "89379" ) ]
895+ const fn try_from_fn_erased< T , R , F > (
882896 buffer : & mut [ MaybeUninit < T > ] ,
883- mut generator : impl FnMut ( usize ) -> R ,
897+ mut generator : F ,
884898) -> ControlFlow < R :: Residual >
885899where
886- R : Try < Output = T > ,
900+ T : [ const ] Destruct ,
901+ R : [ const ] Try < Output = T > ,
902+ F : [ const ] FnMut ( usize ) -> R + [ const ] Destruct ,
887903{
888904 let mut guard = Guard { array_mut : buffer , initialized : 0 } ;
889905
@@ -923,7 +939,8 @@ impl<T> Guard<'_, T> {
923939 ///
924940 /// No more than N elements must be initialized.
925941 #[ inline]
926- pub ( crate ) unsafe fn push_unchecked ( & mut self , item : T ) {
942+ #[ rustc_const_unstable( feature = "array_try_from_fn" , issue = "89379" ) ]
943+ pub ( crate ) const unsafe fn push_unchecked ( & mut self , item : T ) {
927944 // SAFETY: If `initialized` was correct before and the caller does not
928945 // invoke this method more than N times then writes will be in-bounds
929946 // and slots will not be initialized more than once.
@@ -934,11 +951,11 @@ impl<T> Guard<'_, T> {
934951 }
935952}
936953
937- impl < T > Drop for Guard < ' _ , T > {
954+ #[ rustc_const_unstable( feature = "array_try_from_fn" , issue = "89379" ) ]
955+ impl <T : [ const ] Destruct > const Drop for Guard < ' _ , T > {
938956 #[ inline ]
939957 fn drop ( & mut self ) {
940958 debug_assert ! ( self . initialized <= self . array_mut. len( ) ) ;
941-
942959 // SAFETY: this slice will contain only initialized objects.
943960 unsafe {
944961 self . array_mut . get_unchecked_mut ( ..self . initialized ) . assume_init_drop ( ) ;
0 commit comments