@@ -400,6 +400,25 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
400400 self . 0 . iter ( ) . map ( |p| * p)
401401 }
402402
403+ // If the first pattern is an or-pattern, expand this pattern. Otherwise, return `None`.
404+ fn expand_or_pat ( & self ) -> Option < Vec < Self > > {
405+ if self . is_empty ( ) {
406+ None
407+ } else if let PatKind :: Or { pats } = & * self . head ( ) . kind {
408+ Some (
409+ pats. iter ( )
410+ . map ( |pat| {
411+ let mut new_patstack = PatStack :: from_pattern ( pat) ;
412+ new_patstack. 0 . extend_from_slice ( & self . 0 [ 1 ..] ) ;
413+ new_patstack
414+ } )
415+ . collect ( ) ,
416+ )
417+ } else {
418+ None
419+ }
420+ }
421+
403422 /// This computes `D(self)`. See top of the file for explanations.
404423 fn specialize_wildcard ( & self ) -> Option < Self > {
405424 if self . head ( ) . is_wildcard ( ) { Some ( self . to_tail ( ) ) } else { None }
@@ -447,8 +466,13 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
447466 Matrix ( vec ! [ ] )
448467 }
449468
469+ /// Pushes a new row to the matrix. If the row starts with an or-pattern, this expands it.
450470 pub fn push ( & mut self , row : PatStack < ' p , ' tcx > ) {
451- self . 0 . push ( row)
471+ if let Some ( rows) = row. expand_or_pat ( ) {
472+ self . 0 . extend ( rows) ;
473+ } else {
474+ self . 0 . push ( row) ;
475+ }
452476 }
453477
454478 /// Iterate over the first component of each row
@@ -472,12 +496,10 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
472496 ' a : ' q ,
473497 ' p : ' q ,
474498 {
475- Matrix (
476- self . 0
477- . iter ( )
478- . filter_map ( |r| r. specialize_constructor ( cx, constructor, ctor_wild_subpatterns) )
479- . collect ( ) ,
480- )
499+ self . 0
500+ . iter ( )
501+ . filter_map ( |r| r. specialize_constructor ( cx, constructor, ctor_wild_subpatterns) )
502+ . collect ( )
481503 }
482504}
483505
@@ -529,7 +551,12 @@ impl<'p, 'tcx> FromIterator<PatStack<'p, 'tcx>> for Matrix<'p, 'tcx> {
529551 where
530552 T : IntoIterator < Item = PatStack < ' p , ' tcx > > ,
531553 {
532- Matrix ( iter. into_iter ( ) . collect ( ) )
554+ let mut matrix = Matrix :: empty ( ) ;
555+ for x in iter {
556+ // Using `push` ensures we correctly expand or-patterns.
557+ matrix. push ( x) ;
558+ }
559+ matrix
533560 }
534561}
535562
@@ -1602,6 +1629,15 @@ pub fn is_useful<'p, 'a, 'tcx>(
16021629
16031630 assert ! ( rows. iter( ) . all( |r| r. len( ) == v. len( ) ) ) ;
16041631
1632+ // If the first pattern is an or-pattern, expand it.
1633+ if let Some ( vs) = v. expand_or_pat ( ) {
1634+ return vs
1635+ . into_iter ( )
1636+ . map ( |v| is_useful ( cx, matrix, & v, witness_preference, hir_id) )
1637+ . find ( |result| result. is_useful ( ) )
1638+ . unwrap_or ( NotUseful ) ;
1639+ }
1640+
16051641 let ( ty, span) = matrix
16061642 . heads ( )
16071643 . map ( |r| ( r. ty , r. span ) )
@@ -1813,9 +1849,7 @@ fn pat_constructor<'tcx>(
18131849 if slice. is_some ( ) { VarLen ( prefix, suffix) } else { FixedLen ( prefix + suffix) } ;
18141850 Some ( Slice ( Slice { array_len, kind } ) )
18151851 }
1816- PatKind :: Or { .. } => {
1817- bug ! ( "support for or-patterns has not been fully implemented yet." ) ;
1818- }
1852+ PatKind :: Or { .. } => bug ! ( "Or-pattern should have been expanded earlier on." ) ,
18191853 }
18201854}
18211855
@@ -2404,9 +2438,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
24042438 _ => span_bug ! ( pat. span, "unexpected ctor {:?} for slice pat" , constructor) ,
24052439 } ,
24062440
2407- PatKind :: Or { .. } => {
2408- bug ! ( "support for or-patterns has not been fully implemented yet." ) ;
2409- }
2441+ PatKind :: Or { .. } => bug ! ( "Or-pattern should have been expanded earlier on." ) ,
24102442 } ;
24112443 debug ! ( "specialize({:#?}, {:#?}) = {:#?}" , pat, ctor_wild_subpatterns, result) ;
24122444
0 commit comments