mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-10 15:14:29 +00:00
New lints: impossible_double_const_comparisons
and ineffective_double_const_comparisons
This commit is contained in:
parent
ab1281f54a
commit
046d3df35e
9 changed files with 506 additions and 21 deletions
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
204
clippy_lints/src/operators/double_const_comparison.rs
Normal file
204
clippy_lints/src/operators/double_const_comparison.rs
Normal 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,
|
||||
¬e,
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(()),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
52
tests/ui/double_const_comparisons.rs
Normal file
52
tests/ui/double_const_comparisons.rs
Normal 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;
|
||||
}
|
180
tests/ui/double_const_comparisons.stderr
Normal file
180
tests/ui/double_const_comparisons.stderr
Normal 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
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)`
|
||||
|
|
Loading…
Reference in a new issue