@@ -1364,38 +1364,33 @@ fn all_constructors<'a, 'tcx>(
1364
1364
ctors
1365
1365
}
1366
1366
1367
- fn max_slice_length < ' p , ' a , ' tcx , I > ( cx : & MatchCheckCtxt < ' a , ' tcx > , patterns : I ) -> u64
1367
+ fn max_slice_length < ' p , ' a , ' tcx , I > ( cx : & MatchCheckCtxt < ' a , ' tcx > , ctors : I ) -> u64
1368
1368
where
1369
- I : Iterator < Item = & ' p Pat < ' tcx > > ,
1369
+ I : Iterator < Item = & ' p Constructor < ' tcx > > ,
1370
1370
' tcx : ' p ,
1371
1371
{
1372
- // The exhaustiveness-checking paper does not include any details on
1373
- // checking variable-length slice patterns. However, they are matched
1374
- // by an infinite collection of fixed-length array patterns.
1375
- //
1376
- // Checking the infinite set directly would take an infinite amount
1377
- // of time. However, it turns out that for each finite set of
1378
- // patterns `P`, all sufficiently large array lengths are equivalent:
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.
1379
1375
//
1380
1376
// Each slice `s` with a "sufficiently-large" length `l ≥ L` that applies
1381
1377
// to exactly the subset `Pₜ` of `P` can be transformed to a slice
1382
1378
// `sₘ` for each sufficiently-large length `m` that applies to exactly
1383
1379
// the same subset of `P`.
1384
1380
//
1385
- // Because of that, each witness for reachability-checking from one
1386
- // of the sufficiently-large lengths can be transformed to an
1387
- // equally-valid witness from any other length, so we only have
1388
- // to check slice lengths from the "minimal sufficiently-large length"
1389
- // and below.
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.
1390
1385
//
1391
- // Note that the fact that there is a *single* `sₘ` for each `m`
1392
- // not depending on the specific pattern in `P` is important: if
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
1393
1388
// you look at the pair of patterns
1394
1389
// `[true, ..]`
1395
1390
// `[.., false]`
1396
1391
// Then any slice of length ≥1 that matches one of these two
1397
1392
// patterns can be trivially turned to a slice of any
1398
- // other length ≥1 that matches them and vice-versa - for
1393
+ // other length ≥1 that matches them and vice-versa -
1399
1394
// but the slice from length 2 `[false, true]` that matches neither
1400
1395
// of these patterns can't be turned to a slice from length 1 that
1401
1396
// matches neither of these patterns, so we have to consider
@@ -1437,9 +1432,9 @@ where
1437
1432
let mut max_suffix_len = 0 ;
1438
1433
let mut max_fixed_len = 0 ;
1439
1434
1440
- for row in patterns {
1441
- match * row . kind {
1442
- PatKind :: Constant { value } => {
1435
+ for ctor in ctors {
1436
+ match * ctor {
1437
+ ConstantValue ( value) => {
1443
1438
// extract the length of an array/slice from a constant
1444
1439
match ( value. val , & value. ty . kind ) {
1445
1440
( _, ty:: Array ( _, n) ) => {
@@ -1451,13 +1446,12 @@ where
1451
1446
_ => { }
1452
1447
}
1453
1448
}
1454
- PatKind :: Slice { ref prefix, slice : None , ref suffix } => {
1455
- let fixed_len = prefix. len ( ) as u64 + suffix. len ( ) as u64 ;
1456
- max_fixed_len = cmp:: max ( max_fixed_len, fixed_len) ;
1449
+ FixedLenSlice ( len) => {
1450
+ max_fixed_len = cmp:: max ( max_fixed_len, len) ;
1457
1451
}
1458
- PatKind :: Slice { ref prefix, slice : Some ( _ ) , ref suffix } => {
1459
- max_prefix_len = cmp:: max ( max_prefix_len, prefix. len ( ) as u64 ) ;
1460
- max_suffix_len = cmp:: max ( max_suffix_len, suffix. len ( ) as u64 ) ;
1452
+ VarLenSlice ( prefix, suffix) => {
1453
+ max_prefix_len = cmp:: max ( max_prefix_len, prefix) ;
1454
+ max_suffix_len = cmp:: max ( max_suffix_len, suffix) ;
1461
1455
}
1462
1456
_ => { }
1463
1457
}
@@ -1761,36 +1755,33 @@ pub fn is_useful<'p, 'a, 'tcx>(
1761
1755
1762
1756
assert ! ( rows. iter( ) . all( |r| r. len( ) == v. len( ) ) ) ;
1763
1757
1764
- let pcx = PatCtxt {
1765
- // TyErr is used to represent the type of wildcard patterns matching
1766
- // against inaccessible (private) fields of structs, so that we won't
1767
- // be able to observe whether the types of the struct's fields are
1768
- // inhabited.
1769
- //
1770
- // If the field is truly inaccessible, then all the patterns
1771
- // matching against it must be wildcard patterns, so its type
1772
- // does not matter.
1773
- //
1774
- // However, if we are matching against non-wildcard patterns, we
1775
- // need to know the real type of the field so we can specialize
1776
- // against it. This primarily occurs through constants - they
1777
- // can include contents for fields that are inaccessible at the
1778
- // location of the match. In that case, the field's type is
1779
- // inhabited - by the constant - so we can just use it.
1780
- //
1781
- // FIXME: this might lead to "unstable" behavior with macro hygiene
1782
- // introducing uninhabited patterns for inaccessible fields. We
1783
- // need to figure out how to model that.
1784
- ty : matrix. heads ( ) . map ( |p| p. ty ) . find ( |ty| !ty. references_error ( ) ) . unwrap_or ( v. head ( ) . ty ) ,
1785
- max_slice_length : max_slice_length ( cx, matrix. heads ( ) . chain ( Some ( v. head ( ) ) ) ) ,
1786
- } ;
1758
+ // TyErr is used to represent the type of wildcard patterns matching
1759
+ // against inaccessible (private) fields of structs, so that we won't
1760
+ // be able to observe whether the types of the struct's fields are
1761
+ // inhabited.
1762
+ //
1763
+ // If the field is truly inaccessible, then all the patterns
1764
+ // matching against it must be wildcard patterns, so its type
1765
+ // does not matter.
1766
+ //
1767
+ // However, if we are matching against non-wildcard patterns, we
1768
+ // need to know the real type of the field so we can specialize
1769
+ // against it. This primarily occurs through constants - they
1770
+ // can include contents for fields that are inaccessible at the
1771
+ // location of the match. In that case, the field's type is
1772
+ // inhabited - by the constant - so we can just use it.
1773
+ //
1774
+ // FIXME: this might lead to "unstable" behavior with macro hygiene
1775
+ // introducing uninhabited patterns for inaccessible fields. We
1776
+ // need to figure out how to model that.
1777
+ let ty = matrix. heads ( ) . map ( |p| p. ty ) . find ( |ty| !ty. references_error ( ) ) . unwrap_or ( v. head ( ) . ty ) ;
1787
1778
1788
- debug ! ( "is_useful_expand_first_col: pcx ={:#?}, expanding {:#?}" , pcx , v. head( ) ) ;
1779
+ debug ! ( "is_useful_expand_first_col: ty ={:#?}, expanding {:#?}" , ty , v. head( ) ) ;
1789
1780
1790
- let v_constructors = pat_constructors ( cx. tcx , cx. param_env , v. head ( ) , pcx ) ;
1781
+ let v_constructors = pat_constructors ( cx. tcx , cx. param_env , v. head ( ) , ty ) ;
1791
1782
1792
1783
if cx. is_non_exhaustive_variant ( v. head ( ) )
1793
- && !cx. is_local ( pcx . ty )
1784
+ && !cx. is_local ( ty)
1794
1785
&& !v_constructors. iter ( ) . any ( |ctor| ctor. is_wildcard ( ) )
1795
1786
{
1796
1787
debug ! ( "is_useful - shortcut because declared non-exhaustive" ) ;
@@ -1800,11 +1791,14 @@ pub fn is_useful<'p, 'a, 'tcx>(
1800
1791
1801
1792
let matrix_head_ctors: Vec < Constructor < ' _ > > = matrix
1802
1793
. heads ( )
1803
- . flat_map ( |p| pat_constructors ( cx. tcx , cx. param_env , p, pcx ) )
1794
+ . flat_map ( |p| pat_constructors ( cx. tcx , cx. param_env , p, ty ) )
1804
1795
. filter ( |ctor| !ctor. is_wildcard ( ) )
1805
1796
. collect ( ) ;
1806
1797
debug ! ( "matrix_head_ctors = {:#?}" , matrix_head_ctors) ;
1807
1798
1799
+ let max_slice_length = max_slice_length ( cx, matrix_head_ctors. iter ( ) . chain ( & v_constructors) ) ;
1800
+ let pcx = PatCtxt { ty, max_slice_length } ;
1801
+
1808
1802
v_constructors
1809
1803
. into_iter ( )
1810
1804
. flat_map ( |ctor| ctor. split_meta_constructor ( cx, pcx, & matrix_head_ctors) )
@@ -1851,11 +1845,11 @@ fn pat_constructors<'tcx>(
1851
1845
tcx : TyCtxt < ' tcx > ,
1852
1846
param_env : ty:: ParamEnv < ' tcx > ,
1853
1847
pat : & Pat < ' tcx > ,
1854
- pcx : PatCtxt < ' tcx > ,
1848
+ ty : Ty < ' tcx > ,
1855
1849
) -> SmallVec < [ Constructor < ' tcx > ; 1 ] > {
1856
1850
match * pat. kind {
1857
1851
PatKind :: AscribeUserType { ref subpattern, .. } => {
1858
- pat_constructors ( tcx, param_env, subpattern, pcx )
1852
+ pat_constructors ( tcx, param_env, subpattern, ty )
1859
1853
}
1860
1854
PatKind :: Binding { .. } | PatKind :: Wild => smallvec ! [ Wildcard ] ,
1861
1855
PatKind :: Leaf { .. } | PatKind :: Deref { .. } => smallvec ! [ Single ] ,
@@ -1869,9 +1863,9 @@ fn pat_constructors<'tcx>(
1869
1863
lo. ty,
1870
1864
end,
1871
1865
) ] ,
1872
- PatKind :: Array { .. } => match pcx . ty . kind {
1866
+ PatKind :: Array { .. } => match ty. kind {
1873
1867
ty:: Array ( _, length) => smallvec ! [ FixedLenSlice ( length. eval_usize( tcx, param_env) ) ] ,
1874
- _ => span_bug ! ( pat. span, "bad ty {:?} for array pattern" , pcx . ty) ,
1868
+ _ => span_bug ! ( pat. span, "bad ty {:?} for array pattern" , ty) ,
1875
1869
} ,
1876
1870
PatKind :: Slice { ref prefix, ref slice, ref suffix } => {
1877
1871
let prefix = prefix. len ( ) as u64 ;
0 commit comments