@@ -6,9 +6,10 @@ use clippy_utils::qualify_min_const_fn::is_stable_const_fn;
66use clippy_utils:: source:: snippet_with_context;
77use clippy_utils:: ty:: implements_trait;
88use rustc_errors:: Applicability ;
9+ use rustc_hir:: def_id:: DefId ;
910use rustc_hir:: { Expr , ExprKind , Pat , PatKind } ;
1011use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
11- use rustc_middle:: ty:: Ty ;
12+ use rustc_middle:: ty:: { Ty , TyCtxt } ;
1213use rustc_session:: impl_lint_pass;
1314
1415declare_clippy_lint ! {
@@ -44,12 +45,36 @@ declare_clippy_lint! {
4445impl_lint_pass ! ( PatternEquality => [ EQUATABLE_IF_LET ] ) ;
4546
4647pub ( super ) struct PatternEquality {
48+ eq_trait : Option < DefId > ,
49+ eq_method : Option < DefId > ,
4750 msrv : Msrv ,
4851}
4952
5053impl PatternEquality {
51- pub ( super ) fn new ( conf : & Conf ) -> Self {
52- Self { msrv : conf. msrv }
54+ pub ( super ) fn new ( tcx : TyCtxt < ' _ > , conf : & Conf ) -> Self {
55+ let eq_trait = tcx. lang_items ( ) . eq_trait ( ) ;
56+ let eq_method = eq_trait
57+ . and_then ( |eq_trait| tcx. provided_trait_methods ( eq_trait) . next ( ) )
58+ . map ( |eq_method| eq_method. def_id ) ;
59+
60+ Self {
61+ eq_trait,
62+ eq_method,
63+ msrv : conf. msrv ,
64+ }
65+ }
66+
67+ fn is_structural_partial_eq < ' tcx > ( & self , cx : & LateContext < ' tcx > , ty : Ty < ' tcx > , other : Ty < ' tcx > ) -> bool {
68+ if ( self . eq_trait ) . is_some_and ( |eq_trait| implements_trait ( cx, ty, eq_trait, & [ other. into ( ) ] ) ) {
69+ if !is_in_const_context ( cx) {
70+ return true ;
71+ }
72+ // TODO: add a MSRV test once `eq` becomes stably-const
73+ self . eq_method
74+ . is_some_and ( |eq_method| is_stable_const_fn ( cx, eq_method, self . msrv ) )
75+ } else {
76+ false
77+ }
5378 }
5479}
5580
@@ -74,27 +99,6 @@ fn unary_pattern(pat: &Pat<'_>) -> bool {
7499 }
75100}
76101
77- fn is_structural_partial_eq < ' tcx > ( cx : & LateContext < ' tcx > , ty : Ty < ' tcx > , other : Ty < ' tcx > , msrv : Msrv ) -> bool {
78- if let Some ( eq_trait) = cx. tcx . lang_items ( ) . eq_trait ( )
79- && implements_trait ( cx, ty, eq_trait, & [ other. into ( ) ] )
80- {
81- if !is_in_const_context ( cx) {
82- return true ;
83- }
84-
85- // TODO: add a MSRV test once `eq` becomes stably-const
86- if let Some ( eq_method) = cx. tcx . provided_trait_methods ( eq_trait) . next ( )
87- && is_stable_const_fn ( cx, eq_method. def_id , msrv)
88- {
89- true
90- } else {
91- false
92- }
93- } else {
94- false
95- }
96- }
97-
98102/// Check if the pattern has any type mismatch that would prevent it from being used in an equality
99103/// check. This can happen if the expr has a reference type and the corresponding pattern is a
100104/// literal.
@@ -137,7 +141,7 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality {
137141 let pat_ty = cx. typeck_results ( ) . pat_ty ( let_expr. pat ) ;
138142 let mut applicability = Applicability :: MachineApplicable ;
139143
140- if is_structural_partial_eq ( cx, exp_ty, pat_ty, self . msrv ) && !contains_type_mismatch ( cx, let_expr. pat ) {
144+ if self . is_structural_partial_eq ( cx, exp_ty, pat_ty) && !contains_type_mismatch ( cx, let_expr. pat ) {
141145 let pat_str = match let_expr. pat . kind {
142146 PatKind :: Struct ( ..) => format ! (
143147 "({})" ,
0 commit comments