From 4064a6bed2ee5675fb40f719b165b297efba33fb Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sun, 16 Feb 2025 10:14:53 +0000 Subject: [PATCH 1/2] Specialize `Iterator::{eq|cmp|partial_cmp}_by` for `TrustedLen` iterators --- library/core/src/iter/traits/iterator.rs | 42 ++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 42886e90f997d..41670392a4e68 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; @@ -3615,7 +3616,7 @@ pub trait Iterator { } } - match iter_compare(self, other.into_iter(), compare(cmp)) { + match SpecIterCompare::spec_iter_compare(self, other.into_iter(), compare(cmp)) { ControlFlow::Continue(ord) => ord, ControlFlow::Break(ord) => ord, } @@ -3707,7 +3708,7 @@ pub trait Iterator { } } - match iter_compare(self, other.into_iter(), compare(partial_cmp)) { + match SpecIterCompare::spec_iter_compare(self, other.into_iter(), compare(partial_cmp)) { ControlFlow::Continue(ord) => Some(ord), ControlFlow::Break(ord) => ord, } @@ -3762,7 +3763,7 @@ pub trait Iterator { } } - match iter_compare(self, other.into_iter(), compare(eq)) { + match SpecIterCompare::spec_iter_compare(self, other.into_iter(), compare(eq)) { ControlFlow::Continue(ord) => ord == Ordering::Equal, ControlFlow::Break(()) => false, } @@ -3984,6 +3985,41 @@ pub trait Iterator { } } +trait SpecIterCompare: Iterator { + fn spec_iter_compare(self, b: B, f: F) -> ControlFlow + where + F: FnMut(Self::Item, B::Item) -> ControlFlow; +} + +impl SpecIterCompare for A { + #[inline] + default fn spec_iter_compare(self, b: B, f: F) -> ControlFlow + where + F: FnMut(A::Item, ::Item) -> ControlFlow, + { + iter_compare(self, b, f) + } +} + +impl SpecIterCompare for A { + #[inline] + fn spec_iter_compare(self, b: B, f: F) -> ControlFlow + where + F: FnMut(Self::Item, ::Item) -> ControlFlow, + { + if let (_, Some(a)) = self.size_hint() + && let (_, Some(b)) = b.size_hint() + { + let ord = a.cmp(&b); + if ord != Ordering::Equal { + return ControlFlow::Continue(ord); + } + } + + iter_compare(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 From d9f58d45d67bc8bdb3283f1691263d7dc0269065 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sun, 16 Feb 2025 11:50:38 +0000 Subject: [PATCH 2/2] This optimization can't be applied to `{partial_}cmp{_by}` --- library/core/src/iter/traits/iterator.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 41670392a4e68..3f0cf04648bbc 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -3616,7 +3616,7 @@ pub trait Iterator { } } - match SpecIterCompare::spec_iter_compare(self, other.into_iter(), compare(cmp)) { + match iter_compare(self, other.into_iter(), compare(cmp)) { ControlFlow::Continue(ord) => ord, ControlFlow::Break(ord) => ord, } @@ -3708,7 +3708,7 @@ pub trait Iterator { } } - match SpecIterCompare::spec_iter_compare(self, other.into_iter(), compare(partial_cmp)) { + match iter_compare(self, other.into_iter(), compare(partial_cmp)) { ControlFlow::Continue(ord) => Some(ord), ControlFlow::Break(ord) => ord, }