@@ -2,17 +2,17 @@ use super::REDUNDANT_PATTERN_MATCHING;
2
2
use clippy_utils:: diagnostics:: span_lint_and_then;
3
3
use clippy_utils:: source:: snippet;
4
4
use clippy_utils:: sugg:: Sugg ;
5
- use clippy_utils:: ty:: needs_ordered_drop;
5
+ use clippy_utils:: ty:: { is_type_diagnostic_item , needs_ordered_drop} ;
6
6
use clippy_utils:: visitors:: any_temporaries_need_ordered_drop;
7
- use clippy_utils:: { higher, is_lang_ctor, is_trait_method, match_def_path , paths } ;
7
+ use clippy_utils:: { higher, is_lang_ctor, is_trait_method} ;
8
8
use if_chain:: if_chain;
9
9
use rustc_ast:: ast:: LitKind ;
10
10
use rustc_errors:: Applicability ;
11
- use rustc_hir:: LangItem :: { OptionNone , PollPending } ;
11
+ use rustc_hir:: LangItem :: { self , OptionSome , OptionNone , PollPending , PollReady , ResultOk , ResultErr } ;
12
12
use rustc_hir:: { Arm , Expr , ExprKind , Node , Pat , PatKind , QPath , UnOp } ;
13
13
use rustc_lint:: LateContext ;
14
14
use rustc_middle:: ty:: { self , subst:: GenericArgKind , DefIdTree , Ty } ;
15
- use rustc_span:: sym;
15
+ use rustc_span:: { sym, Symbol } ;
16
16
17
17
pub ( super ) fn check < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
18
18
if let Some ( higher:: WhileLet { let_pat, let_expr, .. } ) = higher:: WhileLet :: hir ( expr) {
@@ -75,9 +75,9 @@ fn find_sugg_for_if_let<'tcx>(
75
75
( "is_some()" , op_ty)
76
76
} else if Some ( id) == lang_items. poll_ready_variant ( ) {
77
77
( "is_ready()" , op_ty)
78
- } else if match_def_path ( cx, id , & paths :: IPADDR_V4 ) {
78
+ } else if is_pat_variant ( cx, check_pat , qpath , Item :: Diag ( sym :: IpAddr , sym ! ( V4 ) ) ) {
79
79
( "is_ipv4()" , op_ty)
80
- } else if match_def_path ( cx, id , & paths :: IPADDR_V6 ) {
80
+ } else if is_pat_variant ( cx, check_pat , qpath , Item :: Diag ( sym :: IpAddr , sym ! ( V6 ) ) ) {
81
81
( "is_ipv6()" , op_ty)
82
82
} else {
83
83
return ;
@@ -187,8 +187,8 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
187
187
arms,
188
188
path_left,
189
189
path_right,
190
- & paths :: RESULT_OK ,
191
- & paths :: RESULT_ERR ,
190
+ Item :: Lang ( ResultOk ) ,
191
+ Item :: Lang ( ResultErr ) ,
192
192
"is_ok()" ,
193
193
"is_err()" ,
194
194
)
@@ -198,8 +198,8 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
198
198
arms,
199
199
path_left,
200
200
path_right,
201
- & paths :: IPADDR_V4 ,
202
- & paths :: IPADDR_V6 ,
201
+ Item :: Diag ( sym :: IpAddr , sym ! ( V4 ) ) ,
202
+ Item :: Diag ( sym :: IpAddr , sym ! ( V6 ) ) ,
203
203
"is_ipv4()" ,
204
204
"is_ipv6()" ,
205
205
)
@@ -213,13 +213,14 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
213
213
if patterns. len ( ) == 1 =>
214
214
{
215
215
if let PatKind :: Wild = patterns[ 0 ] . kind {
216
+
216
217
find_good_method_for_match (
217
218
cx,
218
219
arms,
219
220
path_left,
220
221
path_right,
221
- & paths :: OPTION_SOME ,
222
- & paths :: OPTION_NONE ,
222
+ Item :: Lang ( OptionSome ) ,
223
+ Item :: Lang ( OptionNone ) ,
223
224
"is_some()" ,
224
225
"is_none()" ,
225
226
)
@@ -229,8 +230,8 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
229
230
arms,
230
231
path_left,
231
232
path_right,
232
- & paths :: POLL_READY ,
233
- & paths :: POLL_PENDING ,
233
+ Item :: Lang ( PollReady ) ,
234
+ Item :: Lang ( PollPending ) ,
234
235
"is_ready()" ,
235
236
"is_pending()" ,
236
237
)
@@ -266,28 +267,61 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
266
267
}
267
268
}
268
269
270
+ #[ derive( Clone , Copy ) ]
271
+ enum Item {
272
+ Lang ( LangItem ) ,
273
+ Diag ( Symbol , Symbol ) ,
274
+ }
275
+
276
+ fn is_pat_variant ( cx : & LateContext < ' _ > , pat : & Pat < ' _ > , path : & QPath < ' _ > , expected_item : Item ) -> bool {
277
+ let Some ( id) = cx. typeck_results ( ) . qpath_res ( path, pat. hir_id ) . opt_def_id ( ) else { return false } ;
278
+
279
+ match expected_item {
280
+ Item :: Lang ( expected_lang_item) => {
281
+ let expected_id = cx. tcx . lang_items ( ) . require ( expected_lang_item) . unwrap ( ) ;
282
+ cx. tcx . parent ( id) == expected_id
283
+ } ,
284
+ Item :: Diag ( expected_ty, expected_variant) => {
285
+ let ty = cx. typeck_results ( ) . pat_ty ( pat) ;
286
+
287
+ if is_type_diagnostic_item ( cx, ty, expected_ty) {
288
+ let variant = ty. ty_adt_def ( )
289
+ . expect ( "struct pattern type is not an ADT" )
290
+ . variant_of_res ( cx. qpath_res ( path, pat. hir_id ) ) ;
291
+
292
+ return variant. name == expected_variant
293
+ }
294
+
295
+ false
296
+ }
297
+ }
298
+ }
299
+
269
300
#[ expect( clippy:: too_many_arguments) ]
270
301
fn find_good_method_for_match < ' a > (
271
302
cx : & LateContext < ' _ > ,
272
303
arms : & [ Arm < ' _ > ] ,
273
304
path_left : & QPath < ' _ > ,
274
305
path_right : & QPath < ' _ > ,
275
- expected_left : & [ & str ] ,
276
- expected_right : & [ & str ] ,
306
+ expected_item_left : Item ,
307
+ expected_item_right : Item ,
277
308
should_be_left : & ' a str ,
278
309
should_be_right : & ' a str ,
279
310
) -> Option < & ' a str > {
280
- let left_id = cx
281
- . typeck_results ( )
282
- . qpath_res ( path_left, arms[ 0 ] . pat . hir_id )
283
- . opt_def_id ( ) ?;
284
- let right_id = cx
285
- . typeck_results ( )
286
- . qpath_res ( path_right, arms[ 1 ] . pat . hir_id )
287
- . opt_def_id ( ) ?;
288
- let body_node_pair = if match_def_path ( cx, left_id, expected_left) && match_def_path ( cx, right_id, expected_right) {
311
+ let pat_left = arms[ 0 ] . pat ;
312
+ let pat_right = arms[ 1 ] . pat ;
313
+
314
+ let body_node_pair = if (
315
+ is_pat_variant ( cx, pat_left, path_left, expected_item_left)
316
+ ) && (
317
+ is_pat_variant ( cx, pat_right, path_right, expected_item_right)
318
+ ) {
289
319
( & arms[ 0 ] . body . kind , & arms[ 1 ] . body . kind )
290
- } else if match_def_path ( cx, right_id, expected_left) && match_def_path ( cx, right_id, expected_right) {
320
+ } else if (
321
+ is_pat_variant ( cx, pat_left, path_left, expected_item_right)
322
+ ) && (
323
+ is_pat_variant ( cx, pat_right, path_right, expected_item_left)
324
+ ) {
291
325
( & arms[ 1 ] . body . kind , & arms[ 0 ] . body . kind )
292
326
} else {
293
327
return None ;
0 commit comments