diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 5c44fda226241..2542d9dc18d4d 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -906,6 +906,10 @@ pub enum BinOpKind { Ge, /// The `>` operator (greater than) Gt, + /// The `<=>` operator (Ord::cmp) + Cmp, + /// The `<==>` operator (PartialOrd::partial_cmp) + CmpPartial, } impl BinOpKind { @@ -930,6 +934,8 @@ impl BinOpKind { Ne => "!=", Ge => ">=", Gt => ">", + Cmp => "<=>", + CmpPartial => "<==>", } } @@ -946,7 +952,7 @@ impl BinOpKind { BitAnd => ExprPrecedence::BitAnd, BitXor => ExprPrecedence::BitXor, BitOr => ExprPrecedence::BitOr, - Lt | Gt | Le | Ge | Eq | Ne => ExprPrecedence::Compare, + Lt | Gt | Le | Ge | Eq | Ne | Cmp | CmpPartial => ExprPrecedence::Compare, And => ExprPrecedence::LAnd, Or => ExprPrecedence::LOr, } @@ -955,7 +961,7 @@ impl BinOpKind { pub fn fixity(&self) -> Fixity { use BinOpKind::*; match self { - Eq | Ne | Lt | Le | Gt | Ge => Fixity::None, + Eq | Ne | Lt | Le | Gt | Ge | Cmp | CmpPartial => Fixity::None, Add | Sub | Mul | Div | Rem | And | Or | BitXor | BitAnd | BitOr | Shl | Shr => { Fixity::Left } @@ -965,7 +971,7 @@ impl BinOpKind { pub fn is_comparison(self) -> bool { use BinOpKind::*; match self { - Eq | Ne | Lt | Le | Gt | Ge => true, + Eq | Ne | Lt | Le | Gt | Ge | Cmp | CmpPartial => true, Add | Sub | Mul | Div | Rem | And | Or | BitXor | BitAnd | BitOr | Shl | Shr => false, } } diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index 1ed44c20bc61e..2149e76d51e94 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -1,4 +1,5 @@ -use rustc_ast::MetaItem; +use rustc_ast::ptr::P; +use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, MetaItem, Mutability}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::{Ident, Span, sym}; use thin_vec::thin_vec; @@ -42,7 +43,6 @@ pub(crate) fn expand_deriving_ord( pub(crate) fn cs_cmp(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr { let test_id = Ident::new(sym::cmp, span); let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); - let cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]); // Builds: // @@ -63,8 +63,23 @@ pub(crate) fn cs_cmp(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> let [other_expr] = &field.other_selflike_exprs[..] else { cx.dcx().span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`"); }; - let args = thin_vec![field.self_expr.clone(), other_expr.clone()]; - cx.expr_call_global(field.span, cmp_path.clone(), args) + let convert = |expr: &P| { + if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = &expr.kind { + if let ExprKind::Block(..) = &inner.kind { + // `&{ x }` form: remove the `&`, add parens. + cx.expr_paren(field.span, inner.clone()) + } else { + // `&x` form: remove the `&`. + inner.clone() + } + } else { + cx.expr_deref(field.span, expr.clone()) + } + }; + + let lhs = convert(&field.self_expr); + let rhs = convert(&other_expr); + cx.expr_binary(field.span, BinOpKind::Cmp, lhs, rhs) } CsFold::Combine(span, expr1, expr2) => { let eq_arm = cx.arm(span, cx.pat_path(span, equal_path.clone()), expr1); diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index f5626937ec456..6451833493100 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -277,6 +277,7 @@ language_item_table! { OrderingEnum, sym::Ordering, ordering_enum, Target::Enum, GenericRequirement::Exact(0); PartialEq, sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1); PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1); + Ord, sym::Ord, ord_trait, Target::Trait, GenericRequirement::Exact(0); CVoid, sym::c_void, c_void, Target::Enum, GenericRequirement::None; // A number of panic-related lang items. The `panic` item corresponds to divide-by-zero and diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 1750c2af1c7ff..7bd899b12ffe8 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -3,6 +3,7 @@ use rustc_data_structures::packed::Pu128; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, struct_span_code_err}; +use rustc_hir::LangItem; use rustc_infer::traits::ObligationCauseCode; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, @@ -194,6 +195,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.demand_suptype(rhs_span, lhs_ty, rhs_ty); tcx.types.bool } + + BinOpCategory::ThreeWayComparison => { + // both LHS and RHS and result will have the same type + self.demand_suptype(rhs_span, lhs_ty, rhs_ty); + tcx.ty_ordering_enum(Some(lhs_span)) + } + + BinOpCategory::ThreeWayComparisonPartial => { + // both LHS and RHS and result will have the same type + self.demand_suptype(rhs_span, lhs_ty, rhs_ty); + let ordering_ty = tcx.ty_ordering_enum(Some(lhs_span)); + Ty::new_lang_item(tcx, ordering_ty, LangItem::Option).unwrap() + } } } @@ -1006,7 +1020,9 @@ fn lang_item_for_op( | hir::BinOpKind::Eq | hir::BinOpKind::Ne | hir::BinOpKind::And - | hir::BinOpKind::Or => { + | hir::BinOpKind::Or + | hir::BinOpKind::Cmp + | hir::BinOpKind::CmpPartial => { span_bug!(span, "impossible assignment operation: {}=", op.node.as_str()) } } @@ -1027,6 +1043,8 @@ fn lang_item_for_op( hir::BinOpKind::Ge => (sym::ge, lang.partial_ord_trait()), hir::BinOpKind::Gt => (sym::gt, lang.partial_ord_trait()), hir::BinOpKind::Eq => (sym::eq, lang.eq_trait()), + hir::BinOpKind::Cmp => (sym::cmp, lang.ord_trait()), + hir::BinOpKind::CmpPartial => (sym::partial_cmp, lang.partial_ord_trait()), hir::BinOpKind::Ne => (sym::ne, lang.eq_trait()), hir::BinOpKind::And | hir::BinOpKind::Or => { span_bug!(span, "&& and || are not overloadable") @@ -1062,6 +1080,9 @@ enum BinOpCategory { /// ==, !=, etc -- takes equal types, produces bools, except for simd, /// which produce the input type Comparison, + + ThreeWayComparison, + ThreeWayComparisonPartial, } impl BinOpCategory { @@ -1086,6 +1107,9 @@ impl BinOpCategory { | hir::BinOpKind::Ge | hir::BinOpKind::Gt => BinOpCategory::Comparison, + hir::BinOpKind::Cmp => BinOpCategory::ThreeWayComparison, + hir::BinOpKind::CmpPartial => BinOpCategory::ThreeWayComparisonPartial, + hir::BinOpKind::And | hir::BinOpKind::Or => BinOpCategory::Shortcircuit, } } @@ -1157,7 +1181,9 @@ fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool || lhs.is_bool() && rhs.is_bool() } - BinOpCategory::Comparison => { + BinOpCategory::Comparison + | BinOpCategory::ThreeWayComparison + | BinOpCategory::ThreeWayComparisonPartial => { lhs.references_error() || rhs.references_error() || lhs.is_scalar() && rhs.is_scalar() } } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 7b43aac90c741..9f8ad0b8bd344 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -161,7 +161,9 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { | hir::BinOpKind::Le | hir::BinOpKind::Ne | hir::BinOpKind::Ge - | hir::BinOpKind::Gt => Some("comparison"), + | hir::BinOpKind::Gt + | hir::BinOpKind::Cmp + | hir::BinOpKind::CmpPartial => Some("comparison"), hir::BinOpKind::Add | hir::BinOpKind::Sub | hir::BinOpKind::Div diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 7139516702e99..35e44da31a9f2 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -1329,6 +1329,9 @@ fn bin_op(op: hir::BinOpKind) -> BinOp { hir::BinOpKind::Ne => BinOp::Ne, hir::BinOpKind::Ge => BinOp::Ge, hir::BinOpKind::Gt => BinOp::Gt, - _ => bug!("no equivalent for ast binop {:?}", op), + hir::BinOpKind::Cmp => BinOp::Cmp, + hir::BinOpKind::And | hir::BinOpKind::Or | hir::BinOpKind::CmpPartial => { + bug!("no equivalent for ast binop {:?}", op) + } } } diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 4ac3a268c9c33..133655b581f8c 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1105,7 +1105,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { check_kinds!( x, "Cannot three-way compare non-integer type {:?}", - ty::Char | ty::Uint(..) | ty::Int(..) + ty::Char | ty::Uint(..) | ty::Int(..) | ty::Bool ) } } diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index fc7a3323fc118..0d304e8331805 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -210,8 +210,6 @@ pub(crate) enum InvalidComparisonOperatorSub { invalid: String, correct: String, }, - #[label(parse_spaceship_operator_invalid)] - Spaceship(#[primary_span] Span), } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index ef29ac2719d9c..ad0e21b3cc181 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -154,7 +154,16 @@ impl<'a> Parser<'a> { } self.expected_token_types.insert(TokenType::Operator); - while let Some(op) = self.check_assoc_op() { + while let Some(mut op) = self.check_assoc_op() { + // Look for `<=>` + if op.node == AssocOp::Binary(BinOpKind::Le) && self.look_ahead(1, |t| *t == token::Gt) { + //let sp = op.span.to(self.token.span); + //op = source_map::respan(sp, AssocOp::Cmp); + op.node = AssocOp::Binary(BinOpKind::Cmp); + self.bump(); + } + let op = op; + let lhs_span = self.interpolated_or_expr_span(&lhs); let cur_op_span = self.token.span; let restrictions = if op.node.is_assign_like() { @@ -225,6 +234,7 @@ impl<'a> Parser<'a> { self.bump(); } + /* // Look for C++'s `<=>` and recover if op.node == AssocOp::Binary(BinOpKind::Le) && self.token == token::Gt @@ -238,6 +248,7 @@ impl<'a> Parser<'a> { }); self.bump(); } + */ if self.prev_token == token::BinOp(token::Plus) && self.token == token::BinOp(token::Plus) diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index c8ced78c4d791..43e6c2b9d2cdd 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -937,6 +937,7 @@ impl Clone for Reverse { /// [`PartialOrd`] and [`PartialEq`] to disagree. /// /// [`cmp`]: Ord::cmp +#[cfg_attr(not(bootstrap), lang = "Ord")] #[doc(alias = "<")] #[doc(alias = ">")] #[doc(alias = "<=")] diff --git a/tests/mir-opt/building/spaceship.bar.built.after.mir b/tests/mir-opt/building/spaceship.bar.built.after.mir new file mode 100644 index 0000000000000..1c9ee887cf294 --- /dev/null +++ b/tests/mir-opt/building/spaceship.bar.built.after.mir @@ -0,0 +1,27 @@ +// MIR for `bar` after built + +fn bar(_1: (i32, u32), _2: (i32, u32)) -> std::cmp::Ordering { + debug a => _1; + debug b => _2; + let mut _0: std::cmp::Ordering; + let mut _3: &(i32, u32); + let mut _4: &(i32, u32); + + bb0: { + StorageLive(_3); + _3 = &_1; + StorageLive(_4); + _4 = &_2; + _0 = <(i32, u32) as Ord>::cmp(move _3, move _4) -> [return: bb1, unwind: bb2]; + } + + bb1: { + StorageDead(_4); + StorageDead(_3); + return; + } + + bb2 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/spaceship.foo.built.after.mir b/tests/mir-opt/building/spaceship.foo.built.after.mir new file mode 100644 index 0000000000000..59503678f89b3 --- /dev/null +++ b/tests/mir-opt/building/spaceship.foo.built.after.mir @@ -0,0 +1,20 @@ +// MIR for `foo` after built + +fn foo(_1: i32, _2: i32) -> std::cmp::Ordering { + debug a => _1; + debug b => _2; + let mut _0: std::cmp::Ordering; + let mut _3: i32; + let mut _4: i32; + + bb0: { + StorageLive(_3); + _3 = copy _1; + StorageLive(_4); + _4 = copy _2; + _0 = Cmp(move _3, move _4); + StorageDead(_4); + StorageDead(_3); + return; + } +} diff --git a/tests/mir-opt/building/spaceship.rs b/tests/mir-opt/building/spaceship.rs new file mode 100644 index 0000000000000..67874bd945a6b --- /dev/null +++ b/tests/mir-opt/building/spaceship.rs @@ -0,0 +1,21 @@ +//@ compile-flags: -C opt-level=0 -Z mir-opt-level=0 +use std::cmp::Ordering; + +// EMIT_MIR spaceship.foo.built.after.mir +// EMIT_MIR spaceship.bar.built.after.mir + +fn foo(a: i32, b: i32) -> Ordering { + // CHECK: [[A:_.+]] = copy _1; + // CHECK: [[B:_.+]] = copy _2; + // CHECK: _0 = Cmp(move [[A]], move [[B]]); + a <=> b +} + +fn bar(a: (i32, u32), b: (i32, u32)) -> Ordering { + // CHECK: [[A:_.+]] = &_1; + // CHECK: [[B:_.+]] = &_2; + // CHECK: _0 = <(i32, u32) as Ord>::cmp(move [[A]], move [[B]]) + a <=> b +} + +fn main() {} diff --git a/tests/mir-opt/pre-codegen/derived_ord.rs b/tests/mir-opt/pre-codegen/derived_ord.rs index bad751edf8419..b2c44283db7dc 100644 --- a/tests/mir-opt/pre-codegen/derived_ord.rs +++ b/tests/mir-opt/pre-codegen/derived_ord.rs @@ -3,7 +3,8 @@ #![crate_type = "lib"] -#[derive(PartialOrd, PartialEq)] +#[derive(PartialOrd, PartialEq, Ord, Eq)] pub struct MultiField(char, i16); // EMIT_MIR derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir +// EMIT_MIR derived_ord.{impl#3}-cmp.PreCodegen.after.mir diff --git a/tests/mir-opt/pre-codegen/derived_ord.{impl#3}-cmp.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/derived_ord.{impl#3}-cmp.PreCodegen.after.mir new file mode 100644 index 0000000000000..ec085d5436427 --- /dev/null +++ b/tests/mir-opt/pre-codegen/derived_ord.{impl#3}-cmp.PreCodegen.after.mir @@ -0,0 +1,48 @@ +// MIR for `::cmp` after PreCodegen + +fn ::cmp(_1: &MultiField, _2: &MultiField) -> std::cmp::Ordering { + debug self => _1; + debug other => _2; + let mut _0: std::cmp::Ordering; + let mut _3: char; + let mut _4: char; + let mut _5: std::cmp::Ordering; + let mut _6: i8; + let mut _7: i16; + let mut _8: i16; + scope 1 { + debug cmp => _5; + } + + bb0: { + 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 = discriminant(_5); + switchInt(move _6) -> [0: bb1, otherwise: bb2]; + } + + bb1: { + StorageLive(_7); + _7 = copy ((*_1).1: i16); + StorageLive(_8); + _8 = copy ((*_2).1: i16); + _0 = Cmp(move _7, move _8); + StorageDead(_8); + StorageDead(_7); + goto -> bb3; + } + + bb2: { + _0 = copy _5; + goto -> bb3; + } + + bb3: { + return; + } +} diff --git a/tests/ui/derives/derives-span-Ord-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Ord-enum-struct-variant.stderr index 96ef59ca9631b..d7696006bd6ac 100644 --- a/tests/ui/derives/derives-span-Ord-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-Ord-enum-struct-variant.stderr @@ -1,19 +1,24 @@ -error[E0277]: the trait bound `Error: Ord` is not satisfied +error[E0369]: binary operation `<=>` cannot be applied to type `Error` --> $DIR/derives-span-Ord-enum-struct-variant.rs:9:6 | LL | #[derive(Ord,Eq,PartialOrd,PartialEq)] | --- in this derive macro expansion ... LL | x: Error - | ^^^^^^^^ the trait `Ord` is not implemented for `Error` + | ^^^^^^^^ | +note: an implementation of `Ord` might be missing for `Error` + --> $DIR/derives-span-Ord-enum-struct-variant.rs:4:1 + | +LL | struct Error; + | ^^^^^^^^^^^^ must implement `Ord` = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider annotating `Error` with `#[derive(Ord)]` +help: consider annotating `Error` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` | -LL + #[derive(Ord)] +LL + #[derive(Eq, Ord, PartialEq, PartialOrd)] LL | struct Error; | error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/derives/derives-span-Ord-enum.stderr b/tests/ui/derives/derives-span-Ord-enum.stderr index 7c75ecb6432e2..5be98fff3a8b9 100644 --- a/tests/ui/derives/derives-span-Ord-enum.stderr +++ b/tests/ui/derives/derives-span-Ord-enum.stderr @@ -1,19 +1,24 @@ -error[E0277]: the trait bound `Error: Ord` is not satisfied +error[E0369]: binary operation `<=>` cannot be applied to type `Error` --> $DIR/derives-span-Ord-enum.rs:9:6 | LL | #[derive(Ord,Eq,PartialOrd,PartialEq)] | --- in this derive macro expansion ... LL | Error - | ^^^^^ the trait `Ord` is not implemented for `Error` + | ^^^^^ | +note: an implementation of `Ord` might be missing for `Error` + --> $DIR/derives-span-Ord-enum.rs:4:1 + | +LL | struct Error; + | ^^^^^^^^^^^^ must implement `Ord` = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider annotating `Error` with `#[derive(Ord)]` +help: consider annotating `Error` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` | -LL + #[derive(Ord)] +LL + #[derive(Eq, Ord, PartialEq, PartialOrd)] LL | struct Error; | error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/derives/derives-span-Ord-struct.stderr b/tests/ui/derives/derives-span-Ord-struct.stderr index 429e7e06f5d9f..a97c301a16783 100644 --- a/tests/ui/derives/derives-span-Ord-struct.stderr +++ b/tests/ui/derives/derives-span-Ord-struct.stderr @@ -1,19 +1,24 @@ -error[E0277]: the trait bound `Error: Ord` is not satisfied +error[E0369]: binary operation `<=>` cannot be applied to type `Error` --> $DIR/derives-span-Ord-struct.rs:8:5 | LL | #[derive(Ord,Eq,PartialOrd,PartialEq)] | --- in this derive macro expansion LL | struct Struct { LL | x: Error - | ^^^^^^^^ the trait `Ord` is not implemented for `Error` + | ^^^^^^^^ | +note: an implementation of `Ord` might be missing for `Error` + --> $DIR/derives-span-Ord-struct.rs:4:1 + | +LL | struct Error; + | ^^^^^^^^^^^^ must implement `Ord` = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider annotating `Error` with `#[derive(Ord)]` +help: consider annotating `Error` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` | -LL + #[derive(Ord)] +LL + #[derive(Eq, Ord, PartialEq, PartialOrd)] LL | struct Error; | error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/derives/derives-span-Ord-tuple-struct.stderr b/tests/ui/derives/derives-span-Ord-tuple-struct.stderr index a46133834c6ad..367a99b1700e1 100644 --- a/tests/ui/derives/derives-span-Ord-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-Ord-tuple-struct.stderr @@ -1,19 +1,24 @@ -error[E0277]: the trait bound `Error: Ord` is not satisfied +error[E0369]: binary operation `<=>` cannot be applied to type `Error` --> $DIR/derives-span-Ord-tuple-struct.rs:8:5 | LL | #[derive(Ord,Eq,PartialOrd,PartialEq)] | --- in this derive macro expansion LL | struct Struct( LL | Error - | ^^^^^ the trait `Ord` is not implemented for `Error` + | ^^^^^ | +note: an implementation of `Ord` might be missing for `Error` + --> $DIR/derives-span-Ord-tuple-struct.rs:4:1 + | +LL | struct Error; + | ^^^^^^^^^^^^ must implement `Ord` = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider annotating `Error` with `#[derive(Ord)]` +help: consider annotating `Error` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` | -LL + #[derive(Ord)] +LL + #[derive(Eq, Ord, PartialEq, PartialOrd)] LL | struct Error; | error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout index 6503c87099040..3456f849c0a99 100644 --- a/tests/ui/deriving/deriving-all-codegen.stdout +++ b/tests/ui/deriving/deriving-all-codegen.stdout @@ -154,9 +154,8 @@ impl ::core::cmp::PartialOrd for Point { impl ::core::cmp::Ord for Point { #[inline] fn cmp(&self, other: &Point) -> ::core::cmp::Ordering { - match ::core::cmp::Ord::cmp(&self.x, &other.x) { - ::core::cmp::Ordering::Equal => - ::core::cmp::Ord::cmp(&self.y, &other.y), + match self.x <=> other.x { + ::core::cmp::Ordering::Equal => self.y <=> other.y, cmp => cmp, } } @@ -241,9 +240,8 @@ impl ::core::cmp::PartialOrd for PackedPoint { impl ::core::cmp::Ord for PackedPoint { #[inline] fn cmp(&self, other: &PackedPoint) -> ::core::cmp::Ordering { - match ::core::cmp::Ord::cmp(&{ self.x }, &{ other.x }) { - ::core::cmp::Ordering::Equal => - ::core::cmp::Ord::cmp(&{ self.y }, &{ other.y }), + match ({ self.x }) <=> ({ other.x }) { + ::core::cmp::Ordering::Equal => ({ self.y }) <=> ({ other.y }), cmp => cmp, } } @@ -387,21 +385,20 @@ impl ::core::cmp::PartialOrd for Big { impl ::core::cmp::Ord for Big { #[inline] fn cmp(&self, other: &Big) -> ::core::cmp::Ordering { - match ::core::cmp::Ord::cmp(&self.b1, &other.b1) { + match self.b1 <=> other.b1 { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&self.b2, &other.b2) { + match self.b2 <=> other.b2 { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&self.b3, &other.b3) { + match self.b3 <=> other.b3 { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&self.b4, &other.b4) { + match self.b4 <=> other.b4 { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&self.b5, &other.b5) { + match self.b5 <=> other.b5 { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&self.b6, &other.b6) { + match self.b6 <=> other.b6 { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&self.b7, &other.b7) { - ::core::cmp::Ordering::Equal => - ::core::cmp::Ord::cmp(&self.b8, &other.b8), + match self.b7 <=> other.b7 { + ::core::cmp::Ordering::Equal => self.b8 <=> other.b8, cmp => cmp, }, cmp => cmp, @@ -512,7 +509,7 @@ impl ::core::cmp::PartialOrd for Unsized { impl ::core::cmp::Ord for Unsized { #[inline] fn cmp(&self, other: &Unsized) -> ::core::cmp::Ordering { - ::core::cmp::Ord::cmp(&self.0, &other.0) + self.0 <=> other.0 } } @@ -621,11 +618,10 @@ impl ::core::cmp::Ord for Generic where T::A: ::core::cmp::Ord { #[inline] fn cmp(&self, other: &Generic) -> ::core::cmp::Ordering { - match ::core::cmp::Ord::cmp(&self.t, &other.t) { + match self.t <=> other.t { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&self.ta, &other.ta) { - ::core::cmp::Ordering::Equal => - ::core::cmp::Ord::cmp(&self.u, &other.u), + match self.ta <=> other.ta { + ::core::cmp::Ordering::Equal => self.u <=> other.u, cmp => cmp, }, cmp => cmp, @@ -748,11 +744,11 @@ impl) -> ::core::cmp::Ordering { - match ::core::cmp::Ord::cmp(&{ self.0 }, &{ other.0 }) { + match ({ self.0 }) <=> ({ other.0 }) { ::core::cmp::Ordering::Equal => - match ::core::cmp::Ord::cmp(&{ self.1 }, &{ other.1 }) { + match ({ self.1 }) <=> ({ other.1 }) { ::core::cmp::Ordering::Equal => - ::core::cmp::Ord::cmp(&{ self.2 }, &{ other.2 }), + ({ self.2 }) <=> ({ other.2 }), cmp => cmp, }, cmp => cmp, @@ -886,7 +882,7 @@ impl ::core::cmp::Ord for Enum1 { fn cmp(&self, other: &Enum1) -> ::core::cmp::Ordering { match (self, other) { (Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), + *__self_0 <=> *__arg1_0, } } } @@ -1023,7 +1019,7 @@ impl ::core::cmp::Ord for Fieldless { fn cmp(&self, other: &Fieldless) -> ::core::cmp::Ordering { let __self_discr = ::core::intrinsics::discriminant_value(self); let __arg1_discr = ::core::intrinsics::discriminant_value(other); - ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) + __self_discr <=> __arg1_discr } } @@ -1148,16 +1144,15 @@ impl ::core::cmp::Ord for Mixed { fn cmp(&self, other: &Mixed) -> ::core::cmp::Ordering { let __self_discr = ::core::intrinsics::discriminant_value(self); let __arg1_discr = ::core::intrinsics::discriminant_value(other); - match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) { + match __self_discr <=> __arg1_discr { ::core::cmp::Ordering::Equal => match (self, other) { (Mixed::R(__self_0), Mixed::R(__arg1_0)) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), + *__self_0 <=> *__arg1_0, (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S { d1: __arg1_0, d2: __arg1_1 }) => - match ::core::cmp::Ord::cmp(__self_0, __arg1_0) { - ::core::cmp::Ordering::Equal => - ::core::cmp::Ord::cmp(__self_1, __arg1_1), + match *__self_0 <=> *__arg1_0 { + ::core::cmp::Ordering::Equal => *__self_1 <=> *__arg1_1, cmp => cmp, }, _ => ::core::cmp::Ordering::Equal, @@ -1271,15 +1266,15 @@ impl ::core::cmp::Ord for Fielded { fn cmp(&self, other: &Fielded) -> ::core::cmp::Ordering { let __self_discr = ::core::intrinsics::discriminant_value(self); let __arg1_discr = ::core::intrinsics::discriminant_value(other); - match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) { + match __self_discr <=> __arg1_discr { ::core::cmp::Ordering::Equal => match (self, other) { (Fielded::X(__self_0), Fielded::X(__arg1_0)) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), + *__self_0 <=> *__arg1_0, (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), + *__self_0 <=> *__arg1_0, (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), + *__self_0 <=> *__arg1_0, _ => unsafe { ::core::intrinsics::unreachable() } }, cmp => cmp, @@ -1392,13 +1387,13 @@ impl ::core::cmp::Ord for fn cmp(&self, other: &EnumGeneric) -> ::core::cmp::Ordering { let __self_discr = ::core::intrinsics::discriminant_value(self); let __arg1_discr = ::core::intrinsics::discriminant_value(other); - match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) { + match __self_discr <=> __arg1_discr { ::core::cmp::Ordering::Equal => match (self, other) { (EnumGeneric::One(__self_0), EnumGeneric::One(__arg1_0)) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), + *__self_0 <=> *__arg1_0, (EnumGeneric::Two(__self_0), EnumGeneric::Two(__arg1_0)) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), + *__self_0 <=> *__arg1_0, _ => unsafe { ::core::intrinsics::unreachable() } }, cmp => cmp, diff --git a/tests/ui/operator-recovery/spaceship.rs b/tests/ui/operator-recovery/spaceship.rs index a65f9389625fc..abfcc14786b81 100644 --- a/tests/ui/operator-recovery/spaceship.rs +++ b/tests/ui/operator-recovery/spaceship.rs @@ -1,4 +1,5 @@ +//@ run-pass + fn main() { - println!("{}", 1 <=> 2); - //~^ERROR invalid comparison operator `<=>` + println!("{:?}", 1 <=> 2); } diff --git a/tests/ui/operator-recovery/spaceship.stderr b/tests/ui/operator-recovery/spaceship.stderr deleted file mode 100644 index 46a81db62b42c..0000000000000 --- a/tests/ui/operator-recovery/spaceship.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: invalid comparison operator `<=>` - --> $DIR/spaceship.rs:2:22 - | -LL | println!("{}", 1 <=> 2); - | ^^^ `<=>` is not a valid comparison operator, use `std::cmp::Ordering` - -error: aborting due to 1 previous error -