@@ -11,7 +11,7 @@ use crate::fmt;
1111use crate :: hash:: { self , Hash } ;
1212use crate :: iter:: TrustedLen ;
1313use crate :: mem:: { self , MaybeUninit } ;
14- use crate :: ops:: { Index , IndexMut } ;
14+ use crate :: ops:: { ControlFlow , Index , IndexMut , Try } ;
1515use crate :: slice:: { Iter , IterMut } ;
1616
1717mod equality;
@@ -24,37 +24,37 @@ pub use iter::IntoIter;
2424///
2525/// # Arguments
2626///
27- /// * `cb`: Callback where the passed argument is the current array index.
27+ /// * `cb`: Callback that must provide the array element
2828///
2929/// # Example
3030///
3131/// ```rust
3232/// #![feature(array_from_fn)]
3333///
34- /// let array = core::array::from_fn(|i| i);
34+ /// let mut idx: usize = 0;
35+ /// let array = core::array::from_fn(|| {
36+ /// let rslt = idx;
37+ /// idx += 1;
38+ /// rslt
39+ /// });
3540/// assert_eq!(array, [0, 1, 2, 3, 4]);
3641/// ```
3742#[ inline]
3843#[ unstable( feature = "array_from_fn" , issue = "89379" ) ]
3944pub fn from_fn < F , T , const N : usize > ( mut cb : F ) -> [ T ; N ]
4045where
41- F : FnMut ( usize ) -> T ,
46+ F : FnMut ( ) -> T ,
4247{
43- let mut idx = 0 ;
44- [ ( ) ; N ] . map ( |_| {
45- let res = cb ( idx) ;
46- idx += 1 ;
47- res
48- } )
48+ [ ( ) ; N ] . map ( |_| cb ( ) )
4949}
5050
5151/// Creates an array `[T; N]` where each fallible array element `T` is returned by the `cb` call.
52- /// Unlike ` core::array::from_fn` , where the element creation can't fail, this version will return an error
52+ /// Unlike [ core::array::from_fn] , where the element creation can't fail, this version will return an error
5353/// if any element creation was unsuccessful.
5454///
5555/// # Arguments
5656///
57- /// * `cb`: Callback where the passed argument is the current array index.
57+ /// * `cb`: Callback that must provide the array element
5858///
5959/// # Example
6060///
@@ -66,21 +66,23 @@ where
6666/// Foo,
6767/// }
6868///
69- /// let array = core::array::try_from_fn(|i | Ok::<_, SomeError>(i ));
70- /// assert_eq!(array, Ok([0 , 1, 2, 3, 4 ]));
69+ /// let array: Result<[i32; 5], SomeError> = core::array::try_from_fn(|| Ok(1 ));
70+ /// assert_eq!(array, Ok([1 , 1, 1, 1, 1 ]));
7171///
72- /// let another_array = core::array::try_from_fn::<SomeError, _, (), 2>(|_ | Err(SomeError::Foo));
72+ /// let another_array: Result<[(); 2], SomeError> = core::array::try_from_fn(| | Err(SomeError::Foo));
7373/// assert_eq!(another_array, Err(SomeError::Foo));
7474/// ```
7575#[ inline]
7676#[ unstable( feature = "array_from_fn" , issue = "89379" ) ]
77- pub fn try_from_fn < E , F , T , const N : usize > ( cb : F ) -> Result < [ T ; N ] , E >
77+ pub fn try_from_fn < AT , ET , F , const N : usize > ( mut cb : F ) -> AT
7878where
79- F : FnMut ( usize ) -> Result < T , E > ,
79+ AT : Try < Output = [ ET :: Output ; N ] , Residual = ET :: Residual > ,
80+ ET : Try ,
81+ F : FnMut ( ) -> ET ,
8082{
8183 // SAFETY: we know for certain that this iterator will yield exactly `N`
8284 // items.
83- unsafe { collect_into_array_rslt_unchecked ( & mut ( 0 ..N ) . map ( cb ) ) }
85+ unsafe { collect_into_array_rslt_unchecked ( & mut ( 0 ..N ) . map ( |_| cb ( ) ) ) }
8486}
8587
8688/// Converts a reference to `T` into a reference to an array of length 1 (without copying).
@@ -592,15 +594,15 @@ impl<T, const N: usize> [T; N] {
592594///
593595/// It is up to the caller to guarantee that `iter` yields at least `N` items.
594596/// Violating this condition causes undefined behavior.
595- unsafe fn collect_into_array_rslt_unchecked < E , I , T , const N : usize > (
596- iter : & mut I ,
597- ) -> Result < [ T ; N ] , E >
597+ unsafe fn collect_into_array_rslt_unchecked < AT , ET , I , const N : usize > ( iter : & mut I ) -> AT
598598where
599+ AT : Try < Output = [ ET :: Output ; N ] , Residual = ET :: Residual > ,
600+ ET : Try ,
599601 // Note: `TrustedLen` here is somewhat of an experiment. This is just an
600602 // internal function, so feel free to remove if this bound turns out to be a
601603 // bad idea. In that case, remember to also remove the lower bound
602604 // `debug_assert!` below!
603- I : Iterator < Item = Result < T , E > > + TrustedLen ,
605+ I : Iterator < Item = ET > + TrustedLen ,
604606{
605607 debug_assert ! ( N <= iter. size_hint( ) . 1 . unwrap_or( usize :: MAX ) ) ;
606608 debug_assert ! ( N <= iter. size_hint( ) . 0 ) ;
@@ -609,7 +611,7 @@ where
609611 unsafe { collect_into_array ( iter) . unwrap_unchecked ( ) }
610612}
611613
612- // Infallible version of ` collect_into_array_rslt_unchecked` .
614+ /// Infallible version of [ collect_into_array_rslt_unchecked] .
613615unsafe fn collect_into_array_unchecked < I , const N : usize > ( iter : & mut I ) -> [ I :: Item ; N ]
614616where
615617 I : Iterator + TrustedLen ,
@@ -634,13 +636,15 @@ where
634636///
635637/// If `iter.next()` panicks, all items already yielded by the iterator are
636638/// dropped.
637- fn collect_into_array < E , I , T , const N : usize > ( iter : & mut I ) -> Option < Result < [ T ; N ] , E > >
639+ fn collect_into_array < AT , ET , I , const N : usize > ( iter : & mut I ) -> Option < AT >
638640where
639- I : Iterator < Item = Result < T , E > > ,
641+ AT : Try < Output = [ ET :: Output ; N ] , Residual = ET :: Residual > ,
642+ ET : Try ,
643+ I : Iterator < Item = ET > ,
640644{
641645 if N == 0 {
642646 // SAFETY: An empty array is always inhabited and has no validity invariants.
643- return unsafe { Some ( Ok ( mem:: zeroed ( ) ) ) } ;
647+ return unsafe { Some ( AT :: from_output ( mem:: zeroed ( ) ) ) } ;
644648 }
645649
646650 struct Guard < ' a , T , const N : usize > {
@@ -665,11 +669,11 @@ where
665669 let mut guard = Guard { array_mut : & mut array, initialized : 0 } ;
666670
667671 while let Some ( item_rslt) = iter. next ( ) {
668- let item = match item_rslt {
669- Err ( err ) => {
670- return Some ( Err ( err ) ) ;
672+ let item = match item_rslt. branch ( ) {
673+ ControlFlow :: Break ( res ) => {
674+ return Some ( AT :: from_residual ( res ) ) ;
671675 }
672- Ok ( elem) => elem,
676+ ControlFlow :: Continue ( elem) => elem,
673677 } ;
674678
675679 // SAFETY: `guard.initialized` starts at 0, is increased by one in the
@@ -687,7 +691,7 @@ where
687691 // SAFETY: the condition above asserts that all elements are
688692 // initialized.
689693 let out = unsafe { MaybeUninit :: array_assume_init ( array) } ;
690- return Some ( Ok ( out) ) ;
694+ return Some ( AT :: from_output ( out) ) ;
691695 }
692696 }
693697
0 commit comments