@@ -269,66 +269,61 @@ fn find_method_sugg_for_if_let<'tcx>(
269
269
}
270
270
271
271
pub ( super ) fn check_match < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > , op : & Expr < ' _ > , arms : & [ Arm < ' _ > ] ) {
272
- if arms. len ( ) == 2 {
273
- let node_pair = ( & arms[ 0 ] . pat . kind , & arms[ 1 ] . pat . kind ) ;
274
-
275
- if let Some ( ( good_method, maybe_guard) ) = found_good_method ( cx, arms, node_pair) {
276
- let span = is_expn_of ( expr. span , sym:: matches) . unwrap_or ( expr. span . to ( op. span ) ) ;
277
- let result_expr = match & op. kind {
278
- ExprKind :: AddrOf ( _, _, borrowed) => borrowed,
279
- _ => op,
280
- } ;
281
- let mut app = Applicability :: MachineApplicable ;
282
- let receiver_sugg = Sugg :: hir_with_applicability ( cx, result_expr, "_" , & mut app) . maybe_paren ( ) ;
283
- let mut sugg = format ! ( "{receiver_sugg}.{good_method}" ) ;
284
-
285
- if let Some ( guard) = maybe_guard {
286
- // wow, the HIR for match guards in `PAT if let PAT = expr && expr => ...` is annoying!
287
- // `guard` here is `Guard::If` with the let expression somewhere deep in the tree of exprs,
288
- // counter to the intuition that it should be `Guard::IfLet`, so we need another check
289
- // to see that there aren't any let chains anywhere in the guard, as that would break
290
- // if we suggest `t.is_none() && (let X = y && z)` for:
291
- // `match t { None if let X = y && z => true, _ => false }`
292
- let has_nested_let_chain = for_each_expr_without_closures ( guard, |expr| {
293
- if matches ! ( expr. kind, ExprKind :: Let ( ..) ) {
294
- ControlFlow :: Break ( ( ) )
295
- } else {
296
- ControlFlow :: Continue ( ( ) )
297
- }
298
- } )
299
- . is_some ( ) ;
300
-
301
- if has_nested_let_chain {
302
- return ;
272
+ if let Ok ( arms) = arms. try_into ( ) // TODO: use `slice::as_array` once stabilized
273
+ && let Some ( ( good_method, maybe_guard) ) = found_good_method ( cx, arms)
274
+ {
275
+ let span = is_expn_of ( expr. span , sym:: matches) . unwrap_or ( expr. span . to ( op. span ) ) ;
276
+ let result_expr = match & op. kind {
277
+ ExprKind :: AddrOf ( _, _, borrowed) => borrowed,
278
+ _ => op,
279
+ } ;
280
+ let mut app = Applicability :: MachineApplicable ;
281
+ let receiver_sugg = Sugg :: hir_with_applicability ( cx, result_expr, "_" , & mut app) . maybe_paren ( ) ;
282
+ let mut sugg = format ! ( "{receiver_sugg}.{good_method}" ) ;
283
+
284
+ if let Some ( guard) = maybe_guard {
285
+ // wow, the HIR for match guards in `PAT if let PAT = expr && expr => ...` is annoying!
286
+ // `guard` here is `Guard::If` with the let expression somewhere deep in the tree of exprs,
287
+ // counter to the intuition that it should be `Guard::IfLet`, so we need another check
288
+ // to see that there aren't any let chains anywhere in the guard, as that would break
289
+ // if we suggest `t.is_none() && (let X = y && z)` for:
290
+ // `match t { None if let X = y && z => true, _ => false }`
291
+ let has_nested_let_chain = for_each_expr_without_closures ( guard, |expr| {
292
+ if matches ! ( expr. kind, ExprKind :: Let ( ..) ) {
293
+ ControlFlow :: Break ( ( ) )
294
+ } else {
295
+ ControlFlow :: Continue ( ( ) )
303
296
}
297
+ } )
298
+ . is_some ( ) ;
304
299
305
- let guard = Sugg :: hir ( cx , guard , ".." ) ;
306
- let _ = write ! ( sugg , " && {}" , guard . maybe_paren ( ) ) ;
300
+ if has_nested_let_chain {
301
+ return ;
307
302
}
308
303
309
- span_lint_and_sugg (
310
- cx,
311
- REDUNDANT_PATTERN_MATCHING ,
312
- span,
313
- format ! ( "redundant pattern matching, consider using `{good_method}`" ) ,
314
- "try" ,
315
- sugg,
316
- app,
317
- ) ;
304
+ let guard = Sugg :: hir ( cx, guard, ".." ) ;
305
+ let _ = write ! ( sugg, " && {}" , guard. maybe_paren( ) ) ;
318
306
}
307
+
308
+ span_lint_and_sugg (
309
+ cx,
310
+ REDUNDANT_PATTERN_MATCHING ,
311
+ span,
312
+ format ! ( "redundant pattern matching, consider using `{good_method}`" ) ,
313
+ "try" ,
314
+ sugg,
315
+ app,
316
+ ) ;
319
317
}
320
318
}
321
319
322
320
fn found_good_method < ' tcx > (
323
321
cx : & LateContext < ' _ > ,
324
- arms : & ' tcx [ Arm < ' tcx > ] ,
325
- node : ( & PatKind < ' _ > , & PatKind < ' _ > ) ,
322
+ arms : & ' tcx [ Arm < ' tcx > ; 2 ] ,
326
323
) -> Option < ( & ' static str , Option < & ' tcx Expr < ' tcx > > ) > {
327
- match node {
328
- ( PatKind :: TupleStruct ( path_left, patterns_left, _) , PatKind :: TupleStruct ( path_right, patterns_right, _) )
329
- if patterns_left. len ( ) == 1 && patterns_right. len ( ) == 1 =>
330
- {
331
- if let ( PatKind :: Wild , PatKind :: Wild ) = ( & patterns_left[ 0 ] . kind , & patterns_right[ 0 ] . kind ) {
324
+ match ( & arms[ 0 ] . pat . kind , & arms[ 1 ] . pat . kind ) {
325
+ ( PatKind :: TupleStruct ( path_left, [ pattern_left] , _) , PatKind :: TupleStruct ( path_right, [ pattern_right] , _) ) => {
326
+ if let ( PatKind :: Wild , PatKind :: Wild ) = ( & pattern_left. kind , & pattern_right. kind ) {
332
327
find_good_method_for_match (
333
328
cx,
334
329
arms,
@@ -356,7 +351,7 @@ fn found_good_method<'tcx>(
356
351
}
357
352
} ,
358
353
(
359
- PatKind :: TupleStruct ( path_left, patterns , _) ,
354
+ PatKind :: TupleStruct ( path_left, [ pattern ] , _) ,
360
355
PatKind :: Expr ( PatExpr {
361
356
kind : PatExprKind :: Path ( path_right) ,
362
357
..
@@ -367,9 +362,9 @@ fn found_good_method<'tcx>(
367
362
kind : PatExprKind :: Path ( path_left) ,
368
363
..
369
364
} ) ,
370
- PatKind :: TupleStruct ( path_right, patterns , _) ,
371
- ) if patterns . len ( ) == 1 => {
372
- if let PatKind :: Wild = patterns [ 0 ] . kind {
365
+ PatKind :: TupleStruct ( path_right, [ pattern ] , _) ,
366
+ ) => {
367
+ if let PatKind :: Wild = pattern . kind {
373
368
find_good_method_for_match (
374
369
cx,
375
370
arms,
@@ -396,8 +391,8 @@ fn found_good_method<'tcx>(
396
391
None
397
392
}
398
393
} ,
399
- ( PatKind :: TupleStruct ( path_left, patterns , _) , PatKind :: Wild ) if patterns . len ( ) == 1 => {
400
- if let PatKind :: Wild = patterns [ 0 ] . kind {
394
+ ( PatKind :: TupleStruct ( path_left, [ pattern ] , _) , PatKind :: Wild ) => {
395
+ if let PatKind :: Wild = pattern . kind {
401
396
get_good_method ( cx, arms, path_left)
402
397
} else {
403
398
None
@@ -426,31 +421,23 @@ fn get_ident(path: &QPath<'_>) -> Option<rustc_span::symbol::Ident> {
426
421
427
422
fn get_good_method < ' tcx > (
428
423
cx : & LateContext < ' _ > ,
429
- arms : & ' tcx [ Arm < ' tcx > ] ,
424
+ arms : & ' tcx [ Arm < ' tcx > ; 2 ] ,
430
425
path_left : & QPath < ' _ > ,
431
426
) -> Option < ( & ' static str , Option < & ' tcx Expr < ' tcx > > ) > {
432
- if let Some ( name) = get_ident ( path_left) {
433
- let ( expected_item_left, should_be_left, should_be_right) = match name. as_str ( ) {
434
- "Ok" => ( Item :: Lang ( ResultOk ) , "is_ok()" , "is_err()" ) ,
435
- "Err" => ( Item :: Lang ( ResultErr ) , "is_err()" , "is_ok()" ) ,
436
- "Some" => ( Item :: Lang ( OptionSome ) , "is_some()" , "is_none()" ) ,
437
- "None" => ( Item :: Lang ( OptionNone ) , "is_none()" , "is_some()" ) ,
438
- "Ready" => ( Item :: Lang ( PollReady ) , "is_ready()" , "is_pending()" ) ,
439
- "Pending" => ( Item :: Lang ( PollPending ) , "is_pending()" , "is_ready()" ) ,
440
- "V4" => ( Item :: Diag ( sym:: IpAddr , sym:: V4 ) , "is_ipv4()" , "is_ipv6()" ) ,
441
- "V6" => ( Item :: Diag ( sym:: IpAddr , sym:: V6 ) , "is_ipv6()" , "is_ipv4()" ) ,
442
- _ => return None ,
443
- } ;
444
- return find_good_method_for_matches_macro (
445
- cx,
446
- arms,
447
- path_left,
448
- expected_item_left,
449
- should_be_left,
450
- should_be_right,
451
- ) ;
452
- }
453
- None
427
+ let ident = get_ident ( path_left) ?;
428
+
429
+ let ( expected_item_left, should_be_left, should_be_right) = match ident. name {
430
+ sym:: Ok => ( Item :: Lang ( ResultOk ) , "is_ok()" , "is_err()" ) ,
431
+ sym:: Err => ( Item :: Lang ( ResultErr ) , "is_err()" , "is_ok()" ) ,
432
+ sym:: Some => ( Item :: Lang ( OptionSome ) , "is_some()" , "is_none()" ) ,
433
+ sym:: None => ( Item :: Lang ( OptionNone ) , "is_none()" , "is_some()" ) ,
434
+ sym:: Ready => ( Item :: Lang ( PollReady ) , "is_ready()" , "is_pending()" ) ,
435
+ sym:: Pending => ( Item :: Lang ( PollPending ) , "is_pending()" , "is_ready()" ) ,
436
+ sym:: V4 => ( Item :: Diag ( sym:: IpAddr , sym:: V4 ) , "is_ipv4()" , "is_ipv6()" ) ,
437
+ sym:: V6 => ( Item :: Diag ( sym:: IpAddr , sym:: V6 ) , "is_ipv6()" , "is_ipv4()" ) ,
438
+ _ => return None ,
439
+ } ;
440
+ find_good_method_for_matches_macro ( cx, arms, path_left, expected_item_left, should_be_left, should_be_right)
454
441
}
455
442
456
443
#[ derive( Clone , Copy ) ]
@@ -490,7 +477,7 @@ fn is_pat_variant(cx: &LateContext<'_>, pat: &Pat<'_>, path: &QPath<'_>, expecte
490
477
#[ expect( clippy:: too_many_arguments) ]
491
478
fn find_good_method_for_match < ' a , ' tcx > (
492
479
cx : & LateContext < ' _ > ,
493
- arms : & ' tcx [ Arm < ' tcx > ] ,
480
+ arms : & ' tcx [ Arm < ' tcx > ; 2 ] ,
494
481
path_left : & QPath < ' _ > ,
495
482
path_right : & QPath < ' _ > ,
496
483
expected_item_left : Item ,
@@ -525,7 +512,7 @@ fn find_good_method_for_match<'a, 'tcx>(
525
512
526
513
fn find_good_method_for_matches_macro < ' a , ' tcx > (
527
514
cx : & LateContext < ' _ > ,
528
- arms : & ' tcx [ Arm < ' tcx > ] ,
515
+ arms : & ' tcx [ Arm < ' tcx > ; 2 ] ,
529
516
path_left : & QPath < ' _ > ,
530
517
expected_item_left : Item ,
531
518
should_be_left : & ' a str ,
0 commit comments