@@ -399,6 +399,25 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
399
399
self . 0 . iter ( ) . map ( |p| * p)
400
400
}
401
401
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
+
402
421
/// This computes `D(self)`. See top of the file for explanations.
403
422
fn specialize_wildcard ( & self ) -> Option < Self > {
404
423
if self . head ( ) . is_wildcard ( ) { Some ( self . to_tail ( ) ) } else { None }
@@ -446,8 +465,13 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
446
465
Matrix ( vec ! [ ] )
447
466
}
448
467
468
+ /// Pushes a new row to the matrix. If the row starts with an or-pattern, this expands it.
449
469
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
+ }
451
475
}
452
476
453
477
/// Iterate over the first component of each row
@@ -471,12 +495,10 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
471
495
' a : ' q ,
472
496
' p : ' q ,
473
497
{
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 ( )
480
502
}
481
503
}
482
504
@@ -528,7 +550,12 @@ impl<'p, 'tcx> FromIterator<PatStack<'p, 'tcx>> for Matrix<'p, 'tcx> {
528
550
where
529
551
T : IntoIterator < Item = PatStack < ' p , ' tcx > > ,
530
552
{
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
532
559
}
533
560
}
534
561
@@ -1601,6 +1628,15 @@ pub fn is_useful<'p, 'a, 'tcx>(
1601
1628
1602
1629
assert ! ( rows. iter( ) . all( |r| r. len( ) == v. len( ) ) ) ;
1603
1630
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
+
1604
1640
let ( ty, span) = matrix
1605
1641
. heads ( )
1606
1642
. map ( |r| ( r. ty , r. span ) )
@@ -1802,9 +1838,7 @@ fn pat_constructor<'tcx>(
1802
1838
if slice. is_some ( ) { VarLen ( prefix, suffix) } else { FixedLen ( prefix + suffix) } ;
1803
1839
Some ( Slice ( Slice { array_len, kind } ) )
1804
1840
}
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.
1808
1842
}
1809
1843
}
1810
1844
@@ -2410,9 +2444,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
2410
2444
_ => span_bug ! ( pat. span, "unexpected ctor {:?} for slice pat" , constructor) ,
2411
2445
} ,
2412
2446
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.
2416
2448
} ;
2417
2449
debug ! ( "specialize({:#?}, {:#?}) = {:#?}" , pat, ctor_wild_subpatterns, result) ;
2418
2450
0 commit comments