Skip to content

Commit 277eeb2

Browse files
scottmcmsaethlin
authored andcommitted
Tweak the default PartialOrd::{lt,le,gt,ge}
1 parent f54c303 commit 277eeb2

File tree

2 files changed

+87
-16
lines changed

2 files changed

+87
-16
lines changed

library/core/src/cmp.rs

+38-16
Original file line numberDiff line numberDiff line change
@@ -360,12 +360,18 @@ impl Ordering {
360360
/// assert_eq!(Ordering::Equal.is_eq(), true);
361361
/// assert_eq!(Ordering::Greater.is_eq(), false);
362362
/// ```
363-
#[inline]
363+
#[inline(always)]
364364
#[must_use]
365365
#[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
366366
#[stable(feature = "ordering_helpers", since = "1.53.0")]
367367
pub const fn is_eq(self) -> bool {
368-
matches!(self, Equal)
368+
// Implementation note: It appears (as of 2022-12) that LLVM has an
369+
// easier time with a comparison against zero like this, as opposed
370+
// to looking for the `Less` value (-1) specifically, maybe because
371+
// it's not always obvious to it that -2 isn't possible.
372+
// Thus this and its siblings below are written this way, rather
373+
// than the potentially-more-obvious `matches!` version.
374+
(self as i8) == 0
369375
}
370376

371377
/// Returns `true` if the ordering is not the `Equal` variant.
@@ -379,12 +385,12 @@ impl Ordering {
379385
/// assert_eq!(Ordering::Equal.is_ne(), false);
380386
/// assert_eq!(Ordering::Greater.is_ne(), true);
381387
/// ```
382-
#[inline]
388+
#[inline(always)]
383389
#[must_use]
384390
#[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
385391
#[stable(feature = "ordering_helpers", since = "1.53.0")]
386392
pub const fn is_ne(self) -> bool {
387-
!matches!(self, Equal)
393+
(self as i8) != 0
388394
}
389395

390396
/// Returns `true` if the ordering is the `Less` variant.
@@ -398,12 +404,12 @@ impl Ordering {
398404
/// assert_eq!(Ordering::Equal.is_lt(), false);
399405
/// assert_eq!(Ordering::Greater.is_lt(), false);
400406
/// ```
401-
#[inline]
407+
#[inline(always)]
402408
#[must_use]
403409
#[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
404410
#[stable(feature = "ordering_helpers", since = "1.53.0")]
405411
pub const fn is_lt(self) -> bool {
406-
matches!(self, Less)
412+
(self as i8) < 0
407413
}
408414

409415
/// Returns `true` if the ordering is the `Greater` variant.
@@ -417,12 +423,12 @@ impl Ordering {
417423
/// assert_eq!(Ordering::Equal.is_gt(), false);
418424
/// assert_eq!(Ordering::Greater.is_gt(), true);
419425
/// ```
420-
#[inline]
426+
#[inline(always)]
421427
#[must_use]
422428
#[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
423429
#[stable(feature = "ordering_helpers", since = "1.53.0")]
424430
pub const fn is_gt(self) -> bool {
425-
matches!(self, Greater)
431+
(self as i8) > 0
426432
}
427433

428434
/// Returns `true` if the ordering is either the `Less` or `Equal` variant.
@@ -436,12 +442,12 @@ impl Ordering {
436442
/// assert_eq!(Ordering::Equal.is_le(), true);
437443
/// assert_eq!(Ordering::Greater.is_le(), false);
438444
/// ```
439-
#[inline]
445+
#[inline(always)]
440446
#[must_use]
441447
#[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
442448
#[stable(feature = "ordering_helpers", since = "1.53.0")]
443449
pub const fn is_le(self) -> bool {
444-
!matches!(self, Greater)
450+
(self as i8) <= 0
445451
}
446452

447453
/// Returns `true` if the ordering is either the `Greater` or `Equal` variant.
@@ -455,12 +461,12 @@ impl Ordering {
455461
/// assert_eq!(Ordering::Equal.is_ge(), true);
456462
/// assert_eq!(Ordering::Greater.is_ge(), true);
457463
/// ```
458-
#[inline]
464+
#[inline(always)]
459465
#[must_use]
460466
#[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
461467
#[stable(feature = "ordering_helpers", since = "1.53.0")]
462468
pub const fn is_ge(self) -> bool {
463-
!matches!(self, Less)
469+
(self as i8) >= 0
464470
}
465471

466472
/// Reverses the `Ordering`.
@@ -1124,7 +1130,11 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
11241130
#[must_use]
11251131
#[stable(feature = "rust1", since = "1.0.0")]
11261132
fn lt(&self, other: &Rhs) -> bool {
1127-
matches!(self.partial_cmp(other), Some(Less))
1133+
if let Some(ordering) = self.partial_cmp(other) {
1134+
ordering.is_lt()
1135+
} else {
1136+
false
1137+
}
11281138
}
11291139

11301140
/// This method tests less than or equal to (for `self` and `other`) and is used by the `<=`
@@ -1143,7 +1153,11 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
11431153
#[must_use]
11441154
#[stable(feature = "rust1", since = "1.0.0")]
11451155
fn le(&self, other: &Rhs) -> bool {
1146-
matches!(self.partial_cmp(other), Some(Less | Equal))
1156+
if let Some(ordering) = self.partial_cmp(other) {
1157+
ordering.is_le()
1158+
} else {
1159+
false
1160+
}
11471161
}
11481162

11491163
/// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
@@ -1161,7 +1175,11 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
11611175
#[must_use]
11621176
#[stable(feature = "rust1", since = "1.0.0")]
11631177
fn gt(&self, other: &Rhs) -> bool {
1164-
matches!(self.partial_cmp(other), Some(Greater))
1178+
if let Some(ordering) = self.partial_cmp(other) {
1179+
ordering.is_gt()
1180+
} else {
1181+
false
1182+
}
11651183
}
11661184

11671185
/// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`
@@ -1180,7 +1198,11 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
11801198
#[must_use]
11811199
#[stable(feature = "rust1", since = "1.0.0")]
11821200
fn ge(&self, other: &Rhs) -> bool {
1183-
matches!(self.partial_cmp(other), Some(Greater | Equal))
1201+
if let Some(ordering) = self.partial_cmp(other) {
1202+
ordering.is_ge()
1203+
} else {
1204+
false
1205+
}
11841206
}
11851207
}
11861208

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// The `derive(PartialOrd)` for a newtype doesn't override `lt`/`le`/`gt`/`ge`.
2+
// This double-checks that the `Option<Ordering>` intermediate values used
3+
// in the operators for such a type all optimize away.
4+
5+
// compile-flags: -C opt-level=1
6+
// min-llvm-version: 15.0
7+
8+
#![crate_type = "lib"]
9+
10+
use std::cmp::Ordering;
11+
12+
#[derive(PartialOrd, PartialEq)]
13+
pub struct Foo(u16);
14+
15+
// CHECK-LABEL: @check_lt
16+
// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
17+
#[no_mangle]
18+
pub fn check_lt(a: Foo, b: Foo) -> bool {
19+
// CHECK: %[[R:.+]] = icmp ult i16 %[[A]], %[[B]]
20+
// CHECK-NEXT: ret i1 %[[R]]
21+
a < b
22+
}
23+
24+
// CHECK-LABEL: @check_le
25+
// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
26+
#[no_mangle]
27+
pub fn check_le(a: Foo, b: Foo) -> bool {
28+
// CHECK: %[[R:.+]] = icmp ule i16 %[[A]], %[[B]]
29+
// CHECK-NEXT: ret i1 %[[R]]
30+
a <= b
31+
}
32+
33+
// CHECK-LABEL: @check_gt
34+
// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
35+
#[no_mangle]
36+
pub fn check_gt(a: Foo, b: Foo) -> bool {
37+
// CHECK: %[[R:.+]] = icmp ugt i16 %[[A]], %[[B]]
38+
// CHECK-NEXT: ret i1 %[[R]]
39+
a > b
40+
}
41+
42+
// CHECK-LABEL: @check_ge
43+
// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
44+
#[no_mangle]
45+
pub fn check_ge(a: Foo, b: Foo) -> bool {
46+
// CHECK: %[[R:.+]] = icmp uge i16 %[[A]], %[[B]]
47+
// CHECK-NEXT: ret i1 %[[R]]
48+
a >= b
49+
}

0 commit comments

Comments
 (0)