diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index d9d7dd9c36208..5a66c2871db2e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -1,7 +1,7 @@ -use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind, Safety}; +use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind, Safety, ast}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::{Ident, Span, sym}; -use thin_vec::thin_vec; +use thin_vec::{ThinVec, thin_vec}; use crate::deriving::generic::ty::*; use crate::deriving::generic::*; @@ -41,6 +41,38 @@ pub(crate) fn expand_deriving_partial_ord( } else { true }; + + let container_id = cx.current_expansion.id.expn_data().parent.expect_local(); + let has_derive_ord = cx.resolver.has_derive_ord(container_id); + let is_simple_candidate = |params: &ThinVec| -> bool { + has_derive_ord + && !params.iter().any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })) + }; + + let default_substructure = combine_substructure(Box::new(|cx, span, substr| { + cs_partial_cmp(cx, span, substr, discr_then_data) + })); + let simple_substructure = combine_substructure(Box::new(|cx, span, _| { + cs_partial_cmp_simple(cx, span, cx.expr_ident(span, Ident::new(sym::other, span))) + })); + let (is_simple, substructure) = match item { + Annotatable::Item(annitem) => match &annitem.kind { + // For unit structs/zero-variant enums, the default generated code is better. + ItemKind::Struct(.., ast::VariantData::Unit(..)) => (false, default_substructure), + ItemKind::Enum(.., enum_def) if enum_def.variants.is_empty() => { + (false, default_substructure) + } + ItemKind::Struct(_, ast::Generics { params, .. }, _) + | ItemKind::Enum(_, ast::Generics { params, .. }, _) + if is_simple_candidate(params) => + { + (true, simple_substructure) + } + _ => (false, default_substructure), + }, + _ => (false, default_substructure), + }; + let partial_cmp_def = MethodDef { name: sym::partial_cmp, generics: Bounds::empty(), @@ -49,9 +81,7 @@ pub(crate) fn expand_deriving_partial_ord( ret_ty, attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, - combine_substructure: combine_substructure(Box::new(|cx, span, substr| { - cs_partial_cmp(cx, span, substr, discr_then_data) - })), + combine_substructure: substructure, }; let trait_def = TraitDef { @@ -68,7 +98,18 @@ pub(crate) fn expand_deriving_partial_ord( safety: Safety::Default, document: true, }; - trait_def.expand(cx, mitem, item, push) + trait_def.expand_ext(cx, mitem, item, push, is_simple) +} + +// Special case for the type deriving both `PartialOrd` and `Ord`. Builds: +// ``` +// Some(::core::cmp::Ord::cmp(self, other)) +// ``` +fn cs_partial_cmp_simple(cx: &ExtCtxt<'_>, span: Span, other_expr: Box) -> BlockOrExpr { + let ord_cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]); + let cmp_expr = + cx.expr_call_global(span, ord_cmp_path, thin_vec![cx.expr_self(span), other_expr]); + BlockOrExpr::new_expr(cx.expr_some(span, cmp_expr)) } fn cs_partial_cmp( @@ -98,7 +139,8 @@ fn cs_partial_cmp( |cx, fold| match fold { CsFold::Single(field) => { let [other_expr] = &field.other_selflike_exprs[..] else { - cx.dcx().span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`"); + cx.dcx() + .span_bug(field.span, "not exactly 2 arguments in `derive(PartialOrd)`"); }; let args = thin_vec![field.self_expr.clone(), other_expr.clone()]; cx.expr_call_global(field.span, partial_cmp_path.clone(), args) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index b8325f7ba3987..5f2a7788c2375 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1117,6 +1117,8 @@ pub trait ResolverExpand { // Resolver interfaces for specific built-in macros. /// Does `#[derive(...)]` attribute with the given `ExpnId` have built-in `Copy` inside it? fn has_derive_copy(&self, expn_id: LocalExpnId) -> bool; + /// Does `#[derive(...)]` attribute with the given `ExpnId` have built-in `Ord` inside it? + fn has_derive_ord(&self, expn_id: LocalExpnId) -> bool; /// Resolve paths inside the `#[derive(...)]` attribute with the given `ExpnId`. fn resolve_derives( &mut self, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index af3006eda385e..a8fffdf5832ec 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1227,7 +1227,10 @@ impl ExternPreludeEntry<'_> { struct DeriveData { resolutions: Vec, helper_attrs: Vec<(usize, IdentKey, Span)>, + // if this list keeps getting extended, we could use `bitflags`, + // something like what [`rustc_type_ir::flags::TypeFlags`] is doing. has_derive_copy: bool, + has_derive_ord: bool, } struct MacroData { @@ -1381,6 +1384,7 @@ pub struct Resolver<'ra, 'tcx> { /// Derive macros cannot modify the item themselves and have to store the markers in the global /// context, so they attach the markers to derive container IDs using this resolver table. containers_deriving_copy: FxHashSet = default::fx_hash_set(), + containers_deriving_ord: FxHashSet = default::fx_hash_set(), /// Parent scopes in which the macros were invoked. /// FIXME: `derives` are missing in these parent scopes and need to be taken from elsewhere. invocation_parent_scopes: FxHashMap> = default::fx_hash_map(), diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index a5024f5ef694c..5a4c688edfb79 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -381,6 +381,10 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { self.containers_deriving_copy.contains(&expn_id) } + fn has_derive_ord(&self, expn_id: LocalExpnId) -> bool { + self.containers_deriving_ord.contains(&expn_id) + } + fn resolve_derives( &mut self, expn_id: LocalExpnId, @@ -400,6 +404,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { resolutions: derive_paths(), helper_attrs: Vec::new(), has_derive_copy: false, + has_derive_ord: false, }); let parent_scope = self.invocation_parent_scopes[&expn_id]; for (i, resolution) in entry.resolutions.iter_mut().enumerate() { @@ -422,6 +427,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { ); } entry.has_derive_copy |= ext.builtin_name == Some(sym::Copy); + entry.has_derive_ord |= ext.builtin_name == Some(sym::Ord); ext } Ok(_) | Err(Determinacy::Determined) => self.dummy_ext(MacroKind::Derive), @@ -457,6 +463,12 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { if entry.has_derive_copy || self.has_derive_copy(parent_scope.expansion) { self.containers_deriving_copy.insert(expn_id); } + // Similar to the above `Copy` and `Clone` case, the code generated for + // `derive(PartialOrd)` changes if `derive(Ord)` is also present. + // FIXME(makai410): this also doesn't work with `#[derive(PartialOrd)] #[derive(Ord)]`. + if entry.has_derive_ord || self.has_derive_ord(parent_scope.expansion) { + self.containers_deriving_ord.insert(expn_id); + } assert!(self.derive_data.is_empty()); self.derive_data = derive_data; Ok(()) diff --git a/tests/mir-opt/pre-codegen/derived_ord_debug.rs b/tests/mir-opt/pre-codegen/derived_ord_debug.rs index 1d6a884cee443..dbe98671d24be 100644 --- a/tests/mir-opt/pre-codegen/derived_ord_debug.rs +++ b/tests/mir-opt/pre-codegen/derived_ord_debug.rs @@ -10,8 +10,8 @@ pub struct MultiField(char, i16); // EMIT_MIR derived_ord_debug.{impl#1}-cmp.PreCodegen.after.mir // CHECK-LABEL: partial_cmp(_1: &MultiField, _2: &MultiField) -> Option -// CHECK: = ::partial_cmp( -// CHECK: = ::partial_cmp( +// CHECK: = ::cmp( +// CHECK: = Option::::Some( // CHECK-LABEL: cmp(_1: &MultiField, _2: &MultiField) -> std::cmp::Ordering // CHECK: = ::cmp( diff --git a/tests/mir-opt/pre-codegen/derived_ord_debug.{impl#0}-partial_cmp.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/derived_ord_debug.{impl#0}-partial_cmp.PreCodegen.after.panic-unwind.mir index 29cc54150764d..f685d05a1f276 100644 --- a/tests/mir-opt/pre-codegen/derived_ord_debug.{impl#0}-partial_cmp.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/derived_ord_debug.{impl#0}-partial_cmp.PreCodegen.after.panic-unwind.mir @@ -4,49 +4,14 @@ fn ::partial_cmp(_1: &MultiField, debug self => _1; debug other => _2; let mut _0: std::option::Option; - let _3: &char; - let _4: &char; - let mut _5: std::option::Option; - let mut _6: isize; - let mut _7: i8; - let _8: &i16; - let _9: &i16; - scope 1 { - debug cmp => _5; - } + let mut _3: std::cmp::Ordering; bb0: { - _3 = &((*_1).0: char); - _4 = &((*_2).0: char); - _5 = ::partial_cmp(copy _3, copy _4) -> [return: bb1, unwind continue]; + _3 = ::cmp(copy _1, copy _2) -> [return: bb1, unwind continue]; } bb1: { - _6 = discriminant(_5); - switchInt(move _6) -> [1: bb2, 0: bb4, otherwise: bb6]; - } - - bb2: { - _7 = discriminant(((_5 as Some).0: std::cmp::Ordering)); - switchInt(move _7) -> [0: bb3, otherwise: bb4]; - } - - bb3: { - _8 = &((*_1).1: i16); - _9 = &((*_2).1: i16); - _0 = ::partial_cmp(copy _8, copy _9) -> [return: bb5, unwind continue]; - } - - bb4: { - _0 = copy _5; - goto -> bb5; - } - - bb5: { + _0 = Option::::Some(move _3); return; } - - bb6: { - unreachable; - } } diff --git a/tests/ui/derives/deriving-with-repr-packed-move-errors.rs b/tests/ui/derives/deriving-with-repr-packed-move-errors.rs index 17aa750332c40..6ff81739cd9a8 100644 --- a/tests/ui/derives/deriving-with-repr-packed-move-errors.rs +++ b/tests/ui/derives/deriving-with-repr-packed-move-errors.rs @@ -18,8 +18,6 @@ struct StructA(String); //~| ERROR: cannot move out of a shared reference [E0507] //~| ERROR: cannot move out of a shared reference [E0507] //~| ERROR: cannot move out of a shared reference [E0507] -//~| ERROR: cannot move out of a shared reference [E0507] -//~| ERROR: cannot move out of a shared reference [E0507] // Unrelated impl: additinal diagnostic should NOT be emitted diff --git a/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr b/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr index e857b308d531f..a40068171212e 100644 --- a/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr +++ b/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr @@ -29,27 +29,6 @@ LL | struct StructA(String); = note: `#[derive(PartialEq)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0507]: cannot move out of a shared reference - --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 - | -LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] - | ---------- in this derive macro expansion -LL | struct StructA(String); - | ^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait - | - = note: `#[derive(PartialOrd)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour - -error[E0507]: cannot move out of a shared reference - --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 - | -LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] - | ---------- in this derive macro expansion -LL | struct StructA(String); - | ^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait - | - = note: `#[derive(PartialOrd)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error[E0507]: cannot move out of a shared reference --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | @@ -92,7 +71,7 @@ LL | struct StructA(String); = note: `#[derive(Clone)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour error[E0507]: cannot move out of `self` which is behind a shared reference - --> $DIR/deriving-with-repr-packed-move-errors.rs:28:9 + --> $DIR/deriving-with-repr-packed-move-errors.rs:26:9 | LL | self.0 | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait @@ -103,7 +82,7 @@ LL | self.0.clone() | ++++++++ error[E0507]: cannot move out of `self` which is behind a shared reference - --> $DIR/deriving-with-repr-packed-move-errors.rs:38:20 + --> $DIR/deriving-with-repr-packed-move-errors.rs:36:20 | LL | let x = &{ self.0 }; | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait @@ -114,7 +93,7 @@ LL | let x = &{ self.0.clone() }; | ++++++++ error[E0507]: cannot move out of `self` which is behind a shared reference - --> $DIR/deriving-with-repr-packed-move-errors.rs:45:12 + --> $DIR/deriving-with-repr-packed-move-errors.rs:43:12 | LL | ({ self.0 }) == ({ other.0 }) | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait @@ -125,7 +104,7 @@ LL | ({ self.0.clone() }) == ({ other.0 }) | ++++++++ error[E0507]: cannot move out of `other` which is behind a shared reference - --> $DIR/deriving-with-repr-packed-move-errors.rs:45:28 + --> $DIR/deriving-with-repr-packed-move-errors.rs:43:28 | LL | ({ self.0 }) == ({ other.0 }) | ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait @@ -136,7 +115,7 @@ LL | ({ self.0 }) == ({ other.0.clone() }) | ++++++++ error[E0507]: cannot move out of `self` which is behind a shared reference - --> $DIR/deriving-with-repr-packed-move-errors.rs:53:36 + --> $DIR/deriving-with-repr-packed-move-errors.rs:51:36 | LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait @@ -147,7 +126,7 @@ LL | PartialOrd::partial_cmp(&{ self.0.clone() }, &{ other.0 }) | ++++++++ error[E0507]: cannot move out of `other` which is behind a shared reference - --> $DIR/deriving-with-repr-packed-move-errors.rs:53:49 + --> $DIR/deriving-with-repr-packed-move-errors.rs:51:49 | LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) | ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait @@ -158,7 +137,7 @@ LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0.clone() }) | ++++++++ error[E0507]: cannot move out of `self` which is behind a shared reference - --> $DIR/deriving-with-repr-packed-move-errors.rs:68:20 + --> $DIR/deriving-with-repr-packed-move-errors.rs:66:20 | LL | let x = &{ self.0 }; | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait @@ -169,7 +148,7 @@ LL | let x = &{ self.0.clone() }; | ++++++++ error[E0507]: cannot move out of `self` which is behind a shared reference - --> $DIR/deriving-with-repr-packed-move-errors.rs:75:12 + --> $DIR/deriving-with-repr-packed-move-errors.rs:73:12 | LL | ({ self.0 }) == ({ other.0 }) | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait @@ -180,7 +159,7 @@ LL | ({ self.0.clone() }) == ({ other.0 }) | ++++++++ error[E0507]: cannot move out of `other` which is behind a shared reference - --> $DIR/deriving-with-repr-packed-move-errors.rs:75:28 + --> $DIR/deriving-with-repr-packed-move-errors.rs:73:28 | LL | ({ self.0 }) == ({ other.0 }) | ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait @@ -191,7 +170,7 @@ LL | ({ self.0 }) == ({ other.0.clone() }) | ++++++++ error[E0507]: cannot move out of `self` which is behind a shared reference - --> $DIR/deriving-with-repr-packed-move-errors.rs:83:36 + --> $DIR/deriving-with-repr-packed-move-errors.rs:81:36 | LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait @@ -202,7 +181,7 @@ LL | PartialOrd::partial_cmp(&{ self.0.clone() }, &{ other.0 }) | ++++++++ error[E0507]: cannot move out of `other` which is behind a shared reference - --> $DIR/deriving-with-repr-packed-move-errors.rs:83:49 + --> $DIR/deriving-with-repr-packed-move-errors.rs:81:49 | LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) | ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait @@ -213,7 +192,7 @@ LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0.clone() }) | ++++++++ error[E0507]: cannot move out of `arg` which is behind a shared reference - --> $DIR/deriving-with-repr-packed-move-errors.rs:92:5 + --> $DIR/deriving-with-repr-packed-move-errors.rs:90:5 | LL | arg.0 | ^^^^^ move occurs because `arg.0` has type `String`, which does not implement the `Copy` trait @@ -223,6 +202,6 @@ help: consider cloning the value if the performance cost is acceptable LL | arg.0.clone() | ++++++++ -error: aborting due to 21 previous errors +error: aborting due to 19 previous errors For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/deriving/deriving-all-codegen.rs b/tests/ui/deriving/deriving-all-codegen.rs index 9f21831960499..343d4095da470 100644 --- a/tests/ui/deriving/deriving-all-codegen.rs +++ b/tests/ui/deriving/deriving-all-codegen.rs @@ -235,3 +235,21 @@ struct FooCopyAndClone(i32); #[derive(Clone)] #[derive(Copy)] struct FooCloneAndCopy(i32); + +#[derive(PartialOrd, Ord)] +struct FooPartialOrdOrd(i32); + +#[derive(Ord, PartialOrd)] +struct FooOrdPartialOrd(i32); + +#[derive(Ord)] +#[derive(PartialOrd)] +struct FooOrdBeforePartialOrd(i32); + +// FIXME: this case should also have a trivial `PartialOrd` impl. +#[derive(PartialOrd)] +#[derive(Ord)] +struct FooPartialOrdBeforeOrd(i32); + +#[derive(PartialOrd, Ord)] +struct UnitStruct; diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout index 94e8b886436df..0fbcda77bba90 100644 --- a/tests/ui/deriving/deriving-all-codegen.stdout +++ b/tests/ui/deriving/deriving-all-codegen.stdout @@ -151,11 +151,7 @@ impl ::core::cmp::PartialOrd for Point { #[inline] fn partial_cmp(&self, other: &Point) -> ::core::option::Option<::core::cmp::Ordering> { - match ::core::cmp::PartialOrd::partial_cmp(&self.x, &other.x) { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - ::core::cmp::PartialOrd::partial_cmp(&self.y, &other.y), - cmp => cmp, - } + ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } } #[automatically_derived] @@ -239,13 +235,7 @@ impl ::core::cmp::PartialOrd for PackedPoint { #[inline] fn partial_cmp(&self, other: &PackedPoint) -> ::core::option::Option<::core::cmp::Ordering> { - match ::core::cmp::PartialOrd::partial_cmp(&{ self.x }, &{ other.x }) - { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - ::core::cmp::PartialOrd::partial_cmp(&{ self.y }, - &{ other.y }), - cmp => cmp, - } + ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } } #[automatically_derived] @@ -322,7 +312,7 @@ impl ::core::cmp::PartialOrd for TupleSingleField { #[inline] fn partial_cmp(&self, other: &TupleSingleField) -> ::core::option::Option<::core::cmp::Ordering> { - ::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0) + ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } } #[automatically_derived] @@ -397,7 +387,7 @@ impl ::core::cmp::PartialOrd for SingleField { #[inline] fn partial_cmp(&self, other: &SingleField) -> ::core::option::Option<::core::cmp::Ordering> { - ::core::cmp::PartialOrd::partial_cmp(&self.foo, &other.foo) + ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } } #[automatically_derived] @@ -502,47 +492,7 @@ impl ::core::cmp::PartialOrd for Big { #[inline] fn partial_cmp(&self, other: &Big) -> ::core::option::Option<::core::cmp::Ordering> { - match ::core::cmp::PartialOrd::partial_cmp(&self.b1, &other.b1) { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) => - match ::core::cmp::PartialOrd::partial_cmp(&self.b2, - &other.b2) { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) - => - match ::core::cmp::PartialOrd::partial_cmp(&self.b3, - &other.b3) { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) - => - match ::core::cmp::PartialOrd::partial_cmp(&self.b4, - &other.b4) { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) - => - match ::core::cmp::PartialOrd::partial_cmp(&self.b5, - &other.b5) { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) - => - match ::core::cmp::PartialOrd::partial_cmp(&self.b6, - &other.b6) { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) - => - match ::core::cmp::PartialOrd::partial_cmp(&self.b7, - &other.b7) { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) - => - ::core::cmp::PartialOrd::partial_cmp(&self.b8, &other.b8), - cmp => cmp, - }, - cmp => cmp, - }, - cmp => cmp, - }, - cmp => cmp, - }, - cmp => cmp, - }, - cmp => cmp, - }, - cmp => cmp, - } + ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } } #[automatically_derived] @@ -766,7 +716,7 @@ impl ::core::cmp::PartialOrd for Unsized { #[inline] fn partial_cmp(&self, other: &Unsized) -> ::core::option::Option<::core::cmp::Ordering> { - ::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0) + ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } } #[automatically_derived] @@ -1138,10 +1088,7 @@ impl ::core::cmp::PartialOrd for Enum1 { #[inline] fn partial_cmp(&self, other: &Enum1) -> ::core::option::Option<::core::cmp::Ordering> { - match (self, other) { - (Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) => - ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), - } + ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } } #[automatically_derived] @@ -1202,7 +1149,7 @@ impl ::core::cmp::PartialOrd for Fieldless1 { #[inline] fn partial_cmp(&self, other: &Fieldless1) -> ::core::option::Option<::core::cmp::Ordering> { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) + ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } } #[automatically_derived] @@ -1279,9 +1226,7 @@ impl ::core::cmp::PartialOrd for Fieldless { #[inline] fn partial_cmp(&self, other: &Fieldless) -> ::core::option::Option<::core::cmp::Ordering> { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - ::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr) + ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } } #[automatically_derived] @@ -1393,23 +1338,7 @@ impl ::core::cmp::PartialOrd for Mixed { #[inline] fn partial_cmp(&self, other: &Mixed) -> ::core::option::Option<::core::cmp::Ordering> { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - match (self, other) { - (Mixed::R(__self_0), Mixed::R(__arg1_0)) => - ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), - (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S { - d1: __arg1_0, d2: __arg1_1 }) => - match ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0) - { - ::core::option::Option::Some(::core::cmp::Ordering::Equal) - => ::core::cmp::PartialOrd::partial_cmp(__self_1, __arg1_1), - cmp => cmp, - }, - _ => - ::core::cmp::PartialOrd::partial_cmp(&__self_discr, - &__arg1_discr), - } + ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } } #[automatically_derived] @@ -1591,19 +1520,7 @@ impl ::core::cmp::PartialOrd for Fielded { #[inline] fn partial_cmp(&self, other: &Fielded) -> ::core::option::Option<::core::cmp::Ordering> { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - match (self, other) { - (Fielded::X(__self_0), Fielded::X(__arg1_0)) => - ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), - (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) => - ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), - (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) => - ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), - _ => - ::core::cmp::PartialOrd::partial_cmp(&__self_discr, - &__arg1_discr), - } + ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } } #[automatically_derived] @@ -1849,3 +1766,89 @@ impl ::core::clone::Clone for FooCloneAndCopy { FooCloneAndCopy(::core::clone::Clone::clone(&self.0)) } } + +struct FooPartialOrdOrd(i32); +#[automatically_derived] +impl ::core::cmp::PartialOrd for FooPartialOrdOrd { + #[inline] + fn partial_cmp(&self, other: &FooPartialOrdOrd) + -> ::core::option::Option<::core::cmp::Ordering> { + ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) + } +} +#[automatically_derived] +impl ::core::cmp::Ord for FooPartialOrdOrd { + #[inline] + fn cmp(&self, other: &FooPartialOrdOrd) -> ::core::cmp::Ordering { + ::core::cmp::Ord::cmp(&self.0, &other.0) + } +} + +struct FooOrdPartialOrd(i32); +#[automatically_derived] +impl ::core::cmp::Ord for FooOrdPartialOrd { + #[inline] + fn cmp(&self, other: &FooOrdPartialOrd) -> ::core::cmp::Ordering { + ::core::cmp::Ord::cmp(&self.0, &other.0) + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for FooOrdPartialOrd { + #[inline] + fn partial_cmp(&self, other: &FooOrdPartialOrd) + -> ::core::option::Option<::core::cmp::Ordering> { + ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) + } +} + +struct FooOrdBeforePartialOrd(i32); +#[automatically_derived] +impl ::core::cmp::PartialOrd for FooOrdBeforePartialOrd { + #[inline] + fn partial_cmp(&self, other: &FooOrdBeforePartialOrd) + -> ::core::option::Option<::core::cmp::Ordering> { + ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) + } +} +#[automatically_derived] +impl ::core::cmp::Ord for FooOrdBeforePartialOrd { + #[inline] + fn cmp(&self, other: &FooOrdBeforePartialOrd) -> ::core::cmp::Ordering { + ::core::cmp::Ord::cmp(&self.0, &other.0) + } +} + +// FIXME: this case should also have a trivial `PartialOrd` impl. +struct FooPartialOrdBeforeOrd(i32); +#[automatically_derived] +impl ::core::cmp::Ord for FooPartialOrdBeforeOrd { + #[inline] + fn cmp(&self, other: &FooPartialOrdBeforeOrd) -> ::core::cmp::Ordering { + ::core::cmp::Ord::cmp(&self.0, &other.0) + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for FooPartialOrdBeforeOrd { + #[inline] + fn partial_cmp(&self, other: &FooPartialOrdBeforeOrd) + -> ::core::option::Option<::core::cmp::Ordering> { + ::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0) + } +} + +struct UnitStruct; +#[automatically_derived] +impl ::core::cmp::PartialOrd for UnitStruct { + #[inline] + fn partial_cmp(&self, other: &UnitStruct) + -> ::core::option::Option<::core::cmp::Ordering> { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + } +} +#[automatically_derived] +impl ::core::cmp::Ord for UnitStruct { + #[inline] + fn cmp(&self, other: &UnitStruct) -> ::core::cmp::Ordering { + ::core::cmp::Ordering::Equal + } +} diff --git a/tests/ui/deriving/deriving-partial-ord-name-collision.rs b/tests/ui/deriving/deriving-partial-ord-name-collision.rs new file mode 100644 index 0000000000000..2a8c5c4c6469b --- /dev/null +++ b/tests/ui/deriving/deriving-partial-ord-name-collision.rs @@ -0,0 +1,11 @@ +//@ check-pass +//@ edition:2021 + +#[derive(PartialEq, Eq, PartialOrd, Ord)] +pub struct NameCollision(i32); + +impl NameCollision { + pub fn cmp(&self, _: &NameCollision) {} +} + +fn main() {} diff --git a/tests/ui/range/range_traits-1.rs b/tests/ui/range/range_traits-1.rs index e28e47435c2c2..63e22b7420368 100644 --- a/tests/ui/range/range_traits-1.rs +++ b/tests/ui/range/range_traits-1.rs @@ -3,23 +3,17 @@ use std::ops::*; #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] struct AllTheRanges { a: Range, - //~^ ERROR can't compare - //~| ERROR Ord + //~^ ERROR Ord b: RangeTo, - //~^ ERROR can't compare - //~| ERROR Ord + //~^ ERROR Ord c: RangeFrom, - //~^ ERROR can't compare - //~| ERROR Ord + //~^ ERROR Ord d: RangeFull, - //~^ ERROR can't compare - //~| ERROR Ord + //~^ ERROR Ord e: RangeInclusive, - //~^ ERROR can't compare - //~| ERROR Ord + //~^ ERROR Ord f: RangeToInclusive, - //~^ ERROR can't compare - //~| ERROR Ord + //~^ ERROR Ord } fn main() {} diff --git a/tests/ui/range/range_traits-1.stderr b/tests/ui/range/range_traits-1.stderr index ab1035778cd6c..3a200adfc96f8 100644 --- a/tests/ui/range/range_traits-1.stderr +++ b/tests/ui/range/range_traits-1.stderr @@ -1,69 +1,3 @@ -error[E0277]: can't compare `std::ops::Range` with `std::ops::Range` - --> $DIR/range_traits-1.rs:5:5 - | -LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] - | ---------- in this derive macro expansion -LL | struct AllTheRanges { -LL | a: Range, - | ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range < std::ops::Range` and `std::ops::Range > std::ops::Range` - | - = help: the trait `PartialOrd` is not implemented for `std::ops::Range` - -error[E0277]: can't compare `std::ops::RangeTo` with `std::ops::RangeTo` - --> $DIR/range_traits-1.rs:8:5 - | -LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] - | ---------- in this derive macro expansion -... -LL | b: RangeTo, - | ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo < std::ops::RangeTo` and `std::ops::RangeTo > std::ops::RangeTo` - | - = help: the trait `PartialOrd` is not implemented for `std::ops::RangeTo` - -error[E0277]: can't compare `std::ops::RangeFrom` with `std::ops::RangeFrom` - --> $DIR/range_traits-1.rs:11:5 - | -LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] - | ---------- in this derive macro expansion -... -LL | c: RangeFrom, - | ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom < std::ops::RangeFrom` and `std::ops::RangeFrom > std::ops::RangeFrom` - | - = help: the trait `PartialOrd` is not implemented for `std::ops::RangeFrom` - -error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull` - --> $DIR/range_traits-1.rs:14:5 - | -LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] - | ---------- in this derive macro expansion -... -LL | d: RangeFull, - | ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull` - | - = help: the trait `PartialOrd` is not implemented for `std::ops::RangeFull` - -error[E0277]: can't compare `std::ops::RangeInclusive` with `std::ops::RangeInclusive` - --> $DIR/range_traits-1.rs:17:5 - | -LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] - | ---------- in this derive macro expansion -... -LL | e: RangeInclusive, - | ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive < std::ops::RangeInclusive` and `std::ops::RangeInclusive > std::ops::RangeInclusive` - | - = help: the trait `PartialOrd` is not implemented for `std::ops::RangeInclusive` - -error[E0277]: can't compare `std::ops::RangeToInclusive` with `std::ops::RangeToInclusive` - --> $DIR/range_traits-1.rs:20:5 - | -LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] - | ---------- in this derive macro expansion -... -LL | f: RangeToInclusive, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive < std::ops::RangeToInclusive` and `std::ops::RangeToInclusive > std::ops::RangeToInclusive` - | - = help: the trait `PartialOrd` is not implemented for `std::ops::RangeToInclusive` - error[E0277]: the trait bound `std::ops::Range: Ord` is not satisfied --> $DIR/range_traits-1.rs:5:5 | @@ -74,7 +8,7 @@ LL | a: Range, | ^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::Range` error[E0277]: the trait bound `std::ops::RangeTo: Ord` is not satisfied - --> $DIR/range_traits-1.rs:8:5 + --> $DIR/range_traits-1.rs:7:5 | LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | --- in this derive macro expansion @@ -83,7 +17,7 @@ LL | b: RangeTo, | ^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeTo` error[E0277]: the trait bound `std::ops::RangeFrom: Ord` is not satisfied - --> $DIR/range_traits-1.rs:11:5 + --> $DIR/range_traits-1.rs:9:5 | LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | --- in this derive macro expansion @@ -92,7 +26,7 @@ LL | c: RangeFrom, | ^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeFrom` error[E0277]: the trait bound `std::ops::RangeFull: Ord` is not satisfied - --> $DIR/range_traits-1.rs:14:5 + --> $DIR/range_traits-1.rs:11:5 | LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | --- in this derive macro expansion @@ -101,7 +35,7 @@ LL | d: RangeFull, | ^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeFull` error[E0277]: the trait bound `std::ops::RangeInclusive: Ord` is not satisfied - --> $DIR/range_traits-1.rs:17:5 + --> $DIR/range_traits-1.rs:13:5 | LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | --- in this derive macro expansion @@ -110,7 +44,7 @@ LL | e: RangeInclusive, | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeInclusive` error[E0277]: the trait bound `std::ops::RangeToInclusive: Ord` is not satisfied - --> $DIR/range_traits-1.rs:20:5 + --> $DIR/range_traits-1.rs:15:5 | LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | --- in this derive macro expansion @@ -118,6 +52,6 @@ LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] LL | f: RangeToInclusive, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeToInclusive` -error: aborting due to 12 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/stats/macro-stats.stderr b/tests/ui/stats/macro-stats.stderr index e46e7e02862fa..c70895067eb5f 100644 --- a/tests/ui/stats/macro-stats.stderr +++ b/tests/ui/stats/macro-stats.stderr @@ -3,7 +3,6 @@ macro-stats MACRO EXPANSION STATS: macro_stats macro-stats Macro Name Uses Lines Avg Lines Bytes Avg Bytes macro-stats ----------------------------------------------------------------------------------- macro-stats #[derive(Clone)] 8 67 8.4 1_879 234.9 -macro-stats #[derive(PartialOrd)] 1 17 17.0 675 675.0 macro-stats #[derive(Hash)] 2 17 8.5 565 282.5 macro-stats q! 1 26 26.0 519 519.0 macro-stats #[derive(Ord)] 1 15 15.0 503 503.0 @@ -11,6 +10,7 @@ macro-stats #[derive(Default)] 2 16 8.0 macro-stats #[derive(Eq)] 1 11 11.0 312 312.0 macro-stats #[derive(Debug)] 1 8 8.0 277 277.0 macro-stats #[derive(PartialEq)] 1 9 9.0 267 267.0 +macro-stats #[derive(PartialOrd)] 1 8 8.0 254 254.0 macro-stats #[derive(Copy)] 1 2 2.0 61 61.0 macro-stats p! 1 3 3.0 32 32.0 macro-stats trait_impl_tys! 1 2 2.0 28 28.0 diff --git a/tests/ui/type/pattern_types/derives_fail.rs b/tests/ui/type/pattern_types/derives_fail.rs index a3fbad6672071..a7d6a49c4b2d0 100644 --- a/tests/ui/type/pattern_types/derives_fail.rs +++ b/tests/ui/type/pattern_types/derives_fail.rs @@ -14,7 +14,6 @@ struct Nanoseconds(NanoI32); //~| ERROR: the trait bound `(i32) is 0..=999999999: Ord` is not satisfied //~| ERROR: the trait bound `(i32) is 0..=999999999: Hash` is not satisfied //~| ERROR: the trait bound `(i32) is 0..=999999999: Default` is not satisfied -//~| ERROR: can't compare `(i32) is 0..=999999999` with `_` //~| ERROR: `==` cannot be applied type NanoI32 = crate::pattern_type!(i32 is 0..=999_999_999); diff --git a/tests/ui/type/pattern_types/derives_fail.stderr b/tests/ui/type/pattern_types/derives_fail.stderr index 45c9bae1f2806..b79b34adda52f 100644 --- a/tests/ui/type/pattern_types/derives_fail.stderr +++ b/tests/ui/type/pattern_types/derives_fail.stderr @@ -37,17 +37,6 @@ LL | #[repr(transparent)] LL | struct Nanoseconds(NanoI32); | ^^^^^^^ the trait `Ord` is not implemented for `(i32) is 0..=999999999` -error[E0277]: can't compare `(i32) is 0..=999999999` with `_` - --> $DIR/derives_fail.rs:11:20 - | -LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)] - | ---------- in this derive macro expansion -LL | #[repr(transparent)] -LL | struct Nanoseconds(NanoI32); - | ^^^^^^^ no implementation for `(i32) is 0..=999999999 < _` and `(i32) is 0..=999999999 > _` - | - = help: the trait `PartialOrd<_>` is not implemented for `(i32) is 0..=999999999` - error[E0277]: the trait bound `(i32) is 0..=999999999: Hash` is not satisfied --> $DIR/derives_fail.rs:11:20 | @@ -66,7 +55,7 @@ LL | #[repr(transparent)] LL | struct Nanoseconds(NanoI32); | ^^^^^^^ the trait `Default` is not implemented for `(i32) is 0..=999999999` -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0277, E0369. For more information about an error, try `rustc --explain E0277`.