1
- use super :: _match:: { MatchCheckCtxt , Matrix , expand_pattern, is_useful} ;
1
+ use super :: _match:: { MatchCheckCtxt , Matrix , Witness , expand_pattern, is_useful} ;
2
2
use super :: _match:: Usefulness :: * ;
3
3
use super :: _match:: WitnessPreference :: * ;
4
4
@@ -61,7 +61,7 @@ struct MatchVisitor<'a, 'tcx> {
61
61
signalled_error : SignalledError ,
62
62
}
63
63
64
- impl < ' a , ' tcx > Visitor < ' tcx > for MatchVisitor < ' a , ' tcx > {
64
+ impl < ' tcx > Visitor < ' tcx > for MatchVisitor < ' _ , ' tcx > {
65
65
fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' tcx > {
66
66
NestedVisitorMap :: None
67
67
}
@@ -98,8 +98,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
98
98
}
99
99
}
100
100
101
-
102
- impl < ' a , ' tcx > PatternContext < ' a , ' tcx > {
101
+ impl PatternContext < ' _ , ' _ > {
103
102
fn report_inlining_errors ( & self , pat_span : Span ) {
104
103
for error in & self . errors {
105
104
match * error {
@@ -131,7 +130,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
131
130
}
132
131
}
133
132
134
- impl < ' a , ' tcx > MatchVisitor < ' a , ' tcx > {
133
+ impl < ' tcx > MatchVisitor < ' _ , ' tcx > {
135
134
fn check_patterns ( & mut self , has_guard : bool , pats : & [ P < Pat > ] ) {
136
135
check_legality_of_move_bindings ( self , has_guard, pats) ;
137
136
for pat in pats {
@@ -277,15 +276,9 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
277
276
expand_pattern( cx, pattern)
278
277
] ] . into_iter ( ) . collect ( ) ;
279
278
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,
289
282
} ;
290
283
291
284
let pattern_string = witness[ 0 ] . single_pattern ( ) . to_string ( ) ;
@@ -294,20 +287,15 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
294
287
"refutable pattern in {}: `{}` not covered" ,
295
288
origin, pattern_string
296
289
) ;
297
- let label_msg = match pat. node {
290
+ err . span_label ( pat . span , match pat. node {
298
291
PatKind :: Path ( hir:: QPath :: Resolved ( None , ref path) )
299
292
if path. segments . len ( ) == 1 && path. segments [ 0 ] . args . is_none ( ) => {
300
293
format ! ( "interpreted as {} {} pattern, not new variable" ,
301
294
path. res. article( ) , path. res. descr( ) )
302
295
}
303
296
_ => 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) ;
311
299
err. emit ( ) ;
312
300
} ) ;
313
301
}
@@ -362,9 +350,9 @@ fn pat_is_catchall(pat: &Pat) -> bool {
362
350
}
363
351
364
352
// 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 > ) ] ,
368
356
source : hir:: MatchSource ,
369
357
) {
370
358
let mut seen = Matrix :: empty ( ) ;
@@ -445,104 +433,116 @@ fn check_arms<'a, 'tcx>(
445
433
}
446
434
}
447
435
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 > ,
450
451
scrut_ty : Ty < ' tcx > ,
451
452
sp : Span ,
452
- matrix : & Matrix < ' p , ' tcx > ,
453
+ matrix : & Matrix < ' _ , ' tcx > ,
453
454
) {
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,
458
458
} ;
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
- } ;
466
459
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
+ } ;
482
465
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)
507
474
}
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" ) ;
510
497
}
511
- _ => bug ! ( )
512
498
}
499
+ err. help ( "ensure that all possible cases are being handled, \
500
+ possibly by adding wildcards or more match arms") ;
501
+ err. emit ( ) ;
513
502
}
514
503
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 > {
520
513
let mut covered = vec ! [ ] ;
521
514
if let ty:: Adt ( def, _) = ty. sty {
522
515
// Don't point at variants that have already been covered due to other patterns to avoid
523
- // visual clutter
516
+ // visual clutter.
524
517
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 => {
528
524
let sp = def. variants [ * variant_index] . ident . span ;
529
525
if covered. contains ( & sp) {
530
526
continue ;
531
527
}
532
528
covered. push ( sp) ;
533
- let subpatterns = subpatterns. iter ( )
529
+
530
+ let pats = subpatterns. iter ( )
534
531
. 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) ) ;
539
534
}
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
+ _ => { }
546
546
}
547
547
}
548
548
}
@@ -709,7 +709,7 @@ struct AtBindingPatternVisitor<'a, 'b, 'tcx> {
709
709
bindings_allowed: bool
710
710
}
711
711
712
- impl <' a , ' b , ' tcx , ' v> Visitor <' v> for AtBindingPatternVisitor <' a , ' b , ' tcx > {
712
+ impl <' v> Visitor <' v> for AtBindingPatternVisitor <' _ , ' _ , ' _ > {
713
713
fn nested_visit_map<' this>( & ' this mut self ) -> NestedVisitorMap <' this, ' v> {
714
714
NestedVisitorMap :: None
715
715
}
0 commit comments