]> git.lizzy.rs Git - rust.git/commitdiff
Inline max_slice_length
authorNadrieril <nadrieril+git@gmail.com>
Tue, 5 Nov 2019 16:10:50 +0000 (16:10 +0000)
committerNadrieril <nadrieril+git@gmail.com>
Tue, 5 Nov 2019 18:32:26 +0000 (18:32 +0000)
Note that where we previously ran `max_slice_len` with input having not
only matrix.heads() but also v.head(). Now we run it on matrix.heads()
only, but also take into account the currently processed constructor.
This preserves behavior since `pat_constructors` returns only one
constructor in the case that is of interest for us.

src/librustc_mir/hair/pattern/_match.rs

index 527924266fe20ee50227d7e373818e31e1051363..15f88334e8d5e2e6f36273bf489d61231ab94998 100644 (file)
@@ -985,7 +985,6 @@ pub enum WitnessPreference {
 #[derive(Copy, Clone, Debug)]
 struct PatCtxt<'tcx> {
     ty: Ty<'tcx>,
-    max_slice_length: u64,
     span: Span,
 }
 
@@ -1143,108 +1142,6 @@ fn all_constructors<'a, 'tcx>(
     ctors
 }
 
-fn max_slice_length<'p, 'a, 'tcx, I>(cx: &mut MatchCheckCtxt<'a, 'tcx>, patterns: I) -> u64
-where
-    I: Iterator<Item = &'p Pat<'tcx>>,
-    'tcx: 'p,
-{
-    // The exhaustiveness-checking paper does not include any details on
-    // checking variable-length slice patterns. However, they are matched
-    // by an infinite collection of fixed-length array patterns.
-    //
-    // Checking the infinite set directly would take an infinite amount
-    // of time. However, it turns out that for each finite set of
-    // patterns `P`, all sufficiently large array lengths are equivalent:
-    //
-    // Each slice `s` with a "sufficiently-large" length `l ≥ L` that applies
-    // to exactly the subset `Pₜ` of `P` can be transformed to a slice
-    // `sₘ` for each sufficiently-large length `m` that applies to exactly
-    // the same subset of `P`.
-    //
-    // Because of that, each witness for reachability-checking from one
-    // of the sufficiently-large lengths can be transformed to an
-    // equally-valid witness from any other length, so we only have
-    // to check slice lengths from the "minimal sufficiently-large length"
-    // and below.
-    //
-    // Note that the fact that there is a *single* `sₘ` for each `m`
-    // not depending on the specific pattern in `P` is important: if
-    // you look at the pair of patterns
-    //     `[true, ..]`
-    //     `[.., false]`
-    // Then any slice of length ≥1 that matches one of these two
-    // patterns can be trivially turned to a slice of any
-    // other length ≥1 that matches them and vice-versa - for
-    // but the slice from length 2 `[false, true]` that matches neither
-    // of these patterns can't be turned to a slice from length 1 that
-    // matches neither of these patterns, so we have to consider
-    // slices from length 2 there.
-    //
-    // Now, to see that that length exists and find it, observe that slice
-    // patterns are either "fixed-length" patterns (`[_, _, _]`) or
-    // "variable-length" patterns (`[_, .., _]`).
-    //
-    // For fixed-length patterns, all slices with lengths *longer* than
-    // the pattern's length have the same outcome (of not matching), so
-    // as long as `L` is greater than the pattern's length we can pick
-    // any `sₘ` from that length and get the same result.
-    //
-    // For variable-length patterns, the situation is more complicated,
-    // because as seen above the precise value of `sₘ` matters.
-    //
-    // However, for each variable-length pattern `p` with a prefix of length
-    // `plₚ` and suffix of length `slₚ`, only the first `plₚ` and the last
-    // `slₚ` elements are examined.
-    //
-    // Therefore, as long as `L` is positive (to avoid concerns about empty
-    // types), all elements after the maximum prefix length and before
-    // the maximum suffix length are not examined by any variable-length
-    // pattern, and therefore can be added/removed without affecting
-    // them - creating equivalent patterns from any sufficiently-large
-    // length.
-    //
-    // Of course, if fixed-length patterns exist, we must be sure
-    // that our length is large enough to miss them all, so
-    // we can pick `L = max(FIXED_LEN+1 ∪ {max(PREFIX_LEN) + max(SUFFIX_LEN)})`
-    //
-    // for example, with the above pair of patterns, all elements
-    // but the first and last can be added/removed, so any
-    // witness of length ≥2 (say, `[false, false, true]`) can be
-    // turned to a witness from any other length ≥2.
-
-    let mut max_prefix_len = 0;
-    let mut max_suffix_len = 0;
-    let mut max_fixed_len = 0;
-
-    for row in patterns {
-        match *row.kind {
-            PatKind::Constant { value } => {
-                // extract the length of an array/slice from a constant
-                match (value.val, &value.ty.kind) {
-                    (_, ty::Array(_, n)) => {
-                        max_fixed_len = cmp::max(max_fixed_len, n.eval_usize(cx.tcx, cx.param_env))
-                    }
-                    (ConstValue::Slice { start, end, .. }, ty::Slice(_)) => {
-                        max_fixed_len = cmp::max(max_fixed_len, (end - start) as u64)
-                    }
-                    _ => {}
-                }
-            }
-            PatKind::Slice { ref prefix, slice: None, ref suffix } => {
-                let fixed_len = prefix.len() as u64 + suffix.len() as u64;
-                max_fixed_len = cmp::max(max_fixed_len, fixed_len);
-            }
-            PatKind::Slice { ref prefix, slice: Some(_), ref suffix } => {
-                max_prefix_len = cmp::max(max_prefix_len, prefix.len() as u64);
-                max_suffix_len = cmp::max(max_suffix_len, suffix.len() as u64);
-            }
-            _ => {}
-        }
-    }
-
-    cmp::max(max_fixed_len + 1, max_prefix_len + max_suffix_len)
-}
-
 /// An inclusive interval, used for precise integer exhaustiveness checking.
 /// `IntRange`s always store a contiguous range. This means that values are
 /// encoded such that `0` encodes the minimum value for the integer,
