New lints: impossible_double_const_comparisons and ineffective_double_const_comparisons

This commit is contained in:
Morten Lohne 2023-05-29 21:40:28 +02:00
parent ab1281f54a
commit 046d3df35e
9 changed files with 506 additions and 21 deletions

View File

@ -4897,6 +4897,7 @@ Released 2018-09-13
[`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return
[`implicit_saturating_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_saturating_add
[`implicit_saturating_sub`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_saturating_sub
[`impossible_double_const_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#impossible_double_const_comparisons
[`imprecise_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#imprecise_flops
[`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping
[`inconsistent_struct_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor
@ -4905,6 +4906,7 @@ Released 2018-09-13
[`index_refutable_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice
[`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing
[`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask
[`ineffective_double_const_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_double_const_comparisons
[`inefficient_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#inefficient_to_string
[`infallible_destructuring_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#infallible_destructuring_match
[`infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#infinite_iter

View File

@ -518,7 +518,9 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::operators::FLOAT_CMP_CONST_INFO,
crate::operators::FLOAT_EQUALITY_WITHOUT_ABS_INFO,
crate::operators::IDENTITY_OP_INFO,
crate::operators::IMPOSSIBLE_DOUBLE_CONST_COMPARISONS_INFO,
crate::operators::INEFFECTIVE_BIT_MASK_INFO,
crate::operators::INEFFECTIVE_DOUBLE_CONST_COMPARISONS_INFO,
crate::operators::INTEGER_DIVISION_INFO,
crate::operators::MISREFACTORED_ASSIGN_OP_INFO,
crate::operators::MODULO_ARITHMETIC_INFO,

View File

@ -0,0 +1,204 @@
#![allow(clippy::match_same_arms)]
use std::cmp::Ordering;
use clippy_utils::consts;
use clippy_utils::consts::{ConstEvalLateContext, Constant};
use if_chain::if_chain;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{layout::HasTyCtxt, Ty, TypeckResults};
use rustc_span::source_map::{Span, Spanned};
use clippy_utils::diagnostics::span_lint_and_note;
use clippy_utils::source::snippet;
use clippy_utils::SpanlessEq;
use super::IMPOSSIBLE_DOUBLE_CONST_COMPARISONS;
use super::INEFFECTIVE_DOUBLE_CONST_COMPARISONS;
// Extract a comparison between a const and non-const
// Flip yoda conditionals, turnings expressions like `42 < x` into `x > 42`
fn comparison_to_const<'tcx>(
ctx: &mut ConstEvalLateContext<'_, 'tcx>,
typeck: &TypeckResults<'tcx>,
expr: &'tcx Expr<'tcx>,
) -> Option<(CmpOp, &'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Constant, Ty<'tcx>)> {
if_chain! {
if let ExprKind::Binary(operator, left, right) = expr.kind;
if let Ok(cmp_op) = CmpOp::try_from(operator.node);
then {
match (ctx.expr(left), ctx.expr(right)) {
(Some(_), Some(_)) => None,
(_, Some(con)) => Some((cmp_op, left, right, con, typeck.expr_ty(right))),
(Some(con), _) => Some((cmp_op.reverse(), right, left, con, typeck.expr_ty(left))),
_ => None,
}
} else {
None
}
}
}
pub(super) fn check<'tcx>(
cx: &LateContext<'tcx>,
and_op: Spanned<BinOpKind>,
left_cond: &'tcx Expr<'tcx>,
right_cond: &'tcx Expr<'tcx>,
span: Span,
) {
if_chain! {
// Ensure that the binary operator is &&
if and_op.node == BinOpKind::And;
let typeck_results = cx.typeck_results();
let mut const_context = consts::ConstEvalLateContext::new(cx, typeck_results);
// Check that both operands to '&&' compare a non-literal to a literal
if let Some((left_cmp_op, left_expr, left_const_expr, left_const, left_type)) =
comparison_to_const(&mut const_context, typeck_results, left_cond);
if let Some((right_cmp_op, right_expr, right_const_expr, right_const, right_type)) =
comparison_to_const(&mut const_context, typeck_results, right_cond);
if left_type == right_type;
// Check that the same expression is compared in both comparisons
if SpanlessEq::new(cx).eq_expr(left_expr, right_expr);
if !left_expr.can_have_side_effects();
// Compare the two constant expressions
if let Some(ordering) = Constant::partial_cmp(cx.tcx(), left_type, &left_const, &right_const);
// Rule out the `x >= 42 && x <= 42` corner case immediately
// Mostly to simplify the implementation, but it is also covered by `clippy::double_comparisons`
if !matches!(
(&left_cmp_op, &right_cmp_op, ordering),
(CmpOp::Le | CmpOp::Ge, CmpOp::Le | CmpOp::Ge, Ordering::Equal)
);
then {
if left_cmp_op.direction() == right_cmp_op.direction() {
let lhs_str = snippet(cx, left_cond.span, "");
let rhs_str = snippet(cx, right_cond.span, "");
// We already know that either side of `&&` has no effect,
// but emit a different error message depending on which side it is
if left_side_is_useless(left_cmp_op, ordering) {
span_lint_and_note(
cx,
INEFFECTIVE_DOUBLE_CONST_COMPARISONS,
span,
"left-hand side of `&&` operator has no effect",
Some(left_cond.span.until(right_cond.span)),
&format!("`if `{rhs_str}` evaluates to true, {lhs_str}` will always evaluate to true as well"),
);
} else {
span_lint_and_note(
cx,
INEFFECTIVE_DOUBLE_CONST_COMPARISONS,
span,
"right-hand side of `&&` operator has no effect",
Some(and_op.span.to(right_cond.span)),
&format!("`if `{lhs_str}` evaluates to true, {rhs_str}` will always evaluate to true as well"),
);
}
// We could autofix this error but choose not to,
// because code triggering this lint probably not behaving correctly in the first place
}
else if !comparison_is_possible(left_cmp_op.direction(), ordering) {
let expr_str = snippet(cx, left_expr.span, "");
let lhs_str = snippet(cx, left_const_expr.span, "");
let rhs_str = snippet(cx, right_const_expr.span, "");
let note = match ordering {
Ordering::Less => format!("since `{lhs_str}` < `{rhs_str}`, the expression evaluates to false for any value of `{expr_str}`"),
Ordering::Equal => format!("`{expr_str}` cannot simultaneously be greater than and less than `{lhs_str}`"),
Ordering::Greater => format!("since `{lhs_str}` > `{rhs_str}`, the expression evaluates to false for any value of `{expr_str}`"),
};
span_lint_and_note(
cx,
IMPOSSIBLE_DOUBLE_CONST_COMPARISONS,
span,
"boolean expression will never evaluate to 'true'",
None,
&note,
);
};
}
}
}
fn left_side_is_useless(left_cmp_op: CmpOp, ordering: Ordering) -> bool {
// Special-case for equal constants with an inclusive comparison
if ordering == Ordering::Equal {
match left_cmp_op {
CmpOp::Lt | CmpOp::Gt => false,
CmpOp::Le | CmpOp::Ge => true,
}
} else {
match (left_cmp_op.direction(), ordering) {
(CmpOpDirection::Lesser, Ordering::Less) => false,
(CmpOpDirection::Lesser, Ordering::Equal) => false,
(CmpOpDirection::Lesser, Ordering::Greater) => true,
(CmpOpDirection::Greater, Ordering::Less) => true,
(CmpOpDirection::Greater, Ordering::Equal) => false,
(CmpOpDirection::Greater, Ordering::Greater) => false,
}
}
}
fn comparison_is_possible(left_cmp_direction: CmpOpDirection, ordering: Ordering) -> bool {
match (left_cmp_direction, ordering) {
(CmpOpDirection::Lesser, Ordering::Less | Ordering::Equal) => false,
(CmpOpDirection::Lesser, Ordering::Greater) => true,
(CmpOpDirection::Greater, Ordering::Greater | Ordering::Equal) => false,
(CmpOpDirection::Greater, Ordering::Less) => true,
}
}
#[derive(PartialEq, Eq, Clone, Copy)]
enum CmpOpDirection {
Lesser,
Greater,
}
#[derive(Clone, Copy)]
enum CmpOp {
Lt,
Le,
Ge,
Gt,
}
impl CmpOp {
fn reverse(self) -> Self {
match self {
CmpOp::Lt => CmpOp::Gt,
CmpOp::Le => CmpOp::Ge,
CmpOp::Ge => CmpOp::Le,
CmpOp::Gt => CmpOp::Lt,
}
}
fn direction(self) -> CmpOpDirection {
match self {
CmpOp::Lt => CmpOpDirection::Lesser,
CmpOp::Le => CmpOpDirection::Lesser,
CmpOp::Ge => CmpOpDirection::Greater,
CmpOp::Gt => CmpOpDirection::Greater,
}
}
}
impl TryFrom<BinOpKind> for CmpOp {
type Error = ();
fn try_from(bin_op: BinOpKind) -> Result<Self, Self::Error> {
match bin_op {
BinOpKind::Lt => Ok(CmpOp::Lt),
BinOpKind::Le => Ok(CmpOp::Le),
BinOpKind::Ge => Ok(CmpOp::Ge),
BinOpKind::Gt => Ok(CmpOp::Gt),
_ => Err(()),
}
}
}

View File

@ -3,6 +3,7 @@ mod assign_op_pattern;
mod bit_mask;
mod cmp_owned;
mod double_comparison;
mod double_const_comparison;
mod duration_subsec;
mod eq_op;
mod erasing_op;
@ -298,6 +299,43 @@ declare_clippy_lint! {
"unnecessary double comparisons that can be simplified"
}
declare_clippy_lint! {
/// ### What it does
/// Checks for double comparisons that can never succeed
///
/// ### Why is this bad?
/// The whole expression can be replaced by `false`,
/// which is probably not the programmer's intention
///
/// ### Example
/// ```rust
/// status_code <= 400 && status_code > 500;
/// ```
#[clippy::version = "1.71.0"]
pub IMPOSSIBLE_DOUBLE_CONST_COMPARISONS,
correctness,
"default lint description"
}
declare_clippy_lint! {
/// ### What it does
/// Checks for ineffective double comparisons against constants
///
/// ### Why is this bad?
/// Only one of the comparisons has any effect on the result
/// The programmer probably intended to flip one of the comparison operators,
/// or compare a different value entirely
///
/// ### Example
/// ```rust
/// status_code <= 400 && status_code < 500;
/// ```
#[clippy::version = "1.71.0"]
pub INEFFECTIVE_DOUBLE_CONST_COMPARISONS,
correctness,
"default lint description"
}
declare_clippy_lint! {
/// ### What it does
/// Checks for calculation of subsecond microseconds or milliseconds
@ -742,6 +780,8 @@ impl_lint_pass!(Operators => [
INEFFECTIVE_BIT_MASK,
VERBOSE_BIT_MASK,
DOUBLE_COMPARISONS,
IMPOSSIBLE_DOUBLE_CONST_COMPARISONS,
INEFFECTIVE_DOUBLE_CONST_COMPARISONS,
DURATION_SUBSEC,
EQ_OP,
OP_REF,
@ -786,6 +826,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators {
bit_mask::check(cx, e, op.node, lhs, rhs);
verbose_bit_mask::check(cx, e, op.node, lhs, rhs, self.verbose_bit_mask_threshold);
double_comparison::check(cx, op.node, lhs, rhs, e.span);
double_const_comparison::check(cx, op, lhs, rhs, e.span);
duration_subsec::check(cx, e, op.node, lhs, rhs);
float_equality_without_abs::check(cx, e, op.node, lhs, rhs);
integer_division::check(cx, e, op.node, lhs, rhs);

View File

@ -0,0 +1,52 @@
#![allow(unused)]
#![warn(clippy::impossible_double_const_comparisons)]
#![warn(clippy::ineffective_double_const_comparisons)]
#![allow(clippy::no_effect)]
#![allow(clippy::short_circuit_statement)]
#![allow(clippy::manual_range_contains)]
const STATUS_BAD_REQUEST: u16 = 400;
const STATUS_SERVER_ERROR: u16 = 500;
fn main() {
let status_code = 500; // Value doesn't matter for the lint
status_code >= 400 && status_code < 500; // Correct
status_code <= 400 && status_code > 500;
status_code > 500 && status_code < 400;
status_code < 500 && status_code > 500;
// More complex expressions
status_code < { 400 } && status_code > { 500 };
status_code < STATUS_BAD_REQUEST && status_code > STATUS_SERVER_ERROR;
status_code <= u16::MIN + 1 && status_code > STATUS_SERVER_ERROR;
status_code < STATUS_SERVER_ERROR && status_code > STATUS_SERVER_ERROR;
// Yoda conditions
500 <= status_code && 600 > status_code; // Correct
500 <= status_code && status_code <= 600; // Correct
500 >= status_code && 600 < status_code; // Incorrect
500 >= status_code && status_code > 600; // Incorrect
// Expressions where one of the sides has no effect
status_code < 200 && status_code <= 299;
status_code > 200 && status_code >= 299;
status_code >= 500 && status_code > 500; // Useless left
status_code > 500 && status_code >= 500; // Useless right
status_code <= 500 && status_code < 500; // Useless left
status_code < 500 && status_code <= 500; // Useless right
// Other types
let name = "Steve";
name < "Jennifer" && name > "Shannon";
let numbers = [1, 2];
numbers < [3, 4] && numbers > [5, 6];
let letter = 'a';
letter < 'b' && letter > 'c';
let area = 42.0;
area < std::f32::consts::E && area > std::f32::consts::PI;
}

View File

@ -0,0 +1,180 @@
error: boolean expression will never evaluate to 'true'
--> $DIR/double_const_comparisons.rs:15:5
|
LL | status_code <= 400 && status_code > 500;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: since `400` < `500`, the expression evaluates to false for any value of `status_code`
= note: `-D clippy::impossible-double-const-comparisons` implied by `-D warnings`
error: boolean expression will never evaluate to 'true'
--> $DIR/double_const_comparisons.rs:16:5
|
LL | status_code > 500 && status_code < 400;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: since `500` > `400`, the expression evaluates to false for any value of `status_code`
error: boolean expression will never evaluate to 'true'
--> $DIR/double_const_comparisons.rs:17:5
|
LL | status_code < 500 && status_code > 500;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `status_code` cannot simultaneously be greater than and less than `500`
error: boolean expression will never evaluate to 'true'
--> $DIR/double_const_comparisons.rs:20:5
|
LL | status_code < { 400 } && status_code > { 500 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: since `{ 400 }` < `{ 500 }`, the expression evaluates to false for any value of `status_code`
error: boolean expression will never evaluate to 'true'
--> $DIR/double_const_comparisons.rs:21:5
|
LL | status_code < STATUS_BAD_REQUEST && status_code > STATUS_SERVER_ERROR;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: since `STATUS_BAD_REQUEST` < `STATUS_SERVER_ERROR`, the expression evaluates to false for any value of `status_code`
error: boolean expression will never evaluate to 'true'
--> $DIR/double_const_comparisons.rs:22:5
|
LL | status_code <= u16::MIN + 1 && status_code > STATUS_SERVER_ERROR;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: since `u16::MIN + 1` < `STATUS_SERVER_ERROR`, the expression evaluates to false for any value of `status_code`
error: boolean expression will never evaluate to 'true'
--> $DIR/double_const_comparisons.rs:23:5
|
LL | status_code < STATUS_SERVER_ERROR && status_code > STATUS_SERVER_ERROR;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `status_code` cannot simultaneously be greater than and less than `STATUS_SERVER_ERROR`
error: boolean expression will never evaluate to 'true'
--> $DIR/double_const_comparisons.rs:28:5
|
LL | 500 >= status_code && 600 < status_code; // Incorrect
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: since `500` < `600`, the expression evaluates to false for any value of `status_code`
error: boolean expression will never evaluate to 'true'
--> $DIR/double_const_comparisons.rs:29:5
|
LL | 500 >= status_code && status_code > 600; // Incorrect
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: since `500` < `600`, the expression evaluates to false for any value of `status_code`
error: right-hand side of `&&` operator has no effect
--> $DIR/double_const_comparisons.rs:32:5
|
LL | status_code < 200 && status_code <= 299;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `if `status_code < 200` evaluates to true, status_code <= 299` will always evaluate to true as well
--> $DIR/double_const_comparisons.rs:32:23
|
LL | status_code < 200 && status_code <= 299;
| ^^^^^^^^^^^^^^^^^^^^^
= note: `-D clippy::ineffective-double-const-comparisons` implied by `-D warnings`
error: left-hand side of `&&` operator has no effect
--> $DIR/double_const_comparisons.rs:33:5
|
LL | status_code > 200 && status_code >= 299;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `if `status_code >= 299` evaluates to true, status_code > 200` will always evaluate to true as well
--> $DIR/double_const_comparisons.rs:33:5
|
LL | status_code > 200 && status_code >= 299;
| ^^^^^^^^^^^^^^^^^^^^^
error: left-hand side of `&&` operator has no effect
--> $DIR/double_const_comparisons.rs:35:5
|
LL | status_code >= 500 && status_code > 500; // Useless left
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `if `status_code > 500` evaluates to true, status_code >= 500` will always evaluate to true as well
--> $DIR/double_const_comparisons.rs:35:5
|
LL | status_code >= 500 && status_code > 500; // Useless left
| ^^^^^^^^^^^^^^^^^^^^^^
error: right-hand side of `&&` operator has no effect
--> $DIR/double_const_comparisons.rs:36:5
|
LL | status_code > 500 && status_code >= 500; // Useless right
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `if `status_code > 500` evaluates to true, status_code >= 500` will always evaluate to true as well
--> $DIR/double_const_comparisons.rs:36:23
|
LL | status_code > 500 && status_code >= 500; // Useless right
| ^^^^^^^^^^^^^^^^^^^^^
error: left-hand side of `&&` operator has no effect
--> $DIR/double_const_comparisons.rs:37:5
|
LL | status_code <= 500 && status_code < 500; // Useless left
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `if `status_code < 500` evaluates to true, status_code <= 500` will always evaluate to true as well
--> $DIR/double_const_comparisons.rs:37:5
|
LL | status_code <= 500 && status_code < 500; // Useless left
| ^^^^^^^^^^^^^^^^^^^^^^
error: right-hand side of `&&` operator has no effect
--> $DIR/double_const_comparisons.rs:38:5
|
LL | status_code < 500 && status_code <= 500; // Useless right
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `if `status_code < 500` evaluates to true, status_code <= 500` will always evaluate to true as well
--> $DIR/double_const_comparisons.rs:38:23
|
LL | status_code < 500 && status_code <= 500; // Useless right
| ^^^^^^^^^^^^^^^^^^^^^
error: boolean expression will never evaluate to 'true'
--> $DIR/double_const_comparisons.rs:42:5
|
LL | name < "Jennifer" && name > "Shannon";
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: since `"Jennifer"` < `"Shannon"`, the expression evaluates to false for any value of `name`
error: boolean expression will never evaluate to 'true'
--> $DIR/double_const_comparisons.rs:45:5
|
LL | numbers < [3, 4] && numbers > [5, 6];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: since `[3, 4]` < `[5, 6]`, the expression evaluates to false for any value of `numbers`
error: boolean expression will never evaluate to 'true'
--> $DIR/double_const_comparisons.rs:48:5
|
LL | letter < 'b' && letter > 'c';
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: since `'b'` < `'c'`, the expression evaluates to false for any value of `letter`
error: boolean expression will never evaluate to 'true'
--> $DIR/double_const_comparisons.rs:51:5
|
LL | area < std::f32::consts::E && area > std::f32::consts::PI;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: since `std::f32::consts::E` < `std::f32::consts::PI`, the expression evaluates to false for any value of `area`
error: aborting due to 19 previous errors

View File

@ -5,6 +5,8 @@
#![allow(clippy::no_effect)]
#![allow(clippy::short_circuit_statement)]
#![allow(clippy::unnecessary_operation)]
#![allow(clippy::impossible_double_const_comparisons)]
#![allow(clippy::ineffective_double_const_comparisons)]
fn main() {
let x = 9_i32;

View File

@ -5,6 +5,8 @@
#![allow(clippy::no_effect)]
#![allow(clippy::short_circuit_statement)]
#![allow(clippy::unnecessary_operation)]
#![allow(clippy::impossible_double_const_comparisons)]
#![allow(clippy::ineffective_double_const_comparisons)]
fn main() {
let x = 9_i32;

View File

@ -1,5 +1,5 @@
error: manual `Range::contains` implementation
--> $DIR/range_contains.rs:13:5
--> $DIR/range_contains.rs:15:5
|
LL | x >= 8 && x < 12;
| ^^^^^^^^^^^^^^^^ help: use: `(8..12).contains(&x)`
@ -7,121 +7,121 @@ LL | x >= 8 && x < 12;
= note: `-D clippy::manual-range-contains` implied by `-D warnings`
error: manual `Range::contains` implementation
--> $DIR/range_contains.rs:14:5
--> $DIR/range_contains.rs:16:5
|
LL | x < 42 && x >= 21;
| ^^^^^^^^^^^^^^^^^ help: use: `(21..42).contains(&x)`
error: manual `Range::contains` implementation
--> $DIR/range_contains.rs:15:5
--> $DIR/range_contains.rs:17:5
|
LL | 100 > x && 1 <= x;
| ^^^^^^^^^^^^^^^^^ help: use: `(1..100).contains(&x)`
error: manual `RangeInclusive::contains` implementation
--> $DIR/range_contains.rs:18:5
--> $DIR/range_contains.rs:20:5
|
LL | x >= 9 && x <= 99;
| ^^^^^^^^^^^^^^^^^ help: use: `(9..=99).contains(&x)`
error: manual `RangeInclusive::contains` implementation
--> $DIR/range_contains.rs:19:5
--> $DIR/range_contains.rs:21:5
|
LL | x <= 33 && x >= 1;
| ^^^^^^^^^^^^^^^^^ help: use: `(1..=33).contains(&x)`
error: manual `RangeInclusive::contains` implementation
--> $DIR/range_contains.rs:20:5
--> $DIR/range_contains.rs:22:5
|
LL | 999 >= x && 1 <= x;
| ^^^^^^^^^^^^^^^^^^ help: use: `(1..=999).contains(&x)`
error: manual `!Range::contains` implementation
--> $DIR/range_contains.rs:23:5
--> $DIR/range_contains.rs:25:5
|
LL | x < 8 || x >= 12;
| ^^^^^^^^^^^^^^^^ help: use: `!(8..12).contains(&x)`
error: manual `!Range::contains` implementation
--> $DIR/range_contains.rs:24:5
--> $DIR/range_contains.rs:26:5
|
LL | x >= 42 || x < 21;
| ^^^^^^^^^^^^^^^^^ help: use: `!(21..42).contains(&x)`
error: manual `!Range::contains` implementation
--> $DIR/range_contains.rs:25:5
--> $DIR/range_contains.rs:27:5
|
LL | 100 <= x || 1 > x;
| ^^^^^^^^^^^^^^^^^ help: use: `!(1..100).contains(&x)`
error: manual `!RangeInclusive::contains` implementation
--> $DIR/range_contains.rs:28:5
--> $DIR/range_contains.rs:30:5
|
LL | x < 9 || x > 99;
| ^^^^^^^^^^^^^^^ help: use: `!(9..=99).contains(&x)`
error: manual `!RangeInclusive::contains` implementation
--> $DIR/range_contains.rs:29:5
--> $DIR/range_contains.rs:31:5
|
LL | x > 33 || x < 1;
| ^^^^^^^^^^^^^^^ help: use: `!(1..=33).contains(&x)`
error: manual `!RangeInclusive::contains` implementation
--> $DIR/range_contains.rs:30:5
--> $DIR/range_contains.rs:32:5
|
LL | 999 < x || 1 > x;
| ^^^^^^^^^^^^^^^^ help: use: `!(1..=999).contains(&x)`
error: manual `Range::contains` implementation
--> $DIR/range_contains.rs:45:5
--> $DIR/range_contains.rs:47:5
|
LL | y >= 0. && y < 1.;
| ^^^^^^^^^^^^^^^^^ help: use: `(0. ..1.).contains(&y)`
error: manual `!RangeInclusive::contains` implementation
--> $DIR/range_contains.rs:46:5
--> $DIR/range_contains.rs:48:5
|
LL | y < 0. || y > 1.;
| ^^^^^^^^^^^^^^^^ help: use: `!(0. ..=1.).contains(&y)`
error: manual `RangeInclusive::contains` implementation
--> $DIR/range_contains.rs:49:5
--> $DIR/range_contains.rs:51:5
|
LL | x >= -10 && x <= 10;
| ^^^^^^^^^^^^^^^^^^^ help: use: `(-10..=10).contains(&x)`
error: manual `RangeInclusive::contains` implementation
--> $DIR/range_contains.rs:51:5
--> $DIR/range_contains.rs:53:5
|
LL | y >= -3. && y <= 3.;
| ^^^^^^^^^^^^^^^^^^^ help: use: `(-3. ..=3.).contains(&y)`
error: manual `RangeInclusive::contains` implementation
--> $DIR/range_contains.rs:56:30
--> $DIR/range_contains.rs:58: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:56:5
--> $DIR/range_contains.rs:58: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:57:29
--> $DIR/range_contains.rs:59: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:57:5
--> $DIR/range_contains.rs:59: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:76:5
--> $DIR/range_contains.rs:78:5
|
LL | x >= 8 && x < 35;
| ^^^^^^^^^^^^^^^^ help: use: `(8..35).contains(&x)`