diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index c8ced78c4d791..b29251b4b436c 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -397,6 +397,12 @@ pub enum Ordering { } impl Ordering { + #[inline] + const fn as_raw(self) -> i8 { + // FIXME(const-hack): just use `PartialOrd` against `Equal` once that's const + crate::intrinsics::discriminant_value(&self) + } + /// Returns `true` if the ordering is the `Equal` variant. /// /// # Examples @@ -413,7 +419,11 @@ impl Ordering { #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] #[stable(feature = "ordering_helpers", since = "1.53.0")] pub const fn is_eq(self) -> bool { - matches!(self, Equal) + // All the `is_*` methods are implemented as comparisons against zero + // to follow how clang's libcxx implements their equivalents in + // + + self.as_raw() == 0 } /// Returns `true` if the ordering is not the `Equal` variant. @@ -432,7 +442,7 @@ impl Ordering { #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] #[stable(feature = "ordering_helpers", since = "1.53.0")] pub const fn is_ne(self) -> bool { - !matches!(self, Equal) + self.as_raw() != 0 } /// Returns `true` if the ordering is the `Less` variant. @@ -451,7 +461,7 @@ impl Ordering { #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] #[stable(feature = "ordering_helpers", since = "1.53.0")] pub const fn is_lt(self) -> bool { - matches!(self, Less) + self.as_raw() < 0 } /// Returns `true` if the ordering is the `Greater` variant. @@ -470,7 +480,7 @@ impl Ordering { #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] #[stable(feature = "ordering_helpers", since = "1.53.0")] pub const fn is_gt(self) -> bool { - matches!(self, Greater) + self.as_raw() > 0 } /// Returns `true` if the ordering is either the `Less` or `Equal` variant. @@ -489,7 +499,7 @@ impl Ordering { #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] #[stable(feature = "ordering_helpers", since = "1.53.0")] pub const fn is_le(self) -> bool { - !matches!(self, Greater) + self.as_raw() <= 0 } /// Returns `true` if the ordering is either the `Greater` or `Equal` variant. @@ -508,7 +518,7 @@ impl Ordering { #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")] #[stable(feature = "ordering_helpers", since = "1.53.0")] pub const fn is_ge(self) -> bool { - !matches!(self, Less) + self.as_raw() >= 0 } /// Reverses the `Ordering`. diff --git a/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir new file mode 100644 index 0000000000000..49314a64c3fc9 --- /dev/null +++ b/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir @@ -0,0 +1,89 @@ +// MIR for `demo_le` after PreCodegen + +fn demo_le(_1: &MultiField, _2: &MultiField) -> bool { + debug a => _1; + debug b => _2; + let mut _0: bool; + scope 1 (inlined ::le) { + let mut _11: std::option::Option; + scope 2 (inlined Option::::is_some_and:: bool {std::cmp::Ordering::is_le}>) { + let _12: std::cmp::Ordering; + scope 3 { + scope 4 (inlined bool {std::cmp::Ordering::is_le} as FnOnce<(std::cmp::Ordering,)>>::call_once - shim(fn(std::cmp::Ordering) -> bool {std::cmp::Ordering::is_le})) { + scope 5 (inlined std::cmp::Ordering::is_le) { + let mut _13: i8; + scope 6 (inlined std::cmp::Ordering::as_raw) { + } + } + } + } + } + scope 7 (inlined ::partial_cmp) { + let mut _6: std::option::Option; + let mut _7: i8; + scope 8 { + } + scope 9 (inlined std::cmp::impls::::partial_cmp) { + let mut _3: char; + let mut _4: char; + let mut _5: std::cmp::Ordering; + } + scope 10 (inlined std::cmp::impls::::partial_cmp) { + let mut _8: i16; + let mut _9: i16; + let mut _10: std::cmp::Ordering; + } + } + } + + bb0: { + StorageLive(_12); + StorageLive(_11); + StorageLive(_5); + StorageLive(_7); + StorageLive(_3); + _3 = copy ((*_1).0: char); + StorageLive(_4); + _4 = copy ((*_2).0: char); + _5 = Cmp(move _3, move _4); + StorageDead(_4); + StorageDead(_3); + _6 = Option::::Some(copy _5); + _7 = discriminant(_5); + switchInt(move _7) -> [0: bb1, otherwise: bb2]; + } + + bb1: { + StorageLive(_10); + StorageLive(_8); + _8 = copy ((*_1).1: i16); + StorageLive(_9); + _9 = copy ((*_2).1: i16); + _10 = Cmp(move _8, move _9); + StorageDead(_9); + StorageDead(_8); + _11 = Option::::Some(move _10); + StorageDead(_10); + StorageDead(_7); + StorageDead(_5); + goto -> bb3; + } + + bb2: { + _11 = copy _6; + StorageDead(_7); + StorageDead(_5); + goto -> bb3; + } + + bb3: { + _12 = move ((_11 as Some).0: std::cmp::Ordering); + StorageLive(_13); + _13 = discriminant(_12); + _0 = Le(move _13, const 0_i8); + StorageDead(_13); + StorageDead(_11); + StorageDead(_12); + return; + } +} diff --git a/tests/mir-opt/pre-codegen/derived_ord.rs b/tests/mir-opt/pre-codegen/derived_ord.rs index bad751edf8419..73ae923a6cb9c 100644 --- a/tests/mir-opt/pre-codegen/derived_ord.rs +++ b/tests/mir-opt/pre-codegen/derived_ord.rs @@ -1,4 +1,3 @@ -// skip-filecheck //@ compile-flags: -O -Zmir-opt-level=2 -Cdebuginfo=0 #![crate_type = "lib"] @@ -6,4 +5,29 @@ #[derive(PartialOrd, PartialEq)] pub struct MultiField(char, i16); +// Because this isn't derived by the impl, it's not on the `{impl#0}-partial_cmp`, +// and thus we need to call it to see what the inlined generic one produces. +pub fn demo_le(a: &MultiField, b: &MultiField) -> bool { + // CHECK-LABEL: fn demo_le + // CHECK: inlined ::le + // CHECK: inlined{{.+}}is_some_and + // CHECK: inlined ::partial_cmp + + // CHECK: [[A0:_[0-9]+]] = copy ((*_1).0: char); + // CHECK: [[B0:_[0-9]+]] = copy ((*_2).0: char); + // CHECK: Cmp(move [[A0]], move [[B0]]); + + // CHECK: [[D0:_[0-9]+]] = discriminant({{.+}}); + // CHECK: switchInt(move [[D0]]) -> [0: bb{{[0-9]+}}, otherwise: bb{{[0-9]+}}]; + + // CHECK: [[A1:_[0-9]+]] = copy ((*_1).1: i16); + // CHECK: [[B1:_[0-9]+]] = copy ((*_2).1: i16); + // CHECK: Cmp(move [[A1]], move [[B1]]); + + // CHECK: [[D1:_[0-9]+]] = discriminant({{.+}}); + // CHECK: _0 = Le(move [[D1]], const 0_i8); + *a <= *b +} + // EMIT_MIR derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir +// EMIT_MIR derived_ord.demo_le.PreCodegen.after.mir diff --git a/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir index 5f4ec1de2701f..de25eebee77ff 100644 --- a/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir @@ -1,6 +1,6 @@ -// MIR for `::partial_cmp` after PreCodegen +// MIR for `::partial_cmp` after PreCodegen -fn ::partial_cmp(_1: &MultiField, _2: &MultiField) -> Option { +fn ::partial_cmp(_1: &MultiField, _2: &MultiField) -> Option { debug self => _1; debug other => _2; let mut _0: std::option::Option;