From 20431706a863f92cb37dc512fef6e48d192aaf2c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:11:38 +0200 Subject: Merging upstream version 1.66.0+dfsg1. Signed-off-by: Daniel Baumann --- library/core/src/iter/traits/collect.rs | 3 +- library/core/src/iter/traits/iterator.rs | 170 ++++++++++++++++--------------- 2 files changed, 92 insertions(+), 81 deletions(-) (limited to 'library/core/src/iter/traits') diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 12ca508be..e099700e3 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -228,6 +228,7 @@ pub trait FromIterator: Sized { #[rustc_diagnostic_item = "IntoIterator"] #[rustc_skip_array_during_method_dispatch] #[stable(feature = "rust1", since = "1.0.0")] +#[const_trait] pub trait IntoIterator { /// The type of the elements being iterated over. #[stable(feature = "rust1", since = "1.0.0")] @@ -263,7 +264,7 @@ pub trait IntoIterator { #[rustc_const_unstable(feature = "const_intoiterator_identity", issue = "90603")] #[stable(feature = "rust1", since = "1.0.0")] -impl const IntoIterator for I { +impl const IntoIterator for I { type Item = I::Item; type IntoIter = I; diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index b2d08f4b0..789a87968 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -692,7 +692,7 @@ pub trait Iterator { /// assert_eq!(it.next(), Some(NotClone(99))); // The separator. /// assert_eq!(it.next(), Some(NotClone(1))); // The next element from `v`. /// assert_eq!(it.next(), Some(NotClone(99))); // The separator. - /// assert_eq!(it.next(), Some(NotClone(2))); // The last element from from `v`. + /// assert_eq!(it.next(), Some(NotClone(2))); // The last element from `v`. /// assert_eq!(it.next(), None); // The iterator is finished. /// ``` /// @@ -2431,22 +2431,13 @@ pub trait Iterator { /// /// # Example /// - /// Find the maximum value: - /// /// ``` - /// fn find_max(iter: I) -> Option - /// where I: Iterator, - /// I::Item: Ord, - /// { - /// iter.reduce(|accum, item| { - /// if accum >= item { accum } else { item } - /// }) - /// } - /// let a = [10, 20, 5, -23, 0]; - /// let b: [u32; 0] = []; + /// let reduced: i32 = (1..10).reduce(|acc, e| acc + e).unwrap(); + /// assert_eq!(reduced, 45); /// - /// assert_eq!(find_max(a.iter()), Some(&20)); - /// assert_eq!(find_max(b.iter()), None); + /// // Which is equivalent to doing it with `fold`: + /// let folded: i32 = (1..10).fold(0, |acc, e| acc + e); + /// assert_eq!(reduced, folded); /// ``` #[inline] #[stable(feature = "iterator_fold_self", since = "1.51.0")] @@ -2906,14 +2897,14 @@ pub trait Iterator { /// Stopping at the first `true`: /// /// ``` - /// let a = [1, 2, 3]; + /// let a = [-1, 2, 3, 4]; /// /// let mut iter = a.iter(); /// - /// assert_eq!(iter.rposition(|&x| x == 2), Some(1)); + /// assert_eq!(iter.rposition(|&x| x >= 2), Some(3)); /// /// // we can still use `iter`, as there are more elements. - /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.next(), Some(&-1)); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -3461,36 +3452,27 @@ pub trait Iterator { /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] - fn cmp_by(mut self, other: I, mut cmp: F) -> Ordering + fn cmp_by(self, other: I, cmp: F) -> Ordering where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, I::Item) -> Ordering, { - let mut other = other.into_iter(); - - loop { - let x = match self.next() { - None => { - if other.next().is_none() { - return Ordering::Equal; - } else { - return Ordering::Less; - } - } - Some(val) => val, - }; - - let y = match other.next() { - None => return Ordering::Greater, - Some(val) => val, - }; - - match cmp(x, y) { - Ordering::Equal => (), - non_eq => return non_eq, + #[inline] + fn compare(mut cmp: F) -> impl FnMut(X, Y) -> ControlFlow + where + F: FnMut(X, Y) -> Ordering, + { + move |x, y| match cmp(x, y) { + Ordering::Equal => ControlFlow::CONTINUE, + non_eq => ControlFlow::Break(non_eq), } } + + match iter_compare(self, other.into_iter(), compare(cmp)) { + ControlFlow::Continue(ord) => ord, + ControlFlow::Break(ord) => ord, + } } /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those @@ -3546,36 +3528,27 @@ pub trait Iterator { /// ); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] - fn partial_cmp_by(mut self, other: I, mut partial_cmp: F) -> Option + fn partial_cmp_by(self, other: I, partial_cmp: F) -> Option where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, I::Item) -> Option, { - let mut other = other.into_iter(); - - loop { - let x = match self.next() { - None => { - if other.next().is_none() { - return Some(Ordering::Equal); - } else { - return Some(Ordering::Less); - } - } - Some(val) => val, - }; - - let y = match other.next() { - None => return Some(Ordering::Greater), - Some(val) => val, - }; - - match partial_cmp(x, y) { - Some(Ordering::Equal) => (), - non_eq => return non_eq, + #[inline] + fn compare(mut partial_cmp: F) -> impl FnMut(X, Y) -> ControlFlow> + where + F: FnMut(X, Y) -> Option, + { + move |x, y| match partial_cmp(x, y) { + Some(Ordering::Equal) => ControlFlow::CONTINUE, + non_eq => ControlFlow::Break(non_eq), } } + + match iter_compare(self, other.into_iter(), compare(partial_cmp)) { + ControlFlow::Continue(ord) => Some(ord), + ControlFlow::Break(ord) => ord, + } } /// Determines if the elements of this [`Iterator`] are equal to those of @@ -3613,29 +3586,26 @@ pub trait Iterator { /// assert!(xs.iter().eq_by(&ys, |&x, &y| x * x == y)); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] - fn eq_by(mut self, other: I, mut eq: F) -> bool + fn eq_by(self, other: I, eq: F) -> bool where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, I::Item) -> bool, { - let mut other = other.into_iter(); - - loop { - let x = match self.next() { - None => return other.next().is_none(), - Some(val) => val, - }; - - let y = match other.next() { - None => return false, - Some(val) => val, - }; - - if !eq(x, y) { - return false; + #[inline] + fn compare(mut eq: F) -> impl FnMut(X, Y) -> ControlFlow<()> + where + F: FnMut(X, Y) -> bool, + { + move |x, y| { + if eq(x, y) { ControlFlow::CONTINUE } else { ControlFlow::BREAK } } } + + match iter_compare(self, other.into_iter(), compare(eq)) { + ControlFlow::Continue(ord) => ord == Ordering::Equal, + ControlFlow::Break(()) => false, + } } /// Determines if the elements of this [`Iterator`] are unequal to those of @@ -3860,6 +3830,46 @@ pub trait Iterator { } } +/// Compares two iterators element-wise using the given function. +/// +/// If `ControlFlow::CONTINUE` is returned from the function, the comparison moves on to the next +/// elements of both iterators. Returning `ControlFlow::Break(x)` short-circuits the iteration and +/// returns `ControlFlow::Break(x)`. If one of the iterators runs out of elements, +/// `ControlFlow::Continue(ord)` is returned where `ord` is the result of comparing the lengths of +/// the iterators. +/// +/// Isolates the logic shared by ['cmp_by'](Iterator::cmp_by), +/// ['partial_cmp_by'](Iterator::partial_cmp_by), and ['eq_by'](Iterator::eq_by). +#[inline] +fn iter_compare(mut a: A, mut b: B, f: F) -> ControlFlow +where + A: Iterator, + B: Iterator, + F: FnMut(A::Item, B::Item) -> ControlFlow, +{ + #[inline] + fn compare<'a, B, X, T>( + b: &'a mut B, + mut f: impl FnMut(X, B::Item) -> ControlFlow + 'a, + ) -> impl FnMut(X) -> ControlFlow> + 'a + where + B: Iterator, + { + move |x| match b.next() { + None => ControlFlow::Break(ControlFlow::Continue(Ordering::Greater)), + Some(y) => f(x, y).map_break(ControlFlow::Break), + } + } + + match a.try_for_each(compare(&mut b, f)) { + ControlFlow::Continue(()) => ControlFlow::Continue(match b.next() { + None => Ordering::Equal, + Some(_) => Ordering::Less, + }), + ControlFlow::Break(x) => x, + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for &mut I { type Item = I::Item; -- cgit v1.2.3