Fix manual_range_contains with equal precedence

This commit is contained in:
Evan Typanski 2022-05-24 11:50:12 -04:00
parent 050cdd6689
commit 78f7e3745f
4 changed files with 46 additions and 3 deletions

View file

@ -194,7 +194,7 @@ impl<'tcx> LateLintPass<'tcx> for Ranges {
},
ExprKind::Binary(ref op, l, r) => {
if meets_msrv(self.msrv, msrvs::RANGE_CONTAINS) {
check_possible_range_contains(cx, op.node, l, r, expr);
check_possible_range_contains(cx, op.node, l, r, expr, expr.span);
}
},
_ => {},
@ -213,12 +213,12 @@ fn check_possible_range_contains(
left: &Expr<'_>,
right: &Expr<'_>,
expr: &Expr<'_>,
span: Span,
) {
if in_constant(cx, expr.hir_id) {
return;
}
let span = expr.span;
let combine_and = match op {
BinOpKind::And | BinOpKind::BitAnd => true,
BinOpKind::Or | BinOpKind::BitOr => false,
@ -294,6 +294,15 @@ fn check_possible_range_contains(
);
}
}
// If the LHS is the same operator, we have to recurse to get the "real" RHS, since they have
// the same operator precedence.
if let ExprKind::Binary(ref lhs_op, _left, new_lhs) = left.kind {
if op == lhs_op.node {
let new_span = Span::new(new_lhs.span.lo(), right.span.hi(), expr.span.ctxt(), expr.span.parent());
check_possible_range_contains(cx, op, new_lhs, right, expr, new_span);
}
}
}
struct RangeBounds<'a> {

View file

@ -49,6 +49,11 @@ fn main() {
x >= 10 && x <= -10;
(-3. ..=3.).contains(&y);
y >= 3. && y <= -3.;
// Fix #8745
let z = 42;
(0..=10).contains(&x) && (0..=10).contains(&z);
!(0..10).contains(&x) || !(0..10).contains(&z);
}
// Fix #6373

View file

@ -49,6 +49,11 @@ fn main() {
x >= 10 && x <= -10;
y >= -3. && y <= 3.;
y >= 3. && y <= -3.;
// Fix #8745
let z = 42;
(x >= 0) && (x <= 10) && (z >= 0) && (z <= 10);
(x < 0) || (x >= 10) || (z < 0) || (z >= 10);
}
// Fix #6373

View file

@ -96,5 +96,29 @@ error: manual `RangeInclusive::contains` implementation
LL | y >= -3. && y <= 3.;
| ^^^^^^^^^^^^^^^^^^^ help: use: `(-3. ..=3.).contains(&y)`
error: aborting due to 16 previous errors
error: manual `RangeInclusive::contains` implementation
--> $DIR/range_contains.rs:55:30
|
LL | (x >= 0) && (x <= 10) && (z >= 0) && (z <= 10);
| ^^^^^^^^^^^^^^^^^^^^^ help: use: `(0..=10).contains(&z)`
error: manual `RangeInclusive::contains` implementation
--> $DIR/range_contains.rs:55:5
|
LL | (x >= 0) && (x <= 10) && (z >= 0) && (z <= 10);
| ^^^^^^^^^^^^^^^^^^^^^ help: use: `(0..=10).contains(&x)`
error: manual `!Range::contains` implementation
--> $DIR/range_contains.rs:56:29
|
LL | (x < 0) || (x >= 10) || (z < 0) || (z >= 10);
| ^^^^^^^^^^^^^^^^^^^^ help: use: `!(0..10).contains(&z)`
error: manual `!Range::contains` implementation
--> $DIR/range_contains.rs:56:5
|
LL | (x < 0) || (x >= 10) || (z < 0) || (z >= 10);
| ^^^^^^^^^^^^^^^^^^^^ help: use: `!(0..10).contains(&x)`
error: aborting due to 20 previous errors