diff options
| author | Yotam Ofek <yotam.ofek@gmail.com> | 2025-02-16 10:14:53 +0000 |
|---|---|---|
| committer | Yotam Ofek <yotam.ofek@gmail.com> | 2025-09-18 22:47:54 +0300 |
| commit | eb7abeb2614fb64f4d23afaa83df7380159b72c2 (patch) | |
| tree | 1bf81475d3be1bcb3b1c50224be670e75f115530 | |
| parent | 4cd91ef8223ef54111d21aa9e9e71b3b26477dd3 (diff) | |
| download | rust-eb7abeb2614fb64f4d23afaa83df7380159b72c2.tar.gz rust-eb7abeb2614fb64f4d23afaa83df7380159b72c2.zip | |
Specialize `Iterator::eq[_by]` for `TrustedLen` iterators
| -rw-r--r-- | library/core/src/iter/traits/iterator.rs | 52 |
1 files changed, 48 insertions, 4 deletions
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 7fb162a653f..695f8d1e195 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4,6 +4,7 @@ use super::super::{ Product, Rev, Scan, Skip, SkipWhile, StepBy, Sum, Take, TakeWhile, TrustedRandomAccessNoCoerce, Zip, try_process, }; +use super::TrustedLen; use crate::array; use crate::cmp::{self, Ordering}; use crate::num::NonZero; @@ -3816,10 +3817,7 @@ pub trait Iterator { } } - match iter_compare(self, other.into_iter(), compare(eq)) { - ControlFlow::Continue(ord) => ord == Ordering::Equal, - ControlFlow::Break(()) => false, - } + SpecIterEq::spec_iter_eq(self, other.into_iter(), compare(eq)) } /// Determines if the elements of this [`Iterator`] are not equal to those of @@ -4038,6 +4036,42 @@ pub trait Iterator { } } +trait SpecIterEq<B: Iterator>: Iterator { + fn spec_iter_eq<F>(self, b: B, f: F) -> bool + where + F: FnMut(Self::Item, <B as Iterator>::Item) -> ControlFlow<()>; +} + +impl<A: Iterator, B: Iterator> SpecIterEq<B> for A { + #[inline] + default fn spec_iter_eq<F>(self, b: B, f: F) -> bool + where + F: FnMut(Self::Item, <B as Iterator>::Item) -> ControlFlow<()>, + { + iter_eq(self, b, f) + } +} + +impl<A: Iterator + TrustedLen, B: Iterator + TrustedLen> SpecIterEq<B> for A { + #[inline] + fn spec_iter_eq<F>(self, b: B, f: F) -> bool + where + F: FnMut(Self::Item, <B as Iterator>::Item) -> ControlFlow<()>, + { + // we *can't* short-circuit if: + match (self.size_hint(), b.size_hint()) { + // ... both iterators have the same length + ((_, Some(a)), (_, Some(b))) if a == b => {} + // ... or both of them are longer than `usize::MAX` (i.e. have an unknown length). + ((_, None), (_, None)) => {} + // otherwise, we can ascertain that they are unequal without actually comparing items + _ => return false, + } + + iter_eq(self, b, f) + } +} + /// Compares two iterators element-wise using the given function. /// /// If `ControlFlow::Continue(())` is returned from the function, the comparison moves on to the next @@ -4078,6 +4112,16 @@ where } } +#[inline] +fn iter_eq<A, B, F>(a: A, b: B, f: F) -> bool +where + A: Iterator, + B: Iterator, + F: FnMut(A::Item, B::Item) -> ControlFlow<()>, +{ + iter_compare(a, b, f).continue_value().is_some_and(|ord| ord == Ordering::Equal) +} + /// Implements `Iterator` for mutable references to iterators, such as those produced by [`Iterator::by_ref`]. /// /// This implementation passes all method calls on to the original iterator. |
