@@ -16,8 +16,8 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
1616use rustc_middle:: ty:: { self , AdtDef , Ty , TyCtxt } ;
1717use rustc_pattern_analysis:: errors:: Uncovered ;
1818use rustc_pattern_analysis:: rustc:: {
19- Constructor , DeconstructedPat , MatchArm , RustcPatCtxt as PatCtxt , Usefulness , UsefulnessReport ,
20- WitnessPat ,
19+ Constructor , DeconstructedPat , MatchArm , RedundancyExplanation , RustcPatCtxt as PatCtxt ,
20+ Usefulness , UsefulnessReport , WitnessPat ,
2121} ;
2222use rustc_session:: lint:: builtin:: {
2323 BINDINGS_WITH_VARIANT_NAME , IRREFUTABLE_LET_PATTERNS , UNREACHABLE_PATTERNS ,
@@ -409,9 +409,9 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
409409 {
410410 let mut redundant_subpats = redundant_subpats. clone ( ) ;
411411 // Emit lints in the order in which they occur in the file.
412- redundant_subpats. sort_unstable_by_key ( |pat| pat. data ( ) . span ) ;
413- for pat in redundant_subpats {
414- report_unreachable_pattern ( cx, arm. arm_data , pat. data ( ) . span , None )
412+ redundant_subpats. sort_unstable_by_key ( |( pat, _ ) | pat. data ( ) . span ) ;
413+ for ( pat, explanation ) in redundant_subpats {
414+ report_unreachable_pattern ( cx, arm. arm_data , pat, & explanation )
415415 }
416416 }
417417 }
@@ -910,26 +910,52 @@ fn report_irrefutable_let_patterns(
910910fn report_unreachable_pattern < ' p , ' tcx > (
911911 cx : & PatCtxt < ' p , ' tcx > ,
912912 hir_id : HirId ,
913- span : Span ,
914- catchall : Option < Span > ,
913+ pat : & DeconstructedPat < ' p , ' tcx > ,
914+ explanation : & RedundancyExplanation < ' p , ' tcx > ,
915915) {
916- cx. tcx . emit_node_span_lint (
917- UNREACHABLE_PATTERNS ,
918- hir_id,
919- span,
920- UnreachablePattern { span : if catchall. is_some ( ) { Some ( span) } else { None } , catchall } ,
921- ) ;
916+ let pat_span = pat. data ( ) . span ;
917+ let mut lint = UnreachablePattern {
918+ span : Some ( pat_span) ,
919+ matches_no_values : None ,
920+ covered_by_catchall : None ,
921+ covered_by_one : None ,
922+ covered_by_many : None ,
923+ } ;
924+ match explanation. covered_by . as_slice ( ) {
925+ [ ] => {
926+ // Empty pattern; we report the uninhabited type that caused the emptiness.
927+ lint. span = None ; // Don't label the pattern itself
928+ pat. walk ( & mut |subpat| {
929+ let ty = * * subpat. ty ( ) ;
930+ if cx. is_uninhabited ( ty) {
931+ lint. matches_no_values = Some ( UnreachableMatchesNoValues { ty } ) ;
932+ false // No need to dig further.
933+ } else if matches ! ( subpat. ctor( ) , Constructor :: Ref | Constructor :: UnionField ) {
934+ false // Don't explore further since they are not by-value.
935+ } else {
936+ true
937+ }
938+ } ) ;
939+ }
940+ [ covering_pat] if pat_is_catchall ( covering_pat) => {
941+ lint. covered_by_catchall = Some ( covering_pat. data ( ) . span ) ;
942+ }
943+ [ covering_pat] => {
944+ lint. covered_by_one = Some ( covering_pat. data ( ) . span ) ;
945+ }
946+ covering_pats => {
947+ let covering_spans = covering_pats. iter ( ) . map ( |p| p. data ( ) . span ) . collect ( ) ;
948+ lint. covered_by_many = Some ( UnreachableCoveredByMany ( covering_spans) ) ;
949+ }
950+ }
951+ cx. tcx . emit_node_span_lint ( UNREACHABLE_PATTERNS , hir_id, pat_span, lint) ;
922952}
923953
924954/// Report unreachable arms, if any.
925955fn report_arm_reachability < ' p , ' tcx > ( cx : & PatCtxt < ' p , ' tcx > , report : & UsefulnessReport < ' p , ' tcx > ) {
926- let mut catchall = None ;
927956 for ( arm, is_useful) in report. arm_usefulness . iter ( ) {
928- if matches ! ( is_useful, Usefulness :: Redundant ) {
929- report_unreachable_pattern ( cx, arm. arm_data , arm. pat . data ( ) . span , catchall)
930- }
931- if !arm. has_guard && catchall. is_none ( ) && pat_is_catchall ( arm. pat ) {
932- catchall = Some ( arm. pat . data ( ) . span ) ;
957+ if let Usefulness :: Redundant ( explanation) = is_useful {
958+ report_unreachable_pattern ( cx, arm. arm_data , arm. pat , explanation)
933959 }
934960 }
935961}
0 commit comments