about summary refs log tree commit diff
diff options
context:
space:
mode:
authorhkalbasi <hamidrezakalbasi@protonmail.com>2021-10-04 10:03:40 +0330
committerhkalbasi <hamidrezakalbasi@protonmail.com>2021-10-04 22:16:42 +0330
commit388a3d098358edd1f7b83f1f47f1e1e157bad067 (patch)
tree6b69b79f7c3c371dda4a7a4860d4913298a7cda3
parent3311b366e96b38f151a986f18ee0ede093fd04ad (diff)
downloadrust-388a3d098358edd1f7b83f1f47f1e1e157bad067.tar.gz
rust-388a3d098358edd1f7b83f1f47f1e1e157bad067.zip
Implement equatable if let lint
-rw-r--r--CHANGELOG.md1
-rw-r--r--clippy_lints/src/attrs.rs2
-rw-r--r--clippy_lints/src/casts/cast_precision_loss.rs2
-rw-r--r--clippy_lints/src/derive.rs4
-rw-r--r--clippy_lints/src/equatable_if_let.rs100
-rw-r--r--clippy_lints/src/erasing_op.rs2
-rw-r--r--clippy_lints/src/escape.rs2
-rw-r--r--clippy_lints/src/eta_reduction.rs2
-rw-r--r--clippy_lints/src/eval_order_dependence.rs2
-rw-r--r--clippy_lints/src/identity_op.rs14
-rw-r--r--clippy_lints/src/integer_division.rs2
-rw-r--r--clippy_lints/src/len_zero.rs12
-rw-r--r--clippy_lints/src/lib.mods.rs1
-rw-r--r--clippy_lints/src/lib.register_lints.rs1
-rw-r--r--clippy_lints/src/lib.register_nursery.rs1
-rw-r--r--clippy_lints/src/lib.rs1
-rw-r--r--clippy_lints/src/loops/mut_range_bound.rs2
-rw-r--r--clippy_lints/src/loops/needless_range_loop.rs2
-rw-r--r--clippy_lints/src/loops/never_loop.rs2
-rw-r--r--clippy_lints/src/manual_async_fn.rs4
-rw-r--r--clippy_lints/src/methods/or_fun_call.rs14
-rw-r--r--clippy_lints/src/modulo_arithmetic.rs2
-rw-r--r--clippy_lints/src/needless_bool.rs2
-rw-r--r--clippy_lints/src/neg_multiply.rs2
-rw-r--r--clippy_lints/src/new_without_default.rs2
-rw-r--r--clippy_lints/src/non_send_fields_in_send_ty.rs2
-rw-r--r--clippy_lints/src/overflow_check_conditional.rs31
-rw-r--r--clippy_lints/src/redundant_pub_crate.rs36
-rw-r--r--clippy_lints/src/repeat_once.rs2
-rw-r--r--clippy_lints/src/transmuting_null.rs4
-rw-r--r--clippy_lints/src/zero_div_zero.rs2
-rw-r--r--clippy_utils/src/lib.rs2
-rw-r--r--clippy_utils/src/numeric_literal.rs4
-rw-r--r--clippy_utils/src/sugg.rs2
-rw-r--r--clippy_utils/src/usage.rs2
-rw-r--r--tests/ui/branches_sharing_code/shared_at_bottom.rs2
-rw-r--r--tests/ui/collapsible_else_if.fixed2
-rw-r--r--tests/ui/collapsible_else_if.rs2
-rw-r--r--tests/ui/collapsible_if.fixed2
-rw-r--r--tests/ui/collapsible_if.rs2
-rw-r--r--tests/ui/collapsible_match.rs7
-rw-r--r--tests/ui/collapsible_match.stderr40
-rw-r--r--tests/ui/crashes/ice-3462.rs2
-rw-r--r--tests/ui/equatable_if_let.fixed69
-rw-r--r--tests/ui/equatable_if_let.rs69
-rw-r--r--tests/ui/equatable_if_let.stderr64
-rw-r--r--tests/ui/if_same_then_else2.rs1
-rw-r--r--tests/ui/if_same_then_else2.stderr24
-rw-r--r--tests/ui/match_expr_like_matches_macro.fixed2
-rw-r--r--tests/ui/match_expr_like_matches_macro.rs2
-rw-r--r--tests/ui/match_overlapping_arm.rs2
-rw-r--r--tests/ui/match_ref_pats.rs1
-rw-r--r--tests/ui/match_ref_pats.stderr16
-rw-r--r--tests/ui/needless_bool/fixable.fixed1
-rw-r--r--tests/ui/needless_bool/fixable.rs1
-rw-r--r--tests/ui/needless_bool/fixable.stderr24
-rw-r--r--tests/ui/needless_return.fixed7
-rw-r--r--tests/ui/needless_return.rs7
-rw-r--r--tests/ui/needless_return.stderr64
-rw-r--r--tests/ui/option_if_let_else.fixed2
-rw-r--r--tests/ui/option_if_let_else.rs2
-rw-r--r--tests/ui/redundant_pattern_matching_drop_order.fixed2
-rw-r--r--tests/ui/redundant_pattern_matching_drop_order.rs2
-rw-r--r--tests/ui/redundant_pattern_matching_option.fixed1
-rw-r--r--tests/ui/redundant_pattern_matching_option.rs1
-rw-r--r--tests/ui/redundant_pattern_matching_option.stderr38
-rw-r--r--tests/ui/redundant_pattern_matching_poll.fixed1
-rw-r--r--tests/ui/redundant_pattern_matching_poll.rs1
-rw-r--r--tests/ui/redundant_pattern_matching_poll.stderr36
-rw-r--r--tests/ui/while_let_on_iterator.fixed8
-rw-r--r--tests/ui/while_let_on_iterator.rs8
-rw-r--r--tests/ui/while_let_on_iterator.stderr42
72 files changed, 572 insertions, 253 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9a4424f5061..7fdb300c977 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2695,6 +2695,7 @@ Released 2018-09-13
 [`enum_glob_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_glob_use
 [`enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names
 [`eq_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#eq_op
+[`equatable_if_let`]: https://rust-lang.github.io/rust-clippy/master/index.html#equatable_if_let
 [`erasing_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#erasing_op
 [`eval_order_dependence`]: https://rust-lang.github.io/rust-clippy/master/index.html#eval_order_dependence
 [`excessive_precision`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision
diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs
index 2ef7dcc1775..6f8b645dd70 100644
--- a/clippy_lints/src/attrs.rs
+++ b/clippy_lints/src/attrs.rs
@@ -563,7 +563,7 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute) {
             skip_item.path.segments.last().expect("empty path in attribute").ident.name == sym::skip;
         // Only lint outer attributes, because custom inner attributes are unstable
         // Tracking issue: https://github.com/rust-lang/rust/issues/54726
-        if let AttrStyle::Outer = attr.style;
+        if attr.style == AttrStyle::Outer;
         then {
             span_lint_and_sugg(
                 cx,
diff --git a/clippy_lints/src/casts/cast_precision_loss.rs b/clippy_lints/src/casts/cast_precision_loss.rs
index 63ac8fd2dd2..334e1646cd4 100644
--- a/clippy_lints/src/casts/cast_precision_loss.rs
+++ b/clippy_lints/src/casts/cast_precision_loss.rs
@@ -12,7 +12,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca
     }
 
     let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
-    let to_nbits = if let ty::Float(FloatTy::F32) = cast_to.kind() {
+    let to_nbits = if cast_to.kind() == &ty::Float(FloatTy::F32) {
         32
     } else {
         64
diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs
index 8416b8440df..24ac5917dcb 100644
--- a/clippy_lints/src/derive.rs
+++ b/clippy_lints/src/derive.rs
@@ -393,7 +393,7 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
 
         if_chain! {
             if let Some(header) = kind.header();
-            if let Unsafety::Unsafe = header.unsafety;
+            if header.unsafety == Unsafety::Unsafe;
             then {
                 self.has_unsafe = true;
             }
@@ -408,7 +408,7 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
         }
 
         if let ExprKind::Block(block, _) = expr.kind {
-            if let BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) = block.rules {
+            if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) {
                 self.has_unsafe = true;
             }
         }
diff --git a/clippy_lints/src/equatable_if_let.rs b/clippy_lints/src/equatable_if_let.rs
new file mode 100644
index 00000000000..0c6ba91c943
--- /dev/null
+++ b/clippy_lints/src/equatable_if_let.rs
@@ -0,0 +1,100 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::ty::implements_trait;
+use if_chain::if_chain;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind, Pat, PatKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::Ty;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for pattern matchings that can be expressed using equality.
+    ///
+    /// ### Why is this bad?
+    ///
+    /// * It reads better and has less cognitive load because equality won't cause binding.
+    /// * It is a [Yoda condition](https://en.wikipedia.org/wiki/Yoda_conditions). Yoda conditions are widely
+    /// criticized for increasing the cognitive load of reading the code.
+    /// * Equality is a simple bool expression and can be merged with `&&` and `||` and
+    /// reuse if blocks
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// if let Some(2) = x {
+    ///     do_thing();
+    /// }
+    /// ```
+    /// Should be written
+    /// ```rust,ignore
+    /// if x == Some(2) {
+    ///     do_thing();
+    /// }
+    /// ```
+    pub EQUATABLE_IF_LET,
+    nursery,
+    "using pattern matching instead of equality"
+}
+
+declare_lint_pass!(PatternEquality => [EQUATABLE_IF_LET]);
+
+/// detects if pattern matches just one thing
+fn unary_pattern(pat: &Pat<'_>) -> bool {
+    fn array_rec(pats: &[Pat<'_>]) -> bool {
+        pats.iter().all(unary_pattern)
+    }
+    match &pat.kind {
+        PatKind::Slice(_, _, _) | PatKind::Range(_, _, _) | PatKind::Binding(..) | PatKind::Wild | PatKind::Or(_) => {
+            false
+        },
+        PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)),
+        PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => !etc.is_some() && array_rec(a),
+        PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x),
+        PatKind::Path(_) | PatKind::Lit(_) => true,
+    }
+}
+
+fn is_structural_partial_eq(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: Ty<'tcx>) -> bool {
+    if let Some(def_id) = cx.tcx.lang_items().eq_trait() {
+        implements_trait(cx, ty, def_id, &[other.into()])
+    } else {
+        false
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for PatternEquality {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        if_chain! {
+            if let ExprKind::Let(pat, exp, _) = expr.kind;
+            if unary_pattern(pat);
+            let exp_ty = cx.typeck_results().expr_ty(exp);
+            let pat_ty = cx.typeck_results().pat_ty(pat);
+            if is_structural_partial_eq(cx, exp_ty, pat_ty);
+            then {
+
+                let mut applicability = Applicability::MachineApplicable;
+                let pat_str = match pat.kind {
+                    PatKind::Struct(..) => format!(
+                        "({})",
+                        snippet_with_applicability(cx, pat.span, "..", &mut applicability),
+                    ),
+                    _ => snippet_with_applicability(cx, pat.span, "..", &mut applicability).to_string(),
+                };
+                span_lint_and_sugg(
+                    cx,
+                    EQUATABLE_IF_LET,
+                    expr.span,
+                    "this pattern matching can be expressed using equality",
+                    "try",
+                    format!(
+                        "{} == {}",
+                        snippet_with_applicability(cx, exp.span, "..", &mut applicability),
+                        pat_str,
+                    ),
+                    applicability,
+                );
+            }
+        }
+    }
+}
diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs
index 026d14d0ea2..d0944c37cf5 100644
--- a/clippy_lints/src/erasing_op.rs
+++ b/clippy_lints/src/erasing_op.rs
@@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for ErasingOp {
 }
 
 fn check(cx: &LateContext<'_>, e: &Expr<'_>, span: Span) {
-    if let Some(Constant::Int(0)) = constant_simple(cx, cx.typeck_results(), e) {
+    if constant_simple(cx, cx.typeck_results(), e) == Some(Constant::Int(0)) {
         span_lint(
             cx,
             ERASING_OP,
diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs
index 090be73af3b..75b1c882c23 100644
--- a/clippy_lints/src/escape.rs
+++ b/clippy_lints/src/escape.rs
@@ -90,7 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
                 for trait_item in items {
                     if trait_item.id.hir_id() == hir_id {
                         // be sure we have `self` parameter in this function
-                        if let AssocItemKind::Fn { has_self: true } = trait_item.kind {
+                        if trait_item.kind == (AssocItemKind::Fn { has_self: true }) {
                             trait_self_ty = Some(
                                 TraitRef::identity(cx.tcx, trait_item.id.def_id.to_def_id())
                                     .self_ty()
diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs
index 9df92cc5b64..765a6c7585a 100644
--- a/clippy_lints/src/eta_reduction.rs
+++ b/clippy_lints/src/eta_reduction.rs
@@ -116,7 +116,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
                     if let Some(mut snippet) = snippet_opt(cx, callee.span) {
                         if_chain! {
                             if let ty::Closure(_, substs) = callee_ty.peel_refs().kind();
-                            if let ClosureKind::FnMut = substs.as_closure().kind();
+                            if substs.as_closure().kind() == ClosureKind::FnMut;
                             if get_enclosing_loop_or_closure(cx.tcx, expr).is_some()
                                 || UsedAfterExprVisitor::is_found(cx, callee);
 
diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs
index 8714ce90164..1b56dd4b081 100644
--- a/clippy_lints/src/eval_order_dependence.rs
+++ b/clippy_lints/src/eval_order_dependence.rs
@@ -141,7 +141,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
                 match typ.kind() {
                     ty::FnDef(..) | ty::FnPtr(_) => {
                         let sig = typ.fn_sig(self.cx.tcx);
-                        if let ty::Never = self.cx.tcx.erase_late_bound_regions(sig).output().kind() {
+                        if self.cx.tcx.erase_late_bound_regions(sig).output().kind() == &ty::Never {
                             self.report_diverging_sub_expr(e);
                         }
                     },
diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs
index 5feb0ce8dec..73bdd67ff5d 100644
--- a/clippy_lints/src/identity_op.rs
+++ b/clippy_lints/src/identity_op.rs
@@ -1,5 +1,4 @@
 use clippy_utils::source::snippet;
-use if_chain::if_chain;
 use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
@@ -62,16 +61,9 @@ impl<'tcx> LateLintPass<'tcx> for IdentityOp {
 
 fn is_allowed(cx: &LateContext<'_>, cmp: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> bool {
     // `1 << 0` is a common pattern in bit manipulation code
-    if_chain! {
-        if let BinOpKind::Shl = cmp.node;
-        if let Some(Constant::Int(0)) = constant_simple(cx, cx.typeck_results(), right);
-        if let Some(Constant::Int(1)) = constant_simple(cx, cx.typeck_results(), left);
-        then {
-            return true;
-        }
-    }
-
-    false
+    cmp.node == BinOpKind::Shl
+        && constant_simple(cx, cx.typeck_results(), right) == Some(Constant::Int(0))
+        && constant_simple(cx, cx.typeck_results(), left) == Some(Constant::Int(1))
 }
 
 #[allow(clippy::cast_possible_wrap)]
diff --git a/clippy_lints/src/integer_division.rs b/clippy_lints/src/integer_division.rs
index a0e6f12b812..c962e814fa5 100644
--- a/clippy_lints/src/integer_division.rs
+++ b/clippy_lints/src/integer_division.rs
@@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for IntegerDivision {
 fn is_integer_division<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) -> bool {
     if_chain! {
         if let hir::ExprKind::Binary(binop, left, right) = &expr.kind;
-        if let hir::BinOpKind::Div = &binop.node;
+        if binop.node == hir::BinOpKind::Div;
         then {
             let (left_ty, right_ty) = (cx.typeck_results().expr_ty(left), cx.typeck_results().expr_ty(right));
             return left_ty.is_integral() && right_ty.is_integral();
diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs
index a519ad90df5..1811f739421 100644
--- a/clippy_lints/src/len_zero.rs
+++ b/clippy_lints/src/len_zero.rs
@@ -455,14 +455,10 @@ fn is_empty_array(expr: &Expr<'_>) -> bool {
 fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     /// Gets an `AssocItem` and return true if it matches `is_empty(self)`.
     fn is_is_empty(cx: &LateContext<'_>, item: &ty::AssocItem) -> bool {
-        if let ty::AssocKind::Fn = item.kind {
-            if item.ident.name.as_str() == "is_empty" {
-                let sig = cx.tcx.fn_sig(item.def_id);
-                let ty = sig.skip_binder();
-                ty.inputs().len() == 1
-            } else {
-                false
-            }
+        if item.kind == ty::AssocKind::Fn && item.ident.name.as_str() == "is_empty" {
+            let sig = cx.tcx.fn_sig(item.def_id);
+            let ty = sig.skip_binder();
+            ty.inputs().len() == 1
         } else {
             false
         }
diff --git a/clippy_lints/src/lib.mods.rs b/clippy_lints/src/lib.mods.rs
index 7fd84783c22..8e899553e69 100644
--- a/clippy_lints/src/lib.mods.rs
+++ b/clippy_lints/src/lib.mods.rs
@@ -49,6 +49,7 @@ mod entry;
 mod enum_clike;
 mod enum_variants;
 mod eq_op;
+mod equatable_if_let;
 mod erasing_op;
 mod escape;
 mod eta_reduction;
diff --git a/clippy_lints/src/lib.register_lints.rs b/clippy_lints/src/lib.register_lints.rs
index 28d54246fbb..2ba2b3da55c 100644
--- a/clippy_lints/src/lib.register_lints.rs
+++ b/clippy_lints/src/lib.register_lints.rs
@@ -116,6 +116,7 @@ store.register_lints(&[
     enum_variants::MODULE_NAME_REPETITIONS,
     eq_op::EQ_OP,
     eq_op::OP_REF,
+    equatable_if_let::EQUATABLE_IF_LET,
     erasing_op::ERASING_OP,
     escape::BOXED_LOCAL,
     eta_reduction::REDUNDANT_CLOSURE,
diff --git a/clippy_lints/src/lib.register_nursery.rs b/clippy_lints/src/lib.register_nursery.rs
index 32606e570d8..96e0b421094 100644
--- a/clippy_lints/src/lib.register_nursery.rs
+++ b/clippy_lints/src/lib.register_nursery.rs
@@ -8,6 +8,7 @@ store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
     LintId::of(copies::BRANCHES_SHARING_CODE),
     LintId::of(disallowed_method::DISALLOWED_METHOD),
     LintId::of(disallowed_type::DISALLOWED_TYPE),
+    LintId::of(equatable_if_let::EQUATABLE_IF_LET),
     LintId::of(fallible_impl_from::FALLIBLE_IMPL_FROM),
     LintId::of(floating_point_arithmetic::IMPRECISE_FLOPS),
     LintId::of(floating_point_arithmetic::SUBOPTIMAL_FLOPS),
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index c3be6db6ffa..04128c8a0cc 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -485,6 +485,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| Box::new(option_if_let_else::OptionIfLetElse));
     store.register_late_pass(|| Box::new(future_not_send::FutureNotSend));
     store.register_late_pass(|| Box::new(if_let_mutex::IfLetMutex));
+    store.register_late_pass(|| Box::new(equatable_if_let::PatternEquality));
     store.register_late_pass(|| Box::new(mut_mutex_lock::MutMutexLock));
     store.register_late_pass(|| Box::new(match_on_vec_items::MatchOnVecItems));
     store.register_late_pass(|| Box::new(manual_async_fn::ManualAsyncFn));
diff --git a/clippy_lints/src/loops/mut_range_bound.rs b/clippy_lints/src/loops/mut_range_bound.rs
index 358d53e8859..aedf0844937 100644
--- a/clippy_lints/src/loops/mut_range_bound.rs
+++ b/clippy_lints/src/loops/mut_range_bound.rs
@@ -92,7 +92,7 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
     fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
 
     fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) {
-        if let ty::BorrowKind::MutBorrow = bk {
+        if bk == ty::BorrowKind::MutBorrow {
             if let PlaceBase::Local(id) = cmt.place.base {
                 if Some(id) == self.hir_id_low && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
                     self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id));
diff --git a/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs
index 7157b801185..172d9fc39a2 100644
--- a/clippy_lints/src/loops/needless_range_loop.rs
+++ b/clippy_lints/src/loops/needless_range_loop.rs
@@ -95,7 +95,7 @@ pub(super) fn check<'tcx>(
                     let mut take_expr = end;
 
                     if let ExprKind::Binary(ref op, left, right) = end.kind {
-                        if let BinOpKind::Add = op.node {
+                        if op.node == BinOpKind::Add {
                             let start_equal_left = SpanlessEq::new(cx).eq_expr(start, left);
                             let start_equal_right = SpanlessEq::new(cx).eq_expr(start, right);
 
diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs
index 41956650c9f..c0fde5e5166 100644
--- a/clippy_lints/src/loops/never_loop.rs
+++ b/clippy_lints/src/loops/never_loop.rs
@@ -14,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             NeverLoopResult::AlwaysBreak => {
                 span_lint_and_then(cx, NEVER_LOOP, expr.span, "this loop never actually loops", |diag| {
                     if_chain! {
-                        if let LoopSource::ForLoop = source;
+                        if source == LoopSource::ForLoop;
                         if let Some((_, Node::Expr(parent_match))) = cx.tcx.hir().parent_iter(expr.hir_id).nth(1);
                         if let Some(ForLoop { arg: iterator, pat, span: for_span, .. }) = ForLoop::hir(parent_match);
                         then {
diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs
index 8e1385fb83a..b632af455f8 100644
--- a/clippy_lints/src/manual_async_fn.rs
+++ b/clippy_lints/src/manual_async_fn.rs
@@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
     ) {
         if_chain! {
             if let Some(header) = kind.header();
-            if let IsAsync::NotAsync = header.asyncness;
+            if header.asyncness == IsAsync::NotAsync;
             // Check that this function returns `impl Future`
             if let FnRetTy::Return(ret_ty) = decl.output;
             if let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty);
@@ -178,7 +178,7 @@ fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>)
         if args.len() == 1;
         if let Expr{kind: ExprKind::Closure(_, _, body_id, ..), ..} = args[0];
         let closure_body = cx.tcx.hir().body(body_id);
-        if let Some(GeneratorKind::Async(AsyncGeneratorKind::Block)) = closure_body.generator_kind;
+        if closure_body.generator_kind == Some(GeneratorKind::Async(AsyncGeneratorKind::Block));
         then {
             return Some(closure_body);
         }
diff --git a/clippy_lints/src/methods/or_fun_call.rs b/clippy_lints/src/methods/or_fun_call.rs
index 30ed1d665a9..a4d3f0bfb6c 100644
--- a/clippy_lints/src/methods/or_fun_call.rs
+++ b/clippy_lints/src/methods/or_fun_call.rs
@@ -178,15 +178,15 @@ pub(super) fn check<'tcx>(
             hir::ExprKind::Index(..) | hir::ExprKind::MethodCall(..) => {
                 check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None);
             },
-            hir::ExprKind::Block(block, _) => {
-                if let BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) = block.rules {
-                    if let Some(block_expr) = block.expr {
-                        if let hir::ExprKind::MethodCall(..) = block_expr.kind {
-                            check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None);
-                        }
+            hir::ExprKind::Block(block, _)
+                if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) =>
+            {
+                if let Some(block_expr) = block.expr {
+                    if let hir::ExprKind::MethodCall(..) = block_expr.kind {
+                        check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None);
                     }
                 }
-            },
+            }
             _ => (),
         }
     }
diff --git a/clippy_lints/src/modulo_arithmetic.rs b/clippy_lints/src/modulo_arithmetic.rs
index 2d14943b56c..f45e68233a1 100644
--- a/clippy_lints/src/modulo_arithmetic.rs
+++ b/clippy_lints/src/modulo_arithmetic.rs
@@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for ModuloArithmetic {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         match &expr.kind {
             ExprKind::Binary(op, lhs, rhs) | ExprKind::AssignOp(op, lhs, rhs) => {
-                if let BinOpKind::Rem = op.node {
+                if op.node == BinOpKind::Rem {
                     let lhs_operand = analyze_operand(lhs, cx, expr);
                     let rhs_operand = analyze_operand(rhs, cx, expr);
                     if_chain! {
diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs
index c9dd94400ef..91944653500 100644
--- a/clippy_lints/src/needless_bool.rs
+++ b/clippy_lints/src/needless_bool.rs
@@ -248,7 +248,7 @@ fn check_comparison<'a, 'tcx>(
         if l_ty.is_bool() && r_ty.is_bool() {
             let mut applicability = Applicability::MachineApplicable;
 
-            if let BinOpKind::Eq = op.node {
+            if op.node == BinOpKind::Eq {
                 let expression_info = one_side_is_unary_not(left_side, right_side);
                 if expression_info.one_side_is_unary_not {
                     span_lint_and_sugg(
diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs
index fa36d8fb1b3..1b15d29439f 100644
--- a/clippy_lints/src/neg_multiply.rs
+++ b/clippy_lints/src/neg_multiply.rs
@@ -46,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for NegMultiply {
 fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
     if_chain! {
         if let ExprKind::Lit(ref l) = lit.kind;
-        if let Constant::Int(1) = consts::lit_to_constant(&l.node, cx.typeck_results().expr_ty_opt(lit));
+        if consts::lit_to_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)) == Constant::Int(1);
         if cx.typeck_results().expr_ty(exp).is_integral();
         then {
             span_lint(cx, NEG_MULTIPLY, span, "negation by multiplying with `-1`");
diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs
index 0ad616a39d2..0ac27f1cba2 100644
--- a/clippy_lints/src/new_without_default.rs
+++ b/clippy_lints/src/new_without_default.rs
@@ -69,7 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
         }) = item.kind
         {
             for assoc_item in items {
-                if let hir::AssocItemKind::Fn { has_self: false } = assoc_item.kind {
+                if assoc_item.kind == (hir::AssocItemKind::Fn { has_self: false }) {
                     let impl_item = cx.tcx.hir().impl_item(assoc_item.id);
                     if in_external_macro(cx.sess(), impl_item.span) {
                         return;
diff --git a/clippy_lints/src/non_send_fields_in_send_ty.rs b/clippy_lints/src/non_send_fields_in_send_ty.rs
index 0dbf296c714..0973e3a1768 100644
--- a/clippy_lints/src/non_send_fields_in_send_ty.rs
+++ b/clippy_lints/src/non_send_fields_in_send_ty.rs
@@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy {
             if let Some(trait_ref) = &hir_impl.of_trait;
             if let Some(trait_id) = trait_ref.trait_def_id();
             if send_trait == trait_id;
-            if let ImplPolarity::Positive = hir_impl.polarity;
+            if hir_impl.polarity == ImplPolarity::Positive;
             if let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.def_id);
             if let self_ty = ty_trait_ref.self_ty();
             if let ty::Adt(adt_def, impl_trait_substs) = self_ty.kind();
diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs
index 34755afdb72..0f9e5ada3a8 100644
--- a/clippy_lints/src/overflow_check_conditional.rs
+++ b/clippy_lints/src/overflow_check_conditional.rs
@@ -26,6 +26,9 @@ declare_clippy_lint! {
 
 declare_lint_pass!(OverflowCheckConditional => [OVERFLOW_CHECK_CONDITIONAL]);
 
+const OVERFLOW_MSG: &str = "you are trying to use classic C overflow conditions that will fail in Rust";
+const UNDERFLOW_MSG: &str = "you are trying to use classic C underflow conditions that will fail in Rust";
+
 impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional {
     // a + b < a, a > a + b, a < a - b, a - b > a
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
@@ -40,17 +43,11 @@ impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional {
             if cx.typeck_results().expr_ty(ident1).is_integral();
             if cx.typeck_results().expr_ty(ident2).is_integral();
             then {
-                if let BinOpKind::Lt = op.node {
-                    if let BinOpKind::Add = op2.node {
-                        span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span,
-                            "you are trying to use classic C overflow conditions that will fail in Rust");
-                    }
+                if op.node == BinOpKind::Lt && op2.node == BinOpKind::Add {
+                    span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, OVERFLOW_MSG);
                 }
-                if let BinOpKind::Gt = op.node {
-                    if let BinOpKind::Sub = op2.node {
-                        span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span,
-                            "you are trying to use classic C underflow conditions that will fail in Rust");
-                    }
+                if op.node == BinOpKind::Gt && op2.node == BinOpKind::Sub {
+                    span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, UNDERFLOW_MSG);
                 }
             }
         }
@@ -65,17 +62,11 @@ impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional {
             if cx.typeck_results().expr_ty(ident1).is_integral();
             if cx.typeck_results().expr_ty(ident2).is_integral();
             then {
-                if let BinOpKind::Gt = op.node {
-                    if let BinOpKind::Add = op2.node {
-                        span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span,
-                            "you are trying to use classic C overflow conditions that will fail in Rust");
-                    }
+                if op.node == BinOpKind::Gt && op2.node == BinOpKind::Add {
+                    span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, OVERFLOW_MSG);
                 }
-                if let BinOpKind::Lt = op.node {
-                    if let BinOpKind::Sub = op2.node {
-                        span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span,
-                            "you are trying to use classic C underflow conditions that will fail in Rust");
-                    }
+                if op.node == BinOpKind::Lt && op2.node == BinOpKind::Sub {
+                    span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, UNDERFLOW_MSG);
                 }
             }
         }
diff --git a/clippy_lints/src/redundant_pub_crate.rs b/clippy_lints/src/redundant_pub_crate.rs
index ed2e1f90fa5..919d4e11e5a 100644
--- a/clippy_lints/src/redundant_pub_crate.rs
+++ b/clippy_lints/src/redundant_pub_crate.rs
@@ -41,25 +41,23 @@ impl_lint_pass!(RedundantPubCrate => [REDUNDANT_PUB_CRATE]);
 impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
         if let VisibilityKind::Crate { .. } = item.vis.node {
-            if !cx.access_levels.is_exported(item.def_id) {
-                if let Some(false) = self.is_exported.last() {
-                    let span = item.span.with_hi(item.ident.span.hi());
-                    let descr = cx.tcx.def_kind(item.def_id).descr(item.def_id.to_def_id());
-                    span_lint_and_then(
-                        cx,
-                        REDUNDANT_PUB_CRATE,
-                        span,
-                        &format!("pub(crate) {} inside private module", descr),
-                        |diag| {
-                            diag.span_suggestion(
-                                item.vis.span,
-                                "consider using",
-                                "pub".to_string(),
-                                Applicability::MachineApplicable,
-                            );
-                        },
-                    );
-                }
+            if !cx.access_levels.is_exported(item.def_id) && self.is_exported.last() == Some(&false) {
+                let span = item.span.with_hi(item.ident.span.hi());
+                let descr = cx.tcx.def_kind(item.def_id).descr(item.def_id.to_def_id());
+                span_lint_and_then(
+                    cx,
+                    REDUNDANT_PUB_CRATE,
+                    span,
+                    &format!("pub(crate) {} inside private module", descr),
+                    |diag| {
+                        diag.span_suggestion(
+                            item.vis.span,
+                            "consider using",
+                            "pub".to_string(),
+                            Applicability::MachineApplicable,
+                        );
+                    },
+                );
             }
         }
 
diff --git a/clippy_lints/src/repeat_once.rs b/clippy_lints/src/repeat_once.rs
index 54b9c8b3275..710de773e9c 100644
--- a/clippy_lints/src/repeat_once.rs
+++ b/clippy_lints/src/repeat_once.rs
@@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce {
         if_chain! {
             if let ExprKind::MethodCall(path, _, [receiver, count], _) = &expr.kind;
             if path.ident.name == sym!(repeat);
-            if let Some(Constant::Int(1)) = constant_context(cx, cx.typeck_results()).expr(count);
+            if constant_context(cx, cx.typeck_results()).expr(count) == Some(Constant::Int(1));
             if !in_macro(receiver.span);
             then {
                 let ty = cx.typeck_results().expr_ty(receiver).peel_refs();
diff --git a/clippy_lints/src/transmuting_null.rs b/clippy_lints/src/transmuting_null.rs
index a67fa792205..ef80663d1da 100644
--- a/clippy_lints/src/transmuting_null.rs
+++ b/clippy_lints/src/transmuting_null.rs
@@ -49,8 +49,8 @@ impl<'tcx> LateLintPass<'tcx> for TransmutingNull {
                 let mut const_eval_context = constant_context(cx, cx.typeck_results());
                 if_chain! {
                     if let ExprKind::Path(ref _qpath) = arg.kind;
-                    let x = const_eval_context.expr(arg);
-                    if let Some(Constant::RawPtr(0)) = x;
+                    if let Some(Constant::RawPtr(x)) = const_eval_context.expr(arg);
+                    if x == 0;
                     then {
                         span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG)
                     }
diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs
index b29ced28ac4..e0746ce4d81 100644
--- a/clippy_lints/src/zero_div_zero.rs
+++ b/clippy_lints/src/zero_div_zero.rs
@@ -32,7 +32,7 @@ impl<'tcx> LateLintPass<'tcx> for ZeroDiv {
         // check for instances of 0.0/0.0
         if_chain! {
             if let ExprKind::Binary(ref op, left, right) = expr.kind;
-            if let BinOpKind::Div = op.node;
+            if op.node == BinOpKind::Div;
             // TODO - constant_simple does not fold many operations involving floats.
             // That's probably fine for this lint - it's pretty unlikely that someone would
             // do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too.
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 231b5b80d18..00cf8a4d077 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -1508,7 +1508,7 @@ pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tc
 
     if let ExprKind::Match(_, arms, ref source) = expr.kind {
         // desugared from a `?` operator
-        if let MatchSource::TryDesugar = *source {
+        if *source == MatchSource::TryDesugar {
             return Some(expr);
         }
 
diff --git a/clippy_utils/src/numeric_literal.rs b/clippy_utils/src/numeric_literal.rs
index 98f65039b7d..7ad21044d7d 100644
--- a/clippy_utils/src/numeric_literal.rs
+++ b/clippy_utils/src/numeric_literal.rs
@@ -74,7 +74,7 @@ impl<'a> NumericLiteral<'a> {
         };
 
         // Grab part of the literal after prefix, if present.
-        let (prefix, mut sans_prefix) = if let Radix::Decimal = radix {
+        let (prefix, mut sans_prefix) = if radix == Radix::Decimal {
             (None, lit)
         } else {
             let (p, s) = lit.split_at(2);
@@ -179,7 +179,7 @@ impl<'a> NumericLiteral<'a> {
 
         // The exponent may have a sign, output it early, otherwise it will be
         // treated as a digit
-        if let Some('-') = digits.clone().next() {
+        if digits.clone().next() == Some('-') {
             let _ = digits.next();
             output.push('-');
         }
diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs
index ab05a0b4238..5b0efb1fd71 100644
--- a/clippy_utils/src/sugg.rs
+++ b/clippy_utils/src/sugg.rs
@@ -311,7 +311,7 @@ impl<'a> Sugg<'a> {
 /// Return `true` if `sugg` is enclosed in parenthesis.
 fn has_enclosing_paren(sugg: impl AsRef<str>) -> bool {
     let mut chars = sugg.as_ref().chars();
-    if let Some('(') = chars.next() {
+    if chars.next() == Some('(') {
         let mut depth = 1;
         for c in &mut chars {
             if c == '(' {
diff --git a/clippy_utils/src/usage.rs b/clippy_utils/src/usage.rs
index 098ec175fe2..34206b5ae2b 100644
--- a/clippy_utils/src/usage.rs
+++ b/clippy_utils/src/usage.rs
@@ -65,7 +65,7 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
     fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
 
     fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, bk: ty::BorrowKind) {
-        if let ty::BorrowKind::MutBorrow = bk {
+        if bk == ty::BorrowKind::MutBorrow {
             self.update(cmt);
         }
     }
diff --git a/tests/ui/branches_sharing_code/shared_at_bottom.rs b/tests/ui/branches_sharing_code/shared_at_bottom.rs
index ce2040bdeb8..12f550d9c9a 100644
--- a/tests/ui/branches_sharing_code/shared_at_bottom.rs
+++ b/tests/ui/branches_sharing_code/shared_at_bottom.rs
@@ -1,4 +1,4 @@
-#![allow(dead_code)]
+#![allow(dead_code, clippy::equatable_if_let)]
 #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
 
 // This tests the branches_sharing_code lint at the end of blocks
diff --git a/tests/ui/collapsible_else_if.fixed b/tests/ui/collapsible_else_if.fixed
index c69a46f0a77..bb6c4c0703d 100644
--- a/tests/ui/collapsible_else_if.fixed
+++ b/tests/ui/collapsible_else_if.fixed
@@ -1,5 +1,5 @@
 // run-rustfix
-#![allow(clippy::assertions_on_constants)]
+#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
 
 #[rustfmt::skip]
 #[warn(clippy::collapsible_if)]
diff --git a/tests/ui/collapsible_else_if.rs b/tests/ui/collapsible_else_if.rs
index 1359c7eb627..6d4f688db8c 100644
--- a/tests/ui/collapsible_else_if.rs
+++ b/tests/ui/collapsible_else_if.rs
@@ -1,5 +1,5 @@
 // run-rustfix
-#![allow(clippy::assertions_on_constants)]
+#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
 
 #[rustfmt::skip]
 #[warn(clippy::collapsible_if)]
diff --git a/tests/ui/collapsible_if.fixed b/tests/ui/collapsible_if.fixed
index e4c088bf6f0..5b0e4a473c4 100644
--- a/tests/ui/collapsible_if.fixed
+++ b/tests/ui/collapsible_if.fixed
@@ -1,5 +1,5 @@
 // run-rustfix
-#![allow(clippy::assertions_on_constants)]
+#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
 
 #[rustfmt::skip]
 #[warn(clippy::collapsible_if)]
diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs
index d6cf01c8319..cd231a5d7ab 100644
--- a/tests/ui/collapsible_if.rs
+++ b/tests/ui/collapsible_if.rs
@@ -1,5 +1,5 @@
 // run-rustfix
-#![allow(clippy::assertions_on_constants)]
+#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
 
 #[rustfmt::skip]
 #[warn(clippy::collapsible_if)]
diff --git a/tests/ui/collapsible_match.rs b/tests/ui/collapsible_match.rs
index 4ce365cc764..603ae7dc9eb 100644
--- a/tests/ui/collapsible_match.rs
+++ b/tests/ui/collapsible_match.rs
@@ -1,5 +1,10 @@
 #![warn(clippy::collapsible_match)]
-#![allow(clippy::needless_return, clippy::no_effect, clippy::single_match)]
+#![allow(
+    clippy::needless_return,
+    clippy::no_effect,
+    clippy::single_match,
+    clippy::equatable_if_let
+)]
 
 fn lint_cases(opt_opt: Option<Option<u32>>, res_opt: Result<Option<u32>, String>) {
     // match without block
diff --git a/tests/ui/collapsible_match.stderr b/tests/ui/collapsible_match.stderr
index c119570e8ab..5f18b693502 100644
--- a/tests/ui/collapsible_match.stderr
+++ b/tests/ui/collapsible_match.stderr
@@ -1,5 +1,5 @@
 error: this `match` can be collapsed into the outer `match`
-  --> $DIR/collapsible_match.rs:7:20
+  --> $DIR/collapsible_match.rs:12:20
    |
 LL |           Ok(val) => match val {
    |  ____________________^
@@ -10,7 +10,7 @@ LL | |         },
    |
    = note: `-D clippy::collapsible-match` implied by `-D warnings`
 help: the outer pattern can be modified to include the inner pattern
-  --> $DIR/collapsible_match.rs:7:12
+  --> $DIR/collapsible_match.rs:12:12
    |
 LL |         Ok(val) => match val {
    |            ^^^ replace this binding
@@ -18,7 +18,7 @@ LL |             Some(n) => foo(n),
    |             ^^^^^^^ with this pattern
 
 error: this `match` can be collapsed into the outer `match`
-  --> $DIR/collapsible_match.rs:16:20
+  --> $DIR/collapsible_match.rs:21:20
    |
 LL |           Ok(val) => match val {
    |  ____________________^
@@ -28,7 +28,7 @@ LL | |         },
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> $DIR/collapsible_match.rs:16:12
+  --> $DIR/collapsible_match.rs:21:12
    |
 LL |         Ok(val) => match val {
    |            ^^^ replace this binding
@@ -36,7 +36,7 @@ LL |             Some(n) => foo(n),
    |             ^^^^^^^ with this pattern
 
 error: this `if let` can be collapsed into the outer `if let`
-  --> $DIR/collapsible_match.rs:25:9
+  --> $DIR/collapsible_match.rs:30:9
    |
 LL | /         if let Some(n) = val {
 LL | |             take(n);
@@ -44,7 +44,7 @@ LL | |         }
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> $DIR/collapsible_match.rs:24:15
+  --> $DIR/collapsible_match.rs:29:15
    |
 LL |     if let Ok(val) = res_opt {
    |               ^^^ replace this binding
@@ -52,7 +52,7 @@ LL |         if let Some(n) = val {
    |                ^^^^^^^ with this pattern
 
 error: this `if let` can be collapsed into the outer `if let`
-  --> $DIR/collapsible_match.rs:32:9
+  --> $DIR/collapsible_match.rs:37:9
    |
 LL | /         if let Some(n) = val {
 LL | |             take(n);
@@ -62,7 +62,7 @@ LL | |         }
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> $DIR/collapsible_match.rs:31:15
+  --> $DIR/collapsible_match.rs:36:15
    |
 LL |     if let Ok(val) = res_opt {
    |               ^^^ replace this binding
@@ -70,7 +70,7 @@ LL |         if let Some(n) = val {
    |                ^^^^^^^ with this pattern
 
 error: this `match` can be collapsed into the outer `if let`
-  --> $DIR/collapsible_match.rs:43:9
+  --> $DIR/collapsible_match.rs:48:9
    |
 LL | /         match val {
 LL | |             Some(n) => foo(n),
@@ -79,7 +79,7 @@ LL | |         }
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> $DIR/collapsible_match.rs:42:15
+  --> $DIR/collapsible_match.rs:47:15
    |
 LL |     if let Ok(val) = res_opt {
    |               ^^^ replace this binding
@@ -88,7 +88,7 @@ LL |             Some(n) => foo(n),
    |             ^^^^^^^ with this pattern
 
 error: this `if let` can be collapsed into the outer `match`
-  --> $DIR/collapsible_match.rs:52:13
+  --> $DIR/collapsible_match.rs:57:13
    |
 LL | /             if let Some(n) = val {
 LL | |                 take(n);
@@ -96,7 +96,7 @@ LL | |             }
    | |_____________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> $DIR/collapsible_match.rs:51:12
+  --> $DIR/collapsible_match.rs:56:12
    |
 LL |         Ok(val) => {
    |            ^^^ replace this binding
@@ -104,7 +104,7 @@ LL |             if let Some(n) = val {
    |                    ^^^^^^^ with this pattern
 
 error: this `match` can be collapsed into the outer `if let`
-  --> $DIR/collapsible_match.rs:61:9
+  --> $DIR/collapsible_match.rs:66:9
    |
 LL | /         match val {
 LL | |             Some(n) => foo(n),
@@ -113,7 +113,7 @@ LL | |         }
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> $DIR/collapsible_match.rs:60:15
+  --> $DIR/collapsible_match.rs:65:15
    |
 LL |     if let Ok(val) = res_opt {
    |               ^^^ replace this binding
@@ -122,7 +122,7 @@ LL |             Some(n) => foo(n),
    |             ^^^^^^^ with this pattern
 
 error: this `if let` can be collapsed into the outer `match`
-  --> $DIR/collapsible_match.rs:72:13
+  --> $DIR/collapsible_match.rs:77:13
    |
 LL | /             if let Some(n) = val {
 LL | |                 take(n);
@@ -132,7 +132,7 @@ LL | |             }
    | |_____________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> $DIR/collapsible_match.rs:71:12
+  --> $DIR/collapsible_match.rs:76:12
    |
 LL |         Ok(val) => {
    |            ^^^ replace this binding
@@ -140,7 +140,7 @@ LL |             if let Some(n) = val {
    |                    ^^^^^^^ with this pattern
 
 error: this `match` can be collapsed into the outer `match`
-  --> $DIR/collapsible_match.rs:83:20
+  --> $DIR/collapsible_match.rs:88:20
    |
 LL |           Ok(val) => match val {
    |  ____________________^
@@ -150,7 +150,7 @@ LL | |         },
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> $DIR/collapsible_match.rs:83:12
+  --> $DIR/collapsible_match.rs:88:12
    |
 LL |         Ok(val) => match val {
    |            ^^^ replace this binding
@@ -158,7 +158,7 @@ LL |             Some(n) => foo(n),
    |             ^^^^^^^ with this pattern
 
 error: this `match` can be collapsed into the outer `match`
-  --> $DIR/collapsible_match.rs:92:22
+  --> $DIR/collapsible_match.rs:97:22
    |
 LL |           Some(val) => match val {
    |  ______________________^
@@ -168,7 +168,7 @@ LL | |         },
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> $DIR/collapsible_match.rs:92:14
+  --> $DIR/collapsible_match.rs:97:14
    |
 LL |         Some(val) => match val {
    |              ^^^ replace this binding
diff --git a/tests/ui/crashes/ice-3462.rs b/tests/ui/crashes/ice-3462.rs
index 7d62e315da2..02c49aa0d7c 100644
--- a/tests/ui/crashes/ice-3462.rs
+++ b/tests/ui/crashes/ice-3462.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::all)]
-#![allow(clippy::blacklisted_name)]
+#![allow(clippy::blacklisted_name, clippy::equatable_if_let)]
 #![allow(unused)]
 
 /// Test for https://github.com/rust-lang/rust-clippy/issues/3462
diff --git a/tests/ui/equatable_if_let.fixed b/tests/ui/equatable_if_let.fixed
new file mode 100644
index 00000000000..ba72cc237b4
--- /dev/null
+++ b/tests/ui/equatable_if_let.fixed
@@ -0,0 +1,69 @@
+// run-rustfix
+
+#![allow(unused_variables, dead_code)]
+#![warn(clippy::equatable_if_let)]
+
+use std::cmp::Ordering;
+
+#[derive(PartialEq)]
+enum Enum {
+    TupleVariant(i32, u64),
+    RecordVariant { a: i64, b: u32 },
+    UnitVariant,
+    Recursive(Struct),
+}
+
+#[derive(PartialEq)]
+struct Struct {
+    a: i32,
+    b: bool,
+}
+
+enum NotPartialEq {
+    A,
+    B,
+}
+
+enum NotStructuralEq {
+    A,
+    B,
+}
+
+impl PartialEq for NotStructuralEq {
+    fn eq(&self, _: &NotStructuralEq) -> bool {
+        false
+    }
+}
+
+fn main() {
+    let a = 2;
+    let b = 3;
+    let c = Some(2);
+    let d = Struct { a: 2, b: false };
+    let e = Enum::UnitVariant;
+    let f = NotPartialEq::A;
+    let g = NotStructuralEq::A;
+
+    // true
+
+    if a == 2 {}
+    if a.cmp(&b) == Ordering::Greater {}
+    if c == Some(2) {}
+    if d == (Struct { a: 2, b: false }) {}
+    if e == Enum::TupleVariant(32, 64) {}
+    if e == (Enum::RecordVariant { a: 64, b: 32 }) {}
+    if e == Enum::UnitVariant {}
+    if (e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false }) {}
+
+    // false
+
+    if let 2 | 3 = a {}
+    if let x @ 2 = a {}
+    if let Some(3 | 4) = c {}
+    if let Struct { a, b: false } = d {}
+    if let Struct { a: 2, b: x } = d {}
+    if let NotPartialEq::A = f {}
+    if g == NotStructuralEq::A {}
+    if let Some(NotPartialEq::A) = Some(f) {}
+    if Some(g) == Some(NotStructuralEq::A) {}
+}
diff --git a/tests/ui/equatable_if_let.rs b/tests/ui/equatable_if_let.rs
new file mode 100644
index 00000000000..12526ca193d
--- /dev/null
+++ b/tests/ui/equatable_if_let.rs
@@ -0,0 +1,69 @@
+// run-rustfix
+
+#![allow(unused_variables, dead_code)]
+#![warn(clippy::equatable_if_let)]
+
+use std::cmp::Ordering;
+
+#[derive(PartialEq)]
+enum Enum {
+    TupleVariant(i32, u64),
+    RecordVariant { a: i64, b: u32 },
+    UnitVariant,
+    Recursive(Struct),
+}
+
+#[derive(PartialEq)]
+struct Struct {
+    a: i32,
+    b: bool,
+}
+
+enum NotPartialEq {
+    A,
+    B,
+}
+
+enum NotStructuralEq {
+    A,
+    B,
+}
+
+impl PartialEq for NotStructuralEq {
+    fn eq(&self, _: &NotStructuralEq) -> bool {
+        false
+    }
+}
+
+fn main() {
+    let a = 2;
+    let b = 3;
+    let c = Some(2);
+    let d = Struct { a: 2, b: false };
+    let e = Enum::UnitVariant;
+    let f = NotPartialEq::A;
+    let g = NotStructuralEq::A;
+
+    // true
+
+    if let 2 = a {}
+    if let Ordering::Greater = a.cmp(&b) {}
+    if let Some(2) = c {}
+    if let Struct { a: 2, b: false } = d {}
+    if let Enum::TupleVariant(32, 64) = e {}
+    if let Enum::RecordVariant { a: 64, b: 32 } = e {}
+    if let Enum::UnitVariant = e {}
+    if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {}
+
+    // false
+
+    if let 2 | 3 = a {}
+    if let x @ 2 = a {}
+    if let Some(3 | 4) = c {}
+    if let Struct { a, b: false } = d {}
+    if let Struct { a: 2, b: x } = d {}
+    if let NotPartialEq::A = f {}
+    if let NotStructuralEq::A = g {}
+    if let Some(NotPartialEq::A) = Some(f) {}
+    if let Some(NotStructuralEq::A) = Some(g) {}
+}
diff --git a/tests/ui/equatable_if_let.stderr b/tests/ui/equatable_if_let.stderr
new file mode 100644
index 00000000000..79ef919384d
--- /dev/null
+++ b/tests/ui/equatable_if_let.stderr
@@ -0,0 +1,64 @@
+error: this pattern matching can be expressed using equality
+  --> $DIR/equatable_if_let.rs:49:8
+   |
+LL |     if let 2 = a {}
+   |        ^^^^^^^^^ help: try: `a == 2`
+   |
+   = note: `-D clippy::equatable-if-let` implied by `-D warnings`
+
+error: this pattern matching can be expressed using equality
+  --> $DIR/equatable_if_let.rs:50:8
+   |
+LL |     if let Ordering::Greater = a.cmp(&b) {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.cmp(&b) == Ordering::Greater`
+
+error: this pattern matching can be expressed using equality
+  --> $DIR/equatable_if_let.rs:51:8
+   |
+LL |     if let Some(2) = c {}
+   |        ^^^^^^^^^^^^^^^ help: try: `c == Some(2)`
+
+error: this pattern matching can be expressed using equality
+  --> $DIR/equatable_if_let.rs:52:8
+   |
+LL |     if let Struct { a: 2, b: false } = d {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `d == (Struct { a: 2, b: false })`
+
+error: this pattern matching can be expressed using equality
+  --> $DIR/equatable_if_let.rs:53:8
+   |
+LL |     if let Enum::TupleVariant(32, 64) = e {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::TupleVariant(32, 64)`
+
+error: this pattern matching can be expressed using equality
+  --> $DIR/equatable_if_let.rs:54:8
+   |
+LL |     if let Enum::RecordVariant { a: 64, b: 32 } = e {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == (Enum::RecordVariant { a: 64, b: 32 })`
+
+error: this pattern matching can be expressed using equality
+  --> $DIR/equatable_if_let.rs:55:8
+   |
+LL |     if let Enum::UnitVariant = e {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::UnitVariant`
+
+error: this pattern matching can be expressed using equality
+  --> $DIR/equatable_if_let.rs:56:8
+   |
+LL |     if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false })`
+
+error: this pattern matching can be expressed using equality
+  --> $DIR/equatable_if_let.rs:66:8
+   |
+LL |     if let NotStructuralEq::A = g {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `g == NotStructuralEq::A`
+
+error: this pattern matching can be expressed using equality
+  --> $DIR/equatable_if_let.rs:68:8
+   |
+LL |     if let Some(NotStructuralEq::A) = Some(g) {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(g) == Some(NotStructuralEq::A)`
+
+error: aborting due to 10 previous errors
+
diff --git a/tests/ui/if_same_then_else2.rs b/tests/ui/if_same_then_else2.rs
index e4dc5b647df..69189d9e0c0 100644
--- a/tests/ui/if_same_then_else2.rs
+++ b/tests/ui/if_same_then_else2.rs
@@ -2,6 +2,7 @@
 #![allow(
     clippy::blacklisted_name,
     clippy::collapsible_else_if,
+    clippy::equatable_if_let,
     clippy::collapsible_if,
     clippy::ifs_same_cond,
     clippy::needless_return,
diff --git a/tests/ui/if_same_then_else2.stderr b/tests/ui/if_same_then_else2.stderr
index 6524be0af85..cac788f859d 100644
--- a/tests/ui/if_same_then_else2.stderr
+++ b/tests/ui/if_same_then_else2.stderr
@@ -1,5 +1,5 @@
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:13:13
+  --> $DIR/if_same_then_else2.rs:14:13
    |
 LL |       if true {
    |  _____________^
@@ -13,7 +13,7 @@ LL | |     } else {
    |
    = note: `-D clippy::if-same-then-else` implied by `-D warnings`
 note: same as this
-  --> $DIR/if_same_then_else2.rs:22:12
+  --> $DIR/if_same_then_else2.rs:23:12
    |
 LL |       } else {
    |  ____________^
@@ -26,7 +26,7 @@ LL | |     }
    | |_____^
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:34:13
+  --> $DIR/if_same_then_else2.rs:35:13
    |
 LL |       if true {
    |  _____________^
@@ -35,7 +35,7 @@ LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:36:12
+  --> $DIR/if_same_then_else2.rs:37:12
    |
 LL |       } else {
    |  ____________^
@@ -45,7 +45,7 @@ LL | |     }
    | |_____^
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:41:13
+  --> $DIR/if_same_then_else2.rs:42:13
    |
 LL |       if true {
    |  _____________^
@@ -54,7 +54,7 @@ LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:43:12
+  --> $DIR/if_same_then_else2.rs:44:12
    |
 LL |       } else {
    |  ____________^
@@ -64,7 +64,7 @@ LL | |     }
    | |_____^
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:91:21
+  --> $DIR/if_same_then_else2.rs:92:21
    |
 LL |       let _ = if true {
    |  _____________________^
@@ -73,7 +73,7 @@ LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:93:12
+  --> $DIR/if_same_then_else2.rs:94:12
    |
 LL |       } else {
    |  ____________^
@@ -83,7 +83,7 @@ LL | |     };
    | |_____^
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:98:13
+  --> $DIR/if_same_then_else2.rs:99:13
    |
 LL |       if true {
    |  _____________^
@@ -92,7 +92,7 @@ LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:100:12
+  --> $DIR/if_same_then_else2.rs:101:12
    |
 LL |       } else {
    |  ____________^
@@ -102,7 +102,7 @@ LL | |     }
    | |_____^
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:122:20
+  --> $DIR/if_same_then_else2.rs:123:20
    |
 LL |       } else if true {
    |  ____________________^
@@ -112,7 +112,7 @@ LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:125:12
+  --> $DIR/if_same_then_else2.rs:126:12
    |
 LL |       } else {
    |  ____________^
diff --git a/tests/ui/match_expr_like_matches_macro.fixed b/tests/ui/match_expr_like_matches_macro.fixed
index 319299862a7..c611f76bf96 100644
--- a/tests/ui/match_expr_like_matches_macro.fixed
+++ b/tests/ui/match_expr_like_matches_macro.fixed
@@ -1,7 +1,7 @@
 // run-rustfix
 
 #![warn(clippy::match_like_matches_macro)]
-#![allow(unreachable_patterns, dead_code)]
+#![allow(unreachable_patterns, dead_code, clippy::equatable_if_let)]
 
 fn main() {
     let x = Some(5);
diff --git a/tests/ui/match_expr_like_matches_macro.rs b/tests/ui/match_expr_like_matches_macro.rs
index 2ef6cf42387..2deeb84e741 100644
--- a/tests/ui/match_expr_like_matches_macro.rs
+++ b/tests/ui/match_expr_like_matches_macro.rs
@@ -1,7 +1,7 @@
 // run-rustfix
 
 #![warn(clippy::match_like_matches_macro)]
-#![allow(unreachable_patterns, dead_code)]
+#![allow(unreachable_patterns, dead_code, clippy::equatable_if_let)]
 
 fn main() {
     let x = Some(5);
diff --git a/tests/ui/match_overlapping_arm.rs b/tests/ui/match_overlapping_arm.rs
index c84e31ea482..846d665d1d8 100644
--- a/tests/ui/match_overlapping_arm.rs
+++ b/tests/ui/match_overlapping_arm.rs
@@ -2,7 +2,7 @@
 #![feature(half_open_range_patterns)]
 #![warn(clippy::match_overlapping_arm)]
 #![allow(clippy::redundant_pattern_matching)]
-#![allow(clippy::if_same_then_else)]
+#![allow(clippy::if_same_then_else, clippy::equatable_if_let)]
 
 /// Tests for match_overlapping_arm
 
diff --git a/tests/ui/match_ref_pats.rs b/tests/ui/match_ref_pats.rs
index 5de43733ad3..6cbb4d32b0d 100644
--- a/tests/ui/match_ref_pats.rs
+++ b/tests/ui/match_ref_pats.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::match_ref_pats)]
+#![allow(clippy::equatable_if_let)]
 
 fn ref_pats() {
     {
diff --git a/tests/ui/match_ref_pats.stderr b/tests/ui/match_ref_pats.stderr
index a57a338b276..072aff445e9 100644
--- a/tests/ui/match_ref_pats.stderr
+++ b/tests/ui/match_ref_pats.stderr
@@ -1,5 +1,5 @@
 error: you don't need to add `&` to all patterns
-  --> $DIR/match_ref_pats.rs:6:9
+  --> $DIR/match_ref_pats.rs:7:9
    |
 LL | /         match v {
 LL | |             &Some(v) => println!("{:?}", v),
@@ -16,7 +16,7 @@ LL ~             None => println!("none"),
    |
 
 error: you don't need to add `&` to all patterns
-  --> $DIR/match_ref_pats.rs:17:5
+  --> $DIR/match_ref_pats.rs:18:5
    |
 LL | /     match tup {
 LL | |         &(v, 1) => println!("{}", v),
@@ -31,7 +31,7 @@ LL ~         (v, 1) => println!("{}", v),
    |
 
 error: you don't need to add `&` to both the expression and the patterns
-  --> $DIR/match_ref_pats.rs:23:5
+  --> $DIR/match_ref_pats.rs:24:5
    |
 LL | /     match &w {
 LL | |         &Some(v) => println!("{:?}", v),
@@ -47,7 +47,7 @@ LL ~         None => println!("none"),
    |
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/match_ref_pats.rs:35:12
+  --> $DIR/match_ref_pats.rs:36:12
    |
 LL |     if let &None = a {
    |     -------^^^^^---- help: try this: `if a.is_none()`
@@ -55,7 +55,7 @@ LL |     if let &None = a {
    = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: you don't need to add `&` to all patterns
-  --> $DIR/match_ref_pats.rs:35:5
+  --> $DIR/match_ref_pats.rs:36:5
    |
 LL | /     if let &None = a {
 LL | |         println!("none");
@@ -68,13 +68,13 @@ LL |     if let None = *a {
    |            ~~~~   ~~
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/match_ref_pats.rs:40:12
+  --> $DIR/match_ref_pats.rs:41:12
    |
 LL |     if let &None = &b {
    |     -------^^^^^----- help: try this: `if b.is_none()`
 
 error: you don't need to add `&` to both the expression and the patterns
-  --> $DIR/match_ref_pats.rs:40:5
+  --> $DIR/match_ref_pats.rs:41:5
    |
 LL | /     if let &None = &b {
 LL | |         println!("none");
@@ -87,7 +87,7 @@ LL |     if let None = b {
    |            ~~~~   ~
 
 error: you don't need to add `&` to all patterns
-  --> $DIR/match_ref_pats.rs:67:9
+  --> $DIR/match_ref_pats.rs:68:9
    |
 LL | /         match foo_variant!(0) {
 LL | |             &Foo::A => println!("A"),
diff --git a/tests/ui/needless_bool/fixable.fixed b/tests/ui/needless_bool/fixable.fixed
index 639eac8b8b3..a2e3988daff 100644
--- a/tests/ui/needless_bool/fixable.fixed
+++ b/tests/ui/needless_bool/fixable.fixed
@@ -6,6 +6,7 @@
     dead_code,
     clippy::no_effect,
     clippy::if_same_then_else,
+    clippy::equatable_if_let,
     clippy::needless_return,
     clippy::self_named_constructors
 )]
diff --git a/tests/ui/needless_bool/fixable.rs b/tests/ui/needless_bool/fixable.rs
index a3ce086a1c9..75805e85789 100644
--- a/tests/ui/needless_bool/fixable.rs
+++ b/tests/ui/needless_bool/fixable.rs
@@ -6,6 +6,7 @@
     dead_code,
     clippy::no_effect,
     clippy::if_same_then_else,
+    clippy::equatable_if_let,
     clippy::needless_return,
     clippy::self_named_constructors
 )]
diff --git a/tests/ui/needless_bool/fixable.stderr b/tests/ui/needless_bool/fixable.stderr
index 8026d643c44..1fa12add167 100644
--- a/tests/ui/needless_bool/fixable.stderr
+++ b/tests/ui/needless_bool/fixable.stderr
@@ -1,5 +1,5 @@
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:40:5
+  --> $DIR/fixable.rs:41:5
    |
 LL | /     if x {
 LL | |         true
@@ -11,7 +11,7 @@ LL | |     };
    = note: `-D clippy::needless-bool` implied by `-D warnings`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:45:5
+  --> $DIR/fixable.rs:46:5
    |
 LL | /     if x {
 LL | |         false
@@ -21,7 +21,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `!x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:50:5
+  --> $DIR/fixable.rs:51:5
    |
 LL | /     if x && y {
 LL | |         false
@@ -31,7 +31,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `!(x && y)`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:70:5
+  --> $DIR/fixable.rs:71:5
    |
 LL | /     if x {
 LL | |         return true;
@@ -41,7 +41,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:78:5
+  --> $DIR/fixable.rs:79:5
    |
 LL | /     if x {
 LL | |         return false;
@@ -51,7 +51,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return !x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:86:5
+  --> $DIR/fixable.rs:87:5
    |
 LL | /     if x && y {
 LL | |         return true;
@@ -61,7 +61,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return x && y`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:94:5
+  --> $DIR/fixable.rs:95:5
    |
 LL | /     if x && y {
 LL | |         return false;
@@ -71,7 +71,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return !(x && y)`
 
 error: equality checks against true are unnecessary
-  --> $DIR/fixable.rs:102:8
+  --> $DIR/fixable.rs:103:8
    |
 LL |     if x == true {};
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
@@ -79,25 +79,25 @@ LL |     if x == true {};
    = note: `-D clippy::bool-comparison` implied by `-D warnings`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/fixable.rs:106:8
+  --> $DIR/fixable.rs:107:8
    |
 LL |     if x == false {};
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: equality checks against true are unnecessary
-  --> $DIR/fixable.rs:116:8
+  --> $DIR/fixable.rs:117:8
    |
 LL |     if x == true {};
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/fixable.rs:117:8
+  --> $DIR/fixable.rs:118:8
    |
 LL |     if x == false {};
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:126:12
+  --> $DIR/fixable.rs:127:12
    |
 LL |       } else if returns_bool() {
    |  ____________^
diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed
index 37efa6274df..9c999e12b4c 100644
--- a/tests/ui/needless_return.fixed
+++ b/tests/ui/needless_return.fixed
@@ -3,7 +3,12 @@
 
 #![feature(let_else)]
 #![allow(unused)]
-#![allow(clippy::if_same_then_else, clippy::single_match, clippy::needless_bool)]
+#![allow(
+    clippy::if_same_then_else,
+    clippy::single_match,
+    clippy::needless_bool,
+    clippy::equatable_if_let
+)]
 #![warn(clippy::needless_return)]
 
 macro_rules! the_answer {
diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs
index cbf384ac9e4..da7dcf4f0a9 100644
--- a/tests/ui/needless_return.rs
+++ b/tests/ui/needless_return.rs
@@ -3,7 +3,12 @@
 
 #![feature(let_else)]
 #![allow(unused)]
-#![allow(clippy::if_same_then_else, clippy::single_match, clippy::needless_bool)]
+#![allow(
+    clippy::if_same_then_else,
+    clippy::single_match,
+    clippy::needless_bool,
+    clippy::equatable_if_let
+)]
 #![warn(clippy::needless_return)]
 
 macro_rules! the_answer {
diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr
index 7ce7028bbae..2e802cff1e6 100644
--- a/tests/ui/needless_return.stderr
+++ b/tests/ui/needless_return.stderr
@@ -1,5 +1,5 @@
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:20:5
+  --> $DIR/needless_return.rs:25:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
@@ -7,187 +7,187 @@ LL |     return true;
    = note: `-D clippy::needless-return` implied by `-D warnings`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:24:5
+  --> $DIR/needless_return.rs:29:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:29:9
+  --> $DIR/needless_return.rs:34:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:31:9
+  --> $DIR/needless_return.rs:36:9
    |
 LL |         return false;
    |         ^^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:37:17
+  --> $DIR/needless_return.rs:42:17
    |
 LL |         true => return false,
    |                 ^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:39:13
+  --> $DIR/needless_return.rs:44:13
    |
 LL |             return true;
    |             ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:46:9
+  --> $DIR/needless_return.rs:51:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:48:16
+  --> $DIR/needless_return.rs:53:16
    |
 LL |     let _ = || return true;
    |                ^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:56:5
+  --> $DIR/needless_return.rs:61:5
    |
 LL |     return;
    |     ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:61:9
+  --> $DIR/needless_return.rs:66:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:63:9
+  --> $DIR/needless_return.rs:68:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:70:14
+  --> $DIR/needless_return.rs:75:14
    |
 LL |         _ => return,
    |              ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:85:9
+  --> $DIR/needless_return.rs:90:9
    |
 LL |         return String::from("test");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:87:9
+  --> $DIR/needless_return.rs:92:9
    |
 LL |         return String::new();
    |         ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:108:32
+  --> $DIR/needless_return.rs:113:32
    |
 LL |         bar.unwrap_or_else(|_| return)
    |                                ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:113:13
+  --> $DIR/needless_return.rs:118:13
    |
 LL |             return;
    |             ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:115:20
+  --> $DIR/needless_return.rs:120:20
    |
 LL |         let _ = || return;
    |                    ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:121:32
+  --> $DIR/needless_return.rs:126:32
    |
 LL |         res.unwrap_or_else(|_| return Foo)
    |                                ^^^^^^^^^^ help: remove `return`: `Foo`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:130:5
+  --> $DIR/needless_return.rs:135:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:134:5
+  --> $DIR/needless_return.rs:139:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:139:9
+  --> $DIR/needless_return.rs:144:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:141:9
+  --> $DIR/needless_return.rs:146:9
    |
 LL |         return false;
    |         ^^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:147:17
+  --> $DIR/needless_return.rs:152:17
    |
 LL |         true => return false,
    |                 ^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:149:13
+  --> $DIR/needless_return.rs:154:13
    |
 LL |             return true;
    |             ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:156:9
+  --> $DIR/needless_return.rs:161:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:158:16
+  --> $DIR/needless_return.rs:163:16
    |
 LL |     let _ = || return true;
    |                ^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:166:5
+  --> $DIR/needless_return.rs:171:5
    |
 LL |     return;
    |     ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:171:9
+  --> $DIR/needless_return.rs:176:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:173:9
+  --> $DIR/needless_return.rs:178:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:180:14
+  --> $DIR/needless_return.rs:185:14
    |
 LL |         _ => return,
    |              ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:195:9
+  --> $DIR/needless_return.rs:200:9
    |
 LL |         return String::from("test");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:197:9
+  --> $DIR/needless_return.rs:202:9
    |
 LL |         return String::new();
    |         ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()`
diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed
index d1815d0aec3..a3ebe5d0703 100644
--- a/tests/ui/option_if_let_else.fixed
+++ b/tests/ui/option_if_let_else.fixed
@@ -2,7 +2,7 @@
 // run-rustfix
 #![warn(clippy::option_if_let_else)]
 #![allow(clippy::redundant_closure)]
-#![allow(clippy::ref_option_ref)]
+#![allow(clippy::ref_option_ref, clippy::equatable_if_let)]
 
 fn bad1(string: Option<&str>) -> (bool, &str) {
     string.map_or((false, "hello"), |x| (true, x))
diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs
index a15627338cb..b11df3db60f 100644
--- a/tests/ui/option_if_let_else.rs
+++ b/tests/ui/option_if_let_else.rs
@@ -2,7 +2,7 @@
 // run-rustfix
 #![warn(clippy::option_if_let_else)]
 #![allow(clippy::redundant_closure)]
-#![allow(clippy::ref_option_ref)]
+#![allow(clippy::ref_option_ref, clippy::equatable_if_let)]
 
 fn bad1(string: Option<&str>) -> (bool, &str) {
     if let Some(x) = string {
diff --git a/tests/ui/redundant_pattern_matching_drop_order.fixed b/tests/ui/redundant_pattern_matching_drop_order.fixed
index 794ed542435..ce3229f1759 100644
--- a/tests/ui/redundant_pattern_matching_drop_order.fixed
+++ b/tests/ui/redundant_pattern_matching_drop_order.fixed
@@ -2,7 +2,7 @@
 
 // Issue #5746
 #![warn(clippy::redundant_pattern_matching)]
-#![allow(clippy::if_same_then_else)]
+#![allow(clippy::if_same_then_else, clippy::equatable_if_let)]
 use std::task::Poll::{Pending, Ready};
 
 fn main() {
diff --git a/tests/ui/redundant_pattern_matching_drop_order.rs b/tests/ui/redundant_pattern_matching_drop_order.rs
index b9c82d86f61..29b8543cf47 100644
--- a/tests/ui/redundant_pattern_matching_drop_order.rs
+++ b/tests/ui/redundant_pattern_matching_drop_order.rs
@@ -2,7 +2,7 @@
 
 // Issue #5746
 #![warn(clippy::redundant_pattern_matching)]
-#![allow(clippy::if_same_then_else)]
+#![allow(clippy::if_same_then_else, clippy::equatable_if_let)]
 use std::task::Poll::{Pending, Ready};
 
 fn main() {
diff --git a/tests/ui/redundant_pattern_matching_option.fixed b/tests/ui/redundant_pattern_matching_option.fixed
index 99714477266..813e268a60c 100644
--- a/tests/ui/redundant_pattern_matching_option.fixed
+++ b/tests/ui/redundant_pattern_matching_option.fixed
@@ -6,6 +6,7 @@
     unused_must_use,
     clippy::needless_bool,
     clippy::match_like_matches_macro,
+    clippy::equatable_if_let,
     clippy::if_same_then_else
 )]
 
diff --git a/tests/ui/redundant_pattern_matching_option.rs b/tests/ui/redundant_pattern_matching_option.rs
index 8309847e181..82a98468943 100644
--- a/tests/ui/redundant_pattern_matching_option.rs
+++ b/tests/ui/redundant_pattern_matching_option.rs
@@ -6,6 +6,7 @@
     unused_must_use,
     clippy::needless_bool,
     clippy::match_like_matches_macro,
+    clippy::equatable_if_let,
     clippy::if_same_then_else
 )]
 
diff --git a/tests/ui/redundant_pattern_matching_option.stderr b/tests/ui/redundant_pattern_matching_option.stderr
index 613a30d4a48..3a58e5ad7be 100644
--- a/tests/ui/redundant_pattern_matching_option.stderr
+++ b/tests/ui/redundant_pattern_matching_option.stderr
@@ -1,5 +1,5 @@
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:13:12
+  --> $DIR/redundant_pattern_matching_option.rs:14:12
    |
 LL |     if let None = None::<()> {}
    |     -------^^^^------------- help: try this: `if None::<()>.is_none()`
@@ -7,43 +7,43 @@ LL |     if let None = None::<()> {}
    = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:15:12
+  --> $DIR/redundant_pattern_matching_option.rs:16:12
    |
 LL |     if let Some(_) = Some(42) {}
    |     -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:17:12
+  --> $DIR/redundant_pattern_matching_option.rs:18:12
    |
 LL |     if let Some(_) = Some(42) {
    |     -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:23:15
+  --> $DIR/redundant_pattern_matching_option.rs:24:15
    |
 LL |     while let Some(_) = Some(42) {}
    |     ----------^^^^^^^----------- help: try this: `while Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:25:15
+  --> $DIR/redundant_pattern_matching_option.rs:26:15
    |
 LL |     while let None = Some(42) {}
    |     ----------^^^^----------- help: try this: `while Some(42).is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:27:15
+  --> $DIR/redundant_pattern_matching_option.rs:28:15
    |
 LL |     while let None = None::<()> {}
    |     ----------^^^^------------- help: try this: `while None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:30:15
+  --> $DIR/redundant_pattern_matching_option.rs:31:15
    |
 LL |     while let Some(_) = v.pop() {
    |     ----------^^^^^^^---------- help: try this: `while v.pop().is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:38:5
+  --> $DIR/redundant_pattern_matching_option.rs:39:5
    |
 LL | /     match Some(42) {
 LL | |         Some(_) => true,
@@ -52,7 +52,7 @@ LL | |     };
    | |_____^ help: try this: `Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:43:5
+  --> $DIR/redundant_pattern_matching_option.rs:44:5
    |
 LL | /     match None::<()> {
 LL | |         Some(_) => false,
@@ -61,7 +61,7 @@ LL | |     };
    | |_____^ help: try this: `None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:48:13
+  --> $DIR/redundant_pattern_matching_option.rs:49:13
    |
 LL |       let _ = match None::<()> {
    |  _____________^
@@ -71,49 +71,49 @@ LL | |     };
    | |_____^ help: try this: `None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:54:20
+  --> $DIR/redundant_pattern_matching_option.rs:55:20
    |
 LL |     let _ = if let Some(_) = opt { true } else { false };
    |             -------^^^^^^^------ help: try this: `if opt.is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:58:20
+  --> $DIR/redundant_pattern_matching_option.rs:59:20
    |
 LL |     let _ = if let Some(_) = gen_opt() {
    |             -------^^^^^^^------------ help: try this: `if gen_opt().is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:60:19
+  --> $DIR/redundant_pattern_matching_option.rs:61:19
    |
 LL |     } else if let None = gen_opt() {
    |            -------^^^^------------ help: try this: `if gen_opt().is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:79:12
+  --> $DIR/redundant_pattern_matching_option.rs:80:12
    |
 LL |     if let Some(_) = Some(42) {}
    |     -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:81:12
+  --> $DIR/redundant_pattern_matching_option.rs:82:12
    |
 LL |     if let None = None::<()> {}
    |     -------^^^^------------- help: try this: `if None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:83:15
+  --> $DIR/redundant_pattern_matching_option.rs:84:15
    |
 LL |     while let Some(_) = Some(42) {}
    |     ----------^^^^^^^----------- help: try this: `while Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:85:15
+  --> $DIR/redundant_pattern_matching_option.rs:86:15
    |
 LL |     while let None = None::<()> {}
    |     ----------^^^^------------- help: try this: `while None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:87:5
+  --> $DIR/redundant_pattern_matching_option.rs:88:5
    |
 LL | /     match Some(42) {
 LL | |         Some(_) => true,
@@ -122,7 +122,7 @@ LL | |     };
    | |_____^ help: try this: `Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:92:5
+  --> $DIR/redundant_pattern_matching_option.rs:93:5
    |
 LL | /     match None::<()> {
 LL | |         Some(_) => false,
diff --git a/tests/ui/redundant_pattern_matching_poll.fixed b/tests/ui/redundant_pattern_matching_poll.fixed
index c2977453804..3645f2c4bfd 100644
--- a/tests/ui/redundant_pattern_matching_poll.fixed
+++ b/tests/ui/redundant_pattern_matching_poll.fixed
@@ -6,6 +6,7 @@
     unused_must_use,
     clippy::needless_bool,
     clippy::match_like_matches_macro,
+    clippy::equatable_if_let,
     clippy::if_same_then_else
 )]
 
diff --git a/tests/ui/redundant_pattern_matching_poll.rs b/tests/ui/redundant_pattern_matching_poll.rs
index 665c8c41750..866c71b7cfa 100644
--- a/tests/ui/redundant_pattern_matching_poll.rs
+++ b/tests/ui/redundant_pattern_matching_poll.rs
@@ -6,6 +6,7 @@
     unused_must_use,
     clippy::needless_bool,
     clippy::match_like_matches_macro,
+    clippy::equatable_if_let,
     clippy::if_same_then_else
 )]
 
diff --git a/tests/ui/redundant_pattern_matching_poll.stderr b/tests/ui/redundant_pattern_matching_poll.stderr
index 5ecf024a733..1b480f3157f 100644
--- a/tests/ui/redundant_pattern_matching_poll.stderr
+++ b/tests/ui/redundant_pattern_matching_poll.stderr
@@ -1,5 +1,5 @@
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:15:12
+  --> $DIR/redundant_pattern_matching_poll.rs:16:12
    |
 LL |     if let Pending = Pending::<()> {}
    |     -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()`
@@ -7,37 +7,37 @@ LL |     if let Pending = Pending::<()> {}
    = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:17:12
+  --> $DIR/redundant_pattern_matching_poll.rs:18:12
    |
 LL |     if let Ready(_) = Ready(42) {}
    |     -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:19:12
+  --> $DIR/redundant_pattern_matching_poll.rs:20:12
    |
 LL |     if let Ready(_) = Ready(42) {
    |     -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:25:15
+  --> $DIR/redundant_pattern_matching_poll.rs:26:15
    |
 LL |     while let Ready(_) = Ready(42) {}
    |     ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:27:15
+  --> $DIR/redundant_pattern_matching_poll.rs:28:15
    |
 LL |     while let Pending = Ready(42) {}
    |     ----------^^^^^^^------------ help: try this: `while Ready(42).is_pending()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:29:15
+  --> $DIR/redundant_pattern_matching_poll.rs:30:15
    |
 LL |     while let Pending = Pending::<()> {}
    |     ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:35:5
+  --> $DIR/redundant_pattern_matching_poll.rs:36:5
    |
 LL | /     match Ready(42) {
 LL | |         Ready(_) => true,
@@ -46,7 +46,7 @@ LL | |     };
    | |_____^ help: try this: `Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:40:5
+  --> $DIR/redundant_pattern_matching_poll.rs:41:5
    |
 LL | /     match Pending::<()> {
 LL | |         Ready(_) => false,
@@ -55,7 +55,7 @@ LL | |     };
    | |_____^ help: try this: `Pending::<()>.is_pending()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:45:13
+  --> $DIR/redundant_pattern_matching_poll.rs:46:13
    |
 LL |       let _ = match Pending::<()> {
    |  _____________^
@@ -65,49 +65,49 @@ LL | |     };
    | |_____^ help: try this: `Pending::<()>.is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:51:20
+  --> $DIR/redundant_pattern_matching_poll.rs:52:20
    |
 LL |     let _ = if let Ready(_) = poll { true } else { false };
    |             -------^^^^^^^^------- help: try this: `if poll.is_ready()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:55:20
+  --> $DIR/redundant_pattern_matching_poll.rs:56:20
    |
 LL |     let _ = if let Ready(_) = gen_poll() {
    |             -------^^^^^^^^------------- help: try this: `if gen_poll().is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:57:19
+  --> $DIR/redundant_pattern_matching_poll.rs:58:19
    |
 LL |     } else if let Pending = gen_poll() {
    |            -------^^^^^^^------------- help: try this: `if gen_poll().is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:73:12
+  --> $DIR/redundant_pattern_matching_poll.rs:74:12
    |
 LL |     if let Ready(_) = Ready(42) {}
    |     -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:75:12
+  --> $DIR/redundant_pattern_matching_poll.rs:76:12
    |
 LL |     if let Pending = Pending::<()> {}
    |     -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:77:15
+  --> $DIR/redundant_pattern_matching_poll.rs:78:15
    |
 LL |     while let Ready(_) = Ready(42) {}
    |     ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:79:15
+  --> $DIR/redundant_pattern_matching_poll.rs:80:15
    |
 LL |     while let Pending = Pending::<()> {}
    |     ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()`
 
 error: redundant pattern matching, consider using `is_ready()`
-  --> $DIR/redundant_pattern_matching_poll.rs:81:5
+  --> $DIR/redundant_pattern_matching_poll.rs:82:5
    |
 LL | /     match Ready(42) {
 LL | |         Ready(_) => true,
@@ -116,7 +116,7 @@ LL | |     };
    | |_____^ help: try this: `Ready(42).is_ready()`
 
 error: redundant pattern matching, consider using `is_pending()`
-  --> $DIR/redundant_pattern_matching_poll.rs:86:5
+  --> $DIR/redundant_pattern_matching_poll.rs:87:5
    |
 LL | /     match Pending::<()> {
 LL | |         Ready(_) => false,
diff --git a/tests/ui/while_let_on_iterator.fixed b/tests/ui/while_let_on_iterator.fixed
index f5a34190902..1e74ad2de65 100644
--- a/tests/ui/while_let_on_iterator.fixed
+++ b/tests/ui/while_let_on_iterator.fixed
@@ -1,7 +1,13 @@
 // run-rustfix
 
 #![warn(clippy::while_let_on_iterator)]
-#![allow(clippy::never_loop, unreachable_code, unused_mut, dead_code)]
+#![allow(
+    clippy::never_loop,
+    unreachable_code,
+    unused_mut,
+    dead_code,
+    clippy::equatable_if_let
+)]
 
 fn base() {
     let mut iter = 1..20;
diff --git a/tests/ui/while_let_on_iterator.rs b/tests/ui/while_let_on_iterator.rs
index 72f34257d1f..69cb636cee8 100644
--- a/tests/ui/while_let_on_iterator.rs
+++ b/tests/ui/while_let_on_iterator.rs
@@ -1,7 +1,13 @@
 // run-rustfix
 
 #![warn(clippy::while_let_on_iterator)]
-#![allow(clippy::never_loop, unreachable_code, unused_mut, dead_code)]
+#![allow(
+    clippy::never_loop,
+    unreachable_code,
+    unused_mut,
+    dead_code,
+    clippy::equatable_if_let
+)]
 
 fn base() {
     let mut iter = 1..20;
diff --git a/tests/ui/while_let_on_iterator.stderr b/tests/ui/while_let_on_iterator.stderr
index 5e2fce4491a..1a11ba26eef 100644
--- a/tests/ui/while_let_on_iterator.stderr
+++ b/tests/ui/while_let_on_iterator.stderr
@@ -1,5 +1,5 @@
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:8:5
+  --> $DIR/while_let_on_iterator.rs:14:5
    |
 LL |     while let Option::Some(x) = iter.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter`
@@ -7,85 +7,85 @@ LL |     while let Option::Some(x) = iter.next() {
    = note: `-D clippy::while-let-on-iterator` implied by `-D warnings`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:13:5
+  --> $DIR/while_let_on_iterator.rs:19:5
    |
 LL |     while let Some(x) = iter.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:18:5
+  --> $DIR/while_let_on_iterator.rs:24:5
    |
 LL |     while let Some(_) = iter.next() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in iter`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:94:9
+  --> $DIR/while_let_on_iterator.rs:100:9
    |
 LL |         while let Some([..]) = it.next() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [..] in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:101:9
+  --> $DIR/while_let_on_iterator.rs:107:9
    |
 LL |         while let Some([_x]) = it.next() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [_x] in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:114:9
+  --> $DIR/while_let_on_iterator.rs:120:9
    |
 LL |         while let Some(x @ [_]) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x @ [_] in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:134:9
+  --> $DIR/while_let_on_iterator.rs:140:9
    |
 LL |         while let Some(_) = y.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in y`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:191:9
+  --> $DIR/while_let_on_iterator.rs:197:9
    |
 LL |         while let Some(m) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:202:5
+  --> $DIR/while_let_on_iterator.rs:208:5
    |
 LL |     while let Some(n) = it.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:204:9
+  --> $DIR/while_let_on_iterator.rs:210:9
    |
 LL |         while let Some(m) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:213:9
+  --> $DIR/while_let_on_iterator.rs:219:9
    |
 LL |         while let Some(m) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:222:9
+  --> $DIR/while_let_on_iterator.rs:228:9
    |
 LL |         while let Some(m) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:239:9
+  --> $DIR/while_let_on_iterator.rs:245:9
    |
 LL |         while let Some(m) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:254:13
+  --> $DIR/while_let_on_iterator.rs:260:13
    |
 LL |             while let Some(i) = self.0.next() {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.by_ref()`
 
 error: manual `!RangeInclusive::contains` implementation
-  --> $DIR/while_let_on_iterator.rs:255:20
+  --> $DIR/while_let_on_iterator.rs:261:20
    |
 LL |                 if i < 3 || i > 7 {
    |                    ^^^^^^^^^^^^^^ help: use: `!(3..=7).contains(&i)`
@@ -93,37 +93,37 @@ LL |                 if i < 3 || i > 7 {
    = note: `-D clippy::manual-range-contains` implied by `-D warnings`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:286:13
+  --> $DIR/while_let_on_iterator.rs:292:13
    |
 LL |             while let Some(i) = self.0.0.0.next() {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.0.0.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:315:5
+  --> $DIR/while_let_on_iterator.rs:321:5
    |
 LL |     while let Some(n) = it.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:327:9
+  --> $DIR/while_let_on_iterator.rs:333:9
    |
 LL |         while let Some(x) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:341:5
+  --> $DIR/while_let_on_iterator.rs:347:5
    |
 LL |     while let Some(x) = it.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:352:5
+  --> $DIR/while_let_on_iterator.rs:358:5
    |
 LL |     while let Some(x) = it.0.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.0.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:371:5
+  --> $DIR/while_let_on_iterator.rs:377:5
    |
 LL |     while let Some(..) = it.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it`