From bf392503761eb356a4f6b8f463f35eb956345c88 Mon Sep 17 00:00:00 2001 From: Kevin Svetlitski Date: Sat, 10 Jul 2021 18:18:24 -0500 Subject: [PATCH] Add impl to collect an iterator of Result into (Collection, Collection) Partitioning an iterator of Results into two collections containing the unwrapped values of the Ok and Err cases respectively requires a significant amount of boilerplate [1]. The feature introduced by this commit provides a more ergonomic method of accomplishing this via a single call to Iterator::collect. [1]: https://github.com/rust-lang/rust-by-example/blob/9a81505a26f199e7d8b0f21c6cd56a4211c2e6b1/src/error/iter_result.md#collect-all-valid-values-and-failures-with-partition --- library/core/src/result.rs | 19 +++++++++++++++++++ library/core/tests/result.rs | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+) 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> FromIterator> for Result { } } +//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 FromIterator> for (U, V) +where + U: Default + Extend, + V: Default + Extend, +{ + fn from_iter>>(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 ops::TryV2 for Result { 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::(one).branch(), Continue(one)); assert_eq!(Err::(()).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)>(); + 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)>(); + assert_eq!(oks, [5, 6, 7]); + assert_eq!(errs, [] as [String; 0]); + // All `Errs`s + let results: [Result; 2] = [Err("hello"), Err("world")]; + let (oks, errs) = IntoIterator::into_iter(results).collect::<(Vec, Vec<_>)>(); + assert_eq!(oks, [] as [i32; 0]); + assert_eq!(errs, ["hello", "world"]); +}