Skip to content

Add check for assert_eq macros to unit_cmp lint #4613

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

Merged
merged 6 commits into from
Oct 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion clippy_lints/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ use rustc_target::spec::abi::Abi;
use rustc_typeck::hir_ty_to_ty;
use syntax::ast::{FloatTy, IntTy, LitIntType, LitKind, UintTy};
use syntax::errors::DiagnosticBuilder;
use syntax::ext::base::MacroKind;
use syntax::ext::hygiene::ExpnKind;
use syntax::source_map::Span;
use syntax::symbol::{sym, Symbol};

Expand Down Expand Up @@ -485,7 +487,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnitValue {
}

declare_clippy_lint! {
/// **What it does:** Checks for comparisons to unit.
/// **What it does:** Checks for comparisons to unit. This includes all binary
/// comparisons (like `==` and `<`) and asserts.
///
/// **Why is this bad?** Unit is always equal to itself, and thus is just a
/// clumsily written constant. Mostly this happens when someone accidentally
Expand Down Expand Up @@ -517,6 +520,14 @@ declare_clippy_lint! {
/// baz();
/// }
/// ```
///
/// For asserts:
/// ```rust
/// # fn foo() {};
/// # fn bar() {};
/// assert_eq!({ foo(); }, { bar(); });
/// ```
/// will always succeed
pub UNIT_CMP,
correctness,
"comparing unit values"
Expand All @@ -527,6 +538,30 @@ declare_lint_pass!(UnitCmp => [UNIT_CMP]);
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitCmp {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if expr.span.from_expansion() {
if let Some(callee) = expr.span.source_callee() {
if let ExpnKind::Macro(MacroKind::Bang, symbol) = callee.kind {
if let ExprKind::Binary(ref cmp, ref left, _) = expr.kind {
let op = cmp.node;
if op.is_comparison() && is_unit(cx.tables.expr_ty(left)) {
let result = match &*symbol.as_str() {
"assert_eq" | "debug_assert_eq" => "succeed",
"assert_ne" | "debug_assert_ne" => "fail",
_ => return,
};
span_lint(
cx,
UNIT_CMP,
expr.span,
&format!(
"`{}` of unit values detected. This will always {}",
symbol.as_str(),
result
),
);
}
}
}
}
return;
}
if let ExprKind::Binary(ref cmp, ref left, _) = expr.kind {
Expand Down
34 changes: 34 additions & 0 deletions tests/ui/unit_cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,38 @@ fn main() {
} > {
false;
} {}

assert_eq!(
{
true;
},
{
false;
}
);
debug_assert_eq!(
{
true;
},
{
false;
}
);

assert_ne!(
{
true;
},
{
false;
}
);
debug_assert_ne!(
{
true;
},
{
false;
}
);
}
58 changes: 57 additions & 1 deletion tests/ui/unit_cmp.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,61 @@ LL | | false;
LL | | } {}
| |_____^

error: aborting due to 2 previous errors
error: `assert_eq` of unit values detected. This will always succeed
--> $DIR/unit_cmp.rs:24:5
|
LL | / assert_eq!(
LL | | {
LL | | true;
LL | | },
... |
LL | | }
LL | | );
| |______^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: `debug_assert_eq` of unit values detected. This will always succeed
--> $DIR/unit_cmp.rs:32:5
|
LL | / debug_assert_eq!(
LL | | {
LL | | true;
LL | | },
... |
LL | | }
LL | | );
| |______^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: `assert_ne` of unit values detected. This will always fail
--> $DIR/unit_cmp.rs:41:5
|
LL | / assert_ne!(
LL | | {
LL | | true;
LL | | },
... |
LL | | }
LL | | );
| |______^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: `debug_assert_ne` of unit values detected. This will always fail
--> $DIR/unit_cmp.rs:49:5
|
LL | / debug_assert_ne!(
LL | | {
LL | | true;
LL | | },
... |
LL | | }
LL | | );
| |______^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: aborting due to 6 previous errors

1 change: 1 addition & 0 deletions tests/ui/unused_unit.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ fn return_unit() { }

#[allow(clippy::needless_return)]
#[allow(clippy::never_loop)]
#[allow(clippy::unit_cmp)]
fn main() {
let u = Unitter;
assert_eq!(u.get_unit(|| {}, return_unit), u.into());
Expand Down
1 change: 1 addition & 0 deletions tests/ui/unused_unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ fn return_unit() -> () { () }

#[allow(clippy::needless_return)]
#[allow(clippy::never_loop)]
#[allow(clippy::unit_cmp)]
fn main() {
let u = Unitter;
assert_eq!(u.get_unit(|| {}, return_unit), u.into());
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/unused_unit.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ LL | fn return_unit() -> () { () }
| ^^ help: remove the final `()`

error: unneeded `()`
--> $DIR/unused_unit.rs:43:14
--> $DIR/unused_unit.rs:44:14
|
LL | break();
| ^^ help: remove the `()`

error: unneeded `()`
--> $DIR/unused_unit.rs:45:11
--> $DIR/unused_unit.rs:46:11
|
LL | return();
| ^^ help: remove the `()`
Expand Down