Skip to content

Commit f5d833f

Browse files
committed
Cleanup comments
Several comments were leftover from before the rework of the algorithm and didn't make sens anymore.
1 parent 72c3a68 commit f5d833f

File tree

1 file changed

+61
-87
lines changed

1 file changed

+61
-87
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 61 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ pub struct MatchCheckCtxt<'a, 'tcx> {
510510
/// checking inhabited-ness of types because whether a type is (visibly)
511511
/// inhabited can depend on whether it was defined in the current module or
512512
/// 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
514514
/// statement.
515515
pub module: DefId,
516516
param_env: ty::ParamEnv<'tcx>,
@@ -565,7 +565,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
565565
}
566566
}
567567

568-
/// Constructors and metaconstructors.
568+
/// Constructors, including base constructors and metaconstructors.
569569
#[derive(Clone, Debug, PartialEq)]
570570
enum Constructor<'tcx> {
571571
// Base constructors
@@ -584,12 +584,12 @@ enum Constructor<'tcx> {
584584
ConstantRange(u128, u128, Ty<'tcx>, RangeEnd),
585585
/// Slice patterns. Captures any array constructor of length >= i+j.
586586
VarLenSlice(u64, u64),
587-
/// Wildcard metaconstructor.
587+
/// Wildcard metaconstructor. Captures all possible constructors for a given type.
588588
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.
593593
MissingConstructors(MissingConstructors<'tcx>),
594594
}
595595

@@ -629,8 +629,7 @@ impl<'tcx> Constructor<'tcx> {
629629

630630
/// Split a constructor into equivalence classes of constructors that behave the same
631631
/// 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.
634633
fn split_meta_constructor(
635634
self,
636635
cx: &MatchCheckCtxt<'_, 'tcx>,
@@ -644,28 +643,20 @@ impl<'tcx> Constructor<'tcx> {
644643
// Any base constructor can be used unchanged.
645644
Single | Variant(_) | ConstantValue(_) | FixedLenSlice(_) => smallvec![self],
646645
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.
667658
//
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
669660
// like the following:
670661
//
671662
// |------| |----------| |-------| ||
@@ -680,12 +671,10 @@ impl<'tcx> Constructor<'tcx> {
680671
// The logic for determining how to split the ranges is fairly straightforward: we
681672
// calculate boundaries for each interval range, sort them, then create
682673
// 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
684675
// above.)
685676

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`.
689678
let ctor_range = IntRange::from_ctor(cx.tcx, cx.param_env, &self).unwrap();
690679

691680
/// Represents a border between 2 integers. Because the intervals spanning borders
@@ -810,7 +799,7 @@ impl<'tcx> Constructor<'tcx> {
810799
for ctor in head_ctors {
811800
match *ctor {
812801
ConstantValue(value) => {
813-
// extract the length of an array/slice from a constant
802+
// Extract the length of an array/slice from a constant
814803
match (value.val, &value.ty.kind) {
815804
(_, ty::Array(_, n)) => {
816805
max_fixed_len =
@@ -845,14 +834,19 @@ impl<'tcx> Constructor<'tcx> {
845834
Wildcard => {
846835
let is_declared_nonexhaustive = !cx.is_local(ty) && cx.is_non_exhaustive_enum(ty);
847836

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.
850838
let all_ctors = all_constructors(cx, ty);
851839

852840
let is_privately_empty = all_ctors.is_empty() && !cx.is_uninhabited(ty);
853841

854842
// For privately empty and non-exhaustive enums, we work as if there were an "extra"
855843
// `_` 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.
856850
let is_non_exhaustive = is_privately_empty
857851
|| is_declared_nonexhaustive
858852
|| (ty.is_ptr_sized_integral()
@@ -865,20 +859,6 @@ impl<'tcx> Constructor<'tcx> {
865859
// Therefore, if there is some pattern that is unmatched by `matrix`,
866860
// it will still be unmatched if the first constructor is replaced by
867861
// 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.
882862
let missing_ctors =
883863
MissingConstructors::new(cx.tcx, cx.param_env, all_ctors, head_ctors.clone());
884864
debug!(
@@ -932,11 +912,12 @@ impl<'tcx> Constructor<'tcx> {
932912
used_ctors: &Vec<Constructor<'tcx>>,
933913
) -> SmallVec<[Constructor<'tcx>; 1]> {
934914
debug!("subtract_meta_constructor {:?}", self);
915+
// The input must not contain a wildcard
935916
assert!(!used_ctors.iter().any(|c| c.is_wildcard()));
936917

937918
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.
940921
Single | Variant(_) => {
941922
if used_ctors.iter().any(|c| c == &self) {
942923
smallvec![]
@@ -953,11 +934,11 @@ impl<'tcx> Constructor<'tcx> {
953934
if used_ctors.iter().any(overlaps) { smallvec![] } else { smallvec![self] }
954935
}
955936
VarLenSlice(self_prefix, self_suffix) => {
956-
let self_len = self_prefix + self_suffix;
957937
// Initially we cover all slice lengths starting from self_len.
938+
let self_len = self_prefix + self_suffix;
958939

959940
// 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.
961942
let max_len: Option<_> = used_ctors
962943
.iter()
963944
.filter_map(|c: &Constructor<'tcx>| match c {
@@ -978,7 +959,7 @@ impl<'tcx> Constructor<'tcx> {
978959
// individual FixedLenSlice lengths in used_ctors. For that,
979960
// we extract all those lengths that are in our remaining range and
980961
// sort them. Every such length becomes a boundary between ranges
981-
// of lengths that will remain.
962+
// of the lengths that will remain.
982963
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
983964
enum Length {
984965
Start,
@@ -988,10 +969,12 @@ impl<'tcx> Constructor<'tcx> {
988969

989970
let mut lengths: Vec<_> = used_ctors
990971
.iter()
972+
// Extract fixed-size lengths
991973
.filter_map(|c: &Constructor<'tcx>| match c {
992974
FixedLenSlice(other_len) => Some(*other_len),
993975
_ => None,
994976
})
977+
// Keep only those in the remaining range
995978
.filter(|l| *l >= self_len)
996979
.filter(|l| match max_len {
997980
Some(max_len) => *l < max_len,
@@ -1004,6 +987,7 @@ impl<'tcx> Constructor<'tcx> {
1004987
lengths.sort_unstable();
1005988
lengths.dedup();
1006989

990+
// For each adjacent pair of lengths, output the lengths in between.
1007991
let mut remaining_ctors: SmallVec<_> = lengths
1008992
.windows(2)
1009993
.flat_map(|window| match (window[0], window[1]) {
@@ -1022,7 +1006,7 @@ impl<'tcx> Constructor<'tcx> {
10221006
Start => self_len,
10231007
Boundary(n) => n + 1,
10241008
};
1025-
// We know final_length >= self_len >= self_suffix
1009+
// We know final_length >= self_len >= self_suffix so this can't underflow.
10261010
remaining_ctors.push(VarLenSlice(final_length - self_suffix, self_suffix));
10271011
}
10281012

@@ -1127,10 +1111,10 @@ impl<'tcx> Constructor<'tcx> {
11271111
}
11281112

11291113
/// 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.
11311115
///
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.
11341118
fn arity<'a>(&self, cx: &MatchCheckCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> u64 {
11351119
debug!("Constructor::arity({:#?}, {:?})", self, ty);
11361120
match *self {
@@ -1342,10 +1326,10 @@ impl<'tcx> Witness<'tcx> {
13421326
/// of values, V, where each value in that set is not covered by any previously
13431327
/// used patterns and is covered by the pattern P'. Examples:
13441328
///
1345-
/// left_ty: tuple of 3 elements
1329+
/// ty: tuple of 3 elements
13461330
/// pats: [10, 20, _] => (10, 20, _)
13471331
///
1348-
/// left_ty: struct X { a: (bool, &'static str), b: usize}
1332+
/// ty: struct X { a: (bool, &'static str), b: usize}
13491333
/// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 }
13501334
fn apply_constructor<'a>(
13511335
mut self,
@@ -1372,9 +1356,8 @@ impl<'tcx> Witness<'tcx> {
13721356
}
13731357

13741358
/// 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.
13781361
///
13791362
/// We make sure to omit constructors that are statically impossible. E.g., for
13801363
/// `Option<!>`, we do not include `Some(_)` in the returned list of constructors.
@@ -1691,23 +1674,22 @@ impl<'tcx> PartialEq<Self> for MissingConstructors<'tcx> {
16911674
}
16921675
}
16931676

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:
16971679
/// (0) We don't exit early if the pattern matrix has zero rows. We just
16981680
/// continue to recurse over columns.
16991681
/// (1) all_constructors will only return constructors that are statically
17001682
/// possible. E.g., it will only return `Ok` for `Result<T, !>`.
17011683
///
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`.
17051687
///
17061688
/// All the patterns at each column of the `matrix ++ v` matrix must
17071689
/// have the same type, except that wildcard (PatKind::Wild) patterns
17081690
/// with type `TyErr` are also allowed, even if the "type of the column"
17091691
/// 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.
17111693
///
17121694
/// This is used both for reachability checking (if a pattern isn't useful in
17131695
/// relation to preceding patterns, it is not reachable) and exhaustiveness
@@ -1811,14 +1793,8 @@ fn is_useful_specialized<'p, 'a, 'tcx>(
18111793
ret
18121794
}
18131795

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).
18221798
fn pat_constructors<'tcx>(
18231799
tcx: TyCtxt<'tcx>,
18241800
param_env: ty::ParamEnv<'tcx>,
@@ -2014,13 +1990,11 @@ fn patterns_for_variant<'p, 'tcx>(
20141990
PatStack::from_vec(result)
20151991
}
20161992

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.
20211997
///
2022-
/// OTOH, slice patterns with a subslice pattern (tail @ ..) can be expanded into multiple
2023-
/// different patterns.
20241998
/// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
20251999
/// fields filled with wild patterns.
20262000
fn specialize_one_pattern<'p, 'a: 'p, 'p2: 'p, 'tcx>(
@@ -2034,7 +2008,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'p2: 'p, 'tcx>(
20342008
}
20352009

20362010
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
20382012
// should be discarded.
20392013
return match *pat.kind {
20402014
PatKind::Binding { .. } | PatKind::Wild => smallvec![PatStack::empty()],

0 commit comments

Comments
 (0)