1 //! Lint on unnecessary double comparisons. Some examples:
3 use clippy_utils
::diagnostics
::span_lint_and_sugg
;
4 use clippy_utils
::eq_expr_value
;
5 use clippy_utils
::source
::snippet_with_applicability
;
6 use rustc_errors
::Applicability
;
7 use rustc_hir
::{BinOpKind, Expr, ExprKind}
;
8 use rustc_lint
::{LateContext, LateLintPass}
;
9 use rustc_session
::{declare_lint_pass, declare_tool_lint}
;
10 use rustc_span
::source_map
::Span
;
12 declare_clippy_lint
! {
13 /// **What it does:** Checks for double comparisons that could be simplified to a single expression.
16 /// **Why is this bad?** Readability.
18 /// **Known problems:** None.
24 /// if x == y || x < y {}
27 /// Could be written as:
34 pub DOUBLE_COMPARISONS
,
36 "unnecessary double comparisons that can be simplified"
39 declare_lint_pass
!(DoubleComparisons
=> [DOUBLE_COMPARISONS
]);
41 impl<'tcx
> DoubleComparisons
{
42 #[allow(clippy::similar_names)]
43 fn check_binop(cx
: &LateContext
<'tcx
>, op
: BinOpKind
, lhs
: &'tcx Expr
<'_
>, rhs
: &'tcx Expr
<'_
>, span
: Span
) {
44 let (lkind
, llhs
, lrhs
, rkind
, rlhs
, rrhs
) = match (&lhs
.kind
, &rhs
.kind
) {
45 (ExprKind
::Binary(lb
, llhs
, lrhs
), ExprKind
::Binary(rb
, rlhs
, rrhs
)) => {
46 (lb
.node
, llhs
, lrhs
, rb
.node
, rlhs
, rrhs
)
50 if !(eq_expr_value(cx
, llhs
, rlhs
) && eq_expr_value(cx
, lrhs
, rrhs
)) {
53 macro_rules
! lint_double_comparison
{
55 let mut applicability
= Applicability
::MachineApplicable
;
56 let lhs_str
= snippet_with_applicability(cx
, llhs
.span
, "", &mut applicability
);
57 let rhs_str
= snippet_with_applicability(cx
, lrhs
.span
, "", &mut applicability
);
58 let sugg
= format
!("{} {} {}", lhs_str
, stringify
!($op
), rhs_str
);
63 "this binary expression can be simplified",
71 match (op
, lkind
, rkind
) {
72 (BinOpKind
::Or
, BinOpKind
::Eq
, BinOpKind
::Lt
) | (BinOpKind
::Or
, BinOpKind
::Lt
, BinOpKind
::Eq
) => {
73 lint_double_comparison
!(<=)
75 (BinOpKind
::Or
, BinOpKind
::Eq
, BinOpKind
::Gt
) | (BinOpKind
::Or
, BinOpKind
::Gt
, BinOpKind
::Eq
) => {
76 lint_double_comparison
!(>=)
78 (BinOpKind
::Or
, BinOpKind
::Lt
, BinOpKind
::Gt
) | (BinOpKind
::Or
, BinOpKind
::Gt
, BinOpKind
::Lt
) => {
79 lint_double_comparison
!(!=)
81 (BinOpKind
::And
, BinOpKind
::Le
, BinOpKind
::Ge
) | (BinOpKind
::And
, BinOpKind
::Ge
, BinOpKind
::Le
) => {
82 lint_double_comparison
!(==)
89 impl<'tcx
> LateLintPass
<'tcx
> for DoubleComparisons
{
90 fn check_expr(&mut self, cx
: &LateContext
<'tcx
>, expr
: &'tcx Expr
<'_
>) {
91 if let ExprKind
::Binary(ref kind
, lhs
, rhs
) = expr
.kind
{
92 Self::check_binop(cx
, kind
.node
, lhs
, rhs
, expr
.span
);