@@ -640,7 +640,7 @@ impl<'tcx> Constructor<'tcx> {
640
640
debug ! ( "split_meta_constructor {:?}" , self ) ;
641
641
assert ! ( !head_ctors. iter( ) . any( |c| c. is_wildcard( ) ) ) ;
642
642
643
- match & self {
643
+ match self {
644
644
// Any base constructor can be used unchanged.
645
645
Single | Variant ( _) | ConstantValue ( _) | FixedLenSlice ( _) => smallvec ! [ self ] ,
646
646
ConstantRange ( ..) if should_treat_range_exhaustively ( cx. tcx , & self ) => {
@@ -739,8 +739,99 @@ impl<'tcx> Constructor<'tcx> {
739
739
. collect ( )
740
740
}
741
741
ConstantRange ( ..) => smallvec ! [ self ] ,
742
- VarLenSlice ( prefix, suffix) => {
743
- ( prefix + suffix..pcx. max_slice_length + 1 ) . map ( FixedLenSlice ) . collect ( )
742
+ VarLenSlice ( self_prefix, self_suffix) => {
743
+ // A variable-length slice pattern is matched by an infinite collection of
744
+ // fixed-length array patterns. However it turns out that for each finite set of
745
+ // patterns `P`, all sufficiently large array lengths are equivalent.
746
+ //
747
+ // Each slice `s` with a "sufficiently-large" length `l ≥ L` that applies
748
+ // to exactly the subset `Pₜ` of `P` can be transformed to a slice
749
+ // `sₘ` for each sufficiently-large length `m` that applies to exactly
750
+ // the same subset of `P`.
751
+ //
752
+ // Because of that, each witness for reachability-checking from one of the
753
+ // sufficiently-large lengths can be transformed to an equally-valid witness from
754
+ // any other length, so we all slice lengths from the "minimal sufficiently-large
755
+ // length" until infinity will behave the same.
756
+ //
757
+ // Note that the fact that there is a *single* `sₘ` for each `m`,
758
+ // not depending on the specific pattern in `P`, is important: if
759
+ // you look at the pair of patterns
760
+ // `[true, ..]`
761
+ // `[.., false]`
762
+ // Then any slice of length ≥1 that matches one of these two
763
+ // patterns can be trivially turned to a slice of any
764
+ // other length ≥1 that matches them and vice-versa -
765
+ // but the slice from length 2 `[false, true]` that matches neither
766
+ // of these patterns can't be turned to a slice from length 1 that
767
+ // matches neither of these patterns, so we have to consider
768
+ // slices from length 2 there.
769
+ //
770
+ // Now, to see that that length exists and find it, observe that slice
771
+ // patterns are either "fixed-length" patterns (`[_, _, _]`) or
772
+ // "variable-length" patterns (`[_, .., _]`).
773
+ //
774
+ // For fixed-length patterns, all slices with lengths *longer* than
775
+ // the pattern's length have the same outcome (of not matching), so
776
+ // as long as `L` is greater than the pattern's length we can pick
777
+ // any `sₘ` from that length and get the same result.
778
+ //
779
+ // For variable-length patterns, the situation is more complicated,
780
+ // because as seen above the precise value of `sₘ` matters.
781
+ //
782
+ // However, for each variable-length pattern `p` with a prefix of length
783
+ // `plₚ` and suffix of length `slₚ`, only the first `plₚ` and the last
784
+ // `slₚ` elements are examined.
785
+ //
786
+ // Therefore, as long as `L` is positive (to avoid concerns about empty
787
+ // types), all elements after the maximum prefix length and before
788
+ // the maximum suffix length are not examined by any variable-length
789
+ // pattern, and therefore can be added/removed without affecting
790
+ // them - creating equivalent patterns from any sufficiently-large
791
+ // length.
792
+ //
793
+ // Of course, if fixed-length patterns exist, we must be sure
794
+ // that our length is large enough to miss them all, so
795
+ // we can pick `L = max(FIXED_LEN+1 ∪ {max(PREFIX_LEN) + max(SUFFIX_LEN)})`
796
+ //
797
+ // For example, with the above pair of patterns, all elements
798
+ // but the first and last can be added/removed, so any
799
+ // witness of length ≥2 (say, `[false, false, true]`) can be
800
+ // turned to a witness from any other length ≥2.
801
+
802
+ let mut max_prefix_len = self_prefix;
803
+ let mut max_suffix_len = self_suffix;
804
+ let mut max_fixed_len = 0 ;
805
+
806
+ for ctor in head_ctors {
807
+ match * ctor {
808
+ ConstantValue ( value) => {
809
+ // extract the length of an array/slice from a constant
810
+ match ( value. val , & value. ty . kind ) {
811
+ ( _, ty:: Array ( _, n) ) => {
812
+ max_fixed_len =
813
+ cmp:: max ( max_fixed_len, n. eval_usize ( cx. tcx , cx. param_env ) )
814
+ }
815
+ ( ConstValue :: Slice { start, end, .. } , ty:: Slice ( _) ) => {
816
+ max_fixed_len = cmp:: max ( max_fixed_len, ( end - start) as u64 )
817
+ }
818
+ _ => { }
819
+ }
820
+ }
821
+ FixedLenSlice ( len) => {
822
+ max_fixed_len = cmp:: max ( max_fixed_len, len) ;
823
+ }
824
+ VarLenSlice ( prefix, suffix) => {
825
+ max_prefix_len = cmp:: max ( max_prefix_len, prefix) ;
826
+ max_suffix_len = cmp:: max ( max_suffix_len, suffix) ;
827
+ }
828
+ _ => { }
829
+ }
830
+ }
831
+
832
+ let max_slice_length = cmp:: max ( max_fixed_len + 1 , max_prefix_len + max_suffix_len) ;
833
+
834
+ ( self_prefix + self_suffix..=max_slice_length) . map ( FixedLenSlice ) . collect ( )
744
835
}
745
836
Wildcard => {
746
837
let is_declared_nonexhaustive =
@@ -1204,7 +1295,6 @@ pub enum WitnessPreference {
1204
1295
#[ derive( Copy , Clone , Debug ) ]
1205
1296
struct PatCtxt < ' tcx > {
1206
1297
ty : Ty < ' tcx > ,
1207
- max_slice_length : u64 ,
1208
1298
}
1209
1299
1210
1300
/// A witness of non-exhaustiveness for error reporting, represented
@@ -1364,102 +1454,6 @@ fn all_constructors<'a, 'tcx>(
1364
1454
ctors
1365
1455
}
1366
1456
1367
- fn max_slice_length < ' p , ' a , ' tcx , I > ( cx : & MatchCheckCtxt < ' a , ' tcx > , ctors : I ) -> u64
1368
- where
1369
- I : Iterator < Item = & ' p Constructor < ' tcx > > ,
1370
- ' tcx : ' p ,
1371
- {
1372
- // A variable-length slice pattern is matched by an infinite collection of fixed-length array
1373
- // patterns. However it turns out that for each finite set of patterns `P`, all sufficiently
1374
- // large array lengths are equivalent.
1375
- //
1376
- // Each slice `s` with a "sufficiently-large" length `l ≥ L` that applies
1377
- // to exactly the subset `Pₜ` of `P` can be transformed to a slice
1378
- // `sₘ` for each sufficiently-large length `m` that applies to exactly
1379
- // the same subset of `P`.
1380
- //
1381
- // Because of that, each witness for reachability-checking from one of the sufficiently-large
1382
- // lengths can be transformed to an equally-valid witness from any other length, so we all
1383
- // slice lengths from the "minimal sufficiently-large length" until infinity will behave the
1384
- // same.
1385
- //
1386
- // Note that the fact that there is a *single* `sₘ` for each `m`,
1387
- // not depending on the specific pattern in `P`, is important: if
1388
- // you look at the pair of patterns
1389
- // `[true, ..]`
1390
- // `[.., false]`
1391
- // Then any slice of length ≥1 that matches one of these two
1392
- // patterns can be trivially turned to a slice of any
1393
- // other length ≥1 that matches them and vice-versa -
1394
- // but the slice from length 2 `[false, true]` that matches neither
1395
- // of these patterns can't be turned to a slice from length 1 that
1396
- // matches neither of these patterns, so we have to consider
1397
- // slices from length 2 there.
1398
- //
1399
- // Now, to see that that length exists and find it, observe that slice
1400
- // patterns are either "fixed-length" patterns (`[_, _, _]`) or
1401
- // "variable-length" patterns (`[_, .., _]`).
1402
- //
1403
- // For fixed-length patterns, all slices with lengths *longer* than
1404
- // the pattern's length have the same outcome (of not matching), so
1405
- // as long as `L` is greater than the pattern's length we can pick
1406
- // any `sₘ` from that length and get the same result.
1407
- //
1408
- // For variable-length patterns, the situation is more complicated,
1409
- // because as seen above the precise value of `sₘ` matters.
1410
- //
1411
- // However, for each variable-length pattern `p` with a prefix of length
1412
- // `plₚ` and suffix of length `slₚ`, only the first `plₚ` and the last
1413
- // `slₚ` elements are examined.
1414
- //
1415
- // Therefore, as long as `L` is positive (to avoid concerns about empty
1416
- // types), all elements after the maximum prefix length and before
1417
- // the maximum suffix length are not examined by any variable-length
1418
- // pattern, and therefore can be added/removed without affecting
1419
- // them - creating equivalent patterns from any sufficiently-large
1420
- // length.
1421
- //
1422
- // Of course, if fixed-length patterns exist, we must be sure
1423
- // that our length is large enough to miss them all, so
1424
- // we can pick `L = max(FIXED_LEN+1 ∪ {max(PREFIX_LEN) + max(SUFFIX_LEN)})`
1425
- //
1426
- // for example, with the above pair of patterns, all elements
1427
- // but the first and last can be added/removed, so any
1428
- // witness of length ≥2 (say, `[false, false, true]`) can be
1429
- // turned to a witness from any other length ≥2.
1430
-
1431
- let mut max_prefix_len = 0 ;
1432
- let mut max_suffix_len = 0 ;
1433
- let mut max_fixed_len = 0 ;
1434
-
1435
- for ctor in ctors {
1436
- match * ctor {
1437
- ConstantValue ( value) => {
1438
- // extract the length of an array/slice from a constant
1439
- match ( value. val , & value. ty . kind ) {
1440
- ( _, ty:: Array ( _, n) ) => {
1441
- max_fixed_len = cmp:: max ( max_fixed_len, n. eval_usize ( cx. tcx , cx. param_env ) )
1442
- }
1443
- ( ConstValue :: Slice { start, end, .. } , ty:: Slice ( _) ) => {
1444
- max_fixed_len = cmp:: max ( max_fixed_len, ( end - start) as u64 )
1445
- }
1446
- _ => { }
1447
- }
1448
- }
1449
- FixedLenSlice ( len) => {
1450
- max_fixed_len = cmp:: max ( max_fixed_len, len) ;
1451
- }
1452
- VarLenSlice ( prefix, suffix) => {
1453
- max_prefix_len = cmp:: max ( max_prefix_len, prefix) ;
1454
- max_suffix_len = cmp:: max ( max_suffix_len, suffix) ;
1455
- }
1456
- _ => { }
1457
- }
1458
- }
1459
-
1460
- cmp:: max ( max_fixed_len + 1 , max_prefix_len + max_suffix_len)
1461
- }
1462
-
1463
1457
/// An inclusive interval, used for precise integer exhaustiveness checking.
1464
1458
/// `IntRange`s always store a contiguous range. This means that values are
1465
1459
/// encoded such that `0` encodes the minimum value for the integer,
@@ -1796,8 +1790,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
1796
1790
. collect ( ) ;
1797
1791
debug ! ( "matrix_head_ctors = {:#?}" , matrix_head_ctors) ;
1798
1792
1799
- let max_slice_length = max_slice_length ( cx, matrix_head_ctors. iter ( ) . chain ( & v_constructors) ) ;
1800
- let pcx = PatCtxt { ty, max_slice_length } ;
1793
+ let pcx = PatCtxt { ty } ;
1801
1794
1802
1795
v_constructors
1803
1796
. into_iter ( )
0 commit comments