diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 325efe721e30c..8eb1ed641cfae 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1626,6 +1626,25 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> { } } +//FIXME: Figure out how to mark this as unstable without x.py refusing to run any tests +#[stable(feature = "tuple_from_result_iter", since = "1.53.0")] +impl<T, E, U, V> FromIterator<Result<T, E>> for (U, V) +where + U: Default + Extend<T>, + V: Default + Extend<E>, +{ + fn from_iter<I: IntoIterator<Item = Result<T, E>>>(iter: I) -> (U, V) { + let (mut oks, mut errs) = (U::default(), V::default()); + for result in iter { + match result { + Ok(ok) => oks.extend_one(ok), + Err(err) => errs.extend_one(err), + } + } + (oks, errs) + } +} + #[unstable(feature = "try_trait_v2", issue = "84277")] impl<T, E> ops::TryV2 for Result<T, E> { type Output = T; diff --git a/library/core/tests/result.rs b/library/core/tests/result.rs index 612f083a5c178..415e2e43cdd82 100644 --- a/library/core/tests/result.rs +++ b/library/core/tests/result.rs @@ -402,3 +402,21 @@ fn result_try_trait_v2_branch() { assert_eq!(Ok::<NonZeroU32, ()>(one).branch(), Continue(one)); assert_eq!(Err::<NonZeroU32, ()>(()).branch(), Break(Err(()))); } + +#[test] +fn tuple_from_result_iter() { + let results = [Ok(1), Err(false), Ok(3), Ok(4), Err(true)]; + let (oks, errs) = IntoIterator::into_iter(results).collect::<(Vec<_>, Vec<bool>)>(); + assert_eq!(oks, [1, 3, 4]); + assert_eq!(errs, [false, true]); + // All `Ok`s + let results = [Ok(5), Ok(6), Ok(7)]; + let (oks, errs) = IntoIterator::into_iter(results).collect::<(Vec<_>, Vec<String>)>(); + assert_eq!(oks, [5, 6, 7]); + assert_eq!(errs, [] as [String; 0]); + // All `Errs`s + let results: [Result<i32, _>; 2] = [Err("hello"), Err("world")]; + let (oks, errs) = IntoIterator::into_iter(results).collect::<(Vec<i32>, Vec<_>)>(); + assert_eq!(oks, [] as [i32; 0]); + assert_eq!(errs, ["hello", "world"]); +}