@@ -52,7 +52,7 @@ struct MatchVisitor<'a, 'tcx> {
52
52
signalled_error : SignalledError ,
53
53
}
54
54
55
- impl < ' a , ' tcx > Visitor < ' tcx > for MatchVisitor < ' a , ' tcx > {
55
+ impl < ' tcx > Visitor < ' tcx > for MatchVisitor < ' _ , ' tcx > {
56
56
fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' tcx > {
57
57
NestedVisitorMap :: None
58
58
}
@@ -89,8 +89,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
89
89
}
90
90
}
91
91
92
-
93
- impl < ' a , ' tcx > PatternContext < ' a , ' tcx > {
92
+ impl PatternContext < ' _ , ' _ > {
94
93
fn report_inlining_errors ( & self , pat_span : Span ) {
95
94
for error in & self . errors {
96
95
match * error {
@@ -122,7 +121,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
122
121
}
123
122
}
124
123
125
- impl < ' a , ' tcx > MatchVisitor < ' a , ' tcx > {
124
+ impl < ' tcx > MatchVisitor < ' _ , ' tcx > {
126
125
fn check_patterns ( & mut self , has_guard : bool , pats : & [ P < Pat > ] ) {
127
126
check_legality_of_move_bindings ( self , has_guard, pats) ;
128
127
for pat in pats {
@@ -265,37 +264,26 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
265
264
expand_pattern( cx, pattern)
266
265
] ] . into_iter ( ) . collect ( ) ;
267
266
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,
277
270
} ;
278
271
279
- let pattern_string = witness [ 0 ] . single_pattern ( ) . to_string ( ) ;
272
+ let joined_patterns = joined_uncovered_patterns ( & witnesses ) ;
280
273
let mut err = struct_span_err ! (
281
274
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
284
277
) ;
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 ( ) => {
288
281
format ! ( "interpreted as {} {} pattern, not new variable" ,
289
282
path. res. article( ) , path. res. descr( ) )
290
283
}
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) ;
299
287
err. emit ( ) ;
300
288
} ) ;
301
289
}
@@ -350,9 +338,9 @@ fn pat_is_catchall(pat: &Pat) -> bool {
350
338
}
351
339
352
340
// 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 > ) ] ,
356
344
source : hir:: MatchSource ,
357
345
) {
358
346
let mut seen = Matrix :: empty ( ) ;
@@ -433,104 +421,124 @@ fn check_arms<'a, 'tcx>(
433
421
}
434
422
}
435
423
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 > ,
438
443
scrut_ty : Ty < ' tcx > ,
439
444
sp : Span ,
440
- matrix : & Matrix < ' p , ' tcx > ,
445
+ matrix : & Matrix < ' _ , ' tcx > ,
441
446
) {
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,
446
450
} ;
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
- } ;
454
451
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
+ }
470
465
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)
495
474
}
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( ) )
498
479
}
499
- _ => bug ! ( )
500
480
}
501
481
}
502
482
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 > {
508
509
let mut covered = vec ! [ ] ;
509
510
if let ty:: Adt ( def, _) = ty. sty {
510
511
// Don't point at variants that have already been covered due to other patterns to avoid
511
- // visual clutter
512
+ // visual clutter.
512
513
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 => {
516
520
let sp = def. variants [ * variant_index] . ident . span ;
517
521
if covered. contains ( & sp) {
518
522
continue ;
519
523
}
520
524
covered. push ( sp) ;
521
- let subpatterns = subpatterns. iter ( )
525
+
526
+ let pats = subpatterns. iter ( )
522
527
. 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) ) ;
527
530
}
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
+ _ => { }
534
542
}
535
543
}
536
544
}
@@ -627,7 +635,7 @@ struct AtBindingPatternVisitor<'a, 'b, 'tcx> {
627
635
bindings_allowed: bool
628
636
}
629
637
630
- impl <' a , ' b , ' tcx , ' v> Visitor <' v> for AtBindingPatternVisitor <' a , ' b , ' tcx > {
638
+ impl <' v> Visitor <' v> for AtBindingPatternVisitor <' _ , ' _ , ' _ > {
631
639
fn nested_visit_map<' this>( & ' this mut self ) -> NestedVisitorMap <' this, ' v> {
632
640
NestedVisitorMap :: None
633
641
}
0 commit comments