@@ -368,31 +368,46 @@ fn raw_pat<'a>(p: &'a Pat) -> &'a Pat {
368
368
fn check_exhaustive ( cx : & MatchCheckCtxt , sp : Span , matrix : & Matrix , source : hir:: MatchSource ) {
369
369
match is_useful ( cx, matrix, & [ DUMMY_WILD_PAT ] , ConstructWitness ) {
370
370
UsefulWithWitness ( pats) => {
371
- let witness = match & pats[ .. ] {
372
- [ ref witness ] => & * * witness ,
373
- [ ] => DUMMY_WILD_PAT ,
374
- _ => unreachable ! ( )
371
+ let witnesses = if pats. is_empty ( ) {
372
+ vec ! [ DUMMY_WILD_PAT ]
373
+ } else {
374
+ pats . iter ( ) . map ( |w| & * * w ) . collect ( )
375
375
} ;
376
376
match source {
377
377
hir:: MatchSource :: ForLoopDesugar => {
378
- // `witness ` has the form `Some(<head>)`, peel off the `Some`
379
- let witness = match witness . node {
378
+ // `witnesses[0] ` has the form `Some(<head>)`, peel off the `Some`
379
+ let witness = match witnesses [ 0 ] . node {
380
380
hir:: PatEnum ( _, Some ( ref pats) ) => match & pats[ ..] {
381
381
[ ref pat] => & * * pat,
382
382
_ => unreachable ! ( ) ,
383
383
} ,
384
384
_ => unreachable ! ( ) ,
385
385
} ;
386
-
387
386
span_err ! ( cx. tcx. sess, sp, E0297 ,
388
387
"refutable pattern in `for` loop binding: \
389
388
`{}` not covered",
390
389
pat_to_string( witness) ) ;
391
390
} ,
392
391
_ => {
392
+ let pattern_strings: Vec < _ > = witnesses. iter ( ) . map ( |w| {
393
+ pat_to_string ( w)
394
+ } ) . collect ( ) ;
395
+ const LIMIT : usize = 3 ;
396
+ let joined_patterns = match pattern_strings. len ( ) {
397
+ 0 => unreachable ! ( ) ,
398
+ 1 => format ! ( "`{}`" , pattern_strings[ 0 ] ) ,
399
+ 2 ...LIMIT => {
400
+ let ( tail, head) = pattern_strings. split_last ( ) . unwrap ( ) ;
401
+ format ! ( "`{}`" , head. join( "`, `" ) + "` and `" + tail)
402
+ } ,
403
+ _ => {
404
+ let ( head, tail) = pattern_strings. split_at ( LIMIT ) ;
405
+ format ! ( "`{}` and {} more" , head. join( "`, `" ) , tail. len( ) )
406
+ }
407
+ } ;
393
408
span_err ! ( cx. tcx. sess, sp, E0004 ,
394
- "non-exhaustive patterns: `{}` not covered" ,
395
- pat_to_string ( witness )
409
+ "non-exhaustive patterns: {} not covered" ,
410
+ joined_patterns
396
411
) ;
397
412
} ,
398
413
}
@@ -594,14 +609,15 @@ impl<'tcx, 'container> ty::AdtDefData<'tcx, 'container> {
594
609
}
595
610
}
596
611
597
- fn missing_constructor ( cx : & MatchCheckCtxt , & Matrix ( ref rows) : & Matrix ,
598
- left_ty : Ty , max_slice_length : usize ) -> Option < Constructor > {
612
+ fn missing_constructors ( cx : & MatchCheckCtxt , & Matrix ( ref rows) : & Matrix ,
613
+ left_ty : Ty , max_slice_length : usize ) -> Vec < Constructor > {
599
614
let used_constructors: Vec < Constructor > = rows. iter ( )
600
615
. flat_map ( |row| pat_constructors ( cx, row[ 0 ] , left_ty, max_slice_length) )
601
616
. collect ( ) ;
602
617
all_constructors ( cx, left_ty, max_slice_length)
603
618
. into_iter ( )
604
- . find ( |c| !used_constructors. contains ( c) )
619
+ . filter ( |c| !used_constructors. contains ( c) )
620
+ . collect ( )
605
621
}
606
622
607
623
/// This determines the set of all possible constructors of a pattern matching
@@ -680,46 +696,44 @@ fn is_useful(cx: &MatchCheckCtxt,
680
696
681
697
let constructors = pat_constructors ( cx, v[ 0 ] , left_ty, max_slice_length) ;
682
698
if constructors. is_empty ( ) {
683
- match missing_constructor ( cx, matrix, left_ty, max_slice_length) {
684
- None => {
685
- all_constructors ( cx, left_ty, max_slice_length) . into_iter ( ) . map ( |c| {
686
- match is_useful_specialized ( cx, matrix, v, c. clone ( ) , left_ty, witness) {
687
- UsefulWithWitness ( pats) => UsefulWithWitness ( {
688
- let arity = constructor_arity ( cx, & c, left_ty) ;
689
- let mut result = {
690
- let pat_slice = & pats[ ..] ;
691
- let subpats: Vec < _ > = ( 0 ..arity) . map ( |i| {
692
- pat_slice. get ( i) . map_or ( DUMMY_WILD_PAT , |p| & * * p)
693
- } ) . collect ( ) ;
694
- vec ! [ construct_witness( cx, & c, subpats, left_ty) ]
695
- } ;
696
- result. extend ( pats. into_iter ( ) . skip ( arity) ) ;
697
- result
698
- } ) ,
699
- result => result
700
- }
701
- } ) . find ( |result| result != & NotUseful ) . unwrap_or ( NotUseful )
702
- } ,
703
-
704
- Some ( constructor) => {
705
- let matrix = rows. iter ( ) . filter_map ( |r| {
706
- if pat_is_binding_or_wild ( & cx. tcx . def_map . borrow ( ) , raw_pat ( r[ 0 ] ) ) {
707
- Some ( r[ 1 ..] . to_vec ( ) )
708
- } else {
709
- None
710
- }
711
- } ) . collect ( ) ;
712
- match is_useful ( cx, & matrix, & v[ 1 ..] , witness) {
713
- UsefulWithWitness ( pats) => {
714
- let arity = constructor_arity ( cx, & constructor, left_ty) ;
715
- let wild_pats = vec ! [ DUMMY_WILD_PAT ; arity] ;
716
- let enum_pat = construct_witness ( cx, & constructor, wild_pats, left_ty) ;
717
- let mut new_pats = vec ! [ enum_pat] ;
718
- new_pats. extend ( pats) ;
719
- UsefulWithWitness ( new_pats)
720
- } ,
699
+ let constructors = missing_constructors ( cx, matrix, left_ty, max_slice_length) ;
700
+ if constructors. is_empty ( ) {
701
+ all_constructors ( cx, left_ty, max_slice_length) . into_iter ( ) . map ( |c| {
702
+ match is_useful_specialized ( cx, matrix, v, c. clone ( ) , left_ty, witness) {
703
+ UsefulWithWitness ( pats) => UsefulWithWitness ( {
704
+ let arity = constructor_arity ( cx, & c, left_ty) ;
705
+ let mut result = {
706
+ let pat_slice = & pats[ ..] ;
707
+ let subpats: Vec < _ > = ( 0 ..arity) . map ( |i| {
708
+ pat_slice. get ( i) . map_or ( DUMMY_WILD_PAT , |p| & * * p)
709
+ } ) . collect ( ) ;
710
+ vec ! [ construct_witness( cx, & c, subpats, left_ty) ]
711
+ } ;
712
+ result. extend ( pats. into_iter ( ) . skip ( arity) ) ;
713
+ result
714
+ } ) ,
721
715
result => result
722
716
}
717
+ } ) . find ( |result| result != & NotUseful ) . unwrap_or ( NotUseful )
718
+ } else {
719
+ let matrix = rows. iter ( ) . filter_map ( |r| {
720
+ if pat_is_binding_or_wild ( & cx. tcx . def_map . borrow ( ) , raw_pat ( r[ 0 ] ) ) {
721
+ Some ( r[ 1 ..] . to_vec ( ) )
722
+ } else {
723
+ None
724
+ }
725
+ } ) . collect ( ) ;
726
+ match is_useful ( cx, & matrix, & v[ 1 ..] , witness) {
727
+ UsefulWithWitness ( pats) => {
728
+ let mut new_pats: Vec < _ > = constructors. into_iter ( ) . map ( |constructor| {
729
+ let arity = constructor_arity ( cx, & constructor, left_ty) ;
730
+ let wild_pats = vec ! [ DUMMY_WILD_PAT ; arity] ;
731
+ construct_witness ( cx, & constructor, wild_pats, left_ty)
732
+ } ) . collect ( ) ;
733
+ new_pats. extend ( pats) ;
734
+ UsefulWithWitness ( new_pats)
735
+ } ,
736
+ result => result
723
737
}
724
738
}
725
739
} else {
0 commit comments