@@ -400,6 +400,25 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
400
400
self . 0 . iter ( ) . map ( |p| * p)
401
401
}
402
402
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
+
403
422
/// This computes `D(self)`. See top of the file for explanations.
404
423
fn specialize_wildcard ( & self ) -> Option < Self > {
405
424
if self . head ( ) . is_wildcard ( ) { Some ( self . to_tail ( ) ) } else { None }
@@ -447,8 +466,13 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
447
466
Matrix ( vec ! [ ] )
448
467
}
449
468
469
+ /// Pushes a new row to the matrix. If the row starts with an or-pattern, this expands it.
450
470
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
+ }
452
476
}
453
477
454
478
/// Iterate over the first component of each row
@@ -472,12 +496,10 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
472
496
' a : ' q ,
473
497
' p : ' q ,
474
498
{
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 ( )
481
503
}
482
504
}
483
505
@@ -529,7 +551,12 @@ impl<'p, 'tcx> FromIterator<PatStack<'p, 'tcx>> for Matrix<'p, 'tcx> {
529
551
where
530
552
T : IntoIterator < Item = PatStack < ' p , ' tcx > > ,
531
553
{
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
533
560
}
534
561
}
535
562
@@ -1602,6 +1629,15 @@ pub fn is_useful<'p, 'a, 'tcx>(
1602
1629
1603
1630
assert ! ( rows. iter( ) . all( |r| r. len( ) == v. len( ) ) ) ;
1604
1631
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
+
1605
1641
let ( ty, span) = matrix
1606
1642
. heads ( )
1607
1643
. map ( |r| ( r. ty , r. span ) )
@@ -1813,9 +1849,7 @@ fn pat_constructor<'tcx>(
1813
1849
if slice. is_some ( ) { VarLen ( prefix, suffix) } else { FixedLen ( prefix + suffix) } ;
1814
1850
Some ( Slice ( Slice { array_len, kind } ) )
1815
1851
}
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." ) ,
1819
1853
}
1820
1854
}
1821
1855
@@ -2404,9 +2438,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
2404
2438
_ => span_bug ! ( pat. span, "unexpected ctor {:?} for slice pat" , constructor) ,
2405
2439
} ,
2406
2440
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." ) ,
2410
2442
} ;
2411
2443
debug ! ( "specialize({:#?}, {:#?}) = {:#?}" , pat, ctor_wild_subpatterns, result) ;
2412
2444
0 commit comments