@@ -399,6 +399,25 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
399399 self . 0 . iter ( ) . map ( |p| * p)
400400 }
401401
402+ // If the first pattern is an or-pattern, expand this pattern. Otherwise, return `None`.
403+ fn expand_or_pat ( & self ) -> Option < Vec < PatStack < ' p , ' tcx > > > {
404+ if self . is_empty ( ) {
405+ None
406+ } else if let PatKind :: Or { pats } = & * self . head ( ) . kind {
407+ Some (
408+ pats. iter ( )
409+ . map ( |pat| {
410+ let mut new_patstack = PatStack :: from_pattern ( pat) ;
411+ new_patstack. 0 . extend_from_slice ( & self . 0 [ 1 ..] ) ;
412+ new_patstack
413+ } )
414+ . collect ( ) ,
415+ )
416+ } else {
417+ None
418+ }
419+ }
420+
402421 /// This computes `D(self)`. See top of the file for explanations.
403422 fn specialize_wildcard ( & self ) -> Option < Self > {
404423 if self . head ( ) . is_wildcard ( ) { Some ( self . to_tail ( ) ) } else { None }
@@ -446,8 +465,13 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
446465 Matrix ( vec ! [ ] )
447466 }
448467
468+ /// Pushes a new row to the matrix. If the row starts with an or-pattern, this expands it.
449469 pub fn push ( & mut self , row : PatStack < ' p , ' tcx > ) {
450- self . 0 . push ( row)
470+ if let Some ( rows) = row. expand_or_pat ( ) {
471+ self . 0 . extend ( rows) ;
472+ } else {
473+ self . 0 . push ( row) ;
474+ }
451475 }
452476
453477 /// Iterate over the first component of each row
@@ -471,12 +495,10 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
471495 ' a : ' q ,
472496 ' p : ' q ,
473497 {
474- Matrix (
475- self . 0
476- . iter ( )
477- . filter_map ( |r| r. specialize_constructor ( cx, constructor, ctor_wild_subpatterns) )
478- . collect ( ) ,
479- )
498+ self . 0
499+ . iter ( )
500+ . filter_map ( |r| r. specialize_constructor ( cx, constructor, ctor_wild_subpatterns) )
501+ . collect ( )
480502 }
481503}
482504
@@ -528,7 +550,12 @@ impl<'p, 'tcx> FromIterator<PatStack<'p, 'tcx>> for Matrix<'p, 'tcx> {
528550 where
529551 T : IntoIterator < Item = PatStack < ' p , ' tcx > > ,
530552 {
531- Matrix ( iter. into_iter ( ) . collect ( ) )
553+ let mut matrix = Matrix :: empty ( ) ;
554+ for x in iter {
555+ // Using `push` ensures we correctly expand or-patterns.
556+ matrix. push ( x) ;
557+ }
558+ matrix
532559 }
533560}
534561
@@ -1601,6 +1628,15 @@ pub fn is_useful<'p, 'a, 'tcx>(
16011628
16021629 assert ! ( rows. iter( ) . all( |r| r. len( ) == v. len( ) ) ) ;
16031630
1631+ // If the first pattern is an or-pattern, expand it.
1632+ if let Some ( vs) = v. expand_or_pat ( ) {
1633+ return vs
1634+ . into_iter ( )
1635+ . map ( |v| is_useful ( cx, matrix, & v, witness_preference, hir_id) )
1636+ . find ( |result| result. is_useful ( ) )
1637+ . unwrap_or ( NotUseful ) ;
1638+ }
1639+
16041640 let ( ty, span) = matrix
16051641 . heads ( )
16061642 . map ( |r| ( r. ty , r. span ) )
@@ -1802,9 +1838,7 @@ fn pat_constructor<'tcx>(
18021838 if slice. is_some ( ) { VarLen ( prefix, suffix) } else { FixedLen ( prefix + suffix) } ;
18031839 Some ( Slice ( Slice { array_len, kind } ) )
18041840 }
1805- PatKind :: Or { .. } => {
1806- bug ! ( "support for or-patterns has not been fully implemented yet." ) ;
1807- }
1841+ PatKind :: Or { .. } => bug ! ( ) , // Should have been expanded earlier on.
18081842 }
18091843}
18101844
@@ -2410,9 +2444,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
24102444 _ => span_bug ! ( pat. span, "unexpected ctor {:?} for slice pat" , constructor) ,
24112445 } ,
24122446
2413- PatKind :: Or { .. } => {
2414- bug ! ( "support for or-patterns has not been fully implemented yet." ) ;
2415- }
2447+ PatKind :: Or { .. } => bug ! ( ) , // Should have been expanded earlier on.
24162448 } ;
24172449 debug ! ( "specialize({:#?}, {:#?}) = {:#?}" , pat, ctor_wild_subpatterns, result) ;
24182450
0 commit comments