From eb24b764293b613c2d1e5da43920d30826b0c4bd Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 13 Aug 2025 21:16:29 +0200 Subject: [PATCH 1/7] fix `equatable_if_let`: FP in const context --- clippy_lints/src/equatable_if_let.rs | 2 ++ tests/ui/equatable_if_let.fixed | 5 +++++ tests/ui/equatable_if_let.rs | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/clippy_lints/src/equatable_if_let.rs b/clippy_lints/src/equatable_if_let.rs index 72f5eaf8a4bc..ac61d1ca35bc 100644 --- a/clippy_lints/src/equatable_if_let.rs +++ b/clippy_lints/src/equatable_if_let.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_in_const_context; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; @@ -105,6 +106,7 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality { if let ExprKind::Let(let_expr) = expr.kind && unary_pattern(let_expr.pat) && !expr.span.in_external_macro(cx.sess().source_map()) + && !is_in_const_context(cx) { let exp_ty = cx.typeck_results().expr_ty(let_expr.init); let pat_ty = cx.typeck_results().pat_ty(let_expr.pat); diff --git a/tests/ui/equatable_if_let.fixed b/tests/ui/equatable_if_let.fixed index ce8b67f9ca7b..e95fdda60a47 100644 --- a/tests/ui/equatable_if_let.fixed +++ b/tests/ui/equatable_if_let.fixed @@ -139,3 +139,8 @@ mod issue8710 { } } } + +fn issue15376() { + // PartialEq is not stable in consts yet + const _: u32 = if let Some(true) = None { 0 } else { 1 }; +} diff --git a/tests/ui/equatable_if_let.rs b/tests/ui/equatable_if_let.rs index ff09533f2651..17882f9bf9c5 100644 --- a/tests/ui/equatable_if_let.rs +++ b/tests/ui/equatable_if_let.rs @@ -139,3 +139,8 @@ mod issue8710 { } } } + +fn issue15376() { + // PartialEq is not stable in consts yet + const _: u32 = if let Some(true) = None { 0 } else { 1 }; +} From b16e39cee5bed76c8c7547c08b48d5fc14fc0c38 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Thu, 14 Aug 2025 14:27:41 +0200 Subject: [PATCH 2/7] allow when `Partial::eq` is const turns out `is_in_const_context` wasn't even supposed to be put in the main let-chain, since it's only relevant for the `is_structural_partial_eq` case Co-authored-by: yanglsh --- clippy_lints/src/equatable_if_let.rs | 39 +++++++++++++++++++++++----- clippy_lints/src/lib.rs | 2 +- tests/ui/equatable_if_let.fixed | 3 ++- tests/ui/equatable_if_let.rs | 1 + tests/ui/equatable_if_let.stderr | 8 +++++- 5 files changed, 43 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/equatable_if_let.rs b/clippy_lints/src/equatable_if_let.rs index ac61d1ca35bc..0b2d4d36da7f 100644 --- a/clippy_lints/src/equatable_if_let.rs +++ b/clippy_lints/src/equatable_if_let.rs @@ -1,12 +1,15 @@ +use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_in_const_context; +use clippy_utils::msrvs::Msrv; +use clippy_utils::qualify_min_const_fn::is_stable_const_fn; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::Ty; -use rustc_session::declare_lint_pass; +use rustc_session::impl_lint_pass; declare_clippy_lint! { /// ### What it does @@ -38,7 +41,17 @@ declare_clippy_lint! { "using pattern matching instead of equality" } -declare_lint_pass!(PatternEquality => [EQUATABLE_IF_LET]); +impl_lint_pass!(PatternEquality => [EQUATABLE_IF_LET]); + +pub(super) struct PatternEquality { + msrv: Msrv, +} + +impl PatternEquality { + pub(super) fn new(conf: &Conf) -> Self { + Self { msrv: conf.msrv } + } +} /// detects if pattern matches just one thing fn unary_pattern(pat: &Pat<'_>) -> bool { @@ -61,9 +74,22 @@ fn unary_pattern(pat: &Pat<'_>) -> bool { } } -fn is_structural_partial_eq<'tcx>(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()]) +fn is_structural_partial_eq<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: Ty<'tcx>, msrv: Msrv) -> bool { + if let Some(eq_trait) = cx.tcx.lang_items().eq_trait() + && implements_trait(cx, ty, eq_trait, &[other.into()]) + { + if !is_in_const_context(cx) { + return true; + } + + // TODO: add a MSRV test once `eq` becomes stably-const + if let Some(eq_method) = cx.tcx.provided_trait_methods(eq_trait).next() + && is_stable_const_fn(cx, eq_method.def_id, msrv) + { + true + } else { + false + } } else { false } @@ -106,13 +132,12 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality { if let ExprKind::Let(let_expr) = expr.kind && unary_pattern(let_expr.pat) && !expr.span.in_external_macro(cx.sess().source_map()) - && !is_in_const_context(cx) { let exp_ty = cx.typeck_results().expr_ty(let_expr.init); let pat_ty = cx.typeck_results().pat_ty(let_expr.pat); let mut applicability = Applicability::MachineApplicable; - if is_structural_partial_eq(cx, exp_ty, pat_ty) && !contains_type_mismatch(cx, let_expr.pat) { + if is_structural_partial_eq(cx, exp_ty, pat_ty, self.msrv) && !contains_type_mismatch(cx, let_expr.pat) { let pat_str = match let_expr.pat.kind { PatKind::Struct(..) => format!( "({})", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d468993e7444..aa466c52d44c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -648,7 +648,7 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co store.register_late_pass(move |_| Box::new(large_futures::LargeFuture::new(conf))); store.register_late_pass(|_| Box::new(if_let_mutex::IfLetMutex)); store.register_late_pass(|_| Box::new(if_not_else::IfNotElse)); - store.register_late_pass(|_| Box::new(equatable_if_let::PatternEquality)); + store.register_late_pass(|_| Box::new(equatable_if_let::PatternEquality::new(conf))); store.register_late_pass(|_| Box::new(manual_async_fn::ManualAsyncFn)); store.register_late_pass(|_| Box::new(panic_in_result_fn::PanicInResultFn)); store.register_early_pass(move || Box::new(non_expressive_names::NonExpressiveNames::new(conf))); diff --git a/tests/ui/equatable_if_let.fixed b/tests/ui/equatable_if_let.fixed index e95fdda60a47..db4e2dbe3210 100644 --- a/tests/ui/equatable_if_let.fixed +++ b/tests/ui/equatable_if_let.fixed @@ -142,5 +142,6 @@ mod issue8710 { fn issue15376() { // PartialEq is not stable in consts yet - const _: u32 = if let Some(true) = None { 0 } else { 1 }; + const _: u32 = if matches!(None, Some(true)) { 0 } else { 1 }; + //~^ ERROR: this pattern matching can be expressed using `matches!` } diff --git a/tests/ui/equatable_if_let.rs b/tests/ui/equatable_if_let.rs index 17882f9bf9c5..f354a7a0b9d5 100644 --- a/tests/ui/equatable_if_let.rs +++ b/tests/ui/equatable_if_let.rs @@ -143,4 +143,5 @@ mod issue8710 { fn issue15376() { // PartialEq is not stable in consts yet const _: u32 = if let Some(true) = None { 0 } else { 1 }; + //~^ ERROR: this pattern matching can be expressed using `matches!` } diff --git a/tests/ui/equatable_if_let.stderr b/tests/ui/equatable_if_let.stderr index dd1832ad68b2..4b823cbd3cae 100644 --- a/tests/ui/equatable_if_let.stderr +++ b/tests/ui/equatable_if_let.stderr @@ -103,5 +103,11 @@ error: this pattern matching can be expressed using `matches!` LL | if let Some(MyEnum::B) = get_enum() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(get_enum(), Some(MyEnum::B))` -error: aborting due to 17 previous errors +error: this pattern matching can be expressed using `matches!` + --> tests/ui/equatable_if_let.rs:145:23 + | +LL | const _: u32 = if let Some(true) = None { 0 } else { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(None, Some(true))` + +error: aborting due to 18 previous errors From d7b1873df8b69c0c72cdf7672f1ee30da007861c Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Thu, 14 Aug 2025 14:31:44 +0200 Subject: [PATCH 3/7] store the def ids in the struct as well we've created it already, so might as well.. --- clippy_lints/src/equatable_if_let.rs | 54 +++++++++++++++------------- clippy_lints/src/lib.rs | 2 +- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/equatable_if_let.rs b/clippy_lints/src/equatable_if_let.rs index 0b2d4d36da7f..9538bc3d9fac 100644 --- a/clippy_lints/src/equatable_if_let.rs +++ b/clippy_lints/src/equatable_if_let.rs @@ -6,9 +6,10 @@ use clippy_utils::qualify_min_const_fn::is_stable_const_fn; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; +use rustc_hir::def_id::DefId; use rustc_hir::{Expr, ExprKind, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{Ty, TyCtxt}; use rustc_session::impl_lint_pass; declare_clippy_lint! { @@ -44,12 +45,36 @@ declare_clippy_lint! { impl_lint_pass!(PatternEquality => [EQUATABLE_IF_LET]); pub(super) struct PatternEquality { + eq_trait: Option, + eq_method: Option, msrv: Msrv, } impl PatternEquality { - pub(super) fn new(conf: &Conf) -> Self { - Self { msrv: conf.msrv } + pub(super) fn new(tcx: TyCtxt<'_>, conf: &Conf) -> Self { + let eq_trait = tcx.lang_items().eq_trait(); + let eq_method = eq_trait + .and_then(|eq_trait| tcx.provided_trait_methods(eq_trait).next()) + .map(|eq_method| eq_method.def_id); + + Self { + eq_trait, + eq_method, + msrv: conf.msrv, + } + } + + fn is_structural_partial_eq<'tcx>(&self, cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: Ty<'tcx>) -> bool { + if (self.eq_trait).is_some_and(|eq_trait| implements_trait(cx, ty, eq_trait, &[other.into()])) { + if !is_in_const_context(cx) { + return true; + } + // TODO: add a MSRV test once `eq` becomes stably-const + self.eq_method + .is_some_and(|eq_method| is_stable_const_fn(cx, eq_method, self.msrv)) + } else { + false + } } } @@ -74,27 +99,6 @@ fn unary_pattern(pat: &Pat<'_>) -> bool { } } -fn is_structural_partial_eq<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: Ty<'tcx>, msrv: Msrv) -> bool { - if let Some(eq_trait) = cx.tcx.lang_items().eq_trait() - && implements_trait(cx, ty, eq_trait, &[other.into()]) - { - if !is_in_const_context(cx) { - return true; - } - - // TODO: add a MSRV test once `eq` becomes stably-const - if let Some(eq_method) = cx.tcx.provided_trait_methods(eq_trait).next() - && is_stable_const_fn(cx, eq_method.def_id, msrv) - { - true - } else { - false - } - } else { - false - } -} - /// Check if the pattern has any type mismatch that would prevent it from being used in an equality /// check. This can happen if the expr has a reference type and the corresponding pattern is a /// literal. @@ -137,7 +141,7 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality { let pat_ty = cx.typeck_results().pat_ty(let_expr.pat); let mut applicability = Applicability::MachineApplicable; - if is_structural_partial_eq(cx, exp_ty, pat_ty, self.msrv) && !contains_type_mismatch(cx, let_expr.pat) { + if self.is_structural_partial_eq(cx, exp_ty, pat_ty) && !contains_type_mismatch(cx, let_expr.pat) { let pat_str = match let_expr.pat.kind { PatKind::Struct(..) => format!( "({})", diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index aa466c52d44c..f327389cd698 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -648,7 +648,7 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co store.register_late_pass(move |_| Box::new(large_futures::LargeFuture::new(conf))); store.register_late_pass(|_| Box::new(if_let_mutex::IfLetMutex)); store.register_late_pass(|_| Box::new(if_not_else::IfNotElse)); - store.register_late_pass(|_| Box::new(equatable_if_let::PatternEquality::new(conf))); + store.register_late_pass(|tcx| Box::new(equatable_if_let::PatternEquality::new(tcx, conf))); store.register_late_pass(|_| Box::new(manual_async_fn::ManualAsyncFn)); store.register_late_pass(|_| Box::new(panic_in_result_fn::PanicInResultFn)); store.register_early_pass(move || Box::new(non_expressive_names::NonExpressiveNames::new(conf))); From 0a068b090c8eb8d780d2b1dbecf08c72995f7313 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Thu, 14 Aug 2025 15:42:28 +0200 Subject: [PATCH 4/7] restructure `is_structual_partial_eq` --- clippy_lints/src/equatable_if_let.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/equatable_if_let.rs b/clippy_lints/src/equatable_if_let.rs index 9538bc3d9fac..4cc2c85152d7 100644 --- a/clippy_lints/src/equatable_if_let.rs +++ b/clippy_lints/src/equatable_if_let.rs @@ -65,16 +65,10 @@ impl PatternEquality { } fn is_structural_partial_eq<'tcx>(&self, cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: Ty<'tcx>) -> bool { - if (self.eq_trait).is_some_and(|eq_trait| implements_trait(cx, ty, eq_trait, &[other.into()])) { - if !is_in_const_context(cx) { - return true; - } - // TODO: add a MSRV test once `eq` becomes stably-const - self.eq_method - .is_some_and(|eq_method| is_stable_const_fn(cx, eq_method, self.msrv)) - } else { - false - } + (self.eq_trait).is_some_and(|eq_trait| implements_trait(cx, ty, eq_trait, &[other.into()])) + && (!is_in_const_context(cx) + // TODO: add a MSRV test once `eq` becomes stably-const + || (self.eq_method).is_some_and(|eq_method| is_stable_const_fn(cx, eq_method, self.msrv))) } } From 3ccda896c3aa07a8ac9110b694279ffc87409ec2 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Thu, 14 Aug 2025 15:41:24 +0200 Subject: [PATCH 5/7] add itermediate variables for more legibility --- clippy_lints/src/equatable_if_let.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/equatable_if_let.rs b/clippy_lints/src/equatable_if_let.rs index 4cc2c85152d7..d2b62d63aa18 100644 --- a/clippy_lints/src/equatable_if_let.rs +++ b/clippy_lints/src/equatable_if_let.rs @@ -65,10 +65,18 @@ impl PatternEquality { } fn is_structural_partial_eq<'tcx>(&self, cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: Ty<'tcx>) -> bool { - (self.eq_trait).is_some_and(|eq_trait| implements_trait(cx, ty, eq_trait, &[other.into()])) - && (!is_in_const_context(cx) - // TODO: add a MSRV test once `eq` becomes stably-const - || (self.eq_method).is_some_and(|eq_method| is_stable_const_fn(cx, eq_method, self.msrv))) + let is_partial_eq = || { + self.eq_trait + .is_some_and(|eq_trait| implements_trait(cx, ty, eq_trait, &[other.into()])) + }; + + // TODO: add a MSRV test once `eq` becomes stably-const + let eq_method_is_const = || { + self.eq_method + .is_some_and(|eq_method| is_stable_const_fn(cx, eq_method, self.msrv)) + }; + + is_partial_eq() && (!is_in_const_context(cx) || eq_method_is_const()) } } From 3a02646a8636f9c3cd762d1aa9f71e7c586f541e Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 19 Aug 2025 20:41:11 +0200 Subject: [PATCH 6/7] fix retrieval of `eq_method` --- clippy_lints/src/equatable_if_let.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/clippy_lints/src/equatable_if_let.rs b/clippy_lints/src/equatable_if_let.rs index d2b62d63aa18..d6533b18ace6 100644 --- a/clippy_lints/src/equatable_if_let.rs +++ b/clippy_lints/src/equatable_if_let.rs @@ -53,9 +53,7 @@ pub(super) struct PatternEquality { impl PatternEquality { pub(super) fn new(tcx: TyCtxt<'_>, conf: &Conf) -> Self { let eq_trait = tcx.lang_items().eq_trait(); - let eq_method = eq_trait - .and_then(|eq_trait| tcx.provided_trait_methods(eq_trait).next()) - .map(|eq_method| eq_method.def_id); + let eq_method = eq_trait.and_then(|eq_trait| tcx.associated_item_def_ids(eq_trait).first().copied()); Self { eq_trait, From 283f89d548bf91f698eeb963d25c0a60d29b2bc9 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 19 Aug 2025 20:01:12 +0200 Subject: [PATCH 7/7] WIP: fix `const PartialEq` check before this, the lint would suggest `==` even for types that aren't `const PartialEq` still doesn't work on nested types for some reason --- clippy_lints/src/equatable_if_let.rs | 14 +++++-- tests/ui/equatable_if_let.fixed | 28 ++++++++++++- tests/ui/equatable_if_let.rs | 28 ++++++++++++- tests/ui/equatable_if_let.stderr | 60 ++++++++++++++++++---------- 4 files changed, 101 insertions(+), 29 deletions(-) diff --git a/clippy_lints/src/equatable_if_let.rs b/clippy_lints/src/equatable_if_let.rs index d6533b18ace6..58311257f58b 100644 --- a/clippy_lints/src/equatable_if_let.rs +++ b/clippy_lints/src/equatable_if_let.rs @@ -9,7 +9,7 @@ use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, ExprKind, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_middle::ty::{Instance, Ty, TyCtxt}; use rustc_session::impl_lint_pass; declare_clippy_lint! { @@ -68,10 +68,16 @@ impl PatternEquality { .is_some_and(|eq_trait| implements_trait(cx, ty, eq_trait, &[other.into()])) }; - // TODO: add a MSRV test once `eq` becomes stably-const let eq_method_is_const = || { - self.eq_method - .is_some_and(|eq_method| is_stable_const_fn(cx, eq_method, self.msrv)) + if let Some(eq_method) = self.eq_method + && let args = cx.tcx.mk_args(&[ty.into(), other.into()]) + && let Ok(Some(instance)) = Instance::try_resolve(cx.tcx, cx.typing_env(), eq_method, args) + && is_stable_const_fn(cx, instance.def_id(), self.msrv) + { + true + } else { + false + } }; is_partial_eq() && (!is_in_const_context(cx) || eq_method_is_const()) diff --git a/tests/ui/equatable_if_let.fixed b/tests/ui/equatable_if_let.fixed index db4e2dbe3210..d98e78a5c765 100644 --- a/tests/ui/equatable_if_let.fixed +++ b/tests/ui/equatable_if_let.fixed @@ -7,6 +7,7 @@ clippy::needless_if )] #![warn(clippy::equatable_if_let)] +#![feature(const_trait_impl, const_cmp)] extern crate proc_macros; use proc_macros::{external, inline_macros}; @@ -140,8 +141,31 @@ mod issue8710 { } } +#[allow(irrefutable_let_patterns, clippy::partialeq_to_none, clippy::eq_op)] fn issue15376() { - // PartialEq is not stable in consts yet - const _: u32 = if matches!(None, Some(true)) { 0 } else { 1 }; + struct NonConstEq; + + impl PartialEq for NonConstEq { + fn eq(&self, _other: &Self) -> bool { + true + } + } + + const _: u32 = if matches!(NonConstEq, NonConstEq) { 0 } else { 1 }; + //~^ ERROR: this pattern matching can be expressed using `matches!` + const _: u32 = if matches!(None, Some(NonConstEq)) { 0 } else { 1 }; //~^ ERROR: this pattern matching can be expressed using `matches!` + + struct ConstEq; + + impl const PartialEq for ConstEq { + fn eq(&self, _other: &Self) -> bool { + true + } + } + + const _: u32 = if ConstEq == ConstEq { 0 } else { 1 }; + //~^ ERROR: this pattern matching can be expressed using equality + const _: u32 = if None == Some(ConstEq) { 0 } else { 1 }; + //~^ ERROR: this pattern matching can be expressed using equality } diff --git a/tests/ui/equatable_if_let.rs b/tests/ui/equatable_if_let.rs index f354a7a0b9d5..35a772ea4bd5 100644 --- a/tests/ui/equatable_if_let.rs +++ b/tests/ui/equatable_if_let.rs @@ -7,6 +7,7 @@ clippy::needless_if )] #![warn(clippy::equatable_if_let)] +#![feature(const_trait_impl, const_cmp)] extern crate proc_macros; use proc_macros::{external, inline_macros}; @@ -140,8 +141,31 @@ mod issue8710 { } } +#[allow(irrefutable_let_patterns, clippy::partialeq_to_none, clippy::eq_op)] fn issue15376() { - // PartialEq is not stable in consts yet - const _: u32 = if let Some(true) = None { 0 } else { 1 }; + struct NonConstEq; + + impl PartialEq for NonConstEq { + fn eq(&self, _other: &Self) -> bool { + true + } + } + + const _: u32 = if let NonConstEq = NonConstEq { 0 } else { 1 }; + //~^ ERROR: this pattern matching can be expressed using `matches!` + const _: u32 = if let Some(NonConstEq) = None { 0 } else { 1 }; //~^ ERROR: this pattern matching can be expressed using `matches!` + + struct ConstEq; + + impl const PartialEq for ConstEq { + fn eq(&self, _other: &Self) -> bool { + true + } + } + + const _: u32 = if let ConstEq = ConstEq { 0 } else { 1 }; + //~^ ERROR: this pattern matching can be expressed using equality + const _: u32 = if let Some(ConstEq) = None { 0 } else { 1 }; + //~^ ERROR: this pattern matching can be expressed using equality } diff --git a/tests/ui/equatable_if_let.stderr b/tests/ui/equatable_if_let.stderr index 4b823cbd3cae..a6ca96e55ca4 100644 --- a/tests/ui/equatable_if_let.stderr +++ b/tests/ui/equatable_if_let.stderr @@ -1,5 +1,5 @@ error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:64:8 + --> tests/ui/equatable_if_let.rs:65:8 | LL | if let 2 = a {} | ^^^^^^^^^ help: try: `a == 2` @@ -8,106 +8,124 @@ LL | if let 2 = a {} = help: to override `-D warnings` add `#[allow(clippy::equatable_if_let)]` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:66:8 + --> tests/ui/equatable_if_let.rs:67: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 - --> tests/ui/equatable_if_let.rs:68:8 + --> tests/ui/equatable_if_let.rs:69:8 | LL | if let Some(2) = c {} | ^^^^^^^^^^^^^^^ help: try: `c == Some(2)` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:70:8 + --> tests/ui/equatable_if_let.rs:71: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 - --> tests/ui/equatable_if_let.rs:72:8 + --> tests/ui/equatable_if_let.rs:73: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 - --> tests/ui/equatable_if_let.rs:74:8 + --> tests/ui/equatable_if_let.rs:75: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 - --> tests/ui/equatable_if_let.rs:76:8 + --> tests/ui/equatable_if_let.rs:77:8 | LL | if let Enum::UnitVariant = e {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::UnitVariant` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:78:8 + --> tests/ui/equatable_if_let.rs:79: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 `matches!` - --> tests/ui/equatable_if_let.rs:88:8 + --> tests/ui/equatable_if_let.rs:89:8 | LL | if let NotPartialEq::A = f {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(f, NotPartialEq::A)` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:90:8 + --> tests/ui/equatable_if_let.rs:91:8 | LL | if let NotStructuralEq::A = g {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `g == NotStructuralEq::A` error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:92:8 + --> tests/ui/equatable_if_let.rs:93:8 | LL | if let Some(NotPartialEq::A) = Some(f) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(f), Some(NotPartialEq::A))` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:94:8 + --> tests/ui/equatable_if_let.rs:95:8 | LL | if let Some(NotStructuralEq::A) = Some(g) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(g) == Some(NotStructuralEq::A)` error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:96:8 + --> tests/ui/equatable_if_let.rs:97:8 | LL | if let NoPartialEqStruct { a: 2, b: false } = h {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(h, NoPartialEqStruct { a: 2, b: false })` error: this pattern matching can be expressed using equality - --> tests/ui/equatable_if_let.rs:99:8 + --> tests/ui/equatable_if_let.rs:100:8 | LL | if let inline!("abc") = "abc" { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"abc" == inline!("abc")` error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:109:12 + --> tests/ui/equatable_if_let.rs:110:12 | LL | if let Some('i') = cs.iter().next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(cs.iter().next(), Some('i'))` error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:117:12 + --> tests/ui/equatable_if_let.rs:118:12 | LL | if let Some(1) = cs.iter().next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(cs.iter().next(), Some(1))` error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:135:12 + --> tests/ui/equatable_if_let.rs:136:12 | LL | if let Some(MyEnum::B) = get_enum() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(get_enum(), Some(MyEnum::B))` error: this pattern matching can be expressed using `matches!` - --> tests/ui/equatable_if_let.rs:145:23 + --> tests/ui/equatable_if_let.rs:154:23 | -LL | const _: u32 = if let Some(true) = None { 0 } else { 1 }; - | ^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(None, Some(true))` +LL | const _: u32 = if let NonConstEq = NonConstEq { 0 } else { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(NonConstEq, NonConstEq)` -error: aborting due to 18 previous errors +error: this pattern matching can be expressed using equality + --> tests/ui/equatable_if_let.rs:156:23 + | +LL | const _: u32 = if let Some(NonConstEq) = None { 0 } else { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `None == Some(NonConstEq)` + +error: this pattern matching can be expressed using equality + --> tests/ui/equatable_if_let.rs:167:23 + | +LL | const _: u32 = if let ConstEq = ConstEq { 0 } else { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `ConstEq == ConstEq` + +error: this pattern matching can be expressed using equality + --> tests/ui/equatable_if_let.rs:169:23 + | +LL | const _: u32 = if let Some(ConstEq) = None { 0 } else { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `None == Some(ConstEq)` + +error: aborting due to 21 previous errors