Skip to content

Commit 32fdb8f

Browse files
committed
Lint on identical variable used as args in assert_eq! macro call
1 parent 6bfc19c commit 32fdb8f

File tree

7 files changed

+72
-3
lines changed

7 files changed

+72
-3
lines changed

clippy_lints/src/eq_op.rs

+36-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
use crate::utils::ast_utils::eq_expr;
12
use crate::utils::{
23
eq_expr_value, implements_trait, in_macro, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then,
34
};
5+
use if_chain::if_chain;
6+
use rustc_ast::{ast, token};
47
use rustc_errors::Applicability;
58
use rustc_hir::{BinOp, BinOpKind, BorrowKind, Expr, ExprKind};
6-
use rustc_lint::{LateContext, LateLintPass};
9+
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
10+
use rustc_parse::parser;
711
use rustc_session::{declare_lint_pass, declare_tool_lint};
812

913
declare_clippy_lint! {
@@ -23,6 +27,12 @@ declare_clippy_lint! {
2327
/// # let x = 1;
2428
/// if x + 1 == x + 1 {}
2529
/// ```
30+
/// or
31+
/// ```rust
32+
/// # let a = 3;
33+
/// # let b = 4;
34+
/// assert_eq!(a, a);
35+
/// ```
2636
pub EQ_OP,
2737
correctness,
2838
"equal operands on both sides of a comparison or bitwise combination (e.g., `x == x`)"
@@ -52,6 +62,31 @@ declare_clippy_lint! {
5262

5363
declare_lint_pass!(EqOp => [EQ_OP, OP_REF]);
5464

65+
impl EarlyLintPass for EqOp {
66+
fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::MacCall) {
67+
if_chain! {
68+
if mac.path == sym!(assert_eq);
69+
let tokens = mac.args.inner_tokens();
70+
let mut parser = parser::Parser::new(&cx.sess.parse_sess, tokens, false, None);
71+
if let Ok(left) = parser.parse_expr();
72+
if parser.eat(&token::Comma);
73+
if let Ok(right) = parser.parse_expr();
74+
let left_expr = left.into_inner();
75+
let right_expr = right.into_inner();
76+
if eq_expr(&left_expr, &right_expr);
77+
78+
then {
79+
span_lint(
80+
cx,
81+
EQ_OP,
82+
left_expr.span.to(right_expr.span),
83+
"identical args used in this `assert_eq!` macro call",
84+
);
85+
}
86+
}
87+
}
88+
}
89+
5590
impl<'tcx> LateLintPass<'tcx> for EqOp {
5691
#[allow(clippy::similar_names, clippy::too_many_lines)]
5792
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {

clippy_lints/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore) {
348348
store.register_pre_expansion_pass(|| box write::Write::default());
349349
store.register_pre_expansion_pass(|| box attrs::EarlyAttributes);
350350
store.register_pre_expansion_pass(|| box dbg_macro::DbgMacro);
351+
store.register_pre_expansion_pass(|| box eq_op::EqOp);
351352
}
352353

353354
#[doc(hidden)]
@@ -910,6 +911,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
910911
let vec_box_size_threshold = conf.vec_box_size_threshold;
911912
store.register_late_pass(move || box types::Types::new(vec_box_size_threshold));
912913
store.register_late_pass(|| box booleans::NonminimalBool);
914+
store.register_early_pass(|| box eq_op::EqOp);
913915
store.register_late_pass(|| box eq_op::EqOp);
914916
store.register_late_pass(|| box enum_clike::UnportableVariant);
915917
store.register_late_pass(|| box float_literal::FloatLiteral);

tests/ui/auxiliary/proc_macro_derive.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#![crate_type = "proc-macro"]
55
#![feature(repr128, proc_macro_quote)]
6+
#![allow(clippy::eq_op)]
67

78
extern crate proc_macro;
89

tests/ui/double_parens.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![warn(clippy::double_parens)]
2-
#![allow(dead_code)]
2+
#![allow(dead_code, clippy::eq_op)]
33
#![feature(custom_inner_attributes)]
44
#![rustfmt::skip]
55

tests/ui/eq_op_early.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![warn(clippy::eq_op)]
2+
3+
fn main() {
4+
let a = 1;
5+
let b = 2;
6+
7+
// lint identical args in `assert_eq!` (see #3574)
8+
assert_eq!(a, a);
9+
assert_eq!(a + 1, a + 1);
10+
11+
// ok
12+
assert_eq!(a, b);
13+
assert_eq!(a, a + 1);
14+
assert_eq!(a + 1, b + 1);
15+
}

tests/ui/eq_op_early.stderr

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: identical args used in this `assert_eq!` macro call
2+
--> $DIR/eq_op_early.rs:8:16
3+
|
4+
LL | assert_eq!(a, a);
5+
| ^^^^
6+
|
7+
= note: `-D clippy::eq-op` implied by `-D warnings`
8+
9+
error: identical args used in this `assert_eq!` macro call
10+
--> $DIR/eq_op_early.rs:9:16
11+
|
12+
LL | assert_eq!(a + 1, a + 1);
13+
| ^^^^^^^^^^^^
14+
15+
error: aborting due to 2 previous errors
16+

tests/ui/used_underscore_binding.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
#![feature(rustc_private)]
55
#![warn(clippy::all)]
6-
#![allow(clippy::blacklisted_name)]
6+
#![allow(clippy::blacklisted_name, clippy::eq_op)]
77
#![warn(clippy::used_underscore_binding)]
88

99
#[macro_use]

0 commit comments

Comments
 (0)