@@ -379,6 +379,25 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
379
379
fn iter ( & self ) -> impl Iterator < Item = & Pat < ' tcx > > {
380
380
self . 0 . iter ( ) . map ( |p| * p)
381
381
}
382
+
383
+ /// This computes `D(self)`. See top of the file for explanations.
384
+ fn specialize_wildcard ( & self ) -> Option < Self > {
385
+ if self . head ( ) . is_wildcard ( ) { Some ( self . to_tail ( ) ) } else { None }
386
+ }
387
+
388
+ /// This computes `S(constructor, self)`. See top of the file for explanations.
389
+ fn specialize_constructor < ' a , ' q > (
390
+ & self ,
391
+ cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
392
+ constructor : & Constructor < ' tcx > ,
393
+ wild_patterns : & [ & ' q Pat < ' tcx > ] ,
394
+ ) -> Option < PatStack < ' q , ' tcx > >
395
+ where
396
+ ' a : ' q ,
397
+ ' p : ' q ,
398
+ {
399
+ specialize ( cx, self , constructor, wild_patterns)
400
+ }
382
401
}
383
402
384
403
impl < ' p , ' tcx > Default for PatStack < ' p , ' tcx > {
@@ -407,6 +426,30 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
407
426
pub fn push ( & mut self , row : PatStack < ' p , ' tcx > ) {
408
427
self . 0 . push ( row)
409
428
}
429
+
430
+ /// This computes `D(self)`. See top of the file for explanations.
431
+ fn specialize_wildcard ( & self ) -> Self {
432
+ self . 0 . iter ( ) . filter_map ( |r| r. specialize_wildcard ( ) ) . collect ( )
433
+ }
434
+
435
+ /// This computes `S(constructor, self)`. See top of the file for explanations.
436
+ fn specialize_constructor < ' a , ' q > (
437
+ & self ,
438
+ cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
439
+ constructor : & Constructor < ' tcx > ,
440
+ wild_patterns : & [ & ' q Pat < ' tcx > ] ,
441
+ ) -> Matrix < ' q , ' tcx >
442
+ where
443
+ ' a : ' q ,
444
+ ' p : ' q ,
445
+ {
446
+ Matrix (
447
+ self . 0
448
+ . iter ( )
449
+ . filter_map ( |r| r. specialize_constructor ( cx, constructor, wild_patterns) )
450
+ . collect ( ) ,
451
+ )
452
+ }
410
453
}
411
454
412
455
/// Pretty-printer for matrices of patterns, example:
@@ -1423,11 +1466,9 @@ pub fn is_useful<'p, 'a, 'tcx>(
1423
1466
. find ( |result| result. is_useful ( ) )
1424
1467
. unwrap_or ( NotUseful )
1425
1468
} else {
1426
- let matrix = rows
1427
- . iter ( )
1428
- . filter_map ( |r| if r. head ( ) . is_wildcard ( ) { Some ( r. to_tail ( ) ) } else { None } )
1429
- . collect ( ) ;
1430
- match is_useful ( cx, & matrix, & v. to_tail ( ) , witness, hir_id) {
1469
+ let matrix = matrix. specialize_wildcard ( ) ;
1470
+ let v = v. to_tail ( ) ;
1471
+ match is_useful ( cx, & matrix, & v, witness, hir_id) {
1431
1472
UsefulWithWitness ( pats) => {
1432
1473
let cx = & * cx;
1433
1474
// In this case, there's at least one "free"
@@ -1523,7 +1564,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
1523
1564
/// to the specialised version of both the pattern matrix `P` and the new pattern `q`.
1524
1565
fn is_useful_specialized < ' p , ' a , ' tcx > (
1525
1566
cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
1526
- & Matrix ( ref m ) : & Matrix < ' p , ' tcx > ,
1567
+ matrix : & Matrix < ' p , ' tcx > ,
1527
1568
v : & PatStack < ' _ , ' tcx > ,
1528
1569
ctor : Constructor < ' tcx > ,
1529
1570
lty : Ty < ' tcx > ,
@@ -1535,9 +1576,8 @@ fn is_useful_specialized<'p, 'a, 'tcx>(
1535
1576
let wild_patterns_owned: Vec < _ > =
1536
1577
sub_pat_tys. iter ( ) . map ( |ty| Pat { ty, span : DUMMY_SP , kind : box PatKind :: Wild } ) . collect ( ) ;
1537
1578
let wild_patterns: Vec < _ > = wild_patterns_owned. iter ( ) . collect ( ) ;
1538
- let matrix =
1539
- Matrix ( m. iter ( ) . filter_map ( |r| specialize ( cx, & r, & ctor, & wild_patterns) ) . collect ( ) ) ;
1540
- match specialize ( cx, v, & ctor, & wild_patterns) {
1579
+ let matrix = matrix. specialize_constructor ( cx, & ctor, & wild_patterns) ;
1580
+ match v. specialize_constructor ( cx, & ctor, & wild_patterns) {
1541
1581
Some ( v) => match is_useful ( cx, & matrix, & v, witness, hir_id) {
1542
1582
UsefulWithWitness ( witnesses) => UsefulWithWitness (
1543
1583
witnesses
@@ -2013,7 +2053,7 @@ fn specialize<'p, 'a: 'p, 'q: 'p, 'tcx>(
2013
2053
) -> Option < PatStack < ' p , ' tcx > > {
2014
2054
let pat = r. head ( ) ;
2015
2055
2016
- let head = match * pat. kind {
2056
+ let new_head = match * pat. kind {
2017
2057
PatKind :: AscribeUserType { ref subpattern, .. } => {
2018
2058
specialize ( cx, & PatStack :: from_pattern ( subpattern) , constructor, wild_patterns)
2019
2059
}
@@ -2167,9 +2207,9 @@ fn specialize<'p, 'a: 'p, 'q: 'p, 'tcx>(
2167
2207
bug ! ( "support for or-patterns has not been fully implemented yet." ) ;
2168
2208
}
2169
2209
} ;
2170
- debug ! ( "specialize({:#?}, {:#?}) = {:#?}" , r. head( ) , wild_patterns, head ) ;
2210
+ debug ! ( "specialize({:#?}, {:#?}) = {:#?}" , r. head( ) , wild_patterns, new_head ) ;
2171
2211
2172
- head . map ( |head| {
2212
+ new_head . map ( |head| {
2173
2213
let mut head = head. 0 ;
2174
2214
head. extend_from_slice ( & r. 0 [ 1 ..] ) ;
2175
2215
PatStack :: from_vec ( head)
0 commit comments