Skip to content

Commit d45e0b6

Browse files
committed
Change array_try_from signatures
1 parent 214cd1f commit d45e0b6

File tree

2 files changed

+49
-38
lines changed

2 files changed

+49
-38
lines changed

library/core/src/array/mod.rs

+35-31
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::fmt;
1111
use crate::hash::{self, Hash};
1212
use crate::iter::TrustedLen;
1313
use crate::mem::{self, MaybeUninit};
14-
use crate::ops::{Index, IndexMut};
14+
use crate::ops::{ControlFlow, Index, IndexMut, Try};
1515
use crate::slice::{Iter, IterMut};
1616

1717
mod 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")]
3944
pub fn from_fn<F, T, const N: usize>(mut cb: F) -> [T; N]
4045
where
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
7878
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,
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
598598
where
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].
613615
unsafe fn collect_into_array_unchecked<I, const N: usize>(iter: &mut I) -> [I::Item; N]
614616
where
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>
638640
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>,
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

library/core/tests/array.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,10 @@ fn cell_allows_array_cycle() {
363363

364364
#[test]
365365
fn array_from_fn() {
366-
let array = core::array::from_fn(|idx| idx);
367-
assert_eq!(array, [0, 1, 2, 3, 4]);
366+
#[derive(Debug, PartialEq)]
367+
struct Foo;
368+
let array = core::array::from_fn(|| Foo);
369+
assert_eq!(array, [Foo, Foo]);
368370
}
369371

370372
#[test]
@@ -374,10 +376,11 @@ fn array_try_from_fn() {
374376
Foo,
375377
}
376378

377-
let array = core::array::try_from_fn(|i| Ok::<_, SomeError>(i));
378-
assert_eq!(array, Ok([0, 1, 2, 3, 4]));
379+
let array: Result<[i32; 5], SomeError> = core::array::try_from_fn(|| Ok(1));
380+
assert_eq!(array, Ok([1, 1, 1, 1, 1]));
379381

380-
let another_array = core::array::try_from_fn::<SomeError, _, (), 2>(|_| Err(SomeError::Foo));
382+
let another_array: Result<[(); 2], SomeError> =
383+
core::array::try_from_fn(|| Err(SomeError::Foo));
381384
assert_eq!(another_array, Err(SomeError::Foo));
382385
}
383386

@@ -394,10 +397,12 @@ fn array_try_from_fn_drops_inserted_elements_on_err() {
394397
}
395398

396399
let _ = catch_unwind_silent(move || {
397-
let _: Result<[CountDrop; 4], ()> = core::array::try_from_fn(|idx| {
400+
let mut idx = 0;
401+
let _: Result<[CountDrop; 4], ()> = core::array::try_from_fn(|| {
398402
if idx == 2 {
399403
return Err(());
400404
}
405+
idx += 1;
401406
Ok(CountDrop)
402407
});
403408
});
@@ -418,10 +423,12 @@ fn array_try_from_fn_drops_inserted_elements_on_panic() {
418423
}
419424

420425
let _ = catch_unwind_silent(move || {
421-
let _: Result<[CountDrop; 4], ()> = core::array::try_from_fn(|idx| {
426+
let mut idx = 0;
427+
let _: Result<[CountDrop; 4], ()> = core::array::try_from_fn(|| {
422428
if idx == 2 {
423429
panic!("peek a boo");
424430
}
431+
idx += 1;
425432
Ok(CountDrop)
426433
});
427434
});

0 commit comments

Comments
 (0)