@@ -52,7 +52,7 @@ struct MatchVisitor<'a, 'tcx> {
5252 signalled_error : SignalledError ,
5353}
5454
55- impl < ' a , ' tcx > Visitor < ' tcx > for MatchVisitor < ' a , ' tcx > {
55+ impl < ' tcx > Visitor < ' tcx > for MatchVisitor < ' _ , ' tcx > {
5656 fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' tcx > {
5757 NestedVisitorMap :: None
5858 }
@@ -89,8 +89,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
8989 }
9090}
9191
92-
93- impl < ' a , ' tcx > PatternContext < ' a , ' tcx > {
92+ impl PatternContext < ' _ , ' _ > {
9493 fn report_inlining_errors ( & self , pat_span : Span ) {
9594 for error in & self . errors {
9695 match * error {
@@ -122,7 +121,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
122121 }
123122}
124123
125- impl < ' a , ' tcx > MatchVisitor < ' a , ' tcx > {
124+ impl < ' tcx > MatchVisitor < ' _ , ' tcx > {
126125 fn check_patterns ( & mut self , has_guard : bool , pats : & [ P < Pat > ] ) {
127126 check_legality_of_move_bindings ( self , has_guard, pats) ;
128127 for pat in pats {
@@ -265,37 +264,26 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
265264 expand_pattern( cx, pattern)
266265 ] ] . into_iter ( ) . collect ( ) ;
267266
268- let wild_pattern = Pattern {
269- ty : pattern_ty,
270- span : DUMMY_SP ,
271- kind : box PatternKind :: Wild ,
272- } ;
273- let witness = match is_useful ( cx, & pats, & [ & wild_pattern] , ConstructWitness ) {
274- UsefulWithWitness ( witness) => witness,
275- NotUseful => return ,
276- Useful => bug ! ( )
267+ let witnesses = match check_not_useful ( cx, pattern_ty, & pats) {
268+ Ok ( _) => return ,
269+ Err ( err) => err,
277270 } ;
278271
279- let pattern_string = witness [ 0 ] . single_pattern ( ) . to_string ( ) ;
272+ let joined_patterns = joined_uncovered_patterns ( & witnesses ) ;
280273 let mut err = struct_span_err ! (
281274 self . tcx. sess, pat. span, E0005 ,
282- "refutable pattern in {}: `{}` not covered" ,
283- origin, pattern_string
275+ "refutable pattern in {}: {} not covered" ,
276+ origin, joined_patterns
284277 ) ;
285- let label_msg = match pat. node {
286- PatKind :: Path ( hir:: QPath :: Resolved ( None , ref path) )
287- if path. segments . len ( ) == 1 && path. segments [ 0 ] . args . is_none ( ) => {
278+ err . span_label ( pat . span , match & pat. node {
279+ PatKind :: Path ( hir:: QPath :: Resolved ( None , path) )
280+ if path. segments . len ( ) == 1 && path. segments [ 0 ] . args . is_none ( ) => {
288281 format ! ( "interpreted as {} {} pattern, not new variable" ,
289282 path. res. article( ) , path. res. descr( ) )
290283 }
291- _ => format ! ( "pattern `{}` not covered" , pattern_string) ,
292- } ;
293- err. span_label ( pat. span , label_msg) ;
294- if let ty:: Adt ( def, _) = pattern_ty. sty {
295- if let Some ( sp) = self . tcx . hir ( ) . span_if_local ( def. did ) {
296- err. span_label ( sp, format ! ( "`{}` defined here" , pattern_ty) ) ;
297- }
298- }
284+ _ => pattern_not_convered_label ( & witnesses, & joined_patterns) ,
285+ } ) ;
286+ adt_defined_here ( cx, & mut err, pattern_ty, & witnesses) ;
299287 err. emit ( ) ;
300288 } ) ;
301289 }
@@ -350,9 +338,9 @@ fn pat_is_catchall(pat: &Pat) -> bool {
350338}
351339
352340// Check for unreachable patterns
353- fn check_arms < ' a , ' tcx > (
354- cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
355- arms : & [ ( Vec < ( & ' a Pattern < ' tcx > , & hir:: Pat ) > , Option < & hir:: Expr > ) ] ,
341+ fn check_arms < ' tcx > (
342+ cx : & mut MatchCheckCtxt < ' _ , ' tcx > ,
343+ arms : & [ ( Vec < ( & Pattern < ' tcx > , & hir:: Pat ) > , Option < & hir:: Expr > ) ] ,
356344 source : hir:: MatchSource ,
357345) {
358346 let mut seen = Matrix :: empty ( ) ;
@@ -433,104 +421,124 @@ fn check_arms<'a, 'tcx>(
433421 }
434422}
435423
436- fn check_exhaustive < ' p , ' a , ' tcx > (
437- cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
424+ fn check_not_useful (
425+ cx : & mut MatchCheckCtxt < ' _ , ' tcx > ,
426+ ty : Ty < ' tcx > ,
427+ matrix : & Matrix < ' _ , ' tcx > ,
428+ ) -> Result < ( ) , Vec < Pattern < ' tcx > > > {
429+ let wild_pattern = Pattern { ty, span : DUMMY_SP , kind : box PatternKind :: Wild } ;
430+ match is_useful ( cx, matrix, & [ & wild_pattern] , ConstructWitness ) {
431+ NotUseful => Ok ( ( ) ) , // This is good, wildcard pattern isn't reachable.
432+ UsefulWithWitness ( pats) => Err ( if pats. is_empty ( ) {
433+ vec ! [ wild_pattern]
434+ } else {
435+ pats. into_iter ( ) . map ( |w| w. single_pattern ( ) ) . collect ( )
436+ } ) ,
437+ Useful => bug ! ( ) ,
438+ }
439+ }
440+
441+ fn check_exhaustive < ' tcx > (
442+ cx : & mut MatchCheckCtxt < ' _ , ' tcx > ,
438443 scrut_ty : Ty < ' tcx > ,
439444 sp : Span ,
440- matrix : & Matrix < ' p , ' tcx > ,
445+ matrix : & Matrix < ' _ , ' tcx > ,
441446) {
442- let wild_pattern = Pattern {
443- ty : scrut_ty,
444- span : DUMMY_SP ,
445- kind : box PatternKind :: Wild ,
447+ let witnesses = match check_not_useful ( cx, scrut_ty, matrix) {
448+ Ok ( _) => return ,
449+ Err ( err) => err,
446450 } ;
447- match is_useful ( cx, matrix, & [ & wild_pattern] , ConstructWitness ) {
448- UsefulWithWitness ( pats) => {
449- let witnesses = if pats. is_empty ( ) {
450- vec ! [ & wild_pattern]
451- } else {
452- pats. iter ( ) . map ( |w| w. single_pattern ( ) ) . collect ( )
453- } ;
454451
455- const LIMIT : usize = 3 ;
456- let joined_patterns = match witnesses. len ( ) {
457- 0 => bug ! ( ) ,
458- 1 => format ! ( "`{}`" , witnesses[ 0 ] ) ,
459- 2 ..=LIMIT => {
460- let ( tail, head) = witnesses. split_last ( ) . unwrap ( ) ;
461- let head: Vec < _ > = head. iter ( ) . map ( |w| w. to_string ( ) ) . collect ( ) ;
462- format ! ( "`{}` and `{}`" , head. join( "`, `" ) , tail)
463- }
464- _ => {
465- let ( head, tail) = witnesses. split_at ( LIMIT ) ;
466- let head: Vec < _ > = head. iter ( ) . map ( |w| w. to_string ( ) ) . collect ( ) ;
467- format ! ( "`{}` and {} more" , head. join( "`, `" ) , tail. len( ) )
468- }
469- } ;
452+ let joined_patterns = joined_uncovered_patterns ( & witnesses) ;
453+ let mut err = create_e0004 (
454+ cx. tcx . sess , sp,
455+ format ! ( "non-exhaustive patterns: {} not covered" , joined_patterns) ,
456+ ) ;
457+ err. span_label ( sp, pattern_not_convered_label ( & witnesses, & joined_patterns) ) ;
458+ adt_defined_here ( cx, & mut err, scrut_ty, & witnesses) ;
459+ err. help (
460+ "ensure that all possible cases are being handled, \
461+ possibly by adding wildcards or more match arms"
462+ )
463+ . emit ( ) ;
464+ }
470465
471- let label_text = match witnesses. len ( ) {
472- 1 => format ! ( "pattern {} not covered" , joined_patterns) ,
473- _ => format ! ( "patterns {} not covered" , joined_patterns) ,
474- } ;
475- let mut err = create_e0004 ( cx. tcx . sess , sp, format ! (
476- "non-exhaustive patterns: {} not covered" ,
477- joined_patterns,
478- ) ) ;
479- err. span_label ( sp, label_text) ;
480- // point at the definition of non-covered enum variants
481- if let ty:: Adt ( def, _) = scrut_ty. sty {
482- if let Some ( sp) = cx. tcx . hir ( ) . span_if_local ( def. did ) {
483- err. span_label ( sp, format ! ( "`{}` defined here" , scrut_ty) ) ;
484- }
485- }
486- let patterns = witnesses. iter ( ) . map ( |p| ( * * p) . clone ( ) ) . collect :: < Vec < Pattern < ' _ > > > ( ) ;
487- if patterns. len ( ) < 4 {
488- for sp in maybe_point_at_variant ( cx, scrut_ty, patterns. as_slice ( ) ) {
489- err. span_label ( sp, "not covered" ) ;
490- }
491- }
492- err. help ( "ensure that all possible cases are being handled, \
493- possibly by adding wildcards or more match arms") ;
494- err. emit ( ) ;
466+ fn joined_uncovered_patterns ( witnesses : & [ Pattern < ' _ > ] ) -> String {
467+ const LIMIT : usize = 3 ;
468+ match witnesses {
469+ [ ] => bug ! ( ) ,
470+ [ witness] => format ! ( "`{}`" , witness) ,
471+ [ head @ .., tail] if head. len ( ) < LIMIT => {
472+ let head: Vec < _ > = head. iter ( ) . map ( <_ >:: to_string) . collect ( ) ;
473+ format ! ( "`{}` and `{}`" , head. join( "`, `" ) , tail)
495474 }
496- NotUseful => {
497- // This is good, wildcard pattern isn't reachable
475+ _ => {
476+ let ( head, tail) = witnesses. split_at ( LIMIT ) ;
477+ let head: Vec < _ > = head. iter ( ) . map ( <_ >:: to_string) . collect ( ) ;
478+ format ! ( "`{}` and {} more" , head. join( "`, `" ) , tail. len( ) )
498479 }
499- _ => bug ! ( )
500480 }
501481}
502482
503- fn maybe_point_at_variant (
504- cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
505- ty : Ty < ' tcx > ,
506- patterns : & [ Pattern < ' _ > ] ,
507- ) -> Vec < Span > {
483+ fn pattern_not_convered_label ( witnesses : & [ Pattern < ' _ > ] , joined_patterns : & str ) -> String {
484+ format ! ( "pattern{} {} not covered" , rustc_errors:: pluralise!( witnesses. len( ) ) , joined_patterns)
485+ }
486+
487+ /// Point at the definition of non-covered `enum` variants.
488+ fn adt_defined_here (
489+ cx : & MatchCheckCtxt < ' _ , ' _ > ,
490+ err : & mut DiagnosticBuilder < ' _ > ,
491+ ty : Ty < ' _ > ,
492+ witnesses : & [ Pattern < ' _ > ] ,
493+ ) {
494+ let ty = ty. peel_refs ( ) ;
495+ if let ty:: Adt ( def, _) = ty. sty {
496+ if let Some ( sp) = cx. tcx . hir ( ) . span_if_local ( def. did ) {
497+ err. span_label ( sp, format ! ( "`{}` defined here" , ty) ) ;
498+ }
499+
500+ if witnesses. len ( ) < 4 {
501+ for sp in maybe_point_at_variant ( ty, & witnesses) {
502+ err. span_label ( sp, "not covered" ) ;
503+ }
504+ }
505+ }
506+ }
507+
508+ fn maybe_point_at_variant ( ty : Ty < ' _ > , patterns : & [ Pattern < ' _ > ] ) -> Vec < Span > {
508509 let mut covered = vec ! [ ] ;
509510 if let ty:: Adt ( def, _) = ty. sty {
510511 // Don't point at variants that have already been covered due to other patterns to avoid
511- // visual clutter
512+ // visual clutter.
512513 for pattern in patterns {
513- let pk: & PatternKind < ' _ > = & pattern. kind ;
514- if let PatternKind :: Variant { adt_def, variant_index, subpatterns, .. } = pk {
515- if adt_def. did == def. did {
514+ use PatternKind :: { AscribeUserType , Deref , Variant , Or , Leaf } ;
515+ match & * pattern. kind {
516+ AscribeUserType { subpattern, .. } | Deref { subpattern } => {
517+ covered. extend ( maybe_point_at_variant ( ty, slice:: from_ref ( & subpattern) ) ) ;
518+ }
519+ Variant { adt_def, variant_index, subpatterns, .. } if adt_def. did == def. did => {
516520 let sp = def. variants [ * variant_index] . ident . span ;
517521 if covered. contains ( & sp) {
518522 continue ;
519523 }
520524 covered. push ( sp) ;
521- let subpatterns = subpatterns. iter ( )
525+
526+ let pats = subpatterns. iter ( )
522527 . map ( |field_pattern| field_pattern. pattern . clone ( ) )
523- . collect :: < Vec < _ > > ( ) ;
524- covered. extend (
525- maybe_point_at_variant ( cx, ty, subpatterns. as_slice ( ) ) ,
526- ) ;
528+ . collect :: < Box < [ _ ] > > ( ) ;
529+ covered. extend ( maybe_point_at_variant ( ty, & pats) ) ;
527530 }
528- }
529- if let PatternKind :: Leaf { subpatterns } = pk {
530- let subpatterns = subpatterns. iter ( )
531- . map ( |field_pattern| field_pattern. pattern . clone ( ) )
532- . collect :: < Vec < _ > > ( ) ;
533- covered. extend ( maybe_point_at_variant ( cx, ty, subpatterns. as_slice ( ) ) ) ;
531+ Leaf { subpatterns } => {
532+ let pats = subpatterns. iter ( )
533+ . map ( |field_pattern| field_pattern. pattern . clone ( ) )
534+ . collect :: < Box < [ _ ] > > ( ) ;
535+ covered. extend ( maybe_point_at_variant ( ty, & pats) ) ;
536+ }
537+ Or { pats } => {
538+ let pats = pats. iter ( ) . cloned ( ) . collect :: < Box < [ _ ] > > ( ) ;
539+ covered. extend ( maybe_point_at_variant ( ty, & pats) ) ;
540+ }
541+ _ => { }
534542 }
535543 }
536544 }
@@ -627,7 +635,7 @@ struct AtBindingPatternVisitor<'a, 'b, 'tcx> {
627635 bindings_allowed: bool
628636}
629637
630- impl <' a , ' b , ' tcx , ' v> Visitor <' v> for AtBindingPatternVisitor <' a , ' b , ' tcx > {
638+ impl <' v> Visitor <' v> for AtBindingPatternVisitor <' _ , ' _ , ' _ > {
631639 fn nested_visit_map<' this>( & ' this mut self ) -> NestedVisitorMap <' this, ' v> {
632640 NestedVisitorMap :: None
633641 }
0 commit comments