|  | 
| 1 | 1 | use crate::cmp::{self, Ordering}; | 
| 2 | 2 | use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; | 
| 3 | 3 | 
 | 
|  | 4 | +use super::super::try_process; | 
| 4 | 5 | use super::super::TrustedRandomAccessNoCoerce; | 
| 5 | 6 | use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse}; | 
| 6 | 7 | use super::super::{FlatMap, Flatten}; | 
| @@ -1777,6 +1778,87 @@ pub trait Iterator { | 
| 1777 | 1778 |  FromIterator::from_iter(self) | 
| 1778 | 1779 |  } | 
| 1779 | 1780 | 
 | 
|  | 1781 | + /// Fallibly transforms an iterator into a collection, short circuiting if | 
|  | 1782 | + /// a failure is encountered. | 
|  | 1783 | + /// | 
|  | 1784 | + /// `try_collect()` is a variation of [`collect()`][`collect`] that allows fallible | 
|  | 1785 | + /// conversions during collection. Its main use case is simplifying conversions from | 
|  | 1786 | + /// iterators yielding [`Option<T>`][`Option`] into `Option<Collection<T>>`, or similarly for other [`Try`] | 
|  | 1787 | + /// types (e.g. [`Result`]). | 
|  | 1788 | + /// | 
|  | 1789 | + /// Importantly, `try_collect()` doesn't require that the outer [`Try`] type also implements [`FromIterator`]; | 
|  | 1790 | + /// only the inner type produced on `Try::Output` must implement it. Concretely, | 
|  | 1791 | + /// this means that collecting into `ControlFlow<_, Vec<i32>>` is valid because `Vec<i32>` implements | 
|  | 1792 | + /// [`FromIterator`], even though [`ControlFlow`] doesn't. | 
|  | 1793 | + /// | 
|  | 1794 | + /// Also, if a failure is encountered during `try_collect()`, the iterator is still valid and | 
|  | 1795 | + /// may continue to be used, in which case it will continue iterating starting after the element that | 
|  | 1796 | + /// triggered the failure. See the last example below for an example of how this works. | 
|  | 1797 | + /// | 
|  | 1798 | + /// # Examples | 
|  | 1799 | + /// Successfully collecting an iterator of `Option<i32>` into `Option<Vec<i32>>`: | 
|  | 1800 | + /// ``` | 
|  | 1801 | + /// #![feature(iterator_try_collect)] | 
|  | 1802 | + /// | 
|  | 1803 | + /// let u = vec![Some(1), Some(2), Some(3)]; | 
|  | 1804 | + /// let v = u.into_iter().try_collect::<Vec<i32>>(); | 
|  | 1805 | + /// assert_eq!(v, Some(vec![1, 2, 3])); | 
|  | 1806 | + /// ``` | 
|  | 1807 | + /// | 
|  | 1808 | + /// Failing to collect in the same way: | 
|  | 1809 | + /// ``` | 
|  | 1810 | + /// #![feature(iterator_try_collect)] | 
|  | 1811 | + /// | 
|  | 1812 | + /// let u = vec![Some(1), Some(2), None, Some(3)]; | 
|  | 1813 | + /// let v = u.into_iter().try_collect::<Vec<i32>>(); | 
|  | 1814 | + /// assert_eq!(v, None); | 
|  | 1815 | + /// ``` | 
|  | 1816 | + /// | 
|  | 1817 | + /// A similar example, but with `Result`: | 
|  | 1818 | + /// ``` | 
|  | 1819 | + /// #![feature(iterator_try_collect)] | 
|  | 1820 | + /// | 
|  | 1821 | + /// let u: Vec<Result<i32, ()>> = vec![Ok(1), Ok(2), Ok(3)]; | 
|  | 1822 | + /// let v = u.into_iter().try_collect::<Vec<i32>>(); | 
|  | 1823 | + /// assert_eq!(v, Ok(vec![1, 2, 3])); | 
|  | 1824 | + /// | 
|  | 1825 | + /// let u = vec![Ok(1), Ok(2), Err(()), Ok(3)]; | 
|  | 1826 | + /// let v = u.into_iter().try_collect::<Vec<i32>>(); | 
|  | 1827 | + /// assert_eq!(v, Err(())); | 
|  | 1828 | + /// ``` | 
|  | 1829 | + /// | 
|  | 1830 | + /// Finally, even [`ControlFlow`] works, despite the fact that it | 
|  | 1831 | + /// doesn't implement [`FromIterator`]. Note also that the iterator can | 
|  | 1832 | + /// continue to be used, even if a failure is encountered: | 
|  | 1833 | + /// | 
|  | 1834 | + /// ``` | 
|  | 1835 | + /// #![feature(iterator_try_collect)] | 
|  | 1836 | + /// | 
|  | 1837 | + /// use core::ops::ControlFlow::{Break, Continue}; | 
|  | 1838 | + /// | 
|  | 1839 | + /// let u = [Continue(1), Continue(2), Break(3), Continue(4), Continue(5)]; | 
|  | 1840 | + /// let mut it = u.into_iter(); | 
|  | 1841 | + /// | 
|  | 1842 | + /// let v = it.try_collect::<Vec<_>>(); | 
|  | 1843 | + /// assert_eq!(v, Break(3)); | 
|  | 1844 | + /// | 
|  | 1845 | + /// let v = it.try_collect::<Vec<_>>(); | 
|  | 1846 | + /// assert_eq!(v, Continue(vec![4, 5])); | 
|  | 1847 | + /// ``` | 
|  | 1848 | + /// | 
|  | 1849 | + /// [`collect`]: Iterator::collect | 
|  | 1850 | + #[inline] | 
|  | 1851 | + #[unstable(feature = "iterator_try_collect", issue = "94047")] | 
|  | 1852 | + fn try_collect<B>(&mut self) -> ChangeOutputType<Self::Item, B> | 
|  | 1853 | + where | 
|  | 1854 | + Self: Sized, | 
|  | 1855 | + <Self as Iterator>::Item: Try, | 
|  | 1856 | + <<Self as Iterator>::Item as Try>::Residual: Residual<B>, | 
|  | 1857 | + B: FromIterator<<Self::Item as Try>::Output>, | 
|  | 1858 | + { | 
|  | 1859 | + try_process(self, |i| i.collect()) | 
|  | 1860 | + } | 
|  | 1861 | + | 
| 1780 | 1862 |  /// Consumes an iterator, creating two collections from it. | 
| 1781 | 1863 |  /// | 
| 1782 | 1864 |  /// The predicate passed to `partition()` can return `true`, or `false`. | 
|  | 
0 commit comments