1- use super :: _match:: { MatchCheckCtxt , Matrix , expand_pattern, is_useful} ;
1+ use super :: _match:: { MatchCheckCtxt , Matrix , Witness , expand_pattern, is_useful} ;
22use super :: _match:: Usefulness :: * ;
33use super :: _match:: WitnessPreference :: * ;
44
@@ -61,7 +61,7 @@ struct MatchVisitor<'a, 'tcx> {
6161 signalled_error : SignalledError ,
6262}
6363
64- impl < ' a , ' tcx > Visitor < ' tcx > for MatchVisitor < ' a , ' tcx > {
64+ impl < ' tcx > Visitor < ' tcx > for MatchVisitor < ' _ , ' tcx > {
6565 fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' tcx > {
6666 NestedVisitorMap :: None
6767 }
@@ -98,8 +98,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
9898 }
9999}
100100
101-
102- impl < ' a , ' tcx > PatternContext < ' a , ' tcx > {
101+ impl PatternContext < ' _ , ' _ > {
103102 fn report_inlining_errors ( & self , pat_span : Span ) {
104103 for error in & self . errors {
105104 match * error {
@@ -131,7 +130,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
131130 }
132131}
133132
134- impl < ' a , ' tcx > MatchVisitor < ' a , ' tcx > {
133+ impl < ' tcx > MatchVisitor < ' _ , ' tcx > {
135134 fn check_patterns ( & mut self , has_guard : bool , pats : & [ P < Pat > ] ) {
136135 check_legality_of_move_bindings ( self , has_guard, pats) ;
137136 for pat in pats {
@@ -277,15 +276,9 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
277276 expand_pattern( cx, pattern)
278277 ] ] . into_iter ( ) . collect ( ) ;
279278
280- let wild_pattern = Pattern {
281- ty : pattern_ty,
282- span : DUMMY_SP ,
283- kind : box PatternKind :: Wild ,
284- } ;
285- let witness = match is_useful ( cx, & pats, & [ & wild_pattern] , ConstructWitness ) {
286- UsefulWithWitness ( witness) => witness,
287- NotUseful => return ,
288- Useful => bug ! ( )
279+ let witness = match check_not_useful ( cx, pattern_ty, & pats) {
280+ Ok ( _) => return ,
281+ Err ( ( witness, _) ) => witness,
289282 } ;
290283
291284 let pattern_string = witness[ 0 ] . single_pattern ( ) . to_string ( ) ;
@@ -294,20 +287,15 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
294287 "refutable pattern in {}: `{}` not covered" ,
295288 origin, pattern_string
296289 ) ;
297- let label_msg = match pat. node {
290+ err . span_label ( pat . span , match pat. node {
298291 PatKind :: Path ( hir:: QPath :: Resolved ( None , ref path) )
299292 if path. segments . len ( ) == 1 && path. segments [ 0 ] . args . is_none ( ) => {
300293 format ! ( "interpreted as {} {} pattern, not new variable" ,
301294 path. res. article( ) , path. res. descr( ) )
302295 }
303296 _ => format ! ( "pattern `{}` not covered" , pattern_string) ,
304- } ;
305- err. span_label ( pat. span , label_msg) ;
306- if let ty:: Adt ( def, _) = pattern_ty. sty {
307- if let Some ( sp) = self . tcx . hir ( ) . span_if_local ( def. did ) {
308- err. span_label ( sp, format ! ( "`{}` defined here" , pattern_ty) ) ;
309- }
310- }
297+ } ) ;
298+ adt_defined_here ( cx, pattern_ty. peel_refs ( ) , & mut err) ;
311299 err. emit ( ) ;
312300 } ) ;
313301 }
@@ -362,9 +350,9 @@ fn pat_is_catchall(pat: &Pat) -> bool {
362350}
363351
364352// Check for unreachable patterns
365- fn check_arms < ' a , ' tcx > (
366- cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
367- arms : & [ ( Vec < ( & ' a Pattern < ' tcx > , & hir:: Pat ) > , Option < & hir:: Expr > ) ] ,
353+ fn check_arms < ' tcx > (
354+ cx : & mut MatchCheckCtxt < ' _ , ' tcx > ,
355+ arms : & [ ( Vec < ( & Pattern < ' tcx > , & hir:: Pat ) > , Option < & hir:: Expr > ) ] ,
368356 source : hir:: MatchSource ,
369357) {
370358 let mut seen = Matrix :: empty ( ) ;
@@ -445,104 +433,116 @@ fn check_arms<'a, 'tcx>(
445433 }
446434}
447435
448- fn check_exhaustive < ' p , ' a , ' tcx > (
449- cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
436+ fn check_not_useful (
437+ cx : & mut MatchCheckCtxt < ' _ , ' tcx > ,
438+ ty : Ty < ' tcx > ,
439+ matrix : & Matrix < ' _ , ' tcx > ,
440+ ) -> Result < ( ) , ( Vec < Witness < ' tcx > > , Pattern < ' tcx > ) > {
441+ let wild_pattern = Pattern { ty, span : DUMMY_SP , kind : box PatternKind :: Wild } ;
442+ match is_useful ( cx, matrix, & [ & wild_pattern] , ConstructWitness ) {
443+ NotUseful => Ok ( ( ) ) , // This is good, wildcard pattern isn't reachable.
444+ UsefulWithWitness ( pats) => Err ( ( pats, wild_pattern) ) ,
445+ Useful => bug ! ( ) ,
446+ }
447+ }
448+
449+ fn check_exhaustive < ' tcx > (
450+ cx : & mut MatchCheckCtxt < ' _ , ' tcx > ,
450451 scrut_ty : Ty < ' tcx > ,
451452 sp : Span ,
452- matrix : & Matrix < ' p , ' tcx > ,
453+ matrix : & Matrix < ' _ , ' tcx > ,
453454) {
454- let wild_pattern = Pattern {
455- ty : scrut_ty,
456- span : DUMMY_SP ,
457- kind : box PatternKind :: Wild ,
455+ let ( pats, wild_pattern) = match check_not_useful ( cx, scrut_ty, matrix) {
456+ Ok ( _) => return ,
457+ Err ( err) => err,
458458 } ;
459- match is_useful ( cx, matrix, & [ & wild_pattern] , ConstructWitness ) {
460- UsefulWithWitness ( pats) => {
461- let witnesses = if pats. is_empty ( ) {
462- vec ! [ & wild_pattern]
463- } else {
464- pats. iter ( ) . map ( |w| w. single_pattern ( ) ) . collect ( )
465- } ;
466459
467- const LIMIT : usize = 3 ;
468- let joined_patterns = match witnesses. len ( ) {
469- 0 => bug ! ( ) ,
470- 1 => format ! ( "`{}`" , witnesses[ 0 ] ) ,
471- 2 ..=LIMIT => {
472- let ( tail, head) = witnesses. split_last ( ) . unwrap ( ) ;
473- let head: Vec < _ > = head. iter ( ) . map ( |w| w. to_string ( ) ) . collect ( ) ;
474- format ! ( "`{}` and `{}`" , head. join( "`, `" ) , tail)
475- }
476- _ => {
477- let ( head, tail) = witnesses. split_at ( LIMIT ) ;
478- let head: Vec < _ > = head. iter ( ) . map ( |w| w. to_string ( ) ) . collect ( ) ;
479- format ! ( "`{}` and {} more" , head. join( "`, `" ) , tail. len( ) )
480- }
481- } ;
460+ let witnesses = if pats. is_empty ( ) {
461+ vec ! [ & wild_pattern]
462+ } else {
463+ pats. iter ( ) . map ( |w| w. single_pattern ( ) ) . collect ( )
464+ } ;
482465
483- let label_text = match witnesses. len ( ) {
484- 1 => format ! ( "pattern {} not covered" , joined_patterns) ,
485- _ => format ! ( "patterns {} not covered" , joined_patterns) ,
486- } ;
487- let mut err = create_e0004 ( cx. tcx . sess , sp, format ! (
488- "non-exhaustive patterns: {} not covered" ,
489- joined_patterns,
490- ) ) ;
491- err. span_label ( sp, label_text) ;
492- // point at the definition of non-covered enum variants
493- if let ty:: Adt ( def, _) = scrut_ty. sty {
494- if let Some ( sp) = cx. tcx . hir ( ) . span_if_local ( def. did ) {
495- err. span_label ( sp, format ! ( "`{}` defined here" , scrut_ty) ) ;
496- }
497- }
498- let patterns = witnesses. iter ( ) . map ( |p| ( * * p) . clone ( ) ) . collect :: < Vec < Pattern < ' _ > > > ( ) ;
499- if patterns. len ( ) < 4 {
500- for sp in maybe_point_at_variant ( cx, scrut_ty, patterns. as_slice ( ) ) {
501- err. span_label ( sp, "not covered" ) ;
502- }
503- }
504- err. help ( "ensure that all possible cases are being handled, \
505- possibly by adding wildcards or more match arms") ;
506- err. emit ( ) ;
466+ const LIMIT : usize = 3 ;
467+ let joined_patterns = match witnesses. len ( ) {
468+ 0 => bug ! ( ) ,
469+ 1 => format ! ( "`{}`" , witnesses[ 0 ] ) ,
470+ 2 ..=LIMIT => {
471+ let ( tail, head) = witnesses. split_last ( ) . unwrap ( ) ;
472+ let head: Vec < _ > = head. iter ( ) . map ( |w| w. to_string ( ) ) . collect ( ) ;
473+ format ! ( "`{}` and `{}`" , head. join( "`, `" ) , tail)
507474 }
508- NotUseful => {
509- // This is good, wildcard pattern isn't reachable
475+ _ => {
476+ let ( head, tail) = witnesses. split_at ( LIMIT ) ;
477+ let head: Vec < _ > = head. iter ( ) . map ( |w| w. to_string ( ) ) . collect ( ) ;
478+ format ! ( "`{}` and {} more" , head. join( "`, `" ) , tail. len( ) )
479+ }
480+ } ;
481+
482+ let mut err = create_e0004 ( cx. tcx . sess , sp, format ! (
483+ "non-exhaustive patterns: {} not covered" ,
484+ joined_patterns,
485+ ) ) ;
486+ err. span_label ( sp, match witnesses. len ( ) {
487+ 1 => format ! ( "pattern {} not covered" , joined_patterns) ,
488+ _ => format ! ( "patterns {} not covered" , joined_patterns) ,
489+ } ) ;
490+ // point at the definition of non-covered enum variants
491+ let scrut_ty = scrut_ty. peel_refs ( ) ;
492+ adt_defined_here ( cx, scrut_ty, & mut err) ;
493+ let patterns = witnesses. iter ( ) . map ( |p| ( * * p) . clone ( ) ) . collect :: < Vec < Pattern < ' _ > > > ( ) ;
494+ if patterns. len ( ) < 4 {
495+ for sp in maybe_point_at_variant ( scrut_ty, & patterns) {
496+ err. span_label ( sp, "not covered" ) ;
510497 }
511- _ => bug ! ( )
512498 }
499+ err. help ( "ensure that all possible cases are being handled, \
500+ possibly by adding wildcards or more match arms") ;
501+ err. emit ( ) ;
513502}
514503
515- fn maybe_point_at_variant (
516- cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
517- ty : Ty < ' tcx > ,
518- patterns : & [ Pattern < ' _ > ] ,
519- ) -> Vec < Span > {
504+ fn adt_defined_here ( cx : & mut MatchCheckCtxt < ' _ , ' _ > , ty : Ty < ' _ > , err : & mut DiagnosticBuilder < ' _ > ) {
505+ if let ty:: Adt ( def, _) = ty. sty {
506+ if let Some ( sp) = cx. tcx . hir ( ) . span_if_local ( def. did ) {
507+ err. span_label ( sp, format ! ( "`{}` defined here" , ty) ) ;
508+ }
509+ }
510+ }
511+
512+ fn maybe_point_at_variant ( ty : Ty < ' _ > , patterns : & [ Pattern < ' _ > ] ) -> Vec < Span > {
520513 let mut covered = vec ! [ ] ;
521514 if let ty:: Adt ( def, _) = ty. sty {
522515 // Don't point at variants that have already been covered due to other patterns to avoid
523- // visual clutter
516+ // visual clutter.
524517 for pattern in patterns {
525- let pk: & PatternKind < ' _ > = & pattern. kind ;
526- if let PatternKind :: Variant { adt_def, variant_index, subpatterns, .. } = pk {
527- if adt_def. did == def. did {
518+ use PatternKind :: { AscribeUserType , Deref , Variant , Or , Leaf } ;
519+ match & * pattern. kind {
520+ AscribeUserType { subpattern, .. } | Deref { subpattern } => {
521+ covered. extend ( maybe_point_at_variant ( ty, slice:: from_ref ( & subpattern) ) ) ;
522+ }
523+ Variant { adt_def, variant_index, subpatterns, .. } if adt_def. did == def. did => {
528524 let sp = def. variants [ * variant_index] . ident . span ;
529525 if covered. contains ( & sp) {
530526 continue ;
531527 }
532528 covered. push ( sp) ;
533- let subpatterns = subpatterns. iter ( )
529+
530+ let pats = subpatterns. iter ( )
534531 . map ( |field_pattern| field_pattern. pattern . clone ( ) )
535- . collect :: < Vec < _ > > ( ) ;
536- covered. extend (
537- maybe_point_at_variant ( cx, ty, subpatterns. as_slice ( ) ) ,
538- ) ;
532+ . collect :: < Box < [ _ ] > > ( ) ;
533+ covered. extend ( maybe_point_at_variant ( ty, & pats) ) ;
539534 }
540- }
541- if let PatternKind :: Leaf { subpatterns } = pk {
542- let subpatterns = subpatterns. iter ( )
543- . map ( |field_pattern| field_pattern. pattern . clone ( ) )
544- . collect :: < Vec < _ > > ( ) ;
545- covered. extend ( maybe_point_at_variant ( cx, ty, subpatterns. as_slice ( ) ) ) ;
535+ Leaf { subpatterns } => {
536+ let pats = subpatterns. iter ( )
537+ . map ( |field_pattern| field_pattern. pattern . clone ( ) )
538+ . collect :: < Box < [ _ ] > > ( ) ;
539+ covered. extend ( maybe_point_at_variant ( ty, & pats) ) ;
540+ }
541+ Or { pats } => {
542+ let pats = pats. iter ( ) . cloned ( ) . collect :: < Box < [ _ ] > > ( ) ;
543+ covered. extend ( maybe_point_at_variant ( ty, & pats) ) ;
544+ }
545+ _ => { }
546546 }
547547 }
548548 }
@@ -709,7 +709,7 @@ struct AtBindingPatternVisitor<'a, 'b, 'tcx> {
709709 bindings_allowed: bool
710710}
711711
712- impl <' a , ' b , ' tcx , ' v> Visitor <' v> for AtBindingPatternVisitor <' a , ' b , ' tcx > {
712+ impl <' v> Visitor <' v> for AtBindingPatternVisitor <' _ , ' _ , ' _ > {
713713 fn nested_visit_map<' this>( & ' this mut self ) -> NestedVisitorMap <' this, ' v> {
714714 NestedVisitorMap :: None
715715 }
0 commit comments