@@ -11,7 +11,7 @@ use crate::fmt;
11
11
use crate :: hash:: { self , Hash } ;
12
12
use crate :: iter:: TrustedLen ;
13
13
use crate :: mem:: { self , MaybeUninit } ;
14
- use crate :: ops:: { Index , IndexMut } ;
14
+ use crate :: ops:: { ControlFlow , Index , IndexMut , Try } ;
15
15
use crate :: slice:: { Iter , IterMut } ;
16
16
17
17
mod equality;
@@ -24,37 +24,37 @@ pub use iter::IntoIter;
24
24
///
25
25
/// # Arguments
26
26
///
27
- /// * `cb`: Callback where the passed argument is the current array index.
27
+ /// * `cb`: Callback that must provide the array element
28
28
///
29
29
/// # Example
30
30
///
31
31
/// ```rust
32
32
/// #![feature(array_from_fn)]
33
33
///
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
+ /// });
35
40
/// assert_eq!(array, [0, 1, 2, 3, 4]);
36
41
/// ```
37
42
#[ inline]
38
43
#[ unstable( feature = "array_from_fn" , issue = "89379" ) ]
39
44
pub fn from_fn < F , T , const N : usize > ( mut cb : F ) -> [ T ; N ]
40
45
where
41
- F : FnMut ( usize ) -> T ,
46
+ F : FnMut ( ) -> T ,
42
47
{
43
- let mut idx = 0 ;
44
- [ ( ) ; N ] . map ( |_| {
45
- let res = cb ( idx) ;
46
- idx += 1 ;
47
- res
48
- } )
48
+ [ ( ) ; N ] . map ( |_| cb ( ) )
49
49
}
50
50
51
51
/// 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
53
53
/// if any element creation was unsuccessful.
54
54
///
55
55
/// # Arguments
56
56
///
57
- /// * `cb`: Callback where the passed argument is the current array index.
57
+ /// * `cb`: Callback that must provide the array element
58
58
///
59
59
/// # Example
60
60
///
@@ -66,21 +66,23 @@ where
66
66
/// Foo,
67
67
/// }
68
68
///
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 ]));
71
71
///
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));
73
73
/// assert_eq!(another_array, Err(SomeError::Foo));
74
74
/// ```
75
75
#[ inline]
76
76
#[ 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
78
78
where
79
- F : FnMut ( usize ) -> Result < T , E > ,
79
+ AT : Try < Output = [ ET :: Output ; N ] , Residual = ET :: Residual > ,
80
+ ET : Try ,
81
+ F : FnMut ( ) -> ET ,
80
82
{
81
83
// SAFETY: we know for certain that this iterator will yield exactly `N`
82
84
// 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 ( ) ) ) }
84
86
}
85
87
86
88
/// 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] {
592
594
///
593
595
/// It is up to the caller to guarantee that `iter` yields at least `N` items.
594
596
/// 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
598
598
where
599
+ AT : Try < Output = [ ET :: Output ; N ] , Residual = ET :: Residual > ,
600
+ ET : Try ,
599
601
// Note: `TrustedLen` here is somewhat of an experiment. This is just an
600
602
// internal function, so feel free to remove if this bound turns out to be a
601
603
// bad idea. In that case, remember to also remove the lower bound
602
604
// `debug_assert!` below!
603
- I : Iterator < Item = Result < T , E > > + TrustedLen ,
605
+ I : Iterator < Item = ET > + TrustedLen ,
604
606
{
605
607
debug_assert ! ( N <= iter. size_hint( ) . 1 . unwrap_or( usize :: MAX ) ) ;
606
608
debug_assert ! ( N <= iter. size_hint( ) . 0 ) ;
@@ -609,7 +611,7 @@ where
609
611
unsafe { collect_into_array ( iter) . unwrap_unchecked ( ) }
610
612
}
611
613
612
- // Infallible version of ` collect_into_array_rslt_unchecked` .
614
+ /// Infallible version of [ collect_into_array_rslt_unchecked] .
613
615
unsafe fn collect_into_array_unchecked < I , const N : usize > ( iter : & mut I ) -> [ I :: Item ; N ]
614
616
where
615
617
I : Iterator + TrustedLen ,
@@ -634,13 +636,15 @@ where
634
636
///
635
637
/// If `iter.next()` panicks, all items already yielded by the iterator are
636
638
/// 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 >
638
640
where
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 > ,
640
644
{
641
645
if N == 0 {
642
646
// 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 ( ) ) ) } ;
644
648
}
645
649
646
650
struct Guard < ' a , T , const N : usize > {
@@ -665,11 +669,11 @@ where
665
669
let mut guard = Guard { array_mut : & mut array, initialized : 0 } ;
666
670
667
671
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 ) ) ;
671
675
}
672
- Ok ( elem) => elem,
676
+ ControlFlow :: Continue ( elem) => elem,
673
677
} ;
674
678
675
679
// SAFETY: `guard.initialized` starts at 0, is increased by one in the
@@ -687,7 +691,7 @@ where
687
691
// SAFETY: the condition above asserts that all elements are
688
692
// initialized.
689
693
let out = unsafe { MaybeUninit :: array_assume_init ( array) } ;
690
- return Some ( Ok ( out) ) ;
694
+ return Some ( AT :: from_output ( out) ) ;
691
695
}
692
696
}
693
697
0 commit comments