@@ -510,7 +510,7 @@ pub struct MatchCheckCtxt<'a, 'tcx> {
510
510
/// checking inhabited-ness of types because whether a type is (visibly)
511
511
/// inhabited can depend on whether it was defined in the current module or
512
512
/// not. E.g., `struct Foo { _private: ! }` cannot be seen to be empty
513
- /// outside it's module and should not be matchable with an empty match
513
+ /// outside its module and should not be matchable with an empty match
514
514
/// statement.
515
515
pub module : DefId ,
516
516
param_env : ty:: ParamEnv < ' tcx > ,
@@ -565,7 +565,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
565
565
}
566
566
}
567
567
568
- /// Constructors and metaconstructors.
568
+ /// Constructors, including base constructors and metaconstructors.
569
569
#[ derive( Clone , Debug , PartialEq ) ]
570
570
enum Constructor < ' tcx > {
571
571
// Base constructors
@@ -584,12 +584,12 @@ enum Constructor<'tcx> {
584
584
ConstantRange ( u128 , u128 , Ty < ' tcx > , RangeEnd ) ,
585
585
/// Slice patterns. Captures any array constructor of length >= i+j.
586
586
VarLenSlice ( u64 , u64 ) ,
587
- /// Wildcard metaconstructor.
587
+ /// Wildcard metaconstructor. Captures all possible constructors for a given type.
588
588
Wildcard ,
589
- /// List of constructors that were _not_ present in the first column
590
- /// of the matrix when encountering a wildcard. The contained list must
591
- /// be nonempty .
592
- /// This is only used in the output of splitting the wildcard metaconstructor .
589
+ /// Special wildcard-like constructor that carries only a subset of all possible constructors.
590
+ /// It is used only when splitting `Constructor::Wildcard` and some constructors were not
591
+ /// present in the matrix .
592
+ /// The contained list must be nonempty .
593
593
MissingConstructors ( MissingConstructors < ' tcx > ) ,
594
594
}
595
595
@@ -629,8 +629,7 @@ impl<'tcx> Constructor<'tcx> {
629
629
630
630
/// Split a constructor into equivalence classes of constructors that behave the same
631
631
/// for the given matrix. See description of the algorithm for details.
632
- /// Note: We can rely on this returning an empty list if the type is uninhabited and
633
- /// we're not in the privately_empty case.
632
+ /// Note: We can rely on this returning an empty list if the type is (visibly) uninhabited.
634
633
fn split_meta_constructor (
635
634
self ,
636
635
cx : & MatchCheckCtxt < ' _ , ' tcx > ,
@@ -644,28 +643,20 @@ impl<'tcx> Constructor<'tcx> {
644
643
// Any base constructor can be used unchanged.
645
644
Single | Variant ( _) | ConstantValue ( _) | FixedLenSlice ( _) => smallvec ! [ self ] ,
646
645
ConstantRange ( ..) if should_treat_range_exhaustively ( cx. tcx , & self ) => {
647
- // For exhaustive integer matching, some constructors are grouped within other
648
- // constructors (namely integer typed values are grouped within ranges). However,
649
- // when specialising these constructors, we want to be specialising for the
650
- // underlying constructors (the integers), not the groups (the ranges). Thus we
651
- // need to split the groups up. Splitting them up naïvely would mean creating a
652
- // separate constructor for every single value in the range, which is clearly
653
- // impractical. However, observe that for some ranges of integers, the
654
- // specialisation will be identical across all values in that range (i.e., there
655
- // are equivalence classes of ranges of constructors based on their
656
- // `is_useful_specialized` outcome). These classes are grouped by the patterns that
657
- // apply to them (in the matrix `P`). We can split the range whenever the patterns
658
- // that apply to that range (specifically: the patterns that *intersect* with that
659
- // range) change.
660
- // Our solution, therefore, is to split the range constructor into subranges at
661
- // every single point the group of intersecting patterns changes (using the method
662
- // described below). And voilà! We're testing precisely those ranges that we need
663
- // to, without any exhaustive matching on actual integers. The nice thing about
664
- // this is that the number of subranges is linear in the number of rows in the
665
- // matrix (i.e., the number of cases in the `match` statement), so we don't need to
666
- // be worried about matching over gargantuan ranges.
646
+ // Splitting up a range naïvely would mean creating a separate constructor for
647
+ // every single value in the range, which is clearly impractical. We therefore want
648
+ // to keep together subranges for which the specialisation will be identical across
649
+ // all values in that range. These classes are grouped by the patterns that apply
650
+ // to them (in the matrix `M`). We can split the range whenever the patterns that
651
+ // apply to that range (specifically: the patterns that *intersect* with that
652
+ // range) change. Our solution, therefore, is to split the range constructor into
653
+ // subranges at every single point where the group of intersecting patterns changes
654
+ // (using the method described below). The nice thing about this is that the number
655
+ // of subranges is linear in the number of rows in the matrix (i.e., the number of
656
+ // cases in the `match` statement), so we don't need to be worried about matching
657
+ // over a gargantuan number of ranges.
667
658
//
668
- // Essentially, given the first column of a matrix representing ranges, looking
659
+ // Essentially, given the first column of a matrix representing ranges, that looks
669
660
// like the following:
670
661
//
671
662
// |------| |----------| |-------| ||
@@ -680,12 +671,10 @@ impl<'tcx> Constructor<'tcx> {
680
671
// The logic for determining how to split the ranges is fairly straightforward: we
681
672
// calculate boundaries for each interval range, sort them, then create
682
673
// constructors for each new interval between every pair of boundary points. (This
683
- // essentially sums up to performing the intuitive merging operation depicted
674
+ // essentially amounts to performing the intuitive merging operation depicted
684
675
// above.)
685
676
686
- // We only care about finding all the subranges within the range of the constructor
687
- // range. Anything else is irrelevant, because it is guaranteed to result in
688
- // `NotUseful`, which is the default case anyway, and can be ignored.
677
+ // We only care about finding all the subranges within the range of `self`.
689
678
let ctor_range = IntRange :: from_ctor ( cx. tcx , cx. param_env , & self ) . unwrap ( ) ;
690
679
691
680
/// Represents a border between 2 integers. Because the intervals spanning borders
@@ -810,7 +799,7 @@ impl<'tcx> Constructor<'tcx> {
810
799
for ctor in head_ctors {
811
800
match * ctor {
812
801
ConstantValue ( value) => {
813
- // extract the length of an array/slice from a constant
802
+ // Extract the length of an array/slice from a constant
814
803
match ( value. val , & value. ty . kind ) {
815
804
( _, ty:: Array ( _, n) ) => {
816
805
max_fixed_len =
@@ -845,14 +834,19 @@ impl<'tcx> Constructor<'tcx> {
845
834
Wildcard => {
846
835
let is_declared_nonexhaustive = !cx. is_local ( ty) && cx. is_non_exhaustive_enum ( ty) ;
847
836
848
- // `all_ctors` are all the constructors for the given type, which
849
- // should all be represented (or caught with the wild pattern `_`).
837
+ // `all_ctors` is the list of all the constructors for the given type.
850
838
let all_ctors = all_constructors ( cx, ty) ;
851
839
852
840
let is_privately_empty = all_ctors. is_empty ( ) && !cx. is_uninhabited ( ty) ;
853
841
854
842
// For privately empty and non-exhaustive enums, we work as if there were an "extra"
855
843
// `_` constructor for the type, so we can never match over all constructors.
844
+ // See the `match_privately_empty` test for details.
845
+ //
846
+ // FIXME: currently the only way I know of something can
847
+ // be a privately-empty enum is when the exhaustive_patterns
848
+ // feature flag is not present, so this is only
849
+ // needed for that case.
856
850
let is_non_exhaustive = is_privately_empty
857
851
|| is_declared_nonexhaustive
858
852
|| ( ty. is_ptr_sized_integral ( )
@@ -865,20 +859,6 @@ impl<'tcx> Constructor<'tcx> {
865
859
// Therefore, if there is some pattern that is unmatched by `matrix`,
866
860
// it will still be unmatched if the first constructor is replaced by
867
861
// any of the constructors in `missing_ctors`
868
- //
869
- // However, if our scrutinee is *privately* an empty enum, we
870
- // must treat it as though it had an "unknown" constructor (in
871
- // that case, all other patterns obviously can't be variants)
872
- // to avoid exposing its emptyness. See the `match_privately_empty`
873
- // test for details.
874
- //
875
- // FIXME: currently the only way I know of something can
876
- // be a privately-empty enum is when the exhaustive_patterns
877
- // feature flag is not present, so this is only
878
- // needed for that case.
879
-
880
- // Missing constructors are those that are not matched by any
881
- // non-wildcard patterns in the current column.
882
862
let missing_ctors =
883
863
MissingConstructors :: new ( cx. tcx , cx. param_env , all_ctors, head_ctors. clone ( ) ) ;
884
864
debug ! (
@@ -932,11 +912,12 @@ impl<'tcx> Constructor<'tcx> {
932
912
used_ctors : & Vec < Constructor < ' tcx > > ,
933
913
) -> SmallVec < [ Constructor < ' tcx > ; 1 ] > {
934
914
debug ! ( "subtract_meta_constructor {:?}" , self ) ;
915
+ // The input must not contain a wildcard
935
916
assert ! ( !used_ctors. iter( ) . any( |c| c. is_wildcard( ) ) ) ;
936
917
937
918
match self {
938
- // Those constructors can't match a non-wildcard metaconstructor, so we're fine
939
- // just comparing for equality.
919
+ // Those constructors can't intersect with a non-wildcard metaconstructor, so we're
920
+ // fine just comparing for equality.
940
921
Single | Variant ( _) => {
941
922
if used_ctors. iter ( ) . any ( |c| c == & self ) {
942
923
smallvec ! [ ]
@@ -953,11 +934,11 @@ impl<'tcx> Constructor<'tcx> {
953
934
if used_ctors. iter ( ) . any ( overlaps) { smallvec ! [ ] } else { smallvec ! [ self ] }
954
935
}
955
936
VarLenSlice ( self_prefix, self_suffix) => {
956
- let self_len = self_prefix + self_suffix;
957
937
// Initially we cover all slice lengths starting from self_len.
938
+ let self_len = self_prefix + self_suffix;
958
939
959
940
// If there is a VarLenSlice(n) in used_ctors, then we have to discard
960
- // all lengths >= n. So we pick the smallest one .
941
+ // all lengths >= n. So we pick the smallest such n .
961
942
let max_len: Option < _ > = used_ctors
962
943
. iter ( )
963
944
. filter_map ( |c : & Constructor < ' tcx > | match c {
@@ -978,7 +959,7 @@ impl<'tcx> Constructor<'tcx> {
978
959
// individual FixedLenSlice lengths in used_ctors. For that,
979
960
// we extract all those lengths that are in our remaining range and
980
961
// sort them. Every such length becomes a boundary between ranges
981
- // of lengths that will remain.
962
+ // of the lengths that will remain.
982
963
#[ derive( Clone , Copy , PartialEq , Eq , PartialOrd , Ord ) ]
983
964
enum Length {
984
965
Start ,
@@ -988,10 +969,12 @@ impl<'tcx> Constructor<'tcx> {
988
969
989
970
let mut lengths: Vec < _ > = used_ctors
990
971
. iter ( )
972
+ // Extract fixed-size lengths
991
973
. filter_map ( |c : & Constructor < ' tcx > | match c {
992
974
FixedLenSlice ( other_len) => Some ( * other_len) ,
993
975
_ => None ,
994
976
} )
977
+ // Keep only those in the remaining range
995
978
. filter ( |l| * l >= self_len)
996
979
. filter ( |l| match max_len {
997
980
Some ( max_len) => * l < max_len,
@@ -1004,6 +987,7 @@ impl<'tcx> Constructor<'tcx> {
1004
987
lengths. sort_unstable ( ) ;
1005
988
lengths. dedup ( ) ;
1006
989
990
+ // For each adjacent pair of lengths, output the lengths in between.
1007
991
let mut remaining_ctors: SmallVec < _ > = lengths
1008
992
. windows ( 2 )
1009
993
. flat_map ( |window| match ( window[ 0 ] , window[ 1 ] ) {
@@ -1022,7 +1006,7 @@ impl<'tcx> Constructor<'tcx> {
1022
1006
Start => self_len,
1023
1007
Boundary ( n) => n + 1 ,
1024
1008
} ;
1025
- // We know final_length >= self_len >= self_suffix
1009
+ // We know final_length >= self_len >= self_suffix so this can't underflow.
1026
1010
remaining_ctors. push ( VarLenSlice ( final_length - self_suffix, self_suffix) ) ;
1027
1011
}
1028
1012
@@ -1127,10 +1111,10 @@ impl<'tcx> Constructor<'tcx> {
1127
1111
}
1128
1112
1129
1113
/// This computes the arity of a constructor. The arity of a constructor
1130
- /// is how many subpattern patterns of that constructor should be expanded to .
1114
+ /// is the number of its arguments .
1131
1115
///
1132
- /// For instance, a tuple pattern `(_, 42, Some([]))` has the arity of 3.
1133
- /// A struct pattern's arity is the number of fields it contains, etc.
1116
+ /// For instance, a tuple pattern `(_, 42, Some([]))` has arity 3, a struct pattern's arity is
1117
+ /// the number of fields it contains, etc.
1134
1118
fn arity < ' a > ( & self , cx : & MatchCheckCtxt < ' a , ' tcx > , ty : Ty < ' tcx > ) -> u64 {
1135
1119
debug ! ( "Constructor::arity({:#?}, {:?})" , self , ty) ;
1136
1120
match * self {
@@ -1342,10 +1326,10 @@ impl<'tcx> Witness<'tcx> {
1342
1326
/// of values, V, where each value in that set is not covered by any previously
1343
1327
/// used patterns and is covered by the pattern P'. Examples:
1344
1328
///
1345
- /// left_ty : tuple of 3 elements
1329
+ /// ty : tuple of 3 elements
1346
1330
/// pats: [10, 20, _] => (10, 20, _)
1347
1331
///
1348
- /// left_ty : struct X { a: (bool, &'static str), b: usize}
1332
+ /// ty : struct X { a: (bool, &'static str), b: usize}
1349
1333
/// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 }
1350
1334
fn apply_constructor < ' a > (
1351
1335
mut self ,
@@ -1372,9 +1356,8 @@ impl<'tcx> Witness<'tcx> {
1372
1356
}
1373
1357
1374
1358
/// This determines the set of all possible constructors of a pattern matching
1375
- /// values of type `left_ty`. For vectors, this would normally be an infinite set
1376
- /// but is instead bounded by the maximum fixed length of slice patterns in
1377
- /// the column of patterns being analyzed.
1359
+ /// values of type `ty`. We possibly return metaconstructors like integer ranges
1360
+ /// that capture several base constructors at once.
1378
1361
///
1379
1362
/// We make sure to omit constructors that are statically impossible. E.g., for
1380
1363
/// `Option<!>`, we do not include `Some(_)` in the returned list of constructors.
@@ -1691,23 +1674,22 @@ impl<'tcx> PartialEq<Self> for MissingConstructors<'tcx> {
1691
1674
}
1692
1675
}
1693
1676
1694
- /// Algorithm from http://moscova.inria.fr/~maranget/papers/warn/index.html.
1695
- /// The algorithm from the paper has been modified to correctly handle empty
1696
- /// types. The changes are:
1677
+ /// Main entrypoint of the algorithm described at th top of the file.
1678
+ /// Note that to correctly handle empty types:
1697
1679
/// (0) We don't exit early if the pattern matrix has zero rows. We just
1698
1680
/// continue to recurse over columns.
1699
1681
/// (1) all_constructors will only return constructors that are statically
1700
1682
/// possible. E.g., it will only return `Ok` for `Result<T, !>`.
1701
1683
///
1702
- /// This finds whether a (row) vector `v` of patterns is 'useful' in relation
1703
- /// to a set of such vectors `m` - this is defined as there being a set of
1704
- /// inputs that will match `v` but not any of the sets in `m`.
1684
+ /// This finds whether a pattern-stack `v` is 'useful' in relation to a set of such pattern-stacks
1685
+ /// (aka 'matrix') `m` - this is defined as there being a set of inputs that will match `v` but not
1686
+ /// any of the rows in `m`.
1705
1687
///
1706
1688
/// All the patterns at each column of the `matrix ++ v` matrix must
1707
1689
/// have the same type, except that wildcard (PatKind::Wild) patterns
1708
1690
/// with type `TyErr` are also allowed, even if the "type of the column"
1709
1691
/// is not `TyErr`. That is used to represent private fields, as using their
1710
- /// real type would assert that they are inhabited.
1692
+ /// real type might leak that they are inhabited.
1711
1693
///
1712
1694
/// This is used both for reachability checking (if a pattern isn't useful in
1713
1695
/// relation to preceding patterns, it is not reachable) and exhaustiveness
@@ -1811,14 +1793,8 @@ fn is_useful_specialized<'p, 'a, 'tcx>(
1811
1793
ret
1812
1794
}
1813
1795
1814
- /// Determines the constructors that the given pattern can be specialized to.
1815
- ///
1816
- /// In most cases, there's only one constructor that a specific pattern
1817
- /// represents, such as a specific enum variant or a specific literal value.
1818
- /// Slice patterns, however, can match slices of different lengths. For instance,
1819
- /// `[a, b, tail @ ..]` can match a slice of length 2, 3, 4 and so on.
1820
- ///
1821
- /// Returns `None` in case of a catch-all, which can't be specialized.
1796
+ /// Determines the constructors that are covered by the given pattern.
1797
+ /// Except for or-patterns, this returns only one constructor (possibly a meta-constructor).
1822
1798
fn pat_constructors < ' tcx > (
1823
1799
tcx : TyCtxt < ' tcx > ,
1824
1800
param_env : ty:: ParamEnv < ' tcx > ,
@@ -2014,13 +1990,11 @@ fn patterns_for_variant<'p, 'tcx>(
2014
1990
PatStack :: from_vec ( result)
2015
1991
}
2016
1992
2017
- /// This is the main specialization step. It expands the pattern
2018
- /// into `arity` patterns based on the constructor. For most patterns, the step is trivial,
2019
- /// for instance tuple patterns are flattened and box patterns expand into their inner pattern.
2020
- /// Returns `None` if the pattern does not have the given constructor .
1993
+ /// This is the main specialization step. It expands the pattern into `arity` patterns based on the
1994
+ /// constructor. For most patterns, the step is trivial, for instance tuple patterns are flattened
1995
+ /// and box patterns expand into their inner pattern. Returns vec![] if the pattern does not have
1996
+ /// the given constructor. See the top of the file for details .
2021
1997
///
2022
- /// OTOH, slice patterns with a subslice pattern (tail @ ..) can be expanded into multiple
2023
- /// different patterns.
2024
1998
/// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
2025
1999
/// fields filled with wild patterns.
2026
2000
fn specialize_one_pattern < ' p , ' a : ' p , ' p2 : ' p , ' tcx > (
@@ -2034,7 +2008,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'p2: 'p, 'tcx>(
2034
2008
}
2035
2009
2036
2010
if let MissingConstructors ( _) = constructor {
2037
- // By construction of MissingConstructors, we know that all non-wildcard constructors
2011
+ // By the invariant of MissingConstructors, we know that all non-wildcard constructors
2038
2012
// should be discarded.
2039
2013
return match * pat. kind {
2040
2014
PatKind :: Binding { .. } | PatKind :: Wild => smallvec ! [ PatStack :: empty( ) ] ,
0 commit comments