-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Implement 'Re-implementing PartialEq::ne
' lint
#1307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
use rustc::lint::*; | ||
use rustc::hir::*; | ||
use utils::{is_automatically_derived, span_lint}; | ||
|
||
/// **What it does:** Checks for manual re-implementations of `PartialEq::ne`. | ||
/// | ||
/// **Why is this bad?** `PartialEq::ne` is required to always return the | ||
/// negated result of `PartialEq::eq`, which is exactly what the default | ||
/// implementation does. Therefore, there should never be any need to | ||
/// re-implement it. | ||
/// | ||
/// **Known problems:** None. | ||
/// | ||
/// **Example:** | ||
/// ```rust | ||
/// struct Foo; | ||
/// | ||
/// impl PartialEq for Foo { | ||
/// fn eq(&self, other: &Foo) -> bool { ... } | ||
/// fn ne(&self, other: &Foo) -> bool { !(self == other) } | ||
/// } | ||
/// ``` | ||
declare_lint! { | ||
pub PARTIALEQ_NE_IMPL, | ||
Warn, | ||
"re-implementing `PartialEq::ne`" | ||
} | ||
|
||
#[derive(Clone, Copy)] | ||
pub struct Pass; | ||
|
||
impl LintPass for Pass { | ||
fn get_lints(&self) -> LintArray { | ||
lint_array!(PARTIALEQ_NE_IMPL) | ||
} | ||
} | ||
|
||
impl LateLintPass for Pass { | ||
fn check_item(&mut self, cx: &LateContext, item: &Item) { | ||
if_let_chain! {[ | ||
let ItemImpl(_, _, _, Some(ref trait_ref), _, ref impl_items) = item.node, | ||
!is_automatically_derived(&*item.attrs), | ||
cx.tcx.expect_def(trait_ref.ref_id).def_id() == cx.tcx.lang_items.eq_trait().unwrap(), | ||
], { | ||
for impl_item in impl_items { | ||
if &*impl_item.name.as_str() == "ne" { | ||
span_lint(cx, | ||
PARTIALEQ_NE_IMPL, | ||
impl_item.span, | ||
"re-implementing `PartialEq::ne` is unnecessary") | ||
} | ||
} | ||
}}; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,8 @@ | |
|
||
use rustc::lint::*; | ||
use rustc::hir; | ||
use syntax::ast::{Attribute, MetaItemKind}; | ||
use syntax::ast::Attribute; | ||
use syntax::attr; | ||
|
||
/// **What it does:** Dumps every ast/hir node which has the `#[clippy_dump]` attribute | ||
/// | ||
|
@@ -128,10 +129,7 @@ impl LateLintPass for Pass { | |
} | ||
|
||
fn has_attr(attrs: &[Attribute]) -> bool { | ||
attrs.iter().any(|attr| match attr.node.value.node { | ||
MetaItemKind::Word(ref word) => word == "clippy_dump", | ||
_ => false, | ||
}) | ||
attr::contains_name(attrs, "clippy_dump") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Neat cleanup, didn't know about this function |
||
} | ||
|
||
fn print_decl(cx: &LateContext, decl: &hir::Decl) { | ||
|
@@ -381,12 +379,12 @@ fn print_item(cx: &LateContext, item: &hir::Item) { | |
} | ||
}, | ||
hir::ItemDefaultImpl(_, ref trait_ref) => { | ||
let trait_did = cx.tcx.map.local_def_id(trait_ref.ref_id); | ||
println!("default impl for `{:?}`", cx.tcx.item_path_str(trait_did)); | ||
let trait_did = cx.tcx.expect_def(trait_ref.ref_id).def_id(); | ||
println!("default impl for `{}`", cx.tcx.item_path_str(trait_did)); | ||
}, | ||
hir::ItemImpl(_, _, _, Some(ref trait_ref), _, _) => { | ||
let trait_did = cx.tcx.map.local_def_id(trait_ref.ref_id); | ||
println!("impl of trait `{:?}`", cx.tcx.item_path_str(trait_did)); | ||
let trait_did = cx.tcx.expect_def(trait_ref.ref_id).def_id(); | ||
println!("impl of trait `{}`", cx.tcx.item_path_str(trait_did)); | ||
}, | ||
hir::ItemImpl(_, _, _, None, _, _) => { | ||
println!("impl"); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#![feature(plugin)] | ||
#![plugin(clippy)] | ||
|
||
#![deny(warnings)] | ||
#![allow(dead_code)] | ||
|
||
struct Foo; | ||
|
||
impl PartialEq for Foo { | ||
fn eq(&self, _: &Foo) -> bool { true } | ||
fn ne(&self, _: &Foo) -> bool { false } | ||
//~^ ERROR re-implementing `PartialEq::ne` is unnecessary | ||
} | ||
|
||
fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
#!/bin/sh | ||
rm -rf target*/*so | ||
cargo build --lib && cp -R target target_recur && cargo rustc -- -Zextra-plugins=clippy -Ltarget_recur/debug -Dclippy_pedantic -Dclippy || exit 1 | ||
cargo build --lib && cp -R target target_recur && cargo rustc --lib -- -Zextra-plugins=clippy -Ltarget_recur/debug -Dclippy_pedantic -Dclippy || exit 1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Huh, how did this ever work? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh.... This is dogfood.sh, nevermind. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, seems like nobody's run this ever since There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cargo test will actually run a separate implementation of dogfood, so there wasn't any need for that script as far as I knew |
||
rm -rf target_recur | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should also give a help message telling the user what to do( remove the impl)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any suggestion for wording? Maybe just appending
... is unnecessary
?