From 12796cd6886989c449e62818fb8f0bb40b9ce41e Mon Sep 17 00:00:00 2001 From: mgr-inz-rafal Date: Mon, 23 Mar 2020 20:29:12 +0100 Subject: [PATCH] Initial lint without suggestion --- clippy_lints/src/needless_bool.rs | 29 ++++++++++++++++++++++++++--- tests/ui/bool_comparison.fixed | 10 ++++++++++ tests/ui/bool_comparison.rs | 10 ++++++++++ tests/ui/bool_comparison.stderr | 18 +++++++++++++++++- 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 19c22d2b791..8de2fe2f3ba 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -3,10 +3,11 @@ //! This lint is **warn** by default use crate::utils::sugg::Sugg; -use crate::utils::{higher, parent_node_is_if_expr, span_lint, span_lint_and_sugg}; +use crate::utils::{higher, parent_node_is_if_expr, span_lint, span_lint_and_help, span_lint_and_sugg}; +use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind}; +use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; @@ -188,6 +189,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { } } +fn is_unary_not<'tcx>(e: &'tcx Expr<'_>) -> bool { + if_chain! { + if let ExprKind::Unary(unop, _) = e.kind; + if let UnOp::UnNot = unop; + then { + return true; + } + }; + false +} + +fn one_side_is_unary_not<'tcx>(left_side: &'tcx Expr<'_>, right_side: &'tcx Expr<'_>) -> bool { + is_unary_not(left_side) ^ is_unary_not(right_side) +} + fn check_comparison<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>, @@ -199,9 +215,16 @@ fn check_comparison<'a, 'tcx>( ) { use self::Expression::{Bool, Other}; - if let ExprKind::Binary(_, ref left_side, ref right_side) = e.kind { + if let ExprKind::Binary(op, ref left_side, ref right_side) = e.kind { let (l_ty, r_ty) = (cx.tables.expr_ty(left_side), cx.tables.expr_ty(right_side)); if l_ty.is_bool() && r_ty.is_bool() { + if_chain! { + if let BinOpKind::Eq = op.node; + if one_side_is_unary_not(&left_side, &right_side); + then { + span_lint_and_help(cx, BOOL_COMPARISON, e.span, "Here comes", "the suggestion"); + } + }; let mut applicability = Applicability::MachineApplicable; match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { (Bool(true), Other) => left_true.map_or((), |(h, m)| { diff --git a/tests/ui/bool_comparison.fixed b/tests/ui/bool_comparison.fixed index 0bd73ec2c10..d217d03ead4 100644 --- a/tests/ui/bool_comparison.fixed +++ b/tests/ui/bool_comparison.fixed @@ -111,3 +111,13 @@ fn issue3703() { if Foo < false {} if false < Foo {} } + +fn issue4983() { + let a = true; + let b = false; + + if a == !b {}; + if !a == b {}; + if a == b {}; + if !a == !b {}; +} diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index 74f504edfd0..c13575eae71 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -111,3 +111,13 @@ fn issue3703() { if Foo < false {} if false < Foo {} } + +fn issue4983() { + let a = true; + let b = false; + + if a == !b {}; + if !a == b {}; + if a == b {}; + if !a == !b {}; +} diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index 2aa070a00f3..cec7b196a23 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -84,5 +84,21 @@ error: order comparisons between booleans can be simplified LL | if x > y { | ^^^^^ help: try simplifying it as shown: `x & !y` -error: aborting due to 14 previous errors +error: Here comes + --> $DIR/bool_comparison.rs:119:8 + | +LL | if a == !b {}; + | ^^^^^^^ + | + = help: the suggestion + +error: Here comes + --> $DIR/bool_comparison.rs:120:8 + | +LL | if !a == b {}; + | ^^^^^^^ + | + = help: the suggestion + +error: aborting due to 16 previous errors