@@ -3461,36 +3461,27 @@ pub trait Iterator {
34613461 /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater);
34623462 /// ```
34633463 #[ unstable( feature = "iter_order_by" , issue = "64295" ) ]
3464- fn cmp_by < I , F > ( mut self , other : I , mut cmp : F ) -> Ordering
3464+ fn cmp_by < I , F > ( self , other : I , cmp : F ) -> Ordering
34653465 where
34663466 Self : Sized ,
34673467 I : IntoIterator ,
34683468 F : FnMut ( Self :: Item , I :: Item ) -> Ordering ,
34693469 {
3470- let mut other = other. into_iter ( ) ;
3471-
3472- loop {
3473- let x = match self . next ( ) {
3474- None => {
3475- if other. next ( ) . is_none ( ) {
3476- return Ordering :: Equal ;
3477- } else {
3478- return Ordering :: Less ;
3479- }
3480- }
3481- Some ( val) => val,
3482- } ;
3483-
3484- let y = match other. next ( ) {
3485- None => return Ordering :: Greater ,
3486- Some ( val) => val,
3487- } ;
3488-
3489- match cmp ( x, y) {
3490- Ordering :: Equal => ( ) ,
3491- non_eq => return non_eq,
3470+ #[ inline]
3471+ fn compare < X , Y , F > ( mut cmp : F ) -> impl FnMut ( X , Y ) -> ControlFlow < Ordering >
3472+ where
3473+ F : FnMut ( X , Y ) -> Ordering ,
3474+ {
3475+ move |x, y| match cmp ( x, y) {
3476+ Ordering :: Equal => ControlFlow :: CONTINUE ,
3477+ non_eq => ControlFlow :: Break ( non_eq) ,
34923478 }
34933479 }
3480+
3481+ match iter_compare ( self , other. into_iter ( ) , compare ( cmp) ) {
3482+ ControlFlow :: Continue ( ord) => ord,
3483+ ControlFlow :: Break ( ord) => ord,
3484+ }
34943485 }
34953486
34963487 /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those
@@ -3546,36 +3537,27 @@ pub trait Iterator {
35463537 /// );
35473538 /// ```
35483539 #[ unstable( feature = "iter_order_by" , issue = "64295" ) ]
3549- fn partial_cmp_by < I , F > ( mut self , other : I , mut partial_cmp : F ) -> Option < Ordering >
3540+ fn partial_cmp_by < I , F > ( self , other : I , partial_cmp : F ) -> Option < Ordering >
35503541 where
35513542 Self : Sized ,
35523543 I : IntoIterator ,
35533544 F : FnMut ( Self :: Item , I :: Item ) -> Option < Ordering > ,
35543545 {
3555- let mut other = other. into_iter ( ) ;
3556-
3557- loop {
3558- let x = match self . next ( ) {
3559- None => {
3560- if other. next ( ) . is_none ( ) {
3561- return Some ( Ordering :: Equal ) ;
3562- } else {
3563- return Some ( Ordering :: Less ) ;
3564- }
3565- }
3566- Some ( val) => val,
3567- } ;
3568-
3569- let y = match other. next ( ) {
3570- None => return Some ( Ordering :: Greater ) ,
3571- Some ( val) => val,
3572- } ;
3573-
3574- match partial_cmp ( x, y) {
3575- Some ( Ordering :: Equal ) => ( ) ,
3576- non_eq => return non_eq,
3546+ #[ inline]
3547+ fn compare < X , Y , F > ( mut partial_cmp : F ) -> impl FnMut ( X , Y ) -> ControlFlow < Option < Ordering > >
3548+ where
3549+ F : FnMut ( X , Y ) -> Option < Ordering > ,
3550+ {
3551+ move |x, y| match partial_cmp ( x, y) {
3552+ Some ( Ordering :: Equal ) => ControlFlow :: CONTINUE ,
3553+ non_eq => ControlFlow :: Break ( non_eq) ,
35773554 }
35783555 }
3556+
3557+ match iter_compare ( self , other. into_iter ( ) , compare ( partial_cmp) ) {
3558+ ControlFlow :: Continue ( ord) => Some ( ord) ,
3559+ ControlFlow :: Break ( ord) => ord,
3560+ }
35793561 }
35803562
35813563 /// Determines if the elements of this [`Iterator`] are equal to those of
@@ -3613,29 +3595,26 @@ pub trait Iterator {
36133595 /// assert!(xs.iter().eq_by(&ys, |&x, &y| x * x == y));
36143596 /// ```
36153597 #[ unstable( feature = "iter_order_by" , issue = "64295" ) ]
3616- fn eq_by < I , F > ( mut self , other : I , mut eq : F ) -> bool
3598+ fn eq_by < I , F > ( self , other : I , eq : F ) -> bool
36173599 where
36183600 Self : Sized ,
36193601 I : IntoIterator ,
36203602 F : FnMut ( Self :: Item , I :: Item ) -> bool ,
36213603 {
3622- let mut other = other. into_iter ( ) ;
3623-
3624- loop {
3625- let x = match self . next ( ) {
3626- None => return other. next ( ) . is_none ( ) ,
3627- Some ( val) => val,
3628- } ;
3629-
3630- let y = match other. next ( ) {
3631- None => return false ,
3632- Some ( val) => val,
3633- } ;
3634-
3635- if !eq ( x, y) {
3636- return false ;
3604+ #[ inline]
3605+ fn compare < X , Y , F > ( mut eq : F ) -> impl FnMut ( X , Y ) -> ControlFlow < ( ) >
3606+ where
3607+ F : FnMut ( X , Y ) -> bool ,
3608+ {
3609+ move |x, y| {
3610+ if eq ( x, y) { ControlFlow :: CONTINUE } else { ControlFlow :: BREAK }
36373611 }
36383612 }
3613+
3614+ match iter_compare ( self , other. into_iter ( ) , compare ( eq) ) {
3615+ ControlFlow :: Continue ( ord) => ord == Ordering :: Equal ,
3616+ ControlFlow :: Break ( ( ) ) => false ,
3617+ }
36393618 }
36403619
36413620 /// Determines if the elements of this [`Iterator`] are unequal to those of
@@ -3860,6 +3839,46 @@ pub trait Iterator {
38603839 }
38613840}
38623841
3842+ /// Compares two iterators element-wise using the given function.
3843+ ///
3844+ /// If `ControlFlow::CONTINUE` is returned from the function, the comparison moves on to the next
3845+ /// elements of both iterators. Returning `ControlFlow::Break(x)` short-circuits the iteration and
3846+ /// returns `ControlFlow::Break(x)`. If one of the iterators runs out of elements,
3847+ /// `ControlFlow::Continue(ord)` is returned where `ord` is the result of comparing the lengths of
3848+ /// the iterators.
3849+ ///
3850+ /// Isolates the logic shared by ['cmp_by'](Iterator::cmp_by),
3851+ /// ['partial_cmp_by'](Iterator::partial_cmp_by), and ['eq_by'](Iterator::eq_by).
3852+ #[ inline]
3853+ fn iter_compare < A , B , F , T > ( mut a : A , mut b : B , f : F ) -> ControlFlow < T , Ordering >
3854+ where
3855+ A : Iterator ,
3856+ B : Iterator ,
3857+ F : FnMut ( A :: Item , B :: Item ) -> ControlFlow < T > ,
3858+ {
3859+ #[ inline]
3860+ fn compare < ' a , B , X , T > (
3861+ b : & ' a mut B ,
3862+ mut f : impl FnMut ( X , B :: Item ) -> ControlFlow < T > + ' a ,
3863+ ) -> impl FnMut ( X ) -> ControlFlow < ControlFlow < T , Ordering > > + ' a
3864+ where
3865+ B : Iterator ,
3866+ {
3867+ move |x| match b. next ( ) {
3868+ None => ControlFlow :: Break ( ControlFlow :: Continue ( Ordering :: Greater ) ) ,
3869+ Some ( y) => f ( x, y) . map_break ( ControlFlow :: Break ) ,
3870+ }
3871+ }
3872+
3873+ match a. try_for_each ( compare ( & mut b, f) ) {
3874+ ControlFlow :: Continue ( ( ) ) => ControlFlow :: Continue ( match b. next ( ) {
3875+ None => Ordering :: Equal ,
3876+ Some ( _) => Ordering :: Less ,
3877+ } ) ,
3878+ ControlFlow :: Break ( x) => x,
3879+ }
3880+ }
3881+
38633882#[ stable( feature = "rust1" , since = "1.0.0" ) ]
38643883impl < I : Iterator + ?Sized > Iterator for & mut I {
38653884 type Item = I :: Item ;
0 commit comments