From 5a644964fc05752a1283dab238b81de7583f7d03 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 26 Jul 2020 20:40:57 -0600 Subject: [PATCH 01/12] run cargo dev new_lint specifically: cargo dev new_lint --name derive_ord_xor_partial_ord --category correctness --pass late --- CHANGELOG.md | 1 + .../src/derive_ord_xor_partial_ord.rs | 28 +++++++++++++++++++ clippy_lints/src/lib.rs | 4 +++ src/lintlist/mod.rs | 7 +++++ tests/ui/derive_ord_xor_partial_ord.rs | 5 ++++ 5 files changed, 45 insertions(+) create mode 100644 clippy_lints/src/derive_ord_xor_partial_ord.rs create mode 100644 tests/ui/derive_ord_xor_partial_ord.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 776b04295f94..a17807250443 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1454,6 +1454,7 @@ Released 2018-09-13 [`deprecated_semver`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_semver [`deref_addrof`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_addrof [`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq +[`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression [`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown [`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons diff --git a/clippy_lints/src/derive_ord_xor_partial_ord.rs b/clippy_lints/src/derive_ord_xor_partial_ord.rs new file mode 100644 index 000000000000..7913aab6f24b --- /dev/null +++ b/clippy_lints/src/derive_ord_xor_partial_ord.rs @@ -0,0 +1,28 @@ +use rustc_lint::{LateLintPass, LateContext}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_hir::*; + +declare_clippy_lint! { + /// **What it does:** + /// + /// **Why is this bad?** + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// // example code where clippy issues a warning + /// ``` + /// Use instead: + /// ```rust + /// // example code which does not raise clippy warning + /// ``` + pub DERIVE_ORD_XOR_PARTIAL_ORD, + correctness, + "default lint description" +} + +declare_lint_pass!(DeriveOrdXorPartialOrd => [DERIVE_ORD_XOR_PARTIAL_ORD]); + +impl LateLintPass<'_, '_> for DeriveOrdXorPartialOrd {} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f371942dbeec..6d6dd06cc216 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -173,6 +173,7 @@ mod dbg_macro; mod default_trait_access; mod dereference; mod derive; +mod derive_ord_xor_partial_ord; mod doc; mod double_comparison; mod double_parens; @@ -515,6 +516,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &derive::DERIVE_HASH_XOR_EQ, &derive::EXPL_IMPL_CLONE_ON_COPY, &derive::UNSAFE_DERIVE_DESERIALIZE, + &derive_ord_xor_partial_ord::DERIVE_ORD_XOR_PARTIAL_ORD, &doc::DOC_MARKDOWN, &doc::MISSING_ERRORS_DOC, &doc::MISSING_SAFETY_DOC, @@ -1230,6 +1232,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&copies::IFS_SAME_COND), LintId::of(&copies::IF_SAME_THEN_ELSE), LintId::of(&derive::DERIVE_HASH_XOR_EQ), + LintId::of(&derive_ord_xor_partial_ord::DERIVE_ORD_XOR_PARTIAL_ORD), LintId::of(&doc::MISSING_SAFETY_DOC), LintId::of(&doc::NEEDLESS_DOCTEST_MAIN), LintId::of(&double_comparison::DOUBLE_COMPARISONS), @@ -1648,6 +1651,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&copies::IFS_SAME_COND), LintId::of(&copies::IF_SAME_THEN_ELSE), LintId::of(&derive::DERIVE_HASH_XOR_EQ), + LintId::of(&derive_ord_xor_partial_ord::DERIVE_ORD_XOR_PARTIAL_ORD), LintId::of(&drop_bounds::DROP_BOUNDS), LintId::of(&drop_forget_ref::DROP_COPY), LintId::of(&drop_forget_ref::DROP_REF), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 1879aae77fb6..00d3df8f94f6 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -360,6 +360,13 @@ pub static ref ALL_LINTS: Vec = vec![ deprecation: None, module: "derive", }, + Lint { + name: "derive_ord_xor_partial_ord", + group: "correctness", + desc: "default lint description", + deprecation: None, + module: "derive_ord_xor_partial_ord", + }, Lint { name: "diverging_sub_expression", group: "complexity", diff --git a/tests/ui/derive_ord_xor_partial_ord.rs b/tests/ui/derive_ord_xor_partial_ord.rs new file mode 100644 index 000000000000..63687e7b3dbd --- /dev/null +++ b/tests/ui/derive_ord_xor_partial_ord.rs @@ -0,0 +1,5 @@ +#![warn(clippy::derive_ord_xor_partial_ord)] + +fn main() { + // test code goes here +} From fc20ee63a105c0df78113126e8749f5958d7dc47 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 26 Jul 2020 20:54:04 -0600 Subject: [PATCH 02/12] move derive_ord_xor_partial_ord into derive mod so we can reuse derive_hash_xor_partial_eq code later --- clippy_lints/src/derive.rs | 23 ++++++++++++++- .../src/derive_ord_xor_partial_ord.rs | 28 ------------------- clippy_lints/src/lib.rs | 7 ++--- src/lintlist/mod.rs | 2 +- 4 files changed, 26 insertions(+), 34 deletions(-) delete mode 100644 clippy_lints/src/derive_ord_xor_partial_ord.rs diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 59c62f1ae944..627475ee1d92 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -43,6 +43,27 @@ declare_clippy_lint! { "deriving `Hash` but implementing `PartialEq` explicitly" } +declare_clippy_lint! { + /// **What it does:** + /// + /// **Why is this bad?** + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// // example code where clippy issues a warning + /// ``` + /// Use instead: + /// ```rust + /// // example code which does not raise clippy warning + /// ``` + pub DERIVE_ORD_XOR_PARTIAL_ORD, + correctness, + "default lint description" +} + declare_clippy_lint! { /// **What it does:** Checks for explicit `Clone` implementations for `Copy` /// types. @@ -103,7 +124,7 @@ declare_clippy_lint! { "deriving `serde::Deserialize` on a type that has methods using `unsafe`" } -declare_lint_pass!(Derive => [EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ, UNSAFE_DERIVE_DESERIALIZE]); +declare_lint_pass!(Derive => [EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ, DERIVE_ORD_XOR_PARTIAL_ORD, UNSAFE_DERIVE_DESERIALIZE]); impl<'tcx> LateLintPass<'tcx> for Derive { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { diff --git a/clippy_lints/src/derive_ord_xor_partial_ord.rs b/clippy_lints/src/derive_ord_xor_partial_ord.rs deleted file mode 100644 index 7913aab6f24b..000000000000 --- a/clippy_lints/src/derive_ord_xor_partial_ord.rs +++ /dev/null @@ -1,28 +0,0 @@ -use rustc_lint::{LateLintPass, LateContext}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_hir::*; - -declare_clippy_lint! { - /// **What it does:** - /// - /// **Why is this bad?** - /// - /// **Known problems:** None. - /// - /// **Example:** - /// - /// ```rust - /// // example code where clippy issues a warning - /// ``` - /// Use instead: - /// ```rust - /// // example code which does not raise clippy warning - /// ``` - pub DERIVE_ORD_XOR_PARTIAL_ORD, - correctness, - "default lint description" -} - -declare_lint_pass!(DeriveOrdXorPartialOrd => [DERIVE_ORD_XOR_PARTIAL_ORD]); - -impl LateLintPass<'_, '_> for DeriveOrdXorPartialOrd {} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6d6dd06cc216..996aad31d3e1 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -173,7 +173,6 @@ mod dbg_macro; mod default_trait_access; mod dereference; mod derive; -mod derive_ord_xor_partial_ord; mod doc; mod double_comparison; mod double_parens; @@ -514,9 +513,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &default_trait_access::DEFAULT_TRAIT_ACCESS, &dereference::EXPLICIT_DEREF_METHODS, &derive::DERIVE_HASH_XOR_EQ, + &derive::DERIVE_ORD_XOR_PARTIAL_ORD, &derive::EXPL_IMPL_CLONE_ON_COPY, &derive::UNSAFE_DERIVE_DESERIALIZE, - &derive_ord_xor_partial_ord::DERIVE_ORD_XOR_PARTIAL_ORD, &doc::DOC_MARKDOWN, &doc::MISSING_ERRORS_DOC, &doc::MISSING_SAFETY_DOC, @@ -1232,7 +1231,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&copies::IFS_SAME_COND), LintId::of(&copies::IF_SAME_THEN_ELSE), LintId::of(&derive::DERIVE_HASH_XOR_EQ), - LintId::of(&derive_ord_xor_partial_ord::DERIVE_ORD_XOR_PARTIAL_ORD), + LintId::of(&derive::DERIVE_ORD_XOR_PARTIAL_ORD), LintId::of(&doc::MISSING_SAFETY_DOC), LintId::of(&doc::NEEDLESS_DOCTEST_MAIN), LintId::of(&double_comparison::DOUBLE_COMPARISONS), @@ -1651,7 +1650,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&copies::IFS_SAME_COND), LintId::of(&copies::IF_SAME_THEN_ELSE), LintId::of(&derive::DERIVE_HASH_XOR_EQ), - LintId::of(&derive_ord_xor_partial_ord::DERIVE_ORD_XOR_PARTIAL_ORD), + LintId::of(&derive::DERIVE_ORD_XOR_PARTIAL_ORD), LintId::of(&drop_bounds::DROP_BOUNDS), LintId::of(&drop_forget_ref::DROP_COPY), LintId::of(&drop_forget_ref::DROP_REF), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 00d3df8f94f6..011504710e13 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -365,7 +365,7 @@ pub static ref ALL_LINTS: Vec = vec![ group: "correctness", desc: "default lint description", deprecation: None, - module: "derive_ord_xor_partial_ord", + module: "derive", }, Lint { name: "diverging_sub_expression", From 0722991b62fd6e4d7d7a51425274f3288bcc96bc Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 26 Jul 2020 21:36:50 -0600 Subject: [PATCH 03/12] add test for derive_ord_xor_partial_ord based on test for derive_hash_xor_partial_eq --- tests/ui/derive_ord_xor_partial_ord.rs | 67 +++++++++++++++++++++- tests/ui/derive_ord_xor_partial_ord.stderr | 1 + 2 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 tests/ui/derive_ord_xor_partial_ord.stderr diff --git a/tests/ui/derive_ord_xor_partial_ord.rs b/tests/ui/derive_ord_xor_partial_ord.rs index 63687e7b3dbd..15f66b7a9c59 100644 --- a/tests/ui/derive_ord_xor_partial_ord.rs +++ b/tests/ui/derive_ord_xor_partial_ord.rs @@ -1,5 +1,68 @@ #![warn(clippy::derive_ord_xor_partial_ord)] -fn main() { - // test code goes here +use std::cmp::Ordering; + +#[derive(PartialOrd, Ord, PartialEq, Eq)] +struct DeriveBoth; + +impl PartialEq for DeriveBoth { + fn eq(&self, _: &u64) -> bool { + true + } +} + +impl PartialOrd for DeriveBoth { + fn partial_cmp(&self, _: &u64) -> Option { + Some(Ordering::Equal) + } } + +#[derive(Ord, PartialEq, Eq)] +struct DeriveOrd; + +impl PartialOrd for DeriveOrd { + fn partial_cmp(&self, other: &Self) -> Option { + Some(other.cmp(self)) + } +} + +#[derive(Ord, PartialEq, Eq)] +struct DeriveOrdWithExplicitTypeVariable; + +impl PartialOrd for DeriveOrdWithExplicitTypeVariable { + fn partial_cmp(&self, other: &Self) -> Option { + Some(other.cmp(self)) + } +} + +#[derive(PartialOrd, PartialEq, Eq)] +struct DerivePartialOrd; + +impl std::cmp::Ord for DerivePartialOrd { + fn cmp(&self, other: &Self) -> Ordering { + Ordering::Less + } +} + +#[derive(PartialOrd, PartialEq, Eq)] +struct ImplUserOrd; + +trait Ord {} + +// We don't want to lint on user-defined traits called `Ord` +impl Ord for ImplUserOrd {} + +mod use_ord { + use std::cmp::{Ord, Ordering}; + + #[derive(PartialOrd, PartialEq, Eq)] + struct DerivePartialOrdInUseOrd; + + impl Ord for DerivePartialOrdInUseOrd { + fn cmp(&self, other: &Self) -> Ordering { + Ordering::Less + } + } +} + +fn main() {} \ No newline at end of file diff --git a/tests/ui/derive_ord_xor_partial_ord.stderr b/tests/ui/derive_ord_xor_partial_ord.stderr new file mode 100644 index 000000000000..30404ce4c546 --- /dev/null +++ b/tests/ui/derive_ord_xor_partial_ord.stderr @@ -0,0 +1 @@ +TODO \ No newline at end of file From 068acbd27b19a4a7be3a9d00954ecfad8a0e6553 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 26 Jul 2020 22:04:46 -0600 Subject: [PATCH 04/12] initial implementation based on code for `derive_hash_xor_partial_eq` which is showing one error when there should be four --- clippy_lints/src/derive.rs | 55 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 627475ee1d92..4f69c2d7af77 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -137,6 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for Derive { let is_automatically_derived = is_automatically_derived(&*item.attrs); check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived); + check_ord_pord(cx, item.span, trait_ref, ty, is_automatically_derived); if is_automatically_derived { check_unsafe_derive_deserialize(cx, item, trait_ref, ty); @@ -201,6 +202,60 @@ fn check_hash_peq<'tcx>( } } +/// Implementation of the `DERIVE_ORD_XOR_PARTIAL_ORD` lint. +fn check_ord_pord<'tcx>( + cx: &LateContext<'tcx>, + span: Span, + trait_ref: &TraitRef<'_>, + ty: Ty<'tcx>, + ord_is_automatically_derived: bool, +) { + if_chain! { + if match_path(&trait_ref.path, &paths::ORD); + if let Some(pord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait(); + if let Some(def_id) = &trait_ref.trait_def_id(); + if !def_id.is_local(); + then { + // Look for the PartialOrd implementations for `ty` + cx.tcx.for_each_relevant_impl(pord_trait_def_id, ty, |impl_id| { + let pord_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id)); + + if pord_is_automatically_derived == ord_is_automatically_derived { + return; + } + + let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); + + // Only care about `impl PartialOrd for Foo` + // For `impl PartialOrd for A, input_types is [A, B] + if trait_ref.substs.type_at(1) == ty { + let mess = if pord_is_automatically_derived { + "you are implementing `Ord` explicitly but have derived `PartialOrd`" + } else { + "you are deriving `Ord` but have implemented `PartialOrd` explicitly" + }; + + span_lint_and_then( + cx, + DERIVE_ORD_XOR_PARTIAL_ORD, + span, + mess, + |diag| { + if let Some(local_def_id) = impl_id.as_local() { + let hir_id = cx.tcx.hir().as_local_hir_id(local_def_id); + diag.span_note( + cx.tcx.hir().span(hir_id), + "`PartialOrd` implemented here" + ); + } + } + ); + } + }); + } + } +} + /// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint. fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>) { if match_path(&trait_ref.path, &paths::CLONE_TRAIT) { From a8d6eda93049f0077c1515bec35fe0359ea43f96 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 26 Jul 2020 23:04:04 -0600 Subject: [PATCH 05/12] use get_trait_def_id to check for Ord trait --- clippy_lints/src/derive.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 4f69c2d7af77..04395621e9ee 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,6 +1,6 @@ use crate::utils::paths; use crate::utils::{ - is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, span_lint_and_then, + get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, span_lint_and_then, }; use if_chain::if_chain; use rustc_hir::def_id::DefId; @@ -211,9 +211,10 @@ fn check_ord_pord<'tcx>( ord_is_automatically_derived: bool, ) { if_chain! { - if match_path(&trait_ref.path, &paths::ORD); + if let Some(ord_trait_def_id) = get_trait_def_id(cx, &paths::ORD); if let Some(pord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait(); if let Some(def_id) = &trait_ref.trait_def_id(); + if *def_id == ord_trait_def_id; if !def_id.is_local(); then { // Look for the PartialOrd implementations for `ty` From 6c3e4591b87e6c690b31166867484675dcb1e48c Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 26 Jul 2020 23:04:25 -0600 Subject: [PATCH 06/12] update reference since we see the expected four errors --- tests/ui/derive_ord_xor_partial_ord.stderr | 72 +++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/tests/ui/derive_ord_xor_partial_ord.stderr b/tests/ui/derive_ord_xor_partial_ord.stderr index 30404ce4c546..66bc4d42ce8c 100644 --- a/tests/ui/derive_ord_xor_partial_ord.stderr +++ b/tests/ui/derive_ord_xor_partial_ord.stderr @@ -1 +1,71 @@ -TODO \ No newline at end of file +error: you are deriving `Ord` but have implemented `PartialOrd` explicitly + --> $DIR/derive_ord_xor_partial_ord.rs:20:10 + | +LL | #[derive(Ord, PartialEq, Eq)] + | ^^^ + | + = note: `-D clippy::derive-ord-xor-partial-ord` implied by `-D warnings` +note: `PartialOrd` implemented here + --> $DIR/derive_ord_xor_partial_ord.rs:23:1 + | +LL | / impl PartialOrd for DeriveOrd { +LL | | fn partial_cmp(&self, other: &Self) -> Option { +LL | | Some(other.cmp(self)) +LL | | } +LL | | } + | |_^ + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: you are deriving `Ord` but have implemented `PartialOrd` explicitly + --> $DIR/derive_ord_xor_partial_ord.rs:29:10 + | +LL | #[derive(Ord, PartialEq, Eq)] + | ^^^ + | +note: `PartialOrd` implemented here + --> $DIR/derive_ord_xor_partial_ord.rs:32:1 + | +LL | / impl PartialOrd for DeriveOrdWithExplicitTypeVariable { +LL | | fn partial_cmp(&self, other: &Self) -> Option { +LL | | Some(other.cmp(self)) +LL | | } +LL | | } + | |_^ + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: you are implementing `Ord` explicitly but have derived `PartialOrd` + --> $DIR/derive_ord_xor_partial_ord.rs:41:1 + | +LL | / impl std::cmp::Ord for DerivePartialOrd { +LL | | fn cmp(&self, other: &Self) -> Ordering { +LL | | Ordering::Less +LL | | } +LL | | } + | |_^ + | +note: `PartialOrd` implemented here + --> $DIR/derive_ord_xor_partial_ord.rs:38:10 + | +LL | #[derive(PartialOrd, PartialEq, Eq)] + | ^^^^^^^^^^ + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: you are implementing `Ord` explicitly but have derived `PartialOrd` + --> $DIR/derive_ord_xor_partial_ord.rs:61:5 + | +LL | / impl Ord for DerivePartialOrdInUseOrd { +LL | | fn cmp(&self, other: &Self) -> Ordering { +LL | | Ordering::Less +LL | | } +LL | | } + | |_____^ + | +note: `PartialOrd` implemented here + --> $DIR/derive_ord_xor_partial_ord.rs:58:14 + | +LL | #[derive(PartialOrd, PartialEq, Eq)] + | ^^^^^^^^^^ + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + From 7dc974815ec8736f026dc10a070137e0d4601d52 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 26 Jul 2020 23:06:36 -0600 Subject: [PATCH 07/12] remove is_local check since getting the def_id directly makes it unnecessary --- clippy_lints/src/derive.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 04395621e9ee..ab001f7773e4 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -215,7 +215,6 @@ fn check_ord_pord<'tcx>( if let Some(pord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait(); if let Some(def_id) = &trait_ref.trait_def_id(); if *def_id == ord_trait_def_id; - if !def_id.is_local(); then { // Look for the PartialOrd implementations for `ty` cx.tcx.for_each_relevant_impl(pord_trait_def_id, ty, |impl_id| { From 431924ccf69bc4d4f0597f12749e8b1bcb285710 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 26 Jul 2020 23:15:36 -0600 Subject: [PATCH 08/12] add description for derive_ord_xor_partial_ord --- clippy_lints/src/derive.rs | 42 ++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index ab001f7773e4..84566252abd7 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -44,20 +44,50 @@ declare_clippy_lint! { } declare_clippy_lint! { - /// **What it does:** + /// **What it does:** Checks for deriving `Ord` but implementing `PartialOrd` + /// explicitly or vice versa. + /// + /// **Why is this bad?** The implementation of these traits must agree (for + /// example for use with `sort`) so it’s probably a bad idea to use a + /// default-generated `Ord` implementation with an explicitly defined + /// `PartialOrd`. In particular, the following must hold for any type + /// implementing `Ord`: /// - /// **Why is this bad?** + /// ```text + /// k1.cmp(&k2) == k1.partial_cmp(&k2).unwrap() + /// ``` /// /// **Known problems:** None. /// /// **Example:** /// - /// ```rust - /// // example code where clippy issues a warning + /// ```rust,ignore + /// #[derive(Ord, PartialEq, Eq)] + /// struct Foo; + /// + /// impl PartialOrd for Foo { + /// ... + /// } /// ``` /// Use instead: - /// ```rust - /// // example code which does not raise clippy warning + /// ```rust,ignore + /// #[derive(PartialEq, Eq)] + /// struct Foo; + /// + /// impl PartialOrd for Foo { + /// fn partial_cmp(&self, other: &Foo) -> Option { + /// Some(self.cmp(other)) + /// } + /// } + /// + /// impl Ord for Foo { + /// ... + /// } + /// ``` + /// or, if you don't need a custom ordering: + /// ```rust,ignore + /// #[derive(Ord, PartialOrd, PartialEq, Eq)] + /// struct Foo; /// ``` pub DERIVE_ORD_XOR_PARTIAL_ORD, correctness, From 668b7474b47791c8c9af10130356b681b3bf3a84 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 26 Jul 2020 23:30:00 -0600 Subject: [PATCH 09/12] run cargo dev fmt and fix overly long line --- clippy_lints/src/derive.rs | 10 ++++++++-- tests/ui/derive_ord_xor_partial_ord.rs | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 84566252abd7..16a6f0c20e1e 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,6 +1,7 @@ use crate::utils::paths; use crate::utils::{ - get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, span_lint_and_then, + get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, + span_lint_and_then, }; use if_chain::if_chain; use rustc_hir::def_id::DefId; @@ -154,7 +155,12 @@ declare_clippy_lint! { "deriving `serde::Deserialize` on a type that has methods using `unsafe`" } -declare_lint_pass!(Derive => [EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ, DERIVE_ORD_XOR_PARTIAL_ORD, UNSAFE_DERIVE_DESERIALIZE]); +declare_lint_pass!(Derive => [ + EXPL_IMPL_CLONE_ON_COPY, + DERIVE_HASH_XOR_EQ, + DERIVE_ORD_XOR_PARTIAL_ORD, + UNSAFE_DERIVE_DESERIALIZE +]); impl<'tcx> LateLintPass<'tcx> for Derive { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { diff --git a/tests/ui/derive_ord_xor_partial_ord.rs b/tests/ui/derive_ord_xor_partial_ord.rs index 15f66b7a9c59..b82dc518a3ba 100644 --- a/tests/ui/derive_ord_xor_partial_ord.rs +++ b/tests/ui/derive_ord_xor_partial_ord.rs @@ -65,4 +65,4 @@ mod use_ord { } } -fn main() {} \ No newline at end of file +fn main() {} From ca03f2b650a022d06df6c02c8947a74944815381 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Mon, 27 Jul 2020 00:21:11 -0600 Subject: [PATCH 10/12] s/pord/partial_ord/ to fix dogfood failure --- clippy_lints/src/derive.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 16a6f0c20e1e..820ce85cff28 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -173,7 +173,7 @@ impl<'tcx> LateLintPass<'tcx> for Derive { let is_automatically_derived = is_automatically_derived(&*item.attrs); check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived); - check_ord_pord(cx, item.span, trait_ref, ty, is_automatically_derived); + check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived); if is_automatically_derived { check_unsafe_derive_deserialize(cx, item, trait_ref, ty); @@ -239,7 +239,7 @@ fn check_hash_peq<'tcx>( } /// Implementation of the `DERIVE_ORD_XOR_PARTIAL_ORD` lint. -fn check_ord_pord<'tcx>( +fn check_ord_partial_ord<'tcx>( cx: &LateContext<'tcx>, span: Span, trait_ref: &TraitRef<'_>, @@ -248,15 +248,15 @@ fn check_ord_pord<'tcx>( ) { if_chain! { if let Some(ord_trait_def_id) = get_trait_def_id(cx, &paths::ORD); - if let Some(pord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait(); + if let Some(partial_ord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait(); if let Some(def_id) = &trait_ref.trait_def_id(); if *def_id == ord_trait_def_id; then { // Look for the PartialOrd implementations for `ty` - cx.tcx.for_each_relevant_impl(pord_trait_def_id, ty, |impl_id| { - let pord_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id)); + cx.tcx.for_each_relevant_impl(partial_ord_trait_def_id, ty, |impl_id| { + let partial_ord_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id)); - if pord_is_automatically_derived == ord_is_automatically_derived { + if partial_ord_is_automatically_derived == ord_is_automatically_derived { return; } @@ -265,7 +265,7 @@ fn check_ord_pord<'tcx>( // Only care about `impl PartialOrd for Foo` // For `impl PartialOrd for A, input_types is [A, B] if trait_ref.substs.type_at(1) == ty { - let mess = if pord_is_automatically_derived { + let mess = if partial_ord_is_automatically_derived { "you are implementing `Ord` explicitly but have derived `PartialOrd`" } else { "you are deriving `Ord` but have implemented `PartialOrd` explicitly" From 12a6eee045f30785a1eb7572a4cfea3c5cec8a4c Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Mon, 27 Jul 2020 00:22:39 -0600 Subject: [PATCH 11/12] fill in lint description for DERIVE_ORD_XOR_PARTIAL_ORD --- clippy_lints/src/derive.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 820ce85cff28..cdb748de0c0a 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,7 +1,6 @@ use crate::utils::paths; use crate::utils::{ - get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, - span_lint_and_then, + get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, span_lint_and_then, }; use if_chain::if_chain; use rustc_hir::def_id::DefId; @@ -92,7 +91,7 @@ declare_clippy_lint! { /// ``` pub DERIVE_ORD_XOR_PARTIAL_ORD, correctness, - "default lint description" + "deriving `Ord` but implementing `PartialOrd` explicitly" } declare_clippy_lint! { From 94b10a6e5ab003a03b6c7b60ffe5a3b366e0529a Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Mon, 27 Jul 2020 00:31:09 -0600 Subject: [PATCH 12/12] run cargo dev update_lints --- clippy_lints/src/derive.rs | 3 ++- src/lintlist/mod.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index cdb748de0c0a..08d8100a8854 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,6 +1,7 @@ use crate::utils::paths; use crate::utils::{ - get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, span_lint_and_then, + get_trait_def_id, is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, + span_lint_and_then, }; use if_chain::if_chain; use rustc_hir::def_id::DefId; diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 011504710e13..119908b3cc45 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -363,7 +363,7 @@ pub static ref ALL_LINTS: Vec = vec![ Lint { name: "derive_ord_xor_partial_ord", group: "correctness", - desc: "default lint description", + desc: "deriving `Ord` but implementing `PartialOrd` explicitly", deprecation: None, module: "derive", },