@@ -39,7 +39,7 @@ use syntax_pos::{Span, DUMMY_SP};
39
39
40
40
use arena:: TypedArena ;
41
41
42
- use std:: cmp:: Ordering ;
42
+ use std:: cmp:: { self , Ordering } ;
43
43
use std:: fmt;
44
44
use std:: iter:: { FromIterator , IntoIterator , repeat} ;
45
45
@@ -419,6 +419,52 @@ fn all_constructors(_cx: &mut MatchCheckCtxt, pcx: PatternContext) -> Vec<Constr
419
419
}
420
420
}
421
421
422
+ fn max_slice_length < ' a : ' b , ' b , ' tcx , I > (
423
+ _cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
424
+ patterns : I ) -> usize
425
+ where I : Iterator < Item =& ' b [ & ' a Pattern < ' tcx > ] >
426
+ {
427
+ // The exhaustiveness-checking paper does not include any details on
428
+ // checking variable-length slice patterns. However, they are matched
429
+ // by an infinite collection of fixed-length array patterns.
430
+ //
431
+ // To check that infinite set, we notice that for every length
432
+ // larger than the length of the maximum fixed-length pattern,
433
+ // only variable-length patterns apply.
434
+ //
435
+ // For variable length patterns, all elements after the first
436
+ // `prefix_len` but before the last `suffix_len` are matched by
437
+ // the wildcard "middle" pattern, and therefore can be added/removed
438
+ // without affecting the match result.
439
+ //
440
+ // This means that all patterns with length at least
441
+ // `max(max_fixed+1,max_prefix+max_suffix)` are equivalent, so we
442
+ // only need to check patterns from that length and below.
443
+
444
+ let mut max_prefix_len = 0 ;
445
+ let mut max_suffix_len = 0 ;
446
+ let mut max_fixed_len = 0 ;
447
+
448
+ for row in patterns {
449
+ match * row[ 0 ] . kind {
450
+ PatternKind :: Constant { value : ConstVal :: ByteStr ( ref data) } => {
451
+ max_fixed_len = cmp:: max ( max_fixed_len, data. len ( ) ) ;
452
+ }
453
+ PatternKind :: Slice { ref prefix, slice : None , ref suffix } => {
454
+ let fixed_len = prefix. len ( ) + suffix. len ( ) ;
455
+ max_fixed_len = cmp:: max ( max_fixed_len, fixed_len) ;
456
+ }
457
+ PatternKind :: Slice { ref prefix, slice : Some ( _) , ref suffix } => {
458
+ max_prefix_len = cmp:: max ( max_prefix_len, prefix. len ( ) ) ;
459
+ max_suffix_len = cmp:: max ( max_suffix_len, suffix. len ( ) ) ;
460
+ }
461
+ _ => { }
462
+ }
463
+ }
464
+
465
+ cmp:: max ( max_fixed_len + 1 , max_prefix_len + max_suffix_len)
466
+ }
467
+
422
468
/// Algorithm from http://moscova.inria.fr/~maranget/papers/warn/index.html
423
469
///
424
470
/// Whether a vector `v` of patterns is 'useful' in relation to a set of such
@@ -453,16 +499,12 @@ pub fn is_useful<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
453
499
454
500
let & Matrix ( ref rows) = matrix;
455
501
assert ! ( rows. iter( ) . all( |r| r. len( ) == v. len( ) ) ) ;
502
+
503
+
456
504
let pcx = PatternContext {
457
505
ty : rows. iter ( ) . map ( |r| r[ 0 ] . ty ) . find ( |ty| !ty. references_error ( ) )
458
506
. unwrap_or ( v[ 0 ] . ty ) ,
459
- max_slice_length : rows. iter ( ) . filter_map ( |row| match * row[ 0 ] . kind {
460
- PatternKind :: Slice { ref prefix, slice : _, ref suffix } =>
461
- Some ( prefix. len ( ) + suffix. len ( ) ) ,
462
- PatternKind :: Constant { value : ConstVal :: ByteStr ( ref data) } =>
463
- Some ( data. len ( ) ) ,
464
- _ => None
465
- } ) . max ( ) . map_or ( 0 , |v| v + 1 )
507
+ max_slice_length : max_slice_length ( cx, rows. iter ( ) . map ( |r| & * * r) . chain ( Some ( v) ) )
466
508
} ;
467
509
468
510
debug ! ( "is_useful_expand_first_col: pcx={:?}, expanding {:?}" , pcx, v[ 0 ] ) ;
0 commit comments