@@ -269,66 +269,61 @@ fn find_method_sugg_for_if_let<'tcx>(
269269}
270270
271271pub ( 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 ( ( ) )
303296 }
297+ } )
298+ . is_some ( ) ;
304299
305- let guard = Sugg :: hir ( cx , guard , ".." ) ;
306- let _ = write ! ( sugg , " && {}" , guard . maybe_paren ( ) ) ;
300+ if has_nested_let_chain {
301+ return ;
307302 }
308303
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( ) ) ;
318306 }
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+ ) ;
319317 }
320318}
321319
322320fn found_good_method < ' tcx > (
323321 cx : & LateContext < ' _ > ,
324- arms : & ' tcx [ Arm < ' tcx > ] ,
325- node : ( & PatKind < ' _ > , & PatKind < ' _ > ) ,
322+ arms : & ' tcx [ Arm < ' tcx > ; 2 ] ,
326323) -> 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 ) {
332327 find_good_method_for_match (
333328 cx,
334329 arms,
@@ -356,7 +351,7 @@ fn found_good_method<'tcx>(
356351 }
357352 } ,
358353 (
359- PatKind :: TupleStruct ( path_left, patterns , _) ,
354+ PatKind :: TupleStruct ( path_left, [ pattern ] , _) ,
360355 PatKind :: Expr ( PatExpr {
361356 kind : PatExprKind :: Path ( path_right) ,
362357 ..
@@ -367,9 +362,9 @@ fn found_good_method<'tcx>(
367362 kind : PatExprKind :: Path ( path_left) ,
368363 ..
369364 } ) ,
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 {
373368 find_good_method_for_match (
374369 cx,
375370 arms,
@@ -396,8 +391,8 @@ fn found_good_method<'tcx>(
396391 None
397392 }
398393 } ,
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 {
401396 get_good_method ( cx, arms, path_left)
402397 } else {
403398 None
@@ -426,31 +421,23 @@ fn get_ident(path: &QPath<'_>) -> Option<rustc_span::symbol::Ident> {
426421
427422fn get_good_method < ' tcx > (
428423 cx : & LateContext < ' _ > ,
429- arms : & ' tcx [ Arm < ' tcx > ] ,
424+ arms : & ' tcx [ Arm < ' tcx > ; 2 ] ,
430425 path_left : & QPath < ' _ > ,
431426) -> 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)
454441}
455442
456443#[ derive( Clone , Copy ) ]
@@ -490,7 +477,7 @@ fn is_pat_variant(cx: &LateContext<'_>, pat: &Pat<'_>, path: &QPath<'_>, expecte
490477#[ expect( clippy:: too_many_arguments) ]
491478fn find_good_method_for_match < ' a , ' tcx > (
492479 cx : & LateContext < ' _ > ,
493- arms : & ' tcx [ Arm < ' tcx > ] ,
480+ arms : & ' tcx [ Arm < ' tcx > ; 2 ] ,
494481 path_left : & QPath < ' _ > ,
495482 path_right : & QPath < ' _ > ,
496483 expected_item_left : Item ,
@@ -525,7 +512,7 @@ fn find_good_method_for_match<'a, 'tcx>(
525512
526513fn find_good_method_for_matches_macro < ' a , ' tcx > (
527514 cx : & LateContext < ' _ > ,
528- arms : & ' tcx [ Arm < ' tcx > ] ,
515+ arms : & ' tcx [ Arm < ' tcx > ; 2 ] ,
529516 path_left : & QPath < ' _ > ,
530517 expected_item_left : Item ,
531518 should_be_left : & ' a str ,
0 commit comments