@@ -16,8 +16,8 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
16
16
use rustc_middle:: ty:: { self , AdtDef , Ty , TyCtxt } ;
17
17
use rustc_pattern_analysis:: errors:: Uncovered ;
18
18
use 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 ,
21
21
} ;
22
22
use rustc_session:: lint:: builtin:: {
23
23
BINDINGS_WITH_VARIANT_NAME , IRREFUTABLE_LET_PATTERNS , UNREACHABLE_PATTERNS ,
@@ -391,12 +391,16 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
391
391
) -> Result < UsefulnessReport < ' p , ' tcx > , ErrorGuaranteed > {
392
392
let pattern_complexity_limit =
393
393
get_limit_size ( cx. tcx . hir ( ) . krate_attrs ( ) , cx. tcx . sess , sym:: pattern_complexity) ;
394
- let report =
395
- rustc_pattern_analysis:: analyze_match ( & cx, & arms, scrut_ty, pattern_complexity_limit)
396
- . map_err ( |err| {
397
- self . error = Err ( err) ;
398
- err
399
- } ) ?;
394
+ let report = rustc_pattern_analysis:: rustc:: analyze_match (
395
+ & cx,
396
+ & arms,
397
+ scrut_ty,
398
+ pattern_complexity_limit,
399
+ )
400
+ . map_err ( |err| {
401
+ self . error = Err ( err) ;
402
+ err
403
+ } ) ?;
400
404
401
405
// Warn unreachable subpatterns.
402
406
for ( arm, is_useful) in report. arm_usefulness . iter ( ) {
@@ -405,9 +409,9 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
405
409
{
406
410
let mut redundant_subpats = redundant_subpats. clone ( ) ;
407
411
// Emit lints in the order in which they occur in the file.
408
- redundant_subpats. sort_unstable_by_key ( |pat| pat. data ( ) . span ) ;
409
- for pat in redundant_subpats {
410
- 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 )
411
415
}
412
416
}
413
417
}
@@ -906,26 +910,52 @@ fn report_irrefutable_let_patterns(
906
910
fn report_unreachable_pattern < ' p , ' tcx > (
907
911
cx : & PatCtxt < ' p , ' tcx > ,
908
912
hir_id : HirId ,
909
- span : Span ,
910
- catchall : Option < Span > ,
913
+ pat : & DeconstructedPat < ' p , ' tcx > ,
914
+ explanation : & RedundancyExplanation < ' p , ' tcx > ,
911
915
) {
912
- cx. tcx . emit_node_span_lint (
913
- UNREACHABLE_PATTERNS ,
914
- hir_id,
915
- span,
916
- UnreachablePattern { span : if catchall. is_some ( ) { Some ( span) } else { None } , catchall } ,
917
- ) ;
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) ;
918
952
}
919
953
920
954
/// Report unreachable arms, if any.
921
955
fn report_arm_reachability < ' p , ' tcx > ( cx : & PatCtxt < ' p , ' tcx > , report : & UsefulnessReport < ' p , ' tcx > ) {
922
- let mut catchall = None ;
923
956
for ( arm, is_useful) in report. arm_usefulness . iter ( ) {
924
- if matches ! ( is_useful, Usefulness :: Redundant ) {
925
- report_unreachable_pattern ( cx, arm. arm_data , arm. pat . data ( ) . span , catchall)
926
- }
927
- if !arm. has_guard && catchall. is_none ( ) && pat_is_catchall ( arm. pat ) {
928
- 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)
929
959
}
930
960
}
931
961
}
0 commit comments