Skip to content

Commit eb7abeb

Browse files
committed
Specialize Iterator::eq[_by] for TrustedLen iterators
1 parent 4cd91ef commit eb7abeb

File tree

1 file changed

+48
-4
lines changed

1 file changed

+48
-4
lines changed

library/core/src/iter/traits/iterator.rs

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use super::super::{
44
Product, Rev, Scan, Skip, SkipWhile, StepBy, Sum, Take, TakeWhile, TrustedRandomAccessNoCoerce,
55
Zip, try_process,
66
};
7+
use super::TrustedLen;
78
use crate::array;
89
use crate::cmp::{self, Ordering};
910
use crate::num::NonZero;
@@ -3816,10 +3817,7 @@ pub trait Iterator {
38163817
}
38173818
}
38183819

3819-
match iter_compare(self, other.into_iter(), compare(eq)) {
3820-
ControlFlow::Continue(ord) => ord == Ordering::Equal,
3821-
ControlFlow::Break(()) => false,
3822-
}
3820+
SpecIterEq::spec_iter_eq(self, other.into_iter(), compare(eq))
38233821
}
38243822

38253823
/// Determines if the elements of this [`Iterator`] are not equal to those of
@@ -4038,6 +4036,42 @@ pub trait Iterator {
40384036
}
40394037
}
40404038

4039+
trait SpecIterEq<B: Iterator>: Iterator {
4040+
fn spec_iter_eq<F>(self, b: B, f: F) -> bool
4041+
where
4042+
F: FnMut(Self::Item, <B as Iterator>::Item) -> ControlFlow<()>;
4043+
}
4044+
4045+
impl<A: Iterator, B: Iterator> SpecIterEq<B> for A {
4046+
#[inline]
4047+
default fn spec_iter_eq<F>(self, b: B, f: F) -> bool
4048+
where
4049+
F: FnMut(Self::Item, <B as Iterator>::Item) -> ControlFlow<()>,
4050+
{
4051+
iter_eq(self, b, f)
4052+
}
4053+
}
4054+
4055+
impl<A: Iterator + TrustedLen, B: Iterator + TrustedLen> SpecIterEq<B> for A {
4056+
#[inline]
4057+
fn spec_iter_eq<F>(self, b: B, f: F) -> bool
4058+
where
4059+
F: FnMut(Self::Item, <B as Iterator>::Item) -> ControlFlow<()>,
4060+
{
4061+
// we *can't* short-circuit if:
4062+
match (self.size_hint(), b.size_hint()) {
4063+
// ... both iterators have the same length
4064+
((_, Some(a)), (_, Some(b))) if a == b => {}
4065+
// ... or both of them are longer than `usize::MAX` (i.e. have an unknown length).
4066+
((_, None), (_, None)) => {}
4067+
// otherwise, we can ascertain that they are unequal without actually comparing items
4068+
_ => return false,
4069+
}
4070+
4071+
iter_eq(self, b, f)
4072+
}
4073+
}
4074+
40414075
/// Compares two iterators element-wise using the given function.
40424076
///
40434077
/// If `ControlFlow::Continue(())` is returned from the function, the comparison moves on to the next
@@ -4078,6 +4112,16 @@ where
40784112
}
40794113
}
40804114

4115+
#[inline]
4116+
fn iter_eq<A, B, F>(a: A, b: B, f: F) -> bool
4117+
where
4118+
A: Iterator,
4119+
B: Iterator,
4120+
F: FnMut(A::Item, B::Item) -> ControlFlow<()>,
4121+
{
4122+
iter_compare(a, b, f).continue_value().is_some_and(|ord| ord == Ordering::Equal)
4123+
}
4124+
40814125
/// Implements `Iterator` for mutable references to iterators, such as those produced by [`Iterator::by_ref`].
40824126
///
40834127
/// This implementation passes all method calls on to the original iterator.

0 commit comments

Comments
 (0)