detect negations of terminals like a != b vs a == b

This commit is contained in:
Oliver Schneider 2016-03-24 16:29:20 +01:00
parent 3a0791e680
commit 96be287f12
2 changed files with 41 additions and 4 deletions

View File

@ -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);

View File

@ -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;
}