Support negative ints in manual_range_contains
Fixes issue where ranges containing ints with different signs would be incorrect due to comparing as unsigned.
This commit is contained in:
parent
94623ee882
commit
d10296910f
@ -219,15 +219,17 @@ fn check_possible_range_contains(cx: &LateContext<'_>, op: BinOpKind, l: &Expr<'
|
||||
_ => return,
|
||||
};
|
||||
// value, name, order (higher/lower), inclusiveness
|
||||
if let (Some((lval, lid, name_span, lval_span, lord, linc)), Some((rval, rid, _, rval_span, rord, rinc))) =
|
||||
(check_range_bounds(cx, l), check_range_bounds(cx, r))
|
||||
if let (
|
||||
Some((lval, lexpr, lid, name_span, lval_span, lord, linc)),
|
||||
Some((rval, _, rid, _, rval_span, rord, rinc)),
|
||||
) = (check_range_bounds(cx, l), check_range_bounds(cx, r))
|
||||
{
|
||||
// we only lint comparisons on the same name and with different
|
||||
// direction
|
||||
if lid != rid || lord == rord {
|
||||
return;
|
||||
}
|
||||
let ord = Constant::partial_cmp(cx.tcx, cx.typeck_results().expr_ty(l), &lval, &rval);
|
||||
let ord = Constant::partial_cmp(cx.tcx, cx.typeck_results().expr_ty(lexpr), &lval, &rval);
|
||||
if combine_and && ord == Some(rord) {
|
||||
// order lower bound and upper bound
|
||||
let (l_span, u_span, l_inc, u_inc) = if rord == Ordering::Less {
|
||||
@ -292,7 +294,10 @@ fn check_possible_range_contains(cx: &LateContext<'_>, op: BinOpKind, l: &Expr<'
|
||||
}
|
||||
}
|
||||
|
||||
fn check_range_bounds(cx: &LateContext<'_>, ex: &Expr<'_>) -> Option<(Constant, HirId, Span, Span, Ordering, bool)> {
|
||||
fn check_range_bounds<'a>(
|
||||
cx: &'a LateContext<'_>,
|
||||
ex: &'a Expr<'_>,
|
||||
) -> Option<(Constant, &'a Expr<'a>, HirId, Span, Span, Ordering, bool)> {
|
||||
if let ExprKind::Binary(ref op, l, r) = ex.kind {
|
||||
let (inclusive, ordering) = match op.node {
|
||||
BinOpKind::Gt => (false, Ordering::Greater),
|
||||
@ -303,11 +308,11 @@ fn check_range_bounds(cx: &LateContext<'_>, ex: &Expr<'_>) -> Option<(Constant,
|
||||
};
|
||||
if let Some(id) = path_to_local(l) {
|
||||
if let Some((c, _)) = constant(cx, cx.typeck_results(), r) {
|
||||
return Some((c, id, l.span, r.span, ordering, inclusive));
|
||||
return Some((c, r, id, l.span, r.span, ordering, inclusive));
|
||||
}
|
||||
} else if let Some(id) = path_to_local(r) {
|
||||
if let Some((c, _)) = constant(cx, cx.typeck_results(), l) {
|
||||
return Some((c, id, r.span, l.span, ordering.reverse(), inclusive));
|
||||
return Some((c, l, id, r.span, l.span, ordering.reverse(), inclusive));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -130,12 +130,10 @@ pub fn partial_cmp(tcx: TyCtxt<'_>, cmp_type: Ty<'_>, left: &Self, right: &Self)
|
||||
match (left, right) {
|
||||
(&Self::Str(ref ls), &Self::Str(ref rs)) => Some(ls.cmp(rs)),
|
||||
(&Self::Char(ref l), &Self::Char(ref r)) => Some(l.cmp(r)),
|
||||
(&Self::Int(l), &Self::Int(r)) => {
|
||||
if let ty::Int(int_ty) = *cmp_type.kind() {
|
||||
Some(sext(tcx, l, int_ty).cmp(&sext(tcx, r, int_ty)))
|
||||
} else {
|
||||
Some(l.cmp(&r))
|
||||
}
|
||||
(&Self::Int(l), &Self::Int(r)) => match *cmp_type.kind() {
|
||||
ty::Int(int_ty) => Some(sext(tcx, l, int_ty).cmp(&sext(tcx, r, int_ty))),
|
||||
ty::Uint(_) => Some(l.cmp(&r)),
|
||||
_ => bug!("Not an int type"),
|
||||
},
|
||||
(&Self::F64(l), &Self::F64(r)) => l.partial_cmp(&r),
|
||||
(&Self::F32(l), &Self::F32(r)) => l.partial_cmp(&r),
|
||||
|
@ -6,7 +6,7 @@
|
||||
#[allow(clippy::short_circuit_statement)]
|
||||
#[allow(clippy::unnecessary_operation)]
|
||||
fn main() {
|
||||
let x = 9_u32;
|
||||
let x = 9_i32;
|
||||
|
||||
// order shouldn't matter
|
||||
(8..12).contains(&x);
|
||||
@ -43,6 +43,12 @@ fn main() {
|
||||
let y = 3.;
|
||||
(0. ..1.).contains(&y);
|
||||
!(0. ..=1.).contains(&y);
|
||||
|
||||
// handle negatives #8721
|
||||
(-10..=10).contains(&x);
|
||||
x >= 10 && x <= -10;
|
||||
(-3. ..=3.).contains(&y);
|
||||
y >= 3. && y <= -3.;
|
||||
}
|
||||
|
||||
// Fix #6373
|
||||
|
@ -6,7 +6,7 @@
|
||||
#[allow(clippy::short_circuit_statement)]
|
||||
#[allow(clippy::unnecessary_operation)]
|
||||
fn main() {
|
||||
let x = 9_u32;
|
||||
let x = 9_i32;
|
||||
|
||||
// order shouldn't matter
|
||||
x >= 8 && x < 12;
|
||||
@ -43,6 +43,12 @@ fn main() {
|
||||
let y = 3.;
|
||||
y >= 0. && y < 1.;
|
||||
y < 0. || y > 1.;
|
||||
|
||||
// handle negatives #8721
|
||||
x >= -10 && x <= 10;
|
||||
x >= 10 && x <= -10;
|
||||
y >= -3. && y <= 3.;
|
||||
y >= 3. && y <= -3.;
|
||||
}
|
||||
|
||||
// Fix #6373
|
||||
|
@ -84,5 +84,17 @@ error: manual `!RangeInclusive::contains` implementation
|
||||
LL | y < 0. || y > 1.;
|
||||
| ^^^^^^^^^^^^^^^^ help: use: `!(0. ..=1.).contains(&y)`
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
error: manual `RangeInclusive::contains` implementation
|
||||
--> $DIR/range_contains.rs:48:5
|
||||
|
|
||||
LL | x >= -10 && x <= 10;
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use: `(-10..=10).contains(&x)`
|
||||
|
||||
error: manual `RangeInclusive::contains` implementation
|
||||
--> $DIR/range_contains.rs:50:5
|
||||
|
|
||||
LL | y >= -3. && y <= 3.;
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use: `(-3. ..=3.).contains(&y)`
|
||||
|
||||
error: aborting due to 16 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user