@@ -413,7 +413,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
413
413
// Emit lints in the order in which they occur in the file.
414
414
redundant_subpats. sort_unstable_by_key ( |( pat, _) | pat. data ( ) . span ) ;
415
415
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 )
417
417
}
418
418
}
419
419
}
@@ -455,8 +455,11 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
455
455
let arm = & self . thir . arms [ arm] ;
456
456
let got_error = self . with_lint_level ( arm. lint_level , |this| {
457
457
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
+ } ;
460
463
tarms. push ( arm) ;
461
464
false
462
465
} ) ;
@@ -474,7 +477,11 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
474
477
hir:: MatchSource :: ForLoopDesugar
475
478
| hir:: MatchSource :: Postfix
476
479
| 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
+ }
478
485
// Unreachable patterns in try and await expressions occur when one of
479
486
// the arms are an uninhabited type. Which is OK.
480
487
hir:: MatchSource :: AwaitDesugar | hir:: MatchSource :: TryDesugar ( _) => { }
@@ -610,9 +617,10 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
610
617
refutability : RefutableFlag ,
611
618
scrut : Option < & Expr < ' tcx > > ,
612
619
) -> 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) ;
614
622
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 } ] ;
616
624
let report = self . analyze_patterns ( & cx, & arms, pat. ty ( ) . inner ( ) ) ?;
617
625
Ok ( ( cx, report) )
618
626
}
@@ -624,7 +632,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
624
632
) -> Result < RefutableFlag , ErrorGuaranteed > {
625
633
let ( cx, report) = self . analyze_binding ( pat, Refutable , scrut) ?;
626
634
// 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 ) ;
628
636
// If the list of witnesses is empty, the match is exhaustive, i.e. the `if let` pattern is
629
637
// irrefutable.
630
638
Ok ( if report. non_exhaustiveness_witnesses . is_empty ( ) { Irrefutable } else { Refutable } )
@@ -912,6 +920,7 @@ fn report_unreachable_pattern<'p, 'tcx>(
912
920
hir_id : HirId ,
913
921
pat : & DeconstructedPat < ' p , ' tcx > ,
914
922
explanation : & RedundancyExplanation < ' p , ' tcx > ,
923
+ suggest_remove : Option < Span > ,
915
924
) {
916
925
let pat_span = pat. data ( ) . span ;
917
926
let mut lint = UnreachablePattern {
@@ -920,6 +929,7 @@ fn report_unreachable_pattern<'p, 'tcx>(
920
929
covered_by_catchall : None ,
921
930
covered_by_one : None ,
922
931
covered_by_many : None ,
932
+ suggest_remove,
923
933
} ;
924
934
match explanation. covered_by . as_slice ( ) {
925
935
[ ] => {
@@ -960,10 +970,27 @@ fn report_unreachable_pattern<'p, 'tcx>(
960
970
}
961
971
962
972
/// 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 ( ) ;
964
979
for ( arm, is_useful) in report. arm_usefulness . iter ( ) {
965
980
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)
967
994
}
968
995
}
969
996
}
0 commit comments