Skip to content

Commit 12796cd

Browse files
committed
Initial lint without suggestion
1 parent 1ff81c1 commit 12796cd

File tree

4 files changed

+63
-4
lines changed

4 files changed

+63
-4
lines changed

clippy_lints/src/needless_bool.rs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
//! This lint is **warn** by default
44
55
use crate::utils::sugg::Sugg;
6-
use crate::utils::{higher, parent_node_is_if_expr, span_lint, span_lint_and_sugg};
6+
use crate::utils::{higher, parent_node_is_if_expr, span_lint, span_lint_and_help, span_lint_and_sugg};
7+
use if_chain::if_chain;
78
use rustc_ast::ast::LitKind;
89
use rustc_errors::Applicability;
9-
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind};
10+
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp};
1011
use rustc_lint::{LateContext, LateLintPass};
1112
use rustc_session::{declare_lint_pass, declare_tool_lint};
1213
use rustc_span::source_map::Spanned;
@@ -188,6 +189,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison {
188189
}
189190
}
190191

192+
fn is_unary_not<'tcx>(e: &'tcx Expr<'_>) -> bool {
193+
if_chain! {
194+
if let ExprKind::Unary(unop, _) = e.kind;
195+
if let UnOp::UnNot = unop;
196+
then {
197+
return true;
198+
}
199+
};
200+
false
201+
}
202+
203+
fn one_side_is_unary_not<'tcx>(left_side: &'tcx Expr<'_>, right_side: &'tcx Expr<'_>) -> bool {
204+
is_unary_not(left_side) ^ is_unary_not(right_side)
205+
}
206+
191207
fn check_comparison<'a, 'tcx>(
192208
cx: &LateContext<'a, 'tcx>,
193209
e: &'tcx Expr<'_>,
@@ -199,9 +215,16 @@ fn check_comparison<'a, 'tcx>(
199215
) {
200216
use self::Expression::{Bool, Other};
201217

202-
if let ExprKind::Binary(_, ref left_side, ref right_side) = e.kind {
218+
if let ExprKind::Binary(op, ref left_side, ref right_side) = e.kind {
203219
let (l_ty, r_ty) = (cx.tables.expr_ty(left_side), cx.tables.expr_ty(right_side));
204220
if l_ty.is_bool() && r_ty.is_bool() {
221+
if_chain! {
222+
if let BinOpKind::Eq = op.node;
223+
if one_side_is_unary_not(&left_side, &right_side);
224+
then {
225+
span_lint_and_help(cx, BOOL_COMPARISON, e.span, "Here comes", "the suggestion");
226+
}
227+
};
205228
let mut applicability = Applicability::MachineApplicable;
206229
match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) {
207230
(Bool(true), Other) => left_true.map_or((), |(h, m)| {

tests/ui/bool_comparison.fixed

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,13 @@ fn issue3703() {
111111
if Foo < false {}
112112
if false < Foo {}
113113
}
114+
115+
fn issue4983() {
116+
let a = true;
117+
let b = false;
118+
119+
if a == !b {};
120+
if !a == b {};
121+
if a == b {};
122+
if !a == !b {};
123+
}

tests/ui/bool_comparison.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,13 @@ fn issue3703() {
111111
if Foo < false {}
112112
if false < Foo {}
113113
}
114+
115+
fn issue4983() {
116+
let a = true;
117+
let b = false;
118+
119+
if a == !b {};
120+
if !a == b {};
121+
if a == b {};
122+
if !a == !b {};
123+
}

tests/ui/bool_comparison.stderr

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,5 +84,21 @@ error: order comparisons between booleans can be simplified
8484
LL | if x > y {
8585
| ^^^^^ help: try simplifying it as shown: `x & !y`
8686

87-
error: aborting due to 14 previous errors
87+
error: Here comes
88+
--> $DIR/bool_comparison.rs:119:8
89+
|
90+
LL | if a == !b {};
91+
| ^^^^^^^
92+
|
93+
= help: the suggestion
94+
95+
error: Here comes
96+
--> $DIR/bool_comparison.rs:120:8
97+
|
98+
LL | if !a == b {};
99+
| ^^^^^^^
100+
|
101+
= help: the suggestion
102+
103+
error: aborting due to 16 previous errors
88104

0 commit comments

Comments
 (0)