@@ -1609,7 +1506,6 @@ pub fn is_useful<'p, 'a, 'tcx>(
         // introducing uninhabited patterns for inaccessible fields. We
         // need to figure out how to model that.
         ty,
-        max_slice_length: max_slice_length(cx, matrix.heads().chain(Some(v.head()))),
         span,
     };
 
@@ -2088,8 +1984,105 @@ fn range_borders(r: IntRange<'_>) -> impl Iterator<Item = Border> {
                     split_ctors.push(IntRange::range_to_ctor(tcx, ty, range, span));
                 }
             }
-            VarLenSlice(prefix, suffix) => {
-                split_ctors.extend((prefix + suffix..pcx.max_slice_length + 1).map(FixedLenSlice))
+            VarLenSlice(self_prefix, self_suffix) => {
+                // The exhaustiveness-checking paper does not include any details on
+                // checking variable-length slice patterns. However, they are matched
+                // by an infinite collection of fixed-length array patterns.
+                //
+                // Checking the infinite set directly would take an infinite amount
+                // of time. However, it turns out that for each finite set of
+                // patterns `P`, all sufficiently large array lengths are equivalent:
+                //
+                // Each slice `s` with a "sufficiently-large" length `l ≥ L` that applies
+                // to exactly the subset `Pₜ` of `P` can be transformed to a slice
+                // `sₘ` for each sufficiently-large length `m` that applies to exactly
+                // the same subset of `P`.
+                //
+                // Because of that, each witness for reachability-checking from one
+                // of the sufficiently-large lengths can be transformed to an
+                // equally-valid witness from any other length, so we only have
+                // to check slice lengths from the "minimal sufficiently-large length"
+                // and below.
+                //
+                // Note that the fact that there is a *single* `sₘ` for each `m`
+                // not depending on the specific pattern in `P` is important: if
+                // you look at the pair of patterns
+                //     `[true, ..]`
+                //     `[.., false]`
+                // Then any slice of length ≥1 that matches one of these two
+                // patterns can be trivially turned to a slice of any
+                // other length ≥1 that matches them and vice-versa - for
+                // but the slice from length 2 `[false, true]` that matches neither
+                // of these patterns can't be turned to a slice from length 1 that
+                // matches neither of these patterns, so we have to consider
+                // slices from length 2 there.
+                //
+                // Now, to see that that length exists and find it, observe that slice
+                // patterns are either "fixed-length" patterns (`[_, _, _]`) or
+                // "variable-length" patterns (`[_, .., _]`).
+                //
+                // For fixed-length patterns, all slices with lengths *longer* than
+                // the pattern's length have the same outcome (of not matching), so
+                // as long as `L` is greater than the pattern's length we can pick
+                // any `sₘ` from that length and get the same result.
+                //
+                // For variable-length patterns, the situation is more complicated,
+                // because as seen above the precise value of `sₘ` matters.
+                //
+                // However, for each variable-length pattern `p` with a prefix of length
+                // `plₚ` and suffix of length `slₚ`, only the first `plₚ` and the last
+                // `slₚ` elements are examined.
+                //
+                // Therefore, as long as `L` is positive (to avoid concerns about empty
+                // types), all elements after the maximum prefix length and before
+                // the maximum suffix length are not examined by any variable-length
+                // pattern, and therefore can be added/removed without affecting
+                // them - creating equivalent patterns from any sufficiently-large
+                // length.
+                //
+                // Of course, if fixed-length patterns exist, we must be sure
+                // that our length is large enough to miss them all, so
+                // we can pick `L = max(FIXED_LEN+1 ∪ {max(PREFIX_LEN) + max(SUFFIX_LEN)})`
+                //
+                // for example, with the above pair of patterns, all elements
+                // but the first and last can be added/removed, so any
+                // witness of length ≥2 (say, `[false, false, true]`) can be
+                // turned to a witness from any other length ≥2.
+
+                let mut max_prefix_len = self_prefix;
+                let mut max_suffix_len = self_suffix;
+                let mut max_fixed_len = 0;
+
+                for row in matrix.heads() {
+                    match *row.kind {
+                        PatKind::Constant { value } => {
+                            // extract the length of an array/slice from a constant
+                            match (value.val, &value.ty.kind) {
+                                (_, ty::Array(_, n)) => {
+                                    max_fixed_len =
+                                        cmp::max(max_fixed_len, n.eval_usize(tcx, param_env))
+                                }
+                                (ConstValue::Slice { start, end, .. }, ty::Slice(_)) => {
+                                    max_fixed_len = cmp::max(max_fixed_len, (end - start) as u64)
+                                }
+                                _ => {}
+                            }
+                        }
+                        PatKind::Slice { ref prefix, slice: None, ref suffix } => {
+                            let fixed_len = prefix.len() as u64 + suffix.len() as u64;
+                            max_fixed_len = cmp::max(max_fixed_len, fixed_len);
+                        }
+                        PatKind::Slice { ref prefix, slice: Some(_), ref suffix } => {
+                            max_prefix_len = cmp::max(max_prefix_len, prefix.len() as u64);
+                            max_suffix_len = cmp::max(max_suffix_len, suffix.len() as u64);
+                        }
+                        _ => {}
+                    }
+                }
+
+                let max_slice_length = cmp::max(max_fixed_len + 1, max_prefix_len + max_suffix_len);
+                split_ctors
+                    .extend((self_prefix + self_suffix..=max_slice_length).map(FixedLenSlice))
             }
             // Any other constructor can be used unchanged.
             _ => split_ctors.push(ctor),