From 518f6439d663d1eb6dce5575d1d77530b719d6c0 Mon Sep 17 00:00:00 2001 From: ccgauche Date: Wed, 2 Jun 2021 12:04:41 +0200 Subject: [PATCH 1/9] Added a note in E0369 if the missing trait is PartialEq to use the derive. This is my first contribution so tell me if some guidelines aren't respected. --- compiler/rustc_typeck/src/check/op.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 963436d05d8ef..564d7a07630c9 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -959,6 +959,13 @@ fn suggest_impl_missing(err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>, missing_tra "an implementation of `{}` might be missing for `{}`", missing_trait, ty )); + // This checks if the missing trait is PartialEq to suggest adding a derive + if missing_trait.ends_with("PartialEq") { + err.note(&format!( + "add `#[derive(PartialEq)]` or manually implement `PartialEq` for `{}`", + ty + )); + } } } } From 01996be1abba87e6b44e704ca84962a2507b239c Mon Sep 17 00:00:00 2001 From: ccgauche Date: Sun, 1 Aug 2021 23:57:41 +0200 Subject: [PATCH 2/9] Updated the fix for #85845 - Made the check stricter. **Note: I've checked and there is no other trait that can be possibly passed than std ones. (BinOps) so there is no need for a `can_derive` or something similar. Furthermore, this mean we can't pass another thing than a str.** --- compiler/rustc_typeck/src/check/op.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 564d7a07630c9..8a758c74b2af1 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -960,7 +960,7 @@ fn suggest_impl_missing(err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>, missing_tra missing_trait, ty )); // This checks if the missing trait is PartialEq to suggest adding a derive - if missing_trait.ends_with("PartialEq") { + if missing_trait.ends_with("std::cmp::PartialEq") { err.note(&format!( "add `#[derive(PartialEq)]` or manually implement `PartialEq` for `{}`", ty From a1d18be5800dccbcc79c8c3fe9d67db2da2ec117 Mon Sep 17 00:00:00 2001 From: ccgauche Date: Mon, 2 Aug 2021 00:02:26 +0200 Subject: [PATCH 3/9] Removed unused contains --- compiler/rustc_typeck/src/check/op.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 8a758c74b2af1..891c517e150c8 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -960,7 +960,7 @@ fn suggest_impl_missing(err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>, missing_tra missing_trait, ty )); // This checks if the missing trait is PartialEq to suggest adding a derive - if missing_trait.ends_with("std::cmp::PartialEq") { + if missing_trait == "std::cmp::PartialEq" { err.note(&format!( "add `#[derive(PartialEq)]` or manually implement `PartialEq` for `{}`", ty From 96c4539ac57c7ae73567dca5437ca20a341ffaf3 Mon Sep 17 00:00:00 2001 From: ccgauche Date: Mon, 2 Aug 2021 00:22:38 +0200 Subject: [PATCH 4/9] Fixed error unit test + Added correction for PartialOrd --- compiler/rustc_typeck/src/check/op.rs | 5 +++++ src/test/ui/binop/issue-28837.stderr | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 891c517e150c8..1abd81cd61f3a 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -965,6 +965,11 @@ fn suggest_impl_missing(err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>, missing_tra "add `#[derive(PartialEq)]` or manually implement `PartialEq` for `{}`", ty )); + } else if missing_trait == "std::cmp::PartialOrd" { + err.note(&format!( + "add `#[derive(PartialOrd)]` or manually implement `PartialOrd` for `{}`", + ty + )); } } } diff --git a/src/test/ui/binop/issue-28837.stderr b/src/test/ui/binop/issue-28837.stderr index 07f67bc3de79d..691861e6a89af 100644 --- a/src/test/ui/binop/issue-28837.stderr +++ b/src/test/ui/binop/issue-28837.stderr @@ -97,6 +97,7 @@ LL | a == a; | A | = note: an implementation of `std::cmp::PartialEq` might be missing for `A` + = note: add `#[derive(PartialEq)]` or manually implement `PartialEq` for `A` error[E0369]: binary operation `!=` cannot be applied to type `A` --> $DIR/issue-28837.rs:26:7 @@ -107,6 +108,7 @@ LL | a != a; | A | = note: an implementation of `std::cmp::PartialEq` might be missing for `A` + = note: add `#[derive(PartialEq)]` or manually implement `PartialEq` for `A` error[E0369]: binary operation `<` cannot be applied to type `A` --> $DIR/issue-28837.rs:28:7 @@ -117,6 +119,7 @@ LL | a < a; | A | = note: an implementation of `std::cmp::PartialOrd` might be missing for `A` + = note: add `#[derive(PartialOrd)]` or manually implement `PartialOrd` for `A` error[E0369]: binary operation `<=` cannot be applied to type `A` --> $DIR/issue-28837.rs:30:7 @@ -127,6 +130,7 @@ LL | a <= a; | A | = note: an implementation of `std::cmp::PartialOrd` might be missing for `A` + = note: add `#[derive(PartialOrd)]` or manually implement `PartialOrd` for `A` error[E0369]: binary operation `>` cannot be applied to type `A` --> $DIR/issue-28837.rs:32:7 @@ -137,6 +141,7 @@ LL | a > a; | A | = note: an implementation of `std::cmp::PartialOrd` might be missing for `A` + = note: add `#[derive(PartialOrd)]` or manually implement `PartialOrd` for `A` error[E0369]: binary operation `>=` cannot be applied to type `A` --> $DIR/issue-28837.rs:34:7 @@ -147,6 +152,7 @@ LL | a >= a; | A | = note: an implementation of `std::cmp::PartialOrd` might be missing for `A` + = note: add `#[derive(PartialOrd)]` or manually implement `PartialOrd` for `A` error: aborting due to 15 previous errors From bcb49dc978b5ac1564bc39d7c1816c0d2710025b Mon Sep 17 00:00:00 2001 From: ccgauche Date: Mon, 2 Aug 2021 00:49:47 +0200 Subject: [PATCH 5/9] Fixed CI 2 --- .../derives/derives-span-PartialEq-enum-struct-variant.stderr | 2 ++ src/test/ui/derives/derives-span-PartialEq-struct.stderr | 2 ++ src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr | 2 ++ src/test/ui/derives/deriving-no-inner-impl-error-message.stderr | 2 ++ src/test/ui/issues/issue-62375.stderr | 1 + 5 files changed, 9 insertions(+) diff --git a/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr index a579d695700d4..ed3f56ee041c2 100644 --- a/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr @@ -5,6 +5,7 @@ LL | x: Error | ^^^^^^^^ | = note: an implementation of `std::cmp::PartialEq` might be missing for `Error` + = note: add `#[derive(PartialEq)]` or manually implement `PartialEq` for `Error` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0369]: binary operation `!=` cannot be applied to type `Error` @@ -14,6 +15,7 @@ LL | x: Error | ^^^^^^^^ | = note: an implementation of `std::cmp::PartialEq` might be missing for `Error` + = note: add `#[derive(PartialEq)]` or manually implement `PartialEq` for `Error` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/test/ui/derives/derives-span-PartialEq-struct.stderr b/src/test/ui/derives/derives-span-PartialEq-struct.stderr index 5fec402dcd856..c6de068ff0682 100644 --- a/src/test/ui/derives/derives-span-PartialEq-struct.stderr +++ b/src/test/ui/derives/derives-span-PartialEq-struct.stderr @@ -5,6 +5,7 @@ LL | x: Error | ^^^^^^^^ | = note: an implementation of `std::cmp::PartialEq` might be missing for `Error` + = note: add `#[derive(PartialEq)]` or manually implement `PartialEq` for `Error` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0369]: binary operation `!=` cannot be applied to type `Error` @@ -14,6 +15,7 @@ LL | x: Error | ^^^^^^^^ | = note: an implementation of `std::cmp::PartialEq` might be missing for `Error` + = note: add `#[derive(PartialEq)]` or manually implement `PartialEq` for `Error` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr b/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr index 0a7f9e14859ae..2daf0e46526d9 100644 --- a/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr @@ -5,6 +5,7 @@ LL | Error | ^^^^^ | = note: an implementation of `std::cmp::PartialEq` might be missing for `Error` + = note: add `#[derive(PartialEq)]` or manually implement `PartialEq` for `Error` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0369]: binary operation `!=` cannot be applied to type `Error` @@ -14,6 +15,7 @@ LL | Error | ^^^^^ | = note: an implementation of `std::cmp::PartialEq` might be missing for `Error` + = note: add `#[derive(PartialEq)]` or manually implement `PartialEq` for `Error` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr b/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr index 0f69f94bf3a2a..8d5e2736598f6 100644 --- a/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr +++ b/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr @@ -5,6 +5,7 @@ LL | x: NoCloneOrEq | ^^^^^^^^^^^^^^ | = note: an implementation of `std::cmp::PartialEq` might be missing for `NoCloneOrEq` + = note: add `#[derive(PartialEq)]` or manually implement `PartialEq` for `NoCloneOrEq` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0369]: binary operation `!=` cannot be applied to type `NoCloneOrEq` @@ -14,6 +15,7 @@ LL | x: NoCloneOrEq | ^^^^^^^^^^^^^^ | = note: an implementation of `std::cmp::PartialEq` might be missing for `NoCloneOrEq` + = note: add `#[derive(PartialEq)]` or manually implement `PartialEq` for `NoCloneOrEq` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `NoCloneOrEq: Clone` is not satisfied diff --git a/src/test/ui/issues/issue-62375.stderr b/src/test/ui/issues/issue-62375.stderr index 6db45630b9437..25b06df47505b 100644 --- a/src/test/ui/issues/issue-62375.stderr +++ b/src/test/ui/issues/issue-62375.stderr @@ -7,6 +7,7 @@ LL | a == A::Value; | A | = note: an implementation of `std::cmp::PartialEq` might be missing for `A` + = note: add `#[derive(PartialEq)]` or manually implement `PartialEq` for `A` error: aborting due to previous error From afcef433f29ad80db92b4fb6cb4ad088c28324bc Mon Sep 17 00:00:00 2001 From: ccgauche Date: Mon, 2 Aug 2021 11:51:22 +0200 Subject: [PATCH 6/9] Fixed derives-span-PartialEq-enum tests --- src/test/ui/derives/derives-span-PartialEq-enum.stderr | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/ui/derives/derives-span-PartialEq-enum.stderr b/src/test/ui/derives/derives-span-PartialEq-enum.stderr index 532430729c7cf..c04a4aa1e6977 100644 --- a/src/test/ui/derives/derives-span-PartialEq-enum.stderr +++ b/src/test/ui/derives/derives-span-PartialEq-enum.stderr @@ -5,6 +5,7 @@ LL | Error | ^^^^^ | = note: an implementation of `std::cmp::PartialEq` might be missing for `Error` + = note: add `#[derive(PartialEq)]` or manually implement `PartialEq` for `Error` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0369]: binary operation `!=` cannot be applied to type `Error` @@ -14,6 +15,7 @@ LL | Error | ^^^^^ | = note: an implementation of `std::cmp::PartialEq` might be missing for `Error` + = note: add `#[derive(PartialEq)]` or manually implement `PartialEq` for `Error` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors From 38830d2d5359b82853903dbd37352c608bf80a4e Mon Sep 17 00:00:00 2001 From: ccgauche Date: Tue, 17 Aug 2021 21:41:56 +0200 Subject: [PATCH 7/9] Replaced String checks with enums so we can ensure that everything will work properly --- compiler/rustc_hir/src/hir.rs | 50 +++++++++++ compiler/rustc_typeck/src/check/op.rs | 114 +++++++++++++++----------- 2 files changed, 116 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index e9055c9541086..fea5551085a95 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1042,6 +1042,49 @@ impl BinOpKind { } } + pub fn as_std_trait(self, assign: bool) -> Option<&'static str> { + Some(if assign { + match self { + BinOpKind::Add => "std::ops::AddAssign", + BinOpKind::Sub => "std::ops::SubAssign", + BinOpKind::Mul => "std::ops::MulAssign", + BinOpKind::Div => "std::ops::DivAssign", + BinOpKind::Rem => "std::ops::RemAssign", + BinOpKind::BitAnd => "std::ops::BitAndAssign", + BinOpKind::BitXor => "std::ops::BitXorAssign", + BinOpKind::BitOr => "std::ops::BitOrAssign", + BinOpKind::Shl => "std::ops::ShlAssign", + BinOpKind::Shr => "std::ops::ShrAssign", + BinOpKind::Eq + | BinOpKind::Ne + | BinOpKind::Lt + | BinOpKind::Le + | BinOpKind::Ge + | BinOpKind::Gt + | BinOpKind::And + | BinOpKind::Or => return None, + } + } else { + match self { + BinOpKind::Add => "std::ops::Add", + BinOpKind::Sub => "std::ops::Sub", + BinOpKind::Mul => "std::ops::Mul", + BinOpKind::Div => "std::ops::Div", + BinOpKind::Rem => "std::ops::Rem", + BinOpKind::BitAnd => "std::ops::BitAnd", + BinOpKind::BitXor => "std::ops::BitXor", + BinOpKind::BitOr => "std::ops::BitOr", + BinOpKind::Shl => "std::ops::Shl", + BinOpKind::Shr => "std::ops::Shr", + BinOpKind::Eq | BinOpKind::Ne => "std::cmp::PartialEq", + BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ge | BinOpKind::Gt => { + "std::cmp::PartialOrd" + } + BinOpKind::And | BinOpKind::Or => return None, + } + }) + } + pub fn is_lazy(self) -> bool { matches!(self, BinOpKind::And | BinOpKind::Or) } @@ -1124,6 +1167,13 @@ impl UnOp { Self::Neg => "-", } } + pub fn as_std_trait(self) -> &'static str { + match self { + Self::Neg => "std::ops::Neg", + Self::Not => "std::ops::Not", + Self::Deref => "std::ops::UnDerf", + } + } /// Returns `true` if the unary operator takes its argument by value. pub fn is_by_value(self) -> bool { diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 1abd81cd61f3a..4ba548a2b1fe3 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -19,6 +19,7 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; +use std::borrow::Borrow; use std::ops::ControlFlow; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -276,71 +277,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_expr.span, format!("cannot use `{}=` on type `{}`", op.node.as_str(), lhs_ty), ); - let missing_trait = match op.node { - hir::BinOpKind::Add => Some("std::ops::AddAssign"), - hir::BinOpKind::Sub => Some("std::ops::SubAssign"), - hir::BinOpKind::Mul => Some("std::ops::MulAssign"), - hir::BinOpKind::Div => Some("std::ops::DivAssign"), - hir::BinOpKind::Rem => Some("std::ops::RemAssign"), - hir::BinOpKind::BitAnd => Some("std::ops::BitAndAssign"), - hir::BinOpKind::BitXor => Some("std::ops::BitXorAssign"), - hir::BinOpKind::BitOr => Some("std::ops::BitOrAssign"), - hir::BinOpKind::Shl => Some("std::ops::ShlAssign"), - hir::BinOpKind::Shr => Some("std::ops::ShrAssign"), - _ => None, - }; - (err, missing_trait, false, false) + (err, Some(STDImplementationMissing::BinOpAssign(op.node)), false, false) } IsAssign::No => { let (message, missing_trait, use_output) = match op.node { hir::BinOpKind::Add => ( format!("cannot add `{}` to `{}`", rhs_ty, lhs_ty), - Some("std::ops::Add"), + Some(op.node), true, ), hir::BinOpKind::Sub => ( format!("cannot subtract `{}` from `{}`", rhs_ty, lhs_ty), - Some("std::ops::Sub"), + Some(op.node), true, ), hir::BinOpKind::Mul => ( format!("cannot multiply `{}` by `{}`", lhs_ty, rhs_ty), - Some("std::ops::Mul"), + Some(op.node), true, ), hir::BinOpKind::Div => ( format!("cannot divide `{}` by `{}`", lhs_ty, rhs_ty), - Some("std::ops::Div"), + Some(op.node), true, ), hir::BinOpKind::Rem => ( format!("cannot mod `{}` by `{}`", lhs_ty, rhs_ty), - Some("std::ops::Rem"), + Some(op.node), true, ), hir::BinOpKind::BitAnd => ( format!("no implementation for `{} & {}`", lhs_ty, rhs_ty), - Some("std::ops::BitAnd"), + Some(op.node), true, ), hir::BinOpKind::BitXor => ( format!("no implementation for `{} ^ {}`", lhs_ty, rhs_ty), - Some("std::ops::BitXor"), + Some(op.node), true, ), hir::BinOpKind::BitOr => ( format!("no implementation for `{} | {}`", lhs_ty, rhs_ty), - Some("std::ops::BitOr"), + Some(op.node), true, ), hir::BinOpKind::Shl => ( format!("no implementation for `{} << {}`", lhs_ty, rhs_ty), - Some("std::ops::Shl"), + Some(op.node), true, ), hir::BinOpKind::Shr => ( format!("no implementation for `{} >> {}`", lhs_ty, rhs_ty), - Some("std::ops::Shr"), + Some(op.node), true, ), hir::BinOpKind::Eq | hir::BinOpKind::Ne => ( @@ -349,7 +337,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { op.node.as_str(), lhs_ty ), - Some("std::cmp::PartialEq"), + Some(op.node), false, ), hir::BinOpKind::Lt @@ -361,7 +349,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { op.node.as_str(), lhs_ty ), - Some("std::cmp::PartialOrd"), + Some(op.node), false, ), _ => ( @@ -428,6 +416,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } if let Some(missing_trait) = missing_trait { + let missing_trait_str = missing_trait.as_std_trait(); let mut visitor = TypeParamVisitor(vec![]); visitor.visit_ty(lhs_ty); @@ -459,7 +448,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut err, ty, rhs_ty, - missing_trait, + missing_trait_str, p, use_output, ); @@ -468,7 +457,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // this note as it is redundant. err.note(&format!( "the trait `{}` is not implemented for `{}`", - missing_trait, lhs_ty + missing_trait_str, lhs_ty )); } } else { @@ -710,12 +699,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Str | Never | Char | Tuple(_) | Array(_, _) => {} Ref(_, ref lty, _) if *lty.kind() == Str => {} _ => { - let missing_trait = match op { - hir::UnOp::Neg => "std::ops::Neg", - hir::UnOp::Not => "std::ops::Not", - hir::UnOp::Deref => "std::ops::UnDerf", - }; - suggest_impl_missing(&mut err, operand_ty, &missing_trait); + suggest_impl_missing( + &mut err, + operand_ty, + &STDImplementationMissing::Unop(op), + ); } } err.emit(); @@ -951,26 +939,56 @@ fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool } } +enum STDImplementationMissing { + Unop(hir::UnOp), + BinOp(hir::BinOpKind), + BinOpAssign(hir::BinOpKind), +} + +impl STDImplementationMissing { + fn as_std_trait(&self) -> Option<&'static str> { + match self { + Self::Unop(e) => Some(e.as_std_trait()), + Self::BinOpAssign(e) => e.as_std_trait(true), + Self::BinOp(e) => e.as_std_trait(false), + } + } +} + /// If applicable, note that an implementation of `trait` for `ty` may fix the error. -fn suggest_impl_missing(err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>, missing_trait: &str) { +fn suggest_impl_missing( + err: &mut DiagnosticBuilder<'_>, + ty: Ty<'_>, + missing_trait: STDImplementationMissing, +) { if let Adt(def, _) = ty.peel_refs().kind() { if def.did.is_local() { - err.note(&format!( - "an implementation of `{}` might be missing for `{}`", - missing_trait, ty - )); - // This checks if the missing trait is PartialEq to suggest adding a derive - if missing_trait == "std::cmp::PartialEq" { - err.note(&format!( - "add `#[derive(PartialEq)]` or manually implement `PartialEq` for `{}`", - ty - )); - } else if missing_trait == "std::cmp::PartialOrd" { + if let Some(missing_trait_name) = missing_trait.as_std_trait() { err.note(&format!( - "add `#[derive(PartialOrd)]` or manually implement `PartialOrd` for `{}`", - ty + "an implementation of `{}` might be missing for `{}`", + missing_trait, ty )); } + // This checks if the missing trait is PartialEq to suggest adding a derive + if let ImplementationMissing::BinOp(binary_op_trait) = missing_trait { + if matches!(binary_op_trait, hir::BinOpKind::Eq | hir::BinOpKind::Ne) { + err.note(&format!( + "add `#[derive(PartialEq)]` or manually implement `PartialEq` for `{}`", + ty + )); + } else if matches!( + binary_op_trait, + hir::BinOpKind::Lt + | hir::BinOpKind::Le + | hir::BinOpKind::Ge + | hir::BinOpKind::Gt + ) { + err.note(&format!( + "add `#[derive(PartialOrd)]` or manually implement `PartialOrd` for `{}`", + ty + )); + } + } } } } From b58393bafdff2b8fcf1543e4a4ea849da78f6c3f Mon Sep 17 00:00:00 2001 From: ccgauche Date: Tue, 17 Aug 2021 23:22:06 +0200 Subject: [PATCH 8/9] Fixed CI errors --- compiler/rustc_typeck/src/check/op.rs | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 4ba548a2b1fe3..3278aacc5ed08 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -19,7 +19,6 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; -use std::borrow::Borrow; use std::ops::ControlFlow; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -283,52 +282,52 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (message, missing_trait, use_output) = match op.node { hir::BinOpKind::Add => ( format!("cannot add `{}` to `{}`", rhs_ty, lhs_ty), - Some(op.node), + Some(STDImplementationMissing::BinOp(op.node)), true, ), hir::BinOpKind::Sub => ( format!("cannot subtract `{}` from `{}`", rhs_ty, lhs_ty), - Some(op.node), + Some(STDImplementationMissing::BinOp(op.node)), true, ), hir::BinOpKind::Mul => ( format!("cannot multiply `{}` by `{}`", lhs_ty, rhs_ty), - Some(op.node), + Some(STDImplementationMissing::BinOp(op.node)), true, ), hir::BinOpKind::Div => ( format!("cannot divide `{}` by `{}`", lhs_ty, rhs_ty), - Some(op.node), + Some(STDImplementationMissing::BinOp(op.node)), true, ), hir::BinOpKind::Rem => ( format!("cannot mod `{}` by `{}`", lhs_ty, rhs_ty), - Some(op.node), + Some(STDImplementationMissing::BinOp(op.node)), true, ), hir::BinOpKind::BitAnd => ( format!("no implementation for `{} & {}`", lhs_ty, rhs_ty), - Some(op.node), + Some(STDImplementationMissing::BinOp(op.node)), true, ), hir::BinOpKind::BitXor => ( format!("no implementation for `{} ^ {}`", lhs_ty, rhs_ty), - Some(op.node), + Some(STDImplementationMissing::BinOp(op.node)), true, ), hir::BinOpKind::BitOr => ( format!("no implementation for `{} | {}`", lhs_ty, rhs_ty), - Some(op.node), + Some(STDImplementationMissing::BinOp(op.node)), true, ), hir::BinOpKind::Shl => ( format!("no implementation for `{} << {}`", lhs_ty, rhs_ty), - Some(op.node), + Some(STDImplementationMissing::BinOp(op.node)), true, ), hir::BinOpKind::Shr => ( format!("no implementation for `{} >> {}`", lhs_ty, rhs_ty), - Some(op.node), + Some(STDImplementationMissing::BinOp(op.node)), true, ), hir::BinOpKind::Eq | hir::BinOpKind::Ne => ( @@ -337,7 +336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { op.node.as_str(), lhs_ty ), - Some(op.node), + Some(STDImplementationMissing::BinOp(op.node)), false, ), hir::BinOpKind::Lt @@ -349,7 +348,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { op.node.as_str(), lhs_ty ), - Some(op.node), + Some(STDImplementationMissing::BinOp(op.node)), false, ), _ => ( @@ -970,7 +969,7 @@ fn suggest_impl_missing( )); } // This checks if the missing trait is PartialEq to suggest adding a derive - if let ImplementationMissing::BinOp(binary_op_trait) = missing_trait { + if let STDImplementationMissing::BinOp(binary_op_trait) = missing_trait { if matches!(binary_op_trait, hir::BinOpKind::Eq | hir::BinOpKind::Ne) { err.note(&format!( "add `#[derive(PartialEq)]` or manually implement `PartialEq` for `{}`", From 207f9b1534b0ad60aa5fc273ddff198c064b3878 Mon Sep 17 00:00:00 2001 From: ccgauche Date: Wed, 18 Aug 2021 00:02:40 +0200 Subject: [PATCH 9/9] Fixed borrow issue --- compiler/rustc_typeck/src/check/op.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 3278aacc5ed08..d5ba4188a248d 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -415,7 +415,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } if let Some(missing_trait) = missing_trait { - let missing_trait_str = missing_trait.as_std_trait(); + let missing_trait_str = missing_trait.as_std_trait().unwrap_or_default(); let mut visitor = TypeParamVisitor(vec![]); visitor.visit_ty(lhs_ty); @@ -463,7 +463,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { bug!("type param visitor stored a non type param: {:?}", ty.kind()); } } else if !suggested_deref && !involves_fn { - suggest_impl_missing(&mut err, lhs_ty, &missing_trait); + suggest_impl_missing(&mut err, lhs_ty, missing_trait); } } err.emit(); @@ -701,7 +701,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { suggest_impl_missing( &mut err, operand_ty, - &STDImplementationMissing::Unop(op), + STDImplementationMissing::Unop(op), ); } } @@ -965,7 +965,7 @@ fn suggest_impl_missing( if let Some(missing_trait_name) = missing_trait.as_std_trait() { err.note(&format!( "an implementation of `{}` might be missing for `{}`", - missing_trait, ty + missing_trait_name, ty )); } // This checks if the missing trait is PartialEq to suggest adding a derive