New lint: [derive_partial_eq_without_eq
]
This commit is contained in:
parent
77effb7bb2
commit
fe84ff3360
29 changed files with 359 additions and 38 deletions
|
@ -3350,6 +3350,7 @@ Released 2018-09-13
|
|||
[`derivable_impls`]: https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls
|
||||
[`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
|
||||
[`derive_partial_eq_without_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq
|
||||
[`disallowed_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods
|
||||
[`disallowed_script_idents`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents
|
||||
[`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types
|
||||
|
|
|
@ -17,7 +17,7 @@ const GENERATED_FILE_COMMENT: &str = "// This file was generated by `cargo dev u
|
|||
|
||||
const DOCS_LINK: &str = "https://rust-lang.github.io/rust-clippy/master/index.html";
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum UpdateMode {
|
||||
Check,
|
||||
Change,
|
||||
|
@ -372,7 +372,7 @@ fn exit_with_failure() {
|
|||
}
|
||||
|
||||
/// Lint data parsed from the Clippy source code.
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
struct Lint {
|
||||
name: String,
|
||||
group: String,
|
||||
|
@ -414,7 +414,7 @@ impl Lint {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
struct DeprecatedLint {
|
||||
name: String,
|
||||
reason: String,
|
||||
|
|
|
@ -123,7 +123,7 @@ struct Conversion<'a> {
|
|||
}
|
||||
|
||||
/// The kind of conversion that is checked
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
enum ConversionType {
|
||||
SignedToUnsigned,
|
||||
SignedToSigned,
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_then};
|
||||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::paths;
|
||||
use clippy_utils::ty::{implements_trait, is_copy};
|
||||
use clippy_utils::{is_automatically_derived, is_lint_allowed, match_def_path};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor};
|
||||
use rustc_hir::{
|
||||
BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, HirId, Impl, Item, ItemKind, TraitRef, UnsafeSource, Unsafety,
|
||||
|
@ -156,11 +157,44 @@ declare_clippy_lint! {
|
|||
"deriving `serde::Deserialize` on a type that has methods using `unsafe`"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for types that derive `PartialEq` and could implement `Eq`.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// If a type `T` derives `PartialEq` and all of its members implement `Eq`,
|
||||
/// then `T` can always implement `Eq`. Implementing `Eq` allows `T` to be used
|
||||
/// in APIs that require `Eq` types. It also allows structs containing `T` to derive
|
||||
/// `Eq` themselves.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// #[derive(PartialEq)]
|
||||
/// struct Foo {
|
||||
/// i_am_eq: i32,
|
||||
/// i_am_eq_too: Vec<String>,
|
||||
/// }
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// #[derive(PartialEq, Eq)]
|
||||
/// struct Foo {
|
||||
/// i_am_eq: i32,
|
||||
/// i_am_eq_too: Vec<String>,
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.62.0"]
|
||||
pub DERIVE_PARTIAL_EQ_WITHOUT_EQ,
|
||||
style,
|
||||
"deriving `PartialEq` on a type that can implement `Eq`, without implementing `Eq`"
|
||||
}
|
||||
|
||||
declare_lint_pass!(Derive => [
|
||||
EXPL_IMPL_CLONE_ON_COPY,
|
||||
DERIVE_HASH_XOR_EQ,
|
||||
DERIVE_ORD_XOR_PARTIAL_ORD,
|
||||
UNSAFE_DERIVE_DESERIALIZE
|
||||
UNSAFE_DERIVE_DESERIALIZE,
|
||||
DERIVE_PARTIAL_EQ_WITHOUT_EQ
|
||||
]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for Derive {
|
||||
|
@ -179,6 +213,7 @@ impl<'tcx> LateLintPass<'tcx> for Derive {
|
|||
|
||||
if is_automatically_derived {
|
||||
check_unsafe_derive_deserialize(cx, item, trait_ref, ty);
|
||||
check_partial_eq_without_eq(cx, item.span, trait_ref, ty);
|
||||
} else {
|
||||
check_copy_clone(cx, item, trait_ref, ty);
|
||||
}
|
||||
|
@ -419,3 +454,36 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
|
|||
self.cx.tcx.hir()
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of the `DERIVE_PARTIAL_EQ_WITHOUT_EQ` lint.
|
||||
fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>) {
|
||||
if_chain! {
|
||||
if let ty::Adt(adt, substs) = ty.kind();
|
||||
if let Some(eq_trait_def_id) = cx.tcx.get_diagnostic_item(sym::Eq);
|
||||
if let Some(def_id) = trait_ref.trait_def_id();
|
||||
if cx.tcx.is_diagnostic_item(sym::PartialEq, def_id);
|
||||
if !implements_trait(cx, ty, eq_trait_def_id, substs);
|
||||
then {
|
||||
// If all of our fields implement `Eq`, we can implement `Eq` too
|
||||
for variant in adt.variants() {
|
||||
for field in &variant.fields {
|
||||
let ty = field.ty(cx.tcx, substs);
|
||||
|
||||
if !implements_trait(cx, ty, eq_trait_def_id, substs) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
DERIVE_PARTIAL_EQ_WITHOUT_EQ,
|
||||
span.ctxt().outer_expn_data().call_site,
|
||||
"you are deriving `PartialEq` and can implement `Eq`",
|
||||
"consider deriving `Eq` as well",
|
||||
"PartialEq, Eq".to_string(),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
|
|||
LintId::of(derivable_impls::DERIVABLE_IMPLS),
|
||||
LintId::of(derive::DERIVE_HASH_XOR_EQ),
|
||||
LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD),
|
||||
LintId::of(derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ),
|
||||
LintId::of(disallowed_methods::DISALLOWED_METHODS),
|
||||
LintId::of(disallowed_types::DISALLOWED_TYPES),
|
||||
LintId::of(doc::MISSING_SAFETY_DOC),
|
||||
|
|
|
@ -113,6 +113,7 @@ store.register_lints(&[
|
|||
derivable_impls::DERIVABLE_IMPLS,
|
||||
derive::DERIVE_HASH_XOR_EQ,
|
||||
derive::DERIVE_ORD_XOR_PARTIAL_ORD,
|
||||
derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ,
|
||||
derive::EXPL_IMPL_CLONE_ON_COPY,
|
||||
derive::UNSAFE_DERIVE_DESERIALIZE,
|
||||
disallowed_methods::DISALLOWED_METHODS,
|
||||
|
|
|
@ -16,6 +16,7 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![
|
|||
LintId::of(comparison_chain::COMPARISON_CHAIN),
|
||||
LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT),
|
||||
LintId::of(dereference::NEEDLESS_BORROW),
|
||||
LintId::of(derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ),
|
||||
LintId::of(disallowed_methods::DISALLOWED_METHODS),
|
||||
LintId::of(disallowed_types::DISALLOWED_TYPES),
|
||||
LintId::of(doc::MISSING_SAFETY_DOC),
|
||||
|
|
|
@ -13,7 +13,7 @@ use rustc_span::symbol::{sym, Symbol};
|
|||
use rustc_typeck::hir_ty_to_ty;
|
||||
use std::iter::Iterator;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum IncrementVisitorVarState {
|
||||
Initial, // Not examined yet
|
||||
IncrOnce, // Incremented exactly once, may be a loop counter
|
||||
|
|
|
@ -2835,7 +2835,7 @@ const TRAIT_METHODS: [ShouldImplTraitCase; 30] = [
|
|||
ShouldImplTraitCase::new("std::ops::Sub", "sub", 2, FN_HEADER, SelfKind::Value, OutType::Any, true),
|
||||
];
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
enum SelfKind {
|
||||
Value,
|
||||
Ref,
|
||||
|
|
|
@ -271,7 +271,7 @@ enum IterUsageKind {
|
|||
NextTuple,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum UnwrapKind {
|
||||
Unwrap,
|
||||
QuestionMark,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use rustc_ast::ast::{Lit, LitFloatType, LitIntType, LitKind};
|
||||
use std::iter;
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
pub enum Radix {
|
||||
Binary,
|
||||
Octal,
|
||||
|
|
|
@ -37,7 +37,7 @@ fn main() {
|
|||
|
||||
use std::cmp::{Ordering, PartialEq, PartialOrd};
|
||||
|
||||
#[derive(PartialEq, PartialOrd)]
|
||||
#[derive(PartialEq, Eq, PartialOrd)]
|
||||
pub struct U(u64);
|
||||
|
||||
impl PartialEq<u32> for U {
|
||||
|
|
|
@ -24,7 +24,7 @@ fn main() {
|
|||
|
||||
use std::ops::{Mul, MulAssign};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Wrap(i64);
|
||||
|
||||
impl Mul<i64> for Wrap {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// run-rustfix
|
||||
#![allow(unused, clippy::redundant_clone)] // See #5700
|
||||
#![allow(unused, clippy::redundant_clone, clippy::derive_partial_eq_without_eq)] // See #5700
|
||||
|
||||
// Define the types in each module to avoid trait impls leaking between modules.
|
||||
macro_rules! impl_types {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// run-rustfix
|
||||
#![allow(unused, clippy::redundant_clone)] // See #5700
|
||||
#![allow(unused, clippy::redundant_clone, clippy::derive_partial_eq_without_eq)] // See #5700
|
||||
|
||||
// Define the types in each module to avoid trait impls leaking between modules.
|
||||
macro_rules! impl_types {
|
||||
|
|
|
@ -45,7 +45,7 @@ impl ToOwned for Foo {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct Bar;
|
||||
|
||||
impl PartialEq<Foo> for Bar {
|
||||
|
@ -61,7 +61,7 @@ impl std::borrow::Borrow<Foo> for Bar {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct Baz;
|
||||
|
||||
impl ToOwned for Baz {
|
||||
|
|
|
@ -45,7 +45,7 @@ impl ToOwned for Foo {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct Bar;
|
||||
|
||||
impl PartialEq<Foo> for Bar {
|
||||
|
@ -61,7 +61,7 @@ impl std::borrow::Borrow<Foo> for Bar {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct Baz;
|
||||
|
||||
impl ToOwned for Baz {
|
||||
|
|
|
@ -26,7 +26,7 @@ impl ToOwned for Foo {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct Baz;
|
||||
|
||||
impl ToOwned for Baz {
|
||||
|
@ -36,7 +36,7 @@ impl ToOwned for Baz {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct Bar;
|
||||
|
||||
impl PartialEq<Foo> for Bar {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())',
|
||||
// compiler/rustc_mir_build/src/thir/pattern/_match.rs:2030:5
|
||||
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(PartialEq)]
|
||||
struct Foo(i32);
|
||||
const FOO_REF_REF: &&Foo = &&Foo(42);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/ice-6254.rs:12:9
|
||||
--> $DIR/ice-6254.rs:13:9
|
||||
|
|
||||
LL | FOO_REF_REF => {},
|
||||
| ^^^^^^^^^^^
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(clippy::derive_partial_eq_without_eq)]
|
||||
|
||||
#[derive(PartialEq, Hash)]
|
||||
struct Foo;
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
error: you are deriving `Hash` but have implemented `PartialEq` explicitly
|
||||
--> $DIR/derive_hash_xor_eq.rs:10:10
|
||||
--> $DIR/derive_hash_xor_eq.rs:12:10
|
||||
|
|
||||
LL | #[derive(Hash)]
|
||||
| ^^^^
|
||||
|
|
||||
= note: `#[deny(clippy::derive_hash_xor_eq)]` on by default
|
||||
note: `PartialEq` implemented here
|
||||
--> $DIR/derive_hash_xor_eq.rs:13:1
|
||||
--> $DIR/derive_hash_xor_eq.rs:15:1
|
||||
|
|
||||
LL | / impl PartialEq for Bar {
|
||||
LL | | fn eq(&self, _: &Bar) -> bool {
|
||||
|
@ -17,13 +17,13 @@ LL | | }
|
|||
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: you are deriving `Hash` but have implemented `PartialEq` explicitly
|
||||
--> $DIR/derive_hash_xor_eq.rs:19:10
|
||||
--> $DIR/derive_hash_xor_eq.rs:21:10
|
||||
|
|
||||
LL | #[derive(Hash)]
|
||||
| ^^^^
|
||||
|
|
||||
note: `PartialEq` implemented here
|
||||
--> $DIR/derive_hash_xor_eq.rs:22:1
|
||||
--> $DIR/derive_hash_xor_eq.rs:24:1
|
||||
|
|
||||
LL | / impl PartialEq<Baz> for Baz {
|
||||
LL | | fn eq(&self, _: &Baz) -> bool {
|
||||
|
@ -34,7 +34,7 @@ LL | | }
|
|||
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: you are implementing `Hash` explicitly but have derived `PartialEq`
|
||||
--> $DIR/derive_hash_xor_eq.rs:31:1
|
||||
--> $DIR/derive_hash_xor_eq.rs:33:1
|
||||
|
|
||||
LL | / impl std::hash::Hash for Bah {
|
||||
LL | | fn hash<H: std::hash::Hasher>(&self, _: &mut H) {}
|
||||
|
@ -42,14 +42,14 @@ LL | | }
|
|||
| |_^
|
||||
|
|
||||
note: `PartialEq` implemented here
|
||||
--> $DIR/derive_hash_xor_eq.rs:28:10
|
||||
--> $DIR/derive_hash_xor_eq.rs:30:10
|
||||
|
|
||||
LL | #[derive(PartialEq)]
|
||||
| ^^^^^^^^^
|
||||
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: you are implementing `Hash` explicitly but have derived `PartialEq`
|
||||
--> $DIR/derive_hash_xor_eq.rs:49:5
|
||||
--> $DIR/derive_hash_xor_eq.rs:51:5
|
||||
|
|
||||
LL | / impl Hash for Foo3 {
|
||||
LL | | fn hash<H: std::hash::Hasher>(&self, _: &mut H) {}
|
||||
|
@ -57,7 +57,7 @@ LL | | }
|
|||
| |_____^
|
||||
|
|
||||
note: `PartialEq` implemented here
|
||||
--> $DIR/derive_hash_xor_eq.rs:46:14
|
||||
--> $DIR/derive_hash_xor_eq.rs:48:14
|
||||
|
|
||||
LL | #[derive(PartialEq)]
|
||||
| ^^^^^^^^^
|
||||
|
|
98
tests/ui/derive_partial_eq_without_eq.fixed
Normal file
98
tests/ui/derive_partial_eq_without_eq.fixed
Normal file
|
@ -0,0 +1,98 @@
|
|||
// run-rustfix
|
||||
|
||||
#![allow(unused)]
|
||||
#![warn(clippy::derive_partial_eq_without_eq)]
|
||||
|
||||
// Don't warn on structs that aren't PartialEq
|
||||
struct NotPartialEq {
|
||||
foo: u32,
|
||||
bar: String,
|
||||
}
|
||||
|
||||
// Eq can be derived but is missing
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct MissingEq {
|
||||
foo: u32,
|
||||
bar: String,
|
||||
}
|
||||
|
||||
// Eq is derived
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct NotMissingEq {
|
||||
foo: u32,
|
||||
bar: String,
|
||||
}
|
||||
|
||||
// Eq is manually implemented
|
||||
#[derive(PartialEq)]
|
||||
struct ManualEqImpl {
|
||||
foo: u32,
|
||||
bar: String,
|
||||
}
|
||||
|
||||
impl Eq for ManualEqImpl {}
|
||||
|
||||
// Cannot be Eq because f32 isn't Eq
|
||||
#[derive(PartialEq)]
|
||||
struct CannotBeEq {
|
||||
foo: u32,
|
||||
bar: f32,
|
||||
}
|
||||
|
||||
// Don't warn if PartialEq is manually implemented
|
||||
struct ManualPartialEqImpl {
|
||||
foo: u32,
|
||||
bar: String,
|
||||
}
|
||||
|
||||
impl PartialEq for ManualPartialEqImpl {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.foo == other.foo && self.bar == other.bar
|
||||
}
|
||||
}
|
||||
|
||||
// Generic fields should be properly checked for Eq-ness
|
||||
#[derive(PartialEq)]
|
||||
struct GenericNotEq<T: Eq, U: PartialEq> {
|
||||
foo: T,
|
||||
bar: U,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct GenericEq<T: Eq, U: Eq> {
|
||||
foo: T,
|
||||
bar: U,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct TupleStruct(u32);
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct GenericTupleStruct<T: Eq>(T);
|
||||
|
||||
#[derive(PartialEq)]
|
||||
struct TupleStructNotEq(f32);
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum Enum {
|
||||
Foo(u32),
|
||||
Bar { a: String, b: () },
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum GenericEnum<T: Eq, U: Eq, V: Eq> {
|
||||
Foo(T),
|
||||
Bar { a: U, b: V },
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum EnumNotEq {
|
||||
Foo(u32),
|
||||
Bar { a: String, b: f32 },
|
||||
}
|
||||
|
||||
// Ensure that rustfix works properly when `PartialEq` has other derives on either side
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
struct RustFixWithOtherDerives;
|
||||
|
||||
fn main() {}
|
98
tests/ui/derive_partial_eq_without_eq.rs
Normal file
98
tests/ui/derive_partial_eq_without_eq.rs
Normal file
|
@ -0,0 +1,98 @@
|
|||
// run-rustfix
|
||||
|
||||
#![allow(unused)]
|
||||
#![warn(clippy::derive_partial_eq_without_eq)]
|
||||
|
||||
// Don't warn on structs that aren't PartialEq
|
||||
struct NotPartialEq {
|
||||
foo: u32,
|
||||
bar: String,
|
||||
}
|
||||
|
||||
// Eq can be derived but is missing
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct MissingEq {
|
||||
foo: u32,
|
||||
bar: String,
|
||||
}
|
||||
|
||||
// Eq is derived
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct NotMissingEq {
|
||||
foo: u32,
|
||||
bar: String,
|
||||
}
|
||||
|
||||
// Eq is manually implemented
|
||||
#[derive(PartialEq)]
|
||||
struct ManualEqImpl {
|
||||
foo: u32,
|
||||
bar: String,
|
||||
}
|
||||
|
||||
impl Eq for ManualEqImpl {}
|
||||
|
||||
// Cannot be Eq because f32 isn't Eq
|
||||
#[derive(PartialEq)]
|
||||
struct CannotBeEq {
|
||||
foo: u32,
|
||||
bar: f32,
|
||||
}
|
||||
|
||||
// Don't warn if PartialEq is manually implemented
|
||||
struct ManualPartialEqImpl {
|
||||
foo: u32,
|
||||
bar: String,
|
||||
}
|
||||
|
||||
impl PartialEq for ManualPartialEqImpl {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.foo == other.foo && self.bar == other.bar
|
||||
}
|
||||
}
|
||||
|
||||
// Generic fields should be properly checked for Eq-ness
|
||||
#[derive(PartialEq)]
|
||||
struct GenericNotEq<T: Eq, U: PartialEq> {
|
||||
foo: T,
|
||||
bar: U,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
struct GenericEq<T: Eq, U: Eq> {
|
||||
foo: T,
|
||||
bar: U,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
struct TupleStruct(u32);
|
||||
|
||||
#[derive(PartialEq)]
|
||||
struct GenericTupleStruct<T: Eq>(T);
|
||||
|
||||
#[derive(PartialEq)]
|
||||
struct TupleStructNotEq(f32);
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum Enum {
|
||||
Foo(u32),
|
||||
Bar { a: String, b: () },
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum GenericEnum<T: Eq, U: Eq, V: Eq> {
|
||||
Foo(T),
|
||||
Bar { a: U, b: V },
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum EnumNotEq {
|
||||
Foo(u32),
|
||||
Bar { a: String, b: f32 },
|
||||
}
|
||||
|
||||
// Ensure that rustfix works properly when `PartialEq` has other derives on either side
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
struct RustFixWithOtherDerives;
|
||||
|
||||
fn main() {}
|
46
tests/ui/derive_partial_eq_without_eq.stderr
Normal file
46
tests/ui/derive_partial_eq_without_eq.stderr
Normal file
|
@ -0,0 +1,46 @@
|
|||
error: you are deriving `PartialEq` and can implement `Eq`
|
||||
--> $DIR/derive_partial_eq_without_eq.rs:13:17
|
||||
|
|
||||
LL | #[derive(Debug, PartialEq)]
|
||||
| ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
|
||||
|
|
||||
= note: `-D clippy::derive-partial-eq-without-eq` implied by `-D warnings`
|
||||
|
||||
error: you are deriving `PartialEq` and can implement `Eq`
|
||||
--> $DIR/derive_partial_eq_without_eq.rs:61:10
|
||||
|
|
||||
LL | #[derive(PartialEq)]
|
||||
| ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
|
||||
|
||||
error: you are deriving `PartialEq` and can implement `Eq`
|
||||
--> $DIR/derive_partial_eq_without_eq.rs:67:10
|
||||
|
|
||||
LL | #[derive(PartialEq)]
|
||||
| ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
|
||||
|
||||
error: you are deriving `PartialEq` and can implement `Eq`
|
||||
--> $DIR/derive_partial_eq_without_eq.rs:70:10
|
||||
|
|
||||
LL | #[derive(PartialEq)]
|
||||
| ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
|
||||
|
||||
error: you are deriving `PartialEq` and can implement `Eq`
|
||||
--> $DIR/derive_partial_eq_without_eq.rs:76:10
|
||||
|
|
||||
LL | #[derive(PartialEq)]
|
||||
| ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
|
||||
|
||||
error: you are deriving `PartialEq` and can implement `Eq`
|
||||
--> $DIR/derive_partial_eq_without_eq.rs:82:10
|
||||
|
|
||||
LL | #[derive(PartialEq)]
|
||||
| ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
|
||||
|
||||
error: you are deriving `PartialEq` and can implement `Eq`
|
||||
--> $DIR/derive_partial_eq_without_eq.rs:95:17
|
||||
|
|
||||
LL | #[derive(Debug, PartialEq, Clone)]
|
||||
| ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// run-rustfix
|
||||
|
||||
#![allow(unused_variables, dead_code)]
|
||||
#![allow(unused_variables, dead_code, clippy::derive_partial_eq_without_eq)]
|
||||
#![warn(clippy::equatable_if_let)]
|
||||
|
||||
use std::cmp::Ordering;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// run-rustfix
|
||||
|
||||
#![allow(unused_variables, dead_code)]
|
||||
#![allow(unused_variables, dead_code, clippy::derive_partial_eq_without_eq)]
|
||||
#![warn(clippy::equatable_if_let)]
|
||||
|
||||
use std::cmp::Ordering;
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#![warn(clippy::unit_cmp)]
|
||||
#![allow(clippy::no_effect, clippy::unnecessary_operation)]
|
||||
#![allow(
|
||||
clippy::no_effect,
|
||||
clippy::unnecessary_operation,
|
||||
clippy::derive_partial_eq_without_eq
|
||||
)]
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub struct ContainsUnit(()); // should be fine
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: ==-comparison of unit values detected. This will always be true
|
||||
--> $DIR/unit_cmp.rs:12:8
|
||||
--> $DIR/unit_cmp.rs:16:8
|
||||
|
|
||||
LL | if {
|
||||
| ________^
|
||||
|
@ -12,7 +12,7 @@ LL | | } {}
|
|||
= note: `-D clippy::unit-cmp` implied by `-D warnings`
|
||||
|
||||
error: >-comparison of unit values detected. This will always be false
|
||||
--> $DIR/unit_cmp.rs:18:8
|
||||
--> $DIR/unit_cmp.rs:22:8
|
||||
|
|
||||
LL | if {
|
||||
| ________^
|
||||
|
@ -23,7 +23,7 @@ LL | | } {}
|
|||
| |_____^
|
||||
|
||||
error: `assert_eq` of unit values detected. This will always succeed
|
||||
--> $DIR/unit_cmp.rs:24:5
|
||||
--> $DIR/unit_cmp.rs:28:5
|
||||
|
|
||||
LL | / assert_eq!(
|
||||
LL | | {
|
||||
|
@ -35,7 +35,7 @@ LL | | );
|
|||
| |_____^
|
||||
|
||||
error: `debug_assert_eq` of unit values detected. This will always succeed
|
||||
--> $DIR/unit_cmp.rs:32:5
|
||||
--> $DIR/unit_cmp.rs:36:5
|
||||
|
|
||||
LL | / debug_assert_eq!(
|
||||
LL | | {
|
||||
|
@ -47,7 +47,7 @@ LL | | );
|
|||
| |_____^
|
||||
|
||||
error: `assert_ne` of unit values detected. This will always fail
|
||||
--> $DIR/unit_cmp.rs:41:5
|
||||
--> $DIR/unit_cmp.rs:45:5
|
||||
|
|
||||
LL | / assert_ne!(
|
||||
LL | | {
|
||||
|
@ -59,7 +59,7 @@ LL | | );
|
|||
| |_____^
|
||||
|
||||
error: `debug_assert_ne` of unit values detected. This will always fail
|
||||
--> $DIR/unit_cmp.rs:49:5
|
||||
--> $DIR/unit_cmp.rs:53:5
|
||||
|
|
||||
LL | / debug_assert_ne!(
|
||||
LL | | {
|
||||
|
|
Loading…
Add table
Reference in a new issue