summaryrefslogtreecommitdiffstats
path: root/library/core/src/iter
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--library/core/src/iter/adapters/array_chunks.rs18
-rw-r--r--library/core/src/iter/adapters/by_ref_sized.rs19
-rw-r--r--library/core/src/iter/adapters/copied.rs74
-rw-r--r--library/core/src/iter/adapters/map_while.rs14
-rw-r--r--library/core/src/iter/adapters/mod.rs10
-rw-r--r--library/core/src/iter/adapters/scan.rs14
-rw-r--r--library/core/src/iter/adapters/skip.rs12
-rw-r--r--library/core/src/iter/adapters/take.rs14
-rw-r--r--library/core/src/iter/adapters/take_while.rs14
-rw-r--r--library/core/src/iter/mod.rs23
-rw-r--r--library/core/src/iter/range.rs28
-rw-r--r--library/core/src/iter/traits/collect.rs3
-rw-r--r--library/core/src/iter/traits/iterator.rs170
13 files changed, 215 insertions, 198 deletions
diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs
index 9b479a9f8..d4fb88610 100644
--- a/library/core/src/iter/adapters/array_chunks.rs
+++ b/library/core/src/iter/adapters/array_chunks.rs
@@ -1,6 +1,6 @@
use crate::array;
use crate::iter::{ByRefSized, FusedIterator, Iterator};
-use crate::ops::{ControlFlow, NeverShortCircuit, Try};
+use crate::ops::{ControlFlow, Try};
/// An iterator over `N` elements of the iterator at a time.
///
@@ -82,13 +82,7 @@ where
}
}
- fn fold<B, F>(mut self, init: B, f: F) -> B
- where
- Self: Sized,
- F: FnMut(B, Self::Item) -> B,
- {
- self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
- }
+ impl_fold_via_try_fold! { fold -> try_fold }
}
#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
@@ -126,13 +120,7 @@ where
try { acc }
}
- fn rfold<B, F>(mut self, init: B, f: F) -> B
- where
- Self: Sized,
- F: FnMut(B, Self::Item) -> B,
- {
- self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0
- }
+ impl_fold_via_try_fold! { rfold -> try_rfold }
}
impl<I, const N: usize> ArrayChunks<I, N>
diff --git a/library/core/src/iter/adapters/by_ref_sized.rs b/library/core/src/iter/adapters/by_ref_sized.rs
index 477e7117c..1945e402f 100644
--- a/library/core/src/iter/adapters/by_ref_sized.rs
+++ b/library/core/src/iter/adapters/by_ref_sized.rs
@@ -1,4 +1,7 @@
-use crate::ops::{NeverShortCircuit, Try};
+use crate::{
+ const_closure::ConstFnMutClosure,
+ ops::{NeverShortCircuit, Try},
+};
/// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics.
///
@@ -36,12 +39,13 @@ impl<I: Iterator> Iterator for ByRefSized<'_, I> {
}
#[inline]
- fn fold<B, F>(self, init: B, f: F) -> B
+ fn fold<B, F>(self, init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
// `fold` needs ownership, so this can't forward directly.
- I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
+ I::try_fold(self.0, init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp))
+ .0
}
#[inline]
@@ -72,12 +76,17 @@ impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> {
}
#[inline]
- fn rfold<B, F>(self, init: B, f: F) -> B
+ fn rfold<B, F>(self, init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
// `rfold` needs ownership, so this can't forward directly.
- I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
+ I::try_rfold(
+ self.0,
+ init,
+ ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp),
+ )
+ .0
}
#[inline]
diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs
index f9bfd77d7..62d3afb81 100644
--- a/library/core/src/iter/adapters/copied.rs
+++ b/library/core/src/iter/adapters/copied.rs
@@ -2,7 +2,10 @@ use crate::iter::adapters::{
zip::try_get_unchecked, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
};
use crate::iter::{FusedIterator, TrustedLen};
+use crate::mem::MaybeUninit;
+use crate::mem::SizedTypeProperties;
use crate::ops::Try;
+use crate::{array, ptr};
/// An iterator that copies the elements of an underlying iterator.
///
@@ -44,6 +47,15 @@ where
self.it.next().copied()
}
+ fn next_chunk<const N: usize>(
+ &mut self,
+ ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>>
+ where
+ Self: Sized,
+ {
+ <I as SpecNextChunk<'_, N, T>>::spec_next_chunk(&mut self.it)
+ }
+
fn size_hint(&self) -> (usize, Option<usize>) {
self.it.size_hint()
}
@@ -166,3 +178,65 @@ where
T: Copy,
{
}
+
+trait SpecNextChunk<'a, const N: usize, T: 'a>: Iterator<Item = &'a T>
+where
+ T: Copy,
+{
+ fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>>;
+}
+
+impl<'a, const N: usize, I, T: 'a> SpecNextChunk<'a, N, T> for I
+where
+ I: Iterator<Item = &'a T>,
+ T: Copy,
+{
+ default fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
+ array::iter_next_chunk(&mut self.map(|e| *e))
+ }
+}
+
+impl<'a, const N: usize, T: 'a> SpecNextChunk<'a, N, T> for crate::slice::Iter<'a, T>
+where
+ T: Copy,
+{
+ fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
+ let mut raw_array = MaybeUninit::uninit_array();
+
+ let len = self.len();
+
+ if T::IS_ZST {
+ if len < N {
+ let _ = self.advance_by(len);
+ // SAFETY: ZSTs can be conjured ex nihilo; only the amount has to be correct
+ return Err(unsafe { array::IntoIter::new_unchecked(raw_array, 0..len) });
+ }
+
+ let _ = self.advance_by(N);
+ // SAFETY: ditto
+ return Ok(unsafe { MaybeUninit::array_assume_init(raw_array) });
+ }
+
+ if len < N {
+ // SAFETY: `len` indicates that this many elements are available and we just checked that
+ // it fits into the array.
+ unsafe {
+ ptr::copy_nonoverlapping(
+ self.as_ref().as_ptr(),
+ raw_array.as_mut_ptr() as *mut T,
+ len,
+ );
+ let _ = self.advance_by(len);
+ return Err(array::IntoIter::new_unchecked(raw_array, 0..len));
+ }
+ }
+
+ // SAFETY: `len` is larger than the array size. Copy a fixed amount here to fully initialize
+ // the array.
+ unsafe {
+ ptr::copy_nonoverlapping(self.as_ref().as_ptr(), raw_array.as_mut_ptr() as *mut T, N);
+ let _ = self.advance_by(N);
+ Ok(MaybeUninit::array_assume_init(raw_array))
+ }
+ }
+}
diff --git a/library/core/src/iter/adapters/map_while.rs b/library/core/src/iter/adapters/map_while.rs
index 1e8d6bf3e..fbdeca4d4 100644
--- a/library/core/src/iter/adapters/map_while.rs
+++ b/library/core/src/iter/adapters/map_while.rs
@@ -64,19 +64,7 @@ where
.into_try()
}
- #[inline]
- fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
- where
- Self: Sized,
- Fold: FnMut(Acc, Self::Item) -> Acc,
- {
- #[inline]
- fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
- move |acc, x| Ok(f(acc, x))
- }
-
- self.try_fold(init, ok(fold)).unwrap()
- }
+ impl_fold_via_try_fold! { fold -> try_fold }
}
#[unstable(issue = "none", feature = "inplace_iteration")]
diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs
index bf4fabad3..8cc2b7cec 100644
--- a/library/core/src/iter/adapters/mod.rs
+++ b/library/core/src/iter/adapters/mod.rs
@@ -1,5 +1,5 @@
use crate::iter::{InPlaceIterable, Iterator};
-use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, NeverShortCircuit, Residual, Try};
+use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try};
mod array_chunks;
mod by_ref_sized;
@@ -203,13 +203,7 @@ where
.into_try()
}
- fn fold<B, F>(mut self, init: B, fold: F) -> B
- where
- Self: Sized,
- F: FnMut(B, Self::Item) -> B,
- {
- self.try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0
- }
+ impl_fold_via_try_fold! { fold -> try_fold }
}
#[unstable(issue = "none", feature = "inplace_iteration")]
diff --git a/library/core/src/iter/adapters/scan.rs b/library/core/src/iter/adapters/scan.rs
index 80bfd2231..62470512c 100644
--- a/library/core/src/iter/adapters/scan.rs
+++ b/library/core/src/iter/adapters/scan.rs
@@ -74,19 +74,7 @@ where
self.iter.try_fold(init, scan(state, f, fold)).into_try()
}
- #[inline]
- fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
- where
- Self: Sized,
- Fold: FnMut(Acc, Self::Item) -> Acc,
- {
- #[inline]
- fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
- move |acc, x| Ok(f(acc, x))
- }
-
- self.try_fold(init, ok(fold)).unwrap()
- }
+ impl_fold_via_try_fold! { fold -> try_fold }
}
#[unstable(issue = "none", feature = "inplace_iteration")]
diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs
index dbf0ae9ec..c6334880d 100644
--- a/library/core/src/iter/adapters/skip.rs
+++ b/library/core/src/iter/adapters/skip.rs
@@ -206,17 +206,7 @@ where
if n == 0 { try { init } } else { self.iter.try_rfold(init, check(n, fold)).into_try() }
}
- fn rfold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
- where
- Fold: FnMut(Acc, Self::Item) -> Acc,
- {
- #[inline]
- fn ok<Acc, T>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, T) -> Result<Acc, !> {
- move |acc, x| Ok(f(acc, x))
- }
-
- self.try_rfold(init, ok(fold)).unwrap()
- }
+ impl_fold_via_try_fold! { rfold -> try_rfold }
#[inline]
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs
index 2962e0104..58a0b9d7b 100644
--- a/library/core/src/iter/adapters/take.rs
+++ b/library/core/src/iter/adapters/take.rs
@@ -98,19 +98,7 @@ where
}
}
- #[inline]
- fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
- where
- Self: Sized,
- Fold: FnMut(Acc, Self::Item) -> Acc,
- {
- #[inline]
- fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
- move |acc, x| Ok(f(acc, x))
- }
-
- self.try_fold(init, ok(fold)).unwrap()
- }
+ impl_fold_via_try_fold! { fold -> try_fold }
#[inline]
#[rustc_inherit_overflow_checks]
diff --git a/library/core/src/iter/adapters/take_while.rs b/library/core/src/iter/adapters/take_while.rs
index ded216da9..ec66dc3ae 100644
--- a/library/core/src/iter/adapters/take_while.rs
+++ b/library/core/src/iter/adapters/take_while.rs
@@ -94,19 +94,7 @@ where
}
}
- #[inline]
- fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
- where
- Self: Sized,
- Fold: FnMut(Acc, Self::Item) -> Acc,
- {
- #[inline]
- fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
- move |acc, x| Ok(f(acc, x))
- }
-
- self.try_fold(init, ok(fold)).unwrap()
- }
+ impl_fold_via_try_fold! { fold -> try_fold }
}
#[stable(feature = "fused", since = "1.26.0")]
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index 9514466bd..ef0f39782 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -352,6 +352,29 @@
#![stable(feature = "rust1", since = "1.0.0")]
+// This needs to be up here in order to be usable in the child modules
+macro_rules! impl_fold_via_try_fold {
+ (fold -> try_fold) => {
+ impl_fold_via_try_fold! { @internal fold -> try_fold }
+ };
+ (rfold -> try_rfold) => {
+ impl_fold_via_try_fold! { @internal rfold -> try_rfold }
+ };
+ (@internal $fold:ident -> $try_fold:ident) => {
+ #[inline]
+ fn $fold<AAA, FFF>(mut self, init: AAA, mut fold: FFF) -> AAA
+ where
+ FFF: FnMut(AAA, Self::Item) -> AAA,
+ {
+ use crate::const_closure::ConstFnMutClosure;
+ use crate::ops::NeverShortCircuit;
+
+ let fold = ConstFnMutClosure::new(&mut fold, NeverShortCircuit::wrap_mut_2_imp);
+ self.$try_fold(init, fold).0
+ }
+ };
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::traits::Iterator;
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index f7aeee8c9..ac7b389b1 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -1150,19 +1150,7 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
self.spec_try_fold(init, f)
}
- #[inline]
- fn fold<B, F>(mut self, init: B, f: F) -> B
- where
- Self: Sized,
- F: FnMut(B, Self::Item) -> B,
- {
- #[inline]
- fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
- move |acc, x| Ok(f(acc, x))
- }
-
- self.try_fold(init, ok(f)).unwrap()
- }
+ impl_fold_via_try_fold! { fold -> try_fold }
#[inline]
fn last(mut self) -> Option<A> {
@@ -1230,19 +1218,7 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
self.spec_try_rfold(init, f)
}
- #[inline]
- fn rfold<B, F>(mut self, init: B, f: F) -> B
- where
- Self: Sized,
- F: FnMut(B, Self::Item) -> B,
- {
- #[inline]
- fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
- move |acc, x| Ok(f(acc, x))
- }
-
- self.try_rfold(init, ok(f)).unwrap()
- }
+ impl_fold_via_try_fold! { rfold -> try_rfold }
}
// Safety: See above implementation for `ops::Range<A>`
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<A>: 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<I: ~const Iterator> const IntoIterator for I {
+impl<I: Iterator> 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<I>(iter: I) -> Option<I::Item>
- /// 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<I, F>(mut self, other: I, mut cmp: F) -> Ordering
+ fn cmp_by<I, F>(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<X, Y, F>(mut cmp: F) -> impl FnMut(X, Y) -> ControlFlow<Ordering>
+ 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<I, F>(mut self, other: I, mut partial_cmp: F) -> Option<Ordering>
+ fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering>
where
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, I::Item) -> Option<Ordering>,
{
- 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<X, Y, F>(mut partial_cmp: F) -> impl FnMut(X, Y) -> ControlFlow<Option<Ordering>>
+ where
+ F: FnMut(X, Y) -> Option<Ordering>,
+ {
+ 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<I, F>(mut self, other: I, mut eq: F) -> bool
+ fn eq_by<I, F>(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<X, Y, F>(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<A, B, F, T>(mut a: A, mut b: B, f: F) -> ControlFlow<T, Ordering>
+where
+ A: Iterator,
+ B: Iterator,
+ F: FnMut(A::Item, B::Item) -> ControlFlow<T>,
+{
+ #[inline]
+ fn compare<'a, B, X, T>(
+ b: &'a mut B,
+ mut f: impl FnMut(X, B::Item) -> ControlFlow<T> + 'a,
+ ) -> impl FnMut(X) -> ControlFlow<ControlFlow<T, Ordering>> + '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<I: Iterator + ?Sized> Iterator for &mut I {
type Item = I::Item;