1
- use super :: _match:: { MatchCheckCtxt , Matrix , Witness , expand_pattern, is_useful} ;
1
+ use super :: _match:: { MatchCheckCtxt , Matrix , expand_pattern, is_useful} ;
2
2
use super :: _match:: Usefulness :: * ;
3
3
use super :: _match:: WitnessPreference :: * ;
4
4
@@ -276,26 +276,26 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
276
276
expand_pattern( cx, pattern)
277
277
] ] . into_iter ( ) . collect ( ) ;
278
278
279
- let witness = match check_not_useful ( cx, pattern_ty, & pats) {
279
+ let witnesses = match check_not_useful ( cx, pattern_ty, & pats) {
280
280
Ok ( _) => return ,
281
- Err ( ( witness , _ ) ) => witness ,
281
+ Err ( err ) => err ,
282
282
} ;
283
283
284
- let pattern_string = witness [ 0 ] . single_pattern ( ) . to_string ( ) ;
284
+ let joined_patterns = joined_uncovered_patterns ( & witnesses ) ;
285
285
let mut err = struct_span_err ! (
286
286
self . tcx. sess, pat. span, E0005 ,
287
- "refutable pattern in {}: `{}` not covered" ,
288
- origin, pattern_string
287
+ "refutable pattern in {}: {} not covered" ,
288
+ origin, joined_patterns
289
289
) ;
290
- err. span_label ( pat. span , match pat. node {
291
- PatKind :: Path ( hir:: QPath :: Resolved ( None , ref path) )
292
- if path. segments . len ( ) == 1 && path. segments [ 0 ] . args . is_none ( ) => {
290
+ err. span_label ( pat. span , match & pat. node {
291
+ PatKind :: Path ( hir:: QPath :: Resolved ( None , path) )
292
+ if path. segments . len ( ) == 1 && path. segments [ 0 ] . args . is_none ( ) => {
293
293
format ! ( "interpreted as {} {} pattern, not new variable" ,
294
294
path. res. article( ) , path. res. descr( ) )
295
295
}
296
- _ => format ! ( "pattern `{}` not covered" , pattern_string ) ,
296
+ _ => pattern_not_convered_label ( & witnesses , & joined_patterns ) ,
297
297
} ) ;
298
- adt_defined_here ( cx, pattern_ty . peel_refs ( ) , & mut err) ;
298
+ adt_defined_here ( cx, & mut err, pattern_ty , & witnesses ) ;
299
299
err. emit ( ) ;
300
300
} ) ;
301
301
}
@@ -437,11 +437,15 @@ fn check_not_useful(
437
437
cx : & mut MatchCheckCtxt < ' _ , ' tcx > ,
438
438
ty : Ty < ' tcx > ,
439
439
matrix : & Matrix < ' _ , ' tcx > ,
440
- ) -> Result < ( ) , ( Vec < Witness < ' tcx > > , Pattern < ' tcx > ) > {
440
+ ) -> Result < ( ) , Vec < Pattern < ' tcx > > > {
441
441
let wild_pattern = Pattern { ty, span : DUMMY_SP , kind : box PatternKind :: Wild } ;
442
442
match is_useful ( cx, matrix, & [ & wild_pattern] , ConstructWitness ) {
443
443
NotUseful => Ok ( ( ) ) , // This is good, wildcard pattern isn't reachable.
444
- UsefulWithWitness ( pats) => Err ( ( pats, wild_pattern) ) ,
444
+ UsefulWithWitness ( pats) => Err ( if pats. is_empty ( ) {
445
+ vec ! [ wild_pattern]
446
+ } else {
447
+ pats. into_iter ( ) . map ( |w| w. single_pattern ( ) ) . collect ( )
448
+ } ) ,
445
449
Useful => bug ! ( ) ,
446
450
}
447
451
}
@@ -452,42 +456,26 @@ fn check_exhaustive<'tcx>(
452
456
sp : Span ,
453
457
matrix : & Matrix < ' _ , ' tcx > ,
454
458
) {
455
- let ( pats , wild_pattern ) = match check_not_useful ( cx, scrut_ty, matrix) {
459
+ let witnesses = match check_not_useful ( cx, scrut_ty, matrix) {
456
460
Ok ( _) => return ,
457
461
Err ( err) => err,
458
462
} ;
459
463
460
- let witnesses = if pats. is_empty ( ) {
461
- vec ! [ & wild_pattern]
462
- } else {
463
- pats. iter ( ) . map ( |w| w. single_pattern ( ) ) . collect ( )
464
- } ;
465
-
466
464
let joined_patterns = joined_uncovered_patterns ( & witnesses) ;
467
-
468
- let mut err = create_e0004 ( cx. tcx . sess , sp, format ! (
469
- "non-exhaustive patterns: {} not covered" ,
470
- joined_patterns,
471
- ) ) ;
472
- err. span_label ( sp, match witnesses. len ( ) {
473
- 1 => format ! ( "pattern {} not covered" , joined_patterns) ,
474
- _ => format ! ( "patterns {} not covered" , joined_patterns) ,
475
- } ) ;
476
- // point at the definition of non-covered enum variants
477
- let scrut_ty = scrut_ty. peel_refs ( ) ;
478
- adt_defined_here ( cx, scrut_ty, & mut err) ;
479
- let patterns = witnesses. iter ( ) . map ( |p| ( * * p) . clone ( ) ) . collect :: < Vec < Pattern < ' _ > > > ( ) ;
480
- if patterns. len ( ) < 4 {
481
- for sp in maybe_point_at_variant ( scrut_ty, & patterns) {
482
- err. span_label ( sp, "not covered" ) ;
483
- }
484
- }
485
- err. help ( "ensure that all possible cases are being handled, \
486
- possibly by adding wildcards or more match arms") ;
487
- err. emit ( ) ;
465
+ let mut err = create_e0004 (
466
+ cx. tcx . sess , sp,
467
+ format ! ( "non-exhaustive patterns: {} not covered" , joined_patterns) ,
468
+ ) ;
469
+ err. span_label ( sp, pattern_not_convered_label ( & witnesses, & joined_patterns) ) ;
470
+ adt_defined_here ( cx, & mut err, scrut_ty, & witnesses) ;
471
+ err. help (
472
+ "ensure that all possible cases are being handled, \
473
+ possibly by adding wildcards or more match arms"
474
+ )
475
+ . emit ( ) ;
488
476
}
489
477
490
- fn joined_uncovered_patterns ( witnesses : & [ & Pattern < ' _ > ] ) -> String {
478
+ fn joined_uncovered_patterns ( witnesses : & [ Pattern < ' _ > ] ) -> String {
491
479
const LIMIT : usize = 3 ;
492
480
match witnesses {
493
481
[ ] => bug ! ( ) ,
@@ -504,11 +492,31 @@ fn joined_uncovered_patterns(witnesses: &[&Pattern<'_>]) -> String {
504
492
}
505
493
}
506
494
507
- fn adt_defined_here ( cx : & mut MatchCheckCtxt < ' _ , ' _ > , ty : Ty < ' _ > , err : & mut DiagnosticBuilder < ' _ > ) {
495
+ fn pattern_not_convered_label ( witnesses : & [ Pattern < ' _ > ] , joined_patterns : & str ) -> String {
496
+ match witnesses. len ( ) {
497
+ 1 => format ! ( "pattern {} not covered" , joined_patterns) ,
498
+ _ => format ! ( "patterns {} not covered" , joined_patterns) ,
499
+ }
500
+ }
501
+
502
+ /// Point at the definition of non-covered `enum` variants.
503
+ fn adt_defined_here (
504
+ cx : & MatchCheckCtxt < ' _ , ' _ > ,
505
+ err : & mut DiagnosticBuilder < ' _ > ,
506
+ ty : Ty < ' _ > ,
507
+ witnesses : & [ Pattern < ' _ > ] ,
508
+ ) {
509
+ let ty = ty. peel_refs ( ) ;
508
510
if let ty:: Adt ( def, _) = ty. sty {
509
511
if let Some ( sp) = cx. tcx . hir ( ) . span_if_local ( def. did ) {
510
512
err. span_label ( sp, format ! ( "`{}` defined here" , ty) ) ;
511
513
}
514
+
515
+ if witnesses. len ( ) < 4 {
516
+ for sp in maybe_point_at_variant ( ty, & witnesses) {
517
+ err. span_label ( sp, "not covered" ) ;
518
+ }
519
+ }
512
520
}
513
521
}
514
522
0 commit comments