!(a == b) --> a != b

This commit is contained in:
Oliver Schneider 2016-03-29 17:18:47 +02:00
parent b05dd13f2c
commit e9c87c777c
2 changed files with 51 additions and 17 deletions

View file

@ -129,18 +129,10 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> {
} }
} }
macro_rules! brackets {
($val:expr => $($name:ident),*) => {
match $val {
$($name(_) => true,)*
_ => false,
}
}
}
fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String { fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String {
fn recurse(brackets: bool, cx: &LateContext, suggestion: &Bool, terminals: &[&Expr], mut s: String) -> String { fn recurse(brackets: bool, cx: &LateContext, suggestion: &Bool, terminals: &[&Expr], mut s: String) -> String {
use quine_mc_cluskey::Bool::*; use quine_mc_cluskey::Bool::*;
let snip = |e: &Expr| snippet_opt(cx, e.span).expect("don't try to improve booleans created by macros");
match *suggestion { match *suggestion {
True => { True => {
s.push_str("true"); s.push_str("true");
@ -151,17 +143,59 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String {
s s
}, },
Not(ref inner) => { Not(ref inner) => {
s.push('!'); match **inner {
recurse(brackets!(**inner => And, Or, Term), cx, inner, terminals, s) And(_) | Or(_) => {
s.push('!');
recurse(true, cx, inner, terminals, s)
},
Term(n) => {
match terminals[n as usize].node {
ExprBinary(binop, ref lhs, ref rhs) => {
let op = match binop.node {
BiEq => " != ",
BiNe => " == ",
BiLt => " >= ",
BiGt => " <= ",
BiLe => " > ",
BiGe => " < ",
_ => {
s.push('!');
return recurse(true, cx, inner, terminals, s)
},
};
s.push_str(&snip(lhs));
s.push_str(op);
s.push_str(&snip(rhs));
s
},
_ => {
s.push('!');
recurse(false, cx, inner, terminals, s)
},
}
},
_ => {
s.push('!');
recurse(false, cx, inner, terminals, s)
},
}
}, },
And(ref v) => { And(ref v) => {
if brackets { if brackets {
s.push('('); s.push('(');
} }
s = recurse(brackets!(v[0] => Or), cx, &v[0], terminals, s); if let Or(_) = v[0] {
s = recurse(true, cx, &v[0], terminals, s);
} else {
s = recurse(false, cx, &v[0], terminals, s);
}
for inner in &v[1..] { for inner in &v[1..] {
s.push_str(" && "); s.push_str(" && ");
s = recurse(brackets!(*inner => Or), cx, inner, terminals, s); if let Or(_) = *inner {
s = recurse(true, cx, inner, terminals, s);
} else {
s = recurse(false, cx, inner, terminals, s);
}
} }
if brackets { if brackets {
s.push(')'); s.push(')');
@ -188,7 +222,7 @@ fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String {
s.push('('); s.push('(');
} }
} }
s.push_str(&snippet_opt(cx, terminals[n as usize].span).expect("don't try to improve booleans created by macros")); s.push_str(&snip(&terminals[n as usize]));
if brackets { if brackets {
if let ExprBinary(..) = terminals[n as usize].node { if let ExprBinary(..) = terminals[n as usize].node {
s.push(')'); s.push(')');

View file

@ -66,7 +66,7 @@ fn equality_stuff() {
//~| HELP for further information visit //~| HELP for further information visit
//~| SUGGESTION let _ = a == b && c == 5; //~| SUGGESTION let _ = a == b && c == 5;
//~| HELP try //~| HELP try
//~| SUGGESTION let _ = !(!(c == 5) || !(a == b)); //~| SUGGESTION let _ = !(c != 5 || a != b);
let _ = a < b && a >= b; //~ ERROR this boolean expression contains a logic bug let _ = a < b && a >= b; //~ ERROR this boolean expression contains a logic bug
//~| HELP for further information visit //~| HELP for further information visit
//~| HELP this expression can be optimized out //~| HELP this expression can be optimized out
@ -81,7 +81,7 @@ fn equality_stuff() {
let _ = a != b || !(a != b || c == d); //~ ERROR this boolean expression can be simplified let _ = a != b || !(a != b || c == d); //~ ERROR this boolean expression can be simplified
//~| HELP for further information visit //~| HELP for further information visit
//~| SUGGESTION let _ = !(c == d) || a != b; //~| SUGGESTION let _ = c != d || a != b;
//~| HELP try //~| HELP try
//~| SUGGESTION let _ = !(!(a != b) && c == d); //~| SUGGESTION let _ = !(a == b && c == d);
} }