@@ -368,31 +368,46 @@ fn raw_pat<'a>(p: &'a Pat) -> &'a Pat {
368368fn check_exhaustive ( cx : & MatchCheckCtxt , sp : Span , matrix : & Matrix , source : hir:: MatchSource ) {
369369 match is_useful ( cx, matrix, & [ DUMMY_WILD_PAT ] , ConstructWitness ) {
370370 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 ( )
375375 } ;
376376 match source {
377377 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 {
380380 hir:: PatEnum ( _, Some ( ref pats) ) => match & pats[ ..] {
381381 [ ref pat] => & * * pat,
382382 _ => unreachable ! ( ) ,
383383 } ,
384384 _ => unreachable ! ( ) ,
385385 } ;
386-
387386 span_err ! ( cx. tcx. sess, sp, E0297 ,
388387 "refutable pattern in `for` loop binding: \
389388 `{}` not covered",
390389 pat_to_string( witness) ) ;
391390 } ,
392391 _ => {
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+ } ;
393408 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
396411 ) ;
397412 } ,
398413 }
@@ -594,14 +609,15 @@ impl<'tcx, 'container> ty::AdtDefData<'tcx, 'container> {
594609 }
595610}
596611
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 > {
599614 let used_constructors: Vec < Constructor > = rows. iter ( )
600615 . flat_map ( |row| pat_constructors ( cx, row[ 0 ] , left_ty, max_slice_length) )
601616 . collect ( ) ;
602617 all_constructors ( cx, left_ty, max_slice_length)
603618 . into_iter ( )
604- . find ( |c| !used_constructors. contains ( c) )
619+ . filter ( |c| !used_constructors. contains ( c) )
620+ . collect ( )
605621}
606622
607623/// This determines the set of all possible constructors of a pattern matching
@@ -680,46 +696,44 @@ fn is_useful(cx: &MatchCheckCtxt,
680696
681697 let constructors = pat_constructors ( cx, v[ 0 ] , left_ty, max_slice_length) ;
682698 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+ } ) ,
721715 result => result
722716 }
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
723737 }
724738 }
725739 } else {
0 commit comments