make sure a < b and a >= b are considered equal by SpanlessEq

This commit is contained in:
Oliver Schneider 2016-03-24 16:11:38 +01:00
parent 25bbde091a
commit 3a0791e680
3 changed files with 35 additions and 2 deletions

View file

@ -75,7 +75,8 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
} }
(&ExprBlock(ref l), &ExprBlock(ref r)) => self.eq_block(l, r), (&ExprBlock(ref l), &ExprBlock(ref r)) => self.eq_block(l, r),
(&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => {
l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) ||
swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr))
} }
(&ExprBreak(li), &ExprBreak(ri)) => both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()), (&ExprBreak(li), &ExprBreak(ri)) => both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()),
(&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r), (&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r),
@ -197,6 +198,23 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
} }
} }
fn swap_binop<'a>(binop: BinOp_, lhs: &'a Expr, rhs: &'a Expr) -> Option<(BinOp_, &'a Expr, &'a Expr)> {
match binop {
BiAdd |
BiMul |
BiBitXor |
BiBitAnd |
BiEq |
BiNe |
BiBitOr => Some((binop, rhs, lhs)),
BiLt => Some((BiGt, rhs, lhs)),
BiLe => Some((BiGe, rhs, lhs)),
BiGe => Some((BiLe, rhs, lhs)),
BiGt => Some((BiLt, rhs, lhs)),
BiShl | BiShr | BiRem | BiSub | BiDiv | BiAnd | BiOr => None,
}
}
/// Check if the two `Option`s are both `None` or some equal values as per `eq_fn`. /// Check if the two `Option`s are both `None` or some equal values as per `eq_fn`.
fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn: F) -> bool fn both<X, F>(l: &Option<X>, r: &Option<X>, mut eq_fn: F) -> bool
where F: FnMut(&X, &X) -> bool where F: FnMut(&X, &X) -> bool

View file

@ -58,6 +58,9 @@ fn equality_stuff() {
let _ = a == b && c == 5 && a == b; //~ ERROR this boolean expression can be simplified let _ = a == b && c == 5 && a == b; //~ ERROR this boolean expression can be simplified
//|~ HELP for further information visit //|~ HELP for further information visit
//|~ SUGGESTION let _ = c == 5 && a == b; //|~ 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; let _ = a > b && a <= b;
let _ = a > b && a == b; let _ = a > b && a == b;

View file

@ -3,7 +3,7 @@
#[deny(eq_op)] #[deny(eq_op)]
#[allow(identity_op)] #[allow(identity_op)]
#[allow(no_effect)] #[allow(no_effect, unused_variables)]
#[deny(nonminimal_bool)] #[deny(nonminimal_bool)]
fn main() { fn main() {
// simple values and comparisons // simple values and comparisons
@ -43,6 +43,18 @@ fn main() {
true || true; //~ERROR equal expressions true || true; //~ERROR equal expressions
//~|ERROR this boolean expression can be simplified //~|ERROR this boolean expression can be simplified
let a: u32 = unimplemented!();
let b: u32 = unimplemented!();
a == b && b == a; //~ERROR equal expressions
//~|ERROR this boolean expression can be simplified
a != b && b != a; //~ERROR equal expressions
//~|ERROR this boolean expression can be simplified
a < b && b > a; //~ERROR equal expressions
//~|ERROR this boolean expression can be simplified
a <= b && b >= a; //~ERROR equal expressions
//~|ERROR this boolean expression can be simplified
let mut a = vec![1]; let mut a = vec![1];
a == a; //~ERROR equal expressions a == a; //~ERROR equal expressions
2*a.len() == 2*a.len(); // ok, functions 2*a.len() == 2*a.len(); // ok, functions