@@ -29,6 +29,7 @@ mod bytewise;
2929pub ( crate )  use  bytewise:: BytewiseEq ; 
3030
3131use  self :: Ordering :: * ; 
32+ use  crate :: ops:: ControlFlow :: { self ,  Break ,  Continue } ; 
3233
3334/// Trait for comparisons using the equality operator. 
3435/// 
@@ -1436,6 +1437,54 @@ pub macro PartialOrd($item:item) {
14361437    /* compiler built-in */ 
14371438} 
14381439
1440+ /// Helpers for chaining together field PartialOrds into the full type's ordering. 
1441+ /// 
1442+ /// If the two values are equal, returns `ControlFlow::Continue`. 
1443+ /// If the two values are not equal, returns `ControlFlow::Break(self OP other)`. 
1444+ /// 
1445+ /// This allows simple types like `i32` and `f64` to just emit two comparisons 
1446+ /// directly, instead of needing to optimize the 3-way comparison. 
1447+ /// 
1448+ /// Currently this is done using specialization, but it doesn't need that: 
1449+ /// it could be provided methods on `PartialOrd` instead and work fine. 
1450+ pub ( crate )  trait  SpecChainingPartialOrd < Rhs >  :  PartialOrd < Rhs >  { 
1451+     fn  spec_chain_lt ( & self ,  other :  & Rhs )  -> ControlFlow < bool > ; 
1452+     fn  spec_chain_le ( & self ,  other :  & Rhs )  -> ControlFlow < bool > ; 
1453+     fn  spec_chain_gt ( & self ,  other :  & Rhs )  -> ControlFlow < bool > ; 
1454+     fn  spec_chain_ge ( & self ,  other :  & Rhs )  -> ControlFlow < bool > ; 
1455+ } 
1456+ 
1457+ impl < T :  PartialOrd < U > ,  U >  SpecChainingPartialOrd < U >  for  T  { 
1458+     #[ inline]  
1459+     default  fn  spec_chain_lt ( & self ,  other :  & U )  -> ControlFlow < bool >  { 
1460+         match  PartialOrd :: partial_cmp ( self ,  other)  { 
1461+             Some ( Equal )  => Continue ( ( ) ) , 
1462+             c => Break ( c. is_some_and ( Ordering :: is_lt) ) , 
1463+         } 
1464+     } 
1465+     #[ inline]  
1466+     default  fn  spec_chain_le ( & self ,  other :  & U )  -> ControlFlow < bool >  { 
1467+         match  PartialOrd :: partial_cmp ( self ,  other)  { 
1468+             Some ( Equal )  => Continue ( ( ) ) , 
1469+             c => Break ( c. is_some_and ( Ordering :: is_le) ) , 
1470+         } 
1471+     } 
1472+     #[ inline]  
1473+     default  fn  spec_chain_gt ( & self ,  other :  & U )  -> ControlFlow < bool >  { 
1474+         match  PartialOrd :: partial_cmp ( self ,  other)  { 
1475+             Some ( Equal )  => Continue ( ( ) ) , 
1476+             c => Break ( c. is_some_and ( Ordering :: is_gt) ) , 
1477+         } 
1478+     } 
1479+     #[ inline]  
1480+     default  fn  spec_chain_ge ( & self ,  other :  & U )  -> ControlFlow < bool >  { 
1481+         match  PartialOrd :: partial_cmp ( self ,  other)  { 
1482+             Some ( Equal )  => Continue ( ( ) ) , 
1483+             c => Break ( c. is_some_and ( Ordering :: is_ge) ) , 
1484+         } 
1485+     } 
1486+ } 
1487+ 
14391488/// Compares and returns the minimum of two values. 
14401489/// 
14411490/// Returns the first argument if the comparison determines them to be equal. 
@@ -1731,6 +1780,7 @@ where
17311780mod  impls { 
17321781    use  crate :: cmp:: Ordering :: { self ,  Equal ,  Greater ,  Less } ; 
17331782    use  crate :: hint:: unreachable_unchecked; 
1783+     use  crate :: ops:: ControlFlow :: { self ,  Break ,  Continue } ; 
17341784
17351785    macro_rules!  partial_eq_impl { 
17361786        ( $( $t: ty) * )  => ( $( 
@@ -1769,6 +1819,40 @@ mod impls {
17691819
17701820    eq_impl !  {  ( )  bool  char  usize  u8  u16  u32  u64  u128  isize  i8  i16  i32  i64  i128  } 
17711821
1822+     macro_rules!  chaining_impl { 
1823+         ( $t: ty)  => { 
1824+             // These implementations are the same for `Ord` or `PartialOrd` types 
1825+             // because if either is NAN the `==` test will fail so we end up in 
1826+             // the `Break` case and the comparison will correctly return `false`. 
1827+             impl  super :: SpecChainingPartialOrd <$t> for  $t { 
1828+                 #[ inline] 
1829+                 fn  spec_chain_lt( & self ,  other:  & Self )  -> ControlFlow <bool > { 
1830+                     let  ( lhs,  rhs)  = ( * self ,  * other) ; 
1831+                     if  lhs == rhs {  Continue ( ( ) )  } 
1832+                     else {  Break ( lhs < rhs)  } 
1833+                 } 
1834+                 #[ inline] 
1835+                 fn  spec_chain_le( & self ,  other:  & Self )  -> ControlFlow <bool > { 
1836+                     let  ( lhs,  rhs)  = ( * self ,  * other) ; 
1837+                     if  lhs == rhs {  Continue ( ( ) )  } 
1838+                     else {  Break ( lhs <= rhs)  } 
1839+                 } 
1840+                 #[ inline] 
1841+                 fn  spec_chain_gt( & self ,  other:  & Self )  -> ControlFlow <bool > { 
1842+                     let  ( lhs,  rhs)  = ( * self ,  * other) ; 
1843+                     if  lhs == rhs {  Continue ( ( ) )  } 
1844+                     else {  Break ( lhs > rhs)  } 
1845+                 } 
1846+                 #[ inline] 
1847+                 fn  spec_chain_ge( & self ,  other:  & Self )  -> ControlFlow <bool > { 
1848+                     let  ( lhs,  rhs)  = ( * self ,  * other) ; 
1849+                     if  lhs == rhs {  Continue ( ( ) )  } 
1850+                     else {  Break ( lhs >= rhs)  } 
1851+                 } 
1852+             } 
1853+         } ; 
1854+     } 
1855+ 
17721856    macro_rules!  partial_ord_impl { 
17731857        ( $( $t: ty) * )  => ( $( 
17741858            #[ stable( feature = "rust1" ,  since = "1.0.0" ) ] 
@@ -1791,6 +1875,8 @@ mod impls {
17911875                #[ inline( always) ] 
17921876                fn  gt( & self ,  other:  & $t)  -> bool  {  ( * self )  > ( * other)  } 
17931877            } 
1878+ 
1879+             chaining_impl!( $t) ; 
17941880        ) * ) 
17951881    } 
17961882
@@ -1830,6 +1916,8 @@ mod impls {
18301916                fn  gt( & self ,  other:  & $t)  -> bool  {  ( * self )  > ( * other)  } 
18311917            } 
18321918
1919+             chaining_impl!( $t) ; 
1920+ 
18331921            #[ stable( feature = "rust1" ,  since = "1.0.0" ) ] 
18341922            impl  Ord  for  $t { 
18351923                #[ inline] 
0 commit comments