@@ -413,7 +413,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
413413 // Emit lints in the order in which they occur in the file.
414414 redundant_subpats. sort_unstable_by_key ( |( pat, _) | pat. data ( ) . span ) ;
415415 for ( pat, explanation) in redundant_subpats {
416- report_unreachable_pattern ( cx, arm. arm_data , pat, & explanation)
416+ report_unreachable_pattern ( cx, arm. arm_data . 0 , pat, & explanation, None )
417417 }
418418 }
419419 }
@@ -455,8 +455,11 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
455455 let arm = & self . thir . arms [ arm] ;
456456 let got_error = self . with_lint_level ( arm. lint_level , |this| {
457457 let Ok ( pat) = this. lower_pattern ( & cx, & arm. pattern ) else { return true } ;
458- let arm =
459- MatchArm { pat, arm_data : this. lint_level , has_guard : arm. guard . is_some ( ) } ;
458+ let arm = MatchArm {
459+ pat,
460+ arm_data : ( this. lint_level , arm. span ) ,
461+ has_guard : arm. guard . is_some ( ) ,
462+ } ;
460463 tarms. push ( arm) ;
461464 false
462465 } ) ;
@@ -474,7 +477,11 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
474477 hir:: MatchSource :: ForLoopDesugar
475478 | hir:: MatchSource :: Postfix
476479 | hir:: MatchSource :: Normal
477- | hir:: MatchSource :: FormatArgs => report_arm_reachability ( & cx, & report) ,
480+ | hir:: MatchSource :: FormatArgs => {
481+ let suggest_removing_if_unreachable =
482+ matches ! ( source, hir:: MatchSource :: Postfix | hir:: MatchSource :: Normal ) ;
483+ report_arm_reachability ( & cx, & report, suggest_removing_if_unreachable) ;
484+ }
478485 // Unreachable patterns in try and await expressions occur when one of
479486 // the arms are an uninhabited type. Which is OK.
480487 hir:: MatchSource :: AwaitDesugar | hir:: MatchSource :: TryDesugar ( _) => { }
@@ -610,9 +617,10 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
610617 refutability : RefutableFlag ,
611618 scrut : Option < & Expr < ' tcx > > ,
612619 ) -> Result < ( PatCtxt < ' p , ' tcx > , UsefulnessReport < ' p , ' tcx > ) , ErrorGuaranteed > {
613- let cx = self . new_cx ( refutability, None , scrut, pat. span ) ;
620+ let pat_span = pat. span ;
621+ let cx = self . new_cx ( refutability, None , scrut, pat_span) ;
614622 let pat = self . lower_pattern ( & cx, pat) ?;
615- let arms = [ MatchArm { pat, arm_data : self . lint_level , has_guard : false } ] ;
623+ let arms = [ MatchArm { pat, arm_data : ( self . lint_level , pat_span ) , has_guard : false } ] ;
616624 let report = self . analyze_patterns ( & cx, & arms, pat. ty ( ) . inner ( ) ) ?;
617625 Ok ( ( cx, report) )
618626 }
@@ -624,7 +632,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
624632 ) -> Result < RefutableFlag , ErrorGuaranteed > {
625633 let ( cx, report) = self . analyze_binding ( pat, Refutable , scrut) ?;
626634 // Report if the pattern is unreachable, which can only occur when the type is uninhabited.
627- report_arm_reachability ( & cx, & report) ;
635+ report_arm_reachability ( & cx, & report, false ) ;
628636 // If the list of witnesses is empty, the match is exhaustive, i.e. the `if let` pattern is
629637 // irrefutable.
630638 Ok ( if report. non_exhaustiveness_witnesses . is_empty ( ) { Irrefutable } else { Refutable } )
@@ -912,6 +920,7 @@ fn report_unreachable_pattern<'p, 'tcx>(
912920 hir_id : HirId ,
913921 pat : & DeconstructedPat < ' p , ' tcx > ,
914922 explanation : & RedundancyExplanation < ' p , ' tcx > ,
923+ suggest_remove : Option < Span > ,
915924) {
916925 let pat_span = pat. data ( ) . span ;
917926 let mut lint = UnreachablePattern {
@@ -920,6 +929,7 @@ fn report_unreachable_pattern<'p, 'tcx>(
920929 covered_by_catchall : None ,
921930 covered_by_one : None ,
922931 covered_by_many : None ,
932+ suggest_remove,
923933 } ;
924934 match explanation. covered_by . as_slice ( ) {
925935 [ ] => {
@@ -960,10 +970,27 @@ fn report_unreachable_pattern<'p, 'tcx>(
960970}
961971
962972/// Report unreachable arms, if any.
963- fn report_arm_reachability < ' p , ' tcx > ( cx : & PatCtxt < ' p , ' tcx > , report : & UsefulnessReport < ' p , ' tcx > ) {
973+ fn report_arm_reachability < ' p , ' tcx > (
974+ cx : & PatCtxt < ' p , ' tcx > ,
975+ report : & UsefulnessReport < ' p , ' tcx > ,
976+ suggest_removing_if_unreachable : bool ,
977+ ) {
978+ let sm = cx. tcx . sess . source_map ( ) ;
964979 for ( arm, is_useful) in report. arm_usefulness . iter ( ) {
965980 if let Usefulness :: Redundant ( explanation) = is_useful {
966- report_unreachable_pattern ( cx, arm. arm_data , arm. pat , explanation)
981+ let ( hid_id, arm_span) = arm. arm_data ;
982+ let suggest_remove = if suggest_removing_if_unreachable {
983+ // If the arm is followed by a comma, extend the span to include it.
984+ let with_whitespace = sm. span_extend_while_whitespace ( arm_span) ;
985+ if let Some ( comma) = sm. span_look_ahead ( with_whitespace, "," , Some ( 1 ) ) {
986+ Some ( arm_span. to ( comma) )
987+ } else {
988+ Some ( arm_span)
989+ }
990+ } else {
991+ None
992+ } ;
993+ report_unreachable_pattern ( cx, hid_id, arm. pat , explanation, suggest_remove)
967994 }
968995 }
969996}
0 commit comments