From 96be287f12ff4199b3b1005a22a2dd7c1f01f5bf Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 24 Mar 2016 16:29:20 +0100 Subject: [PATCH] detect negations of terminals like a != b vs a == b --- src/booleans.rs | 27 ++++++++++++++++++++++++++- tests/compile-fail/booleans.rs | 18 +++++++++++++++--- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/booleans.rs b/src/booleans.rs index 2de59c9bc597..b43f22973115 100644 --- a/src/booleans.rs +++ b/src/booleans.rs @@ -1,7 +1,8 @@ use rustc::lint::{LintArray, LateLintPass, LateContext, LintPass}; use rustc_front::hir::*; use rustc_front::intravisit::*; -use syntax::ast::LitKind; +use syntax::ast::{LitKind, DUMMY_NODE_ID}; +use syntax::codemap::{DUMMY_SP, dummy_spanned}; use utils::{span_lint_and_then, in_macro, snippet_opt, SpanlessEq}; /// **What it does:** This lint checks for boolean expressions that can be written more concisely @@ -92,6 +93,30 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { #[allow(cast_possible_truncation)] return Ok(Bool::Term(n as u8)); } + let negated = match e.node { + ExprBinary(binop, ref lhs, ref rhs) => { + let mk_expr = |op| Expr { + id: DUMMY_NODE_ID, + span: DUMMY_SP, + attrs: None, + node: ExprBinary(dummy_spanned(op), lhs.clone(), rhs.clone()), + }; + match binop.node { + BiEq => mk_expr(BiNe), + BiNe => mk_expr(BiEq), + BiGt => mk_expr(BiLe), + BiGe => mk_expr(BiLt), + BiLt => mk_expr(BiGe), + BiLe => mk_expr(BiGt), + _ => continue, + } + }, + _ => continue, + }; + if SpanlessEq::new(self.cx).ignore_fn().eq_expr(&negated, expr) { + #[allow(cast_possible_truncation)] + return Ok(Bool::Not(Box::new(Bool::Term(n as u8)))); + } } let n = self.terminals.len(); self.terminals.push(e); diff --git a/tests/compile-fail/booleans.rs b/tests/compile-fail/booleans.rs index 43528f5c5dfc..4ad51226d516 100644 --- a/tests/compile-fail/booleans.rs +++ b/tests/compile-fail/booleans.rs @@ -54,14 +54,26 @@ fn equality_stuff() { let c: i32 = unimplemented!(); let d: i32 = unimplemented!(); let e: i32 = unimplemented!(); - let _ = a == b && a != b; + let _ = a == b && a != b; //~ ERROR this boolean expression contains a logic bug + //|~ HELP for further information visit + //|~ HELP this expression can be optimized out + //|~ HELP it would look like the following + //|~ SUGGESTION let _ = false; let _ = a == b && c == 5 && a == b; //~ ERROR this boolean expression can be simplified //|~ HELP for further information visit //|~ SUGGESTION let _ = c == 5 && a == b; let _ = a == b && c == 5 && b == a; //~ ERROR this boolean expression can be simplified //|~ HELP for further information visit //|~ SUGGESTION let _ = c == 5 && a == b; - let _ = a < b && a >= b; - let _ = a > b && a <= b; + let _ = a < b && a >= b; //~ ERROR this boolean expression contains a logic bug + //|~ HELP for further information visit + //|~ HELP this expression can be optimized out + //|~ HELP it would look like the following + //|~ SUGGESTION let _ = false; + let _ = a > b && a <= b; //~ ERROR this boolean expression contains a logic bug + //|~ HELP for further information visit + //|~ HELP this expression can be optimized out + //|~ HELP it would look like the following + //|~ SUGGESTION let _ = false; let _ = a > b && a == b; }