about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs49
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs26
2 files changed, 48 insertions, 27 deletions
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
index 060e4fdf6f8..4860bb0fe87 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -19,7 +19,7 @@ use rustc_middle::mir::Field;
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::{self, Const, Ty, TyCtxt};
 use rustc_session::lint;
-use rustc_span::DUMMY_SP;
+use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{Integer, Size, VariantIdx};
 
 use smallvec::{smallvec, SmallVec};
@@ -184,12 +184,18 @@ impl IntRange {
     }
 
     /// Lint on likely incorrect range patterns (#63987)
-    pub(super) fn lint_overlapping_range_endpoints(&self, pcx: PatCtxt<'_, '_, '_>, hir_id: HirId) {
+    pub(super) fn lint_overlapping_range_endpoints<'a, 'tcx: 'a>(
+        &self,
+        pcx: PatCtxt<'_, '_, 'tcx>,
+        ctors: impl Iterator<Item = (&'a Constructor<'tcx>, Span)>,
+        column_count: usize,
+        hir_id: HirId,
+    ) {
         if self.is_singleton() {
             return;
         }
 
-        if pcx.matrix.column_count().unwrap_or(0) != 1 {
+        if column_count != 1 {
             // FIXME: for now, only check for overlapping ranges on simple range
             // patterns. Otherwise with the current logic the following is detected
             // as overlapping:
@@ -203,9 +209,7 @@ impl IntRange {
             return;
         }
 
-        let overlaps: Vec<_> = pcx
-            .matrix
-            .head_ctors_and_spans(pcx.cx)
+        let overlaps: Vec<_> = ctors
             .filter_map(|(ctor, span)| Some((ctor.as_int_range()?, span)))
             .filter(|(range, _)| self.suspicious_intersection(range))
             .map(|(range, span)| (self.intersection(&range).unwrap(), span))
@@ -655,28 +659,33 @@ impl<'tcx> Constructor<'tcx> {
     /// This function may discard some irrelevant constructors if this preserves behavior and
     /// diagnostics. Eg. for the `_` case, we ignore the constructors already present in the
     /// matrix, unless all of them are.
-    pub(super) fn split<'p>(&self, pcx: PatCtxt<'_, 'p, 'tcx>) -> SmallVec<[Self; 1]> {
-        debug!("Constructor::split({:#?}, {:#?})", self, pcx.matrix);
+    pub(super) fn split<'a>(
+        &self,
+        pcx: PatCtxt<'_, '_, 'tcx>,
+        ctors: impl Iterator<Item = &'a Constructor<'tcx>> + Clone,
+    ) -> SmallVec<[Self; 1]>
+    where
+        'tcx: 'a,
+    {
+        debug!("Constructor::split({:#?})", self);
 
         match self {
             Wildcard => {
                 let mut split_wildcard = SplitWildcard::new(pcx);
-                split_wildcard.split(pcx);
+                split_wildcard.split(pcx, ctors);
                 split_wildcard.into_ctors(pcx)
             }
             // Fast-track if the range is trivial. In particular, we don't do the overlapping
             // ranges check.
             IntRange(ctor_range) if !ctor_range.is_singleton() => {
                 let mut split_range = SplitIntRange::new(ctor_range.clone());
-                let intranges =
-                    pcx.matrix.head_ctors(pcx.cx).filter_map(|ctor| ctor.as_int_range());
+                let intranges = ctors.filter_map(|ctor| ctor.as_int_range());
                 split_range.split(intranges.cloned());
                 split_range.iter().map(IntRange).collect()
             }
             &Slice(Slice { kind: VarLen(self_prefix, self_suffix), array_len }) => {
                 let mut split_self = SplitVarLenSlice::new(self_prefix, self_suffix, array_len);
-                let slices =
-                    pcx.matrix.head_ctors(pcx.cx).filter_map(|c| c.as_slice()).map(|s| s.kind);
+                let slices = ctors.filter_map(|c| c.as_slice()).map(|s| s.kind);
                 split_self.split(slices);
                 split_self.iter().map(Slice).collect()
             }
@@ -912,11 +921,17 @@ impl<'tcx> SplitWildcard<'tcx> {
 
     /// Pass a set of constructors relative to which to split this one. Don't call twice, it won't
     /// do what you want.
-    pub(super) fn split(&mut self, pcx: PatCtxt<'_, '_, 'tcx>) {
-        self.matrix_ctors =
-            pcx.matrix.head_ctors(pcx.cx).cloned().filter(|c| !c.is_wildcard()).collect();
+    pub(super) fn split<'a>(
+        &mut self,
+        pcx: PatCtxt<'_, '_, 'tcx>,
+        ctors: impl Iterator<Item = &'a Constructor<'tcx>> + Clone,
+    ) where
+        'tcx: 'a,
+    {
         // Since `all_ctors` never contains wildcards, this won't recurse further.
-        self.all_ctors = self.all_ctors.iter().flat_map(|ctor| ctor.split(pcx)).collect();
+        self.all_ctors =
+            self.all_ctors.iter().flat_map(|ctor| ctor.split(pcx, ctors.clone())).collect();
+        self.matrix_ctors = ctors.filter(|c| !c.is_wildcard()).cloned().collect();
     }
 
     /// Whether there are any value constructors for this type that are not present in the matrix.
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index 5da42e705df..ad672b59ba4 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -358,8 +358,6 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
 #[derive(Copy, Clone)]
 pub(super) struct PatCtxt<'a, 'p, 'tcx> {
     pub(super) cx: &'a MatchCheckCtxt<'p, 'tcx>,
-    /// Current state of the matrix.
-    pub(super) matrix: &'a Matrix<'p, 'tcx>,
     /// Type of the current column under investigation.
     pub(super) ty: Ty<'tcx>,
     /// Span of the current pattern under investigation.
@@ -538,7 +536,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
     pub(super) fn head_ctors<'a>(
         &'a self,
         cx: &'a MatchCheckCtxt<'p, 'tcx>,
-    ) -> impl Iterator<Item = &'a Constructor<'tcx>> + Captures<'p> {
+    ) -> impl Iterator<Item = &'a Constructor<'tcx>> + Captures<'p> + Clone {
         self.patterns.iter().map(move |r| r.head_ctor(cx))
     }
 
@@ -804,6 +802,7 @@ impl<'tcx> Usefulness<'tcx> {
     fn apply_constructor<'p>(
         self,
         pcx: PatCtxt<'_, 'p, 'tcx>,
+        matrix: &Matrix<'p, 'tcx>, // used to compute missing ctors
         ctor: &Constructor<'tcx>,
         ctor_wild_subpatterns: &Fields<'p, 'tcx>,
     ) -> Self {
@@ -811,7 +810,7 @@ impl<'tcx> Usefulness<'tcx> {
             UsefulWithWitness(witnesses) => {
                 let new_witnesses = if ctor.is_wildcard() {
                     let mut split_wildcard = SplitWildcard::new(pcx);
-                    split_wildcard.split(pcx);
+                    split_wildcard.split(pcx, matrix.head_ctors(pcx.cx));
                     let new_patterns = split_wildcard.report_missing_patterns(pcx);
                     witnesses
                         .into_iter()
@@ -968,7 +967,7 @@ fn is_useful<'p, 'tcx>(
 
     // FIXME(Nadrieril): Hack to work around type normalization issues (see #72476).
     let ty = matrix.heads().next().map(|r| r.ty).unwrap_or(v.head().ty);
-    let pcx = PatCtxt { cx, matrix, ty, span: v.head().span, is_top_level };
+    let pcx = PatCtxt { cx, ty, span: v.head().span, is_top_level };
 
     debug!("is_useful_expand_first_col: ty={:#?}, expanding {:#?}", pcx.ty, v.head());
 
@@ -995,20 +994,27 @@ fn is_useful<'p, 'tcx>(
         let v_ctor = v.head_ctor(cx);
         if let Constructor::IntRange(ctor_range) = &v_ctor {
             // Lint on likely incorrect range patterns (#63987)
-            ctor_range.lint_overlapping_range_endpoints(pcx, hir_id)
+            ctor_range.lint_overlapping_range_endpoints(
+                pcx,
+                matrix.head_ctors_and_spans(cx),
+                matrix.column_count().unwrap_or(0),
+                hir_id,
+            )
         }
         // We split the head constructor of `v`.
-        let split_ctors = v_ctor.split(pcx);
+        let split_ctors = v_ctor.split(pcx, matrix.head_ctors(cx));
         // For each constructor, we compute whether there's a value that starts with it that would
         // witness the usefulness of `v`.
+        let start_matrix = &matrix;
         let usefulnesses = split_ctors.into_iter().map(|ctor| {
             // We cache the result of `Fields::wildcards` because it is used a lot.
             let ctor_wild_subpatterns = Fields::wildcards(pcx, &ctor);
-            let matrix = pcx.matrix.specialize_constructor(pcx, &ctor, &ctor_wild_subpatterns);
+            let spec_matrix =
+                start_matrix.specialize_constructor(pcx, &ctor, &ctor_wild_subpatterns);
             let v = v.pop_head_constructor(&ctor_wild_subpatterns);
             let usefulness =
-                is_useful(pcx.cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
-            usefulness.apply_constructor(pcx, &ctor, &ctor_wild_subpatterns)
+                is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false);
+            usefulness.apply_constructor(pcx, start_matrix, &ctor, &ctor_wild_subpatterns)
         });
         Usefulness::merge(usefulnesses)
     };