@@ -29,6 +29,7 @@ mod bytewise;
29
29
pub ( crate ) use bytewise:: BytewiseEq ;
30
30
31
31
use self :: Ordering :: * ;
32
+ use crate :: ops:: ControlFlow ;
32
33
33
34
/// Trait for comparisons using the equality operator.
34
35
///
@@ -1435,6 +1436,67 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
1435
1436
fn ge ( & self , other : & Rhs ) -> bool {
1436
1437
self . partial_cmp ( other) . is_some_and ( Ordering :: is_ge)
1437
1438
}
1439
+
1440
+ /// If `self == other`, returns `ControlFlow::Continue(())`.
1441
+ /// Otherwise, returns `ControlFlow::Break(self < other)`.
1442
+ ///
1443
+ /// This is useful for chaining together calls when implementing a lexical
1444
+ /// `PartialOrd::lt`, as it allows types (like primitives) which can cheaply
1445
+ /// check `==` and `<` separately to do rather than needing to calculate
1446
+ /// (then optimize out) the three-way `Ordering` result.
1447
+ #[ inline]
1448
+ #[ must_use]
1449
+ // Added to improve the behaviour of tuples; not necessarily stabilization-track.
1450
+ #[ unstable( feature = "partial_ord_chaining_methods" , issue = "none" ) ]
1451
+ #[ doc( hidden) ]
1452
+ fn __chaining_lt ( & self , other : & Rhs ) -> ControlFlow < bool > {
1453
+ default_chaining_impl ( self , other, Ordering :: is_lt)
1454
+ }
1455
+
1456
+ /// Same as `__chaining_lt`, but for `<=` instead of `<`.
1457
+ #[ inline]
1458
+ #[ must_use]
1459
+ #[ unstable( feature = "partial_ord_chaining_methods" , issue = "none" ) ]
1460
+ #[ doc( hidden) ]
1461
+ fn __chaining_le ( & self , other : & Rhs ) -> ControlFlow < bool > {
1462
+ default_chaining_impl ( self , other, Ordering :: is_le)
1463
+ }
1464
+
1465
+ /// Same as `__chaining_lt`, but for `>` instead of `<`.
1466
+ #[ inline]
1467
+ #[ must_use]
1468
+ #[ unstable( feature = "partial_ord_chaining_methods" , issue = "none" ) ]
1469
+ #[ doc( hidden) ]
1470
+ fn __chaining_gt ( & self , other : & Rhs ) -> ControlFlow < bool > {
1471
+ default_chaining_impl ( self , other, Ordering :: is_gt)
1472
+ }
1473
+
1474
+ /// Same as `__chaining_lt`, but for `>=` instead of `<`.
1475
+ #[ inline]
1476
+ #[ must_use]
1477
+ #[ unstable( feature = "partial_ord_chaining_methods" , issue = "none" ) ]
1478
+ #[ doc( hidden) ]
1479
+ fn __chaining_ge ( & self , other : & Rhs ) -> ControlFlow < bool > {
1480
+ default_chaining_impl ( self , other, Ordering :: is_ge)
1481
+ }
1482
+ }
1483
+
1484
+ fn default_chaining_impl < T : ?Sized , U : ?Sized > (
1485
+ lhs : & T ,
1486
+ rhs : & U ,
1487
+ p : impl FnOnce ( Ordering ) -> bool ,
1488
+ ) -> ControlFlow < bool >
1489
+ where
1490
+ T : PartialOrd < U > ,
1491
+ {
1492
+ // It's important that this only call `partial_cmp` once, not call `eq` then
1493
+ // one of the relational operators. We don't want to `bcmp`-then-`memcp` a
1494
+ // `String`, for example, or similarly for other data structures (#108157).
1495
+ match <T as PartialOrd < U > >:: partial_cmp ( lhs, rhs) {
1496
+ Some ( Equal ) => ControlFlow :: Continue ( ( ) ) ,
1497
+ Some ( c) => ControlFlow :: Break ( p ( c) ) ,
1498
+ None => ControlFlow :: Break ( false ) ,
1499
+ }
1438
1500
}
1439
1501
1440
1502
/// Derive macro generating an impl of the trait [`PartialOrd`].
@@ -1741,6 +1803,7 @@ where
1741
1803
mod impls {
1742
1804
use crate :: cmp:: Ordering :: { self , Equal , Greater , Less } ;
1743
1805
use crate :: hint:: unreachable_unchecked;
1806
+ use crate :: ops:: ControlFlow :: { self , Break , Continue } ;
1744
1807
1745
1808
macro_rules! partial_eq_impl {
1746
1809
( $( $t: ty) * ) => ( $(
@@ -1779,6 +1842,35 @@ mod impls {
1779
1842
1780
1843
eq_impl ! { ( ) bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
1781
1844
1845
+ macro_rules! chaining_methods_impl {
1846
+ ( $t: ty) => {
1847
+ // These implementations are the same for `Ord` or `PartialOrd` types
1848
+ // because if either is NAN the `==` test will fail so we end up in
1849
+ // the `Break` case and the comparison will correctly return `false`.
1850
+
1851
+ #[ inline]
1852
+ fn __chaining_lt( & self , other: & Self ) -> ControlFlow <bool > {
1853
+ let ( lhs, rhs) = ( * self , * other) ;
1854
+ if lhs == rhs { Continue ( ( ) ) } else { Break ( lhs < rhs) }
1855
+ }
1856
+ #[ inline]
1857
+ fn __chaining_le( & self , other: & Self ) -> ControlFlow <bool > {
1858
+ let ( lhs, rhs) = ( * self , * other) ;
1859
+ if lhs == rhs { Continue ( ( ) ) } else { Break ( lhs <= rhs) }
1860
+ }
1861
+ #[ inline]
1862
+ fn __chaining_gt( & self , other: & Self ) -> ControlFlow <bool > {
1863
+ let ( lhs, rhs) = ( * self , * other) ;
1864
+ if lhs == rhs { Continue ( ( ) ) } else { Break ( lhs > rhs) }
1865
+ }
1866
+ #[ inline]
1867
+ fn __chaining_ge( & self , other: & Self ) -> ControlFlow <bool > {
1868
+ let ( lhs, rhs) = ( * self , * other) ;
1869
+ if lhs == rhs { Continue ( ( ) ) } else { Break ( lhs >= rhs) }
1870
+ }
1871
+ } ;
1872
+ }
1873
+
1782
1874
macro_rules! partial_ord_impl {
1783
1875
( $( $t: ty) * ) => ( $(
1784
1876
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -1800,6 +1892,8 @@ mod impls {
1800
1892
fn ge( & self , other: & $t) -> bool { ( * self ) >= ( * other) }
1801
1893
#[ inline( always) ]
1802
1894
fn gt( & self , other: & $t) -> bool { ( * self ) > ( * other) }
1895
+
1896
+ chaining_methods_impl!( $t) ;
1803
1897
}
1804
1898
) * )
1805
1899
}
@@ -1838,6 +1932,8 @@ mod impls {
1838
1932
fn ge( & self , other: & $t) -> bool { ( * self ) >= ( * other) }
1839
1933
#[ inline( always) ]
1840
1934
fn gt( & self , other: & $t) -> bool { ( * self ) > ( * other) }
1935
+
1936
+ chaining_methods_impl!( $t) ;
1841
1937
}
1842
1938
1843
1939
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
0 commit comments