summary refs log tree commit diff
path: root/compiler/rustc_pattern_analysis
diff options
context:
space:
mode:
authorNadrieril <nadrieril+git@gmail.com>2024-01-24 21:29:58 +0100
committerNadrieril <nadrieril+git@gmail.com>2024-01-30 17:06:52 +0100
commit6ef836246bc48387bfdbe2bde951037c71350c00 (patch)
treeed572d9237523487f1f7c6bd983ca024324b5bf3 /compiler/rustc_pattern_analysis
parent83e88c6dfcd7aecf1c49d73e2d9e761d15302341 (diff)
downloadrust-6ef836246bc48387bfdbe2bde951037c71350c00.tar.gz
rust-6ef836246bc48387bfdbe2bde951037c71350c00.zip
Make `PatternColumn` part of the public API
Diffstat (limited to 'compiler/rustc_pattern_analysis')
-rw-r--r--compiler/rustc_pattern_analysis/src/constructor.rs10
-rw-r--r--compiler/rustc_pattern_analysis/src/lib.rs4
-rw-r--r--compiler/rustc_pattern_analysis/src/lints.rs87
-rw-r--r--compiler/rustc_pattern_analysis/src/pat_column.rs90
4 files changed, 101 insertions, 90 deletions
diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs
index df5bf3111ad..4be564b1d7b 100644
--- a/compiler/rustc_pattern_analysis/src/constructor.rs
+++ b/compiler/rustc_pattern_analysis/src/constructor.rs
@@ -948,10 +948,10 @@ pub enum ConstructorSet<Cx: TypeCx> {
 /// of the `ConstructorSet` for the type, yet if we forgot to include them in `present` we would be
 /// ignoring any row with `Opaque`s in the algorithm. Hence the importance of point 4.
 #[derive(Debug)]
-pub(crate) struct SplitConstructorSet<Cx: TypeCx> {
-    pub(crate) present: SmallVec<[Constructor<Cx>; 1]>,
-    pub(crate) missing: Vec<Constructor<Cx>>,
-    pub(crate) missing_empty: Vec<Constructor<Cx>>,
+pub struct SplitConstructorSet<Cx: TypeCx> {
+    pub present: SmallVec<[Constructor<Cx>; 1]>,
+    pub missing: Vec<Constructor<Cx>>,
+    pub missing_empty: Vec<Constructor<Cx>>,
 }
 
 impl<Cx: TypeCx> ConstructorSet<Cx> {
@@ -960,7 +960,7 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
     /// or slices. This can get subtle; see [`SplitConstructorSet`] for details of this operation
     /// and its invariants.
     #[instrument(level = "debug", skip(self, ctors), ret)]
-    pub(crate) fn split<'a>(
+    pub fn split<'a>(
         &self,
         ctors: impl Iterator<Item = &'a Constructor<Cx>> + Clone,
     ) -> SplitConstructorSet<Cx>
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index 99c32de7482..3d0eb117d17 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -6,6 +6,7 @@ pub mod errors;
 #[cfg(feature = "rustc")]
 pub(crate) mod lints;
 pub mod pat;
+pub mod pat_column;
 #[cfg(feature = "rustc")]
 pub mod rustc;
 pub mod usefulness;
@@ -67,8 +68,9 @@ use rustc_span::ErrorGuaranteed;
 
 use crate::constructor::{Constructor, ConstructorSet, IntRange};
 #[cfg(feature = "rustc")]
-use crate::lints::{lint_nonexhaustive_missing_variants, PatternColumn};
+use crate::lints::lint_nonexhaustive_missing_variants;
 use crate::pat::DeconstructedPat;
+use crate::pat_column::PatternColumn;
 #[cfg(feature = "rustc")]
 use crate::rustc::RustcMatchCheckCtxt;
 #[cfg(feature = "rustc")]
diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs
index 4cbd5e70189..3f1497540d2 100644
--- a/compiler/rustc_pattern_analysis/src/lints.rs
+++ b/compiler/rustc_pattern_analysis/src/lints.rs
@@ -1,92 +1,11 @@
 use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_span::ErrorGuaranteed;
 
-use crate::constructor::{Constructor, SplitConstructorSet};
+use crate::constructor::Constructor;
 use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered};
-use crate::pat::{DeconstructedPat, PatOrWild};
+use crate::pat_column::PatternColumn;
 use crate::rustc::{RevealedTy, RustcMatchCheckCtxt, WitnessPat};
-use crate::{MatchArm, TypeCx};
-
-/// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that
-/// inspect the same subvalue/place".
-/// This is used to traverse patterns column-by-column for lints. Despite similarities with the
-/// algorithm in [`crate::usefulness`], this does a different traversal. Notably this is linear in
-/// the depth of patterns, whereas `compute_exhaustiveness_and_usefulness` is worst-case exponential
-/// (exhaustiveness is NP-complete). The core difference is that we treat sub-columns separately.
-///
-/// This must not contain an or-pattern. `expand_and_push` takes care to expand them.
-///
-/// This is not used in the usefulness algorithm; only in lints.
-#[derive(Debug)]
-pub(crate) struct PatternColumn<'p, Cx: TypeCx> {
-    patterns: Vec<&'p DeconstructedPat<'p, Cx>>,
-}
-
-impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> {
-    pub(crate) fn new(arms: &[MatchArm<'p, Cx>]) -> Self {
-        let patterns = Vec::with_capacity(arms.len());
-        let mut column = PatternColumn { patterns };
-        for arm in arms {
-            column.expand_and_push(PatOrWild::Pat(arm.pat));
-        }
-        column
-    }
-    /// Pushes a pattern onto the column, expanding any or-patterns into its subpatterns.
-    /// Internal method, prefer [`PatternColumn::new`].
-    fn expand_and_push(&mut self, pat: PatOrWild<'p, Cx>) {
-        // We flatten or-patterns and skip algorithm-generated wildcards.
-        if pat.is_or_pat() {
-            self.patterns.extend(
-                pat.flatten_or_pat().into_iter().filter_map(|pat_or_wild| pat_or_wild.as_pat()),
-            )
-        } else if let Some(pat) = pat.as_pat() {
-            self.patterns.push(pat)
-        }
-    }
-
-    fn head_ty(&self) -> Option<&Cx::Ty> {
-        self.patterns.first().map(|pat| pat.ty())
-    }
-
-    /// Do constructor splitting on the constructors of the column.
-    fn analyze_ctors(&self, cx: &Cx, ty: &Cx::Ty) -> Result<SplitConstructorSet<Cx>, Cx::Error> {
-        let column_ctors = self.patterns.iter().map(|p| p.ctor());
-        let ctors_for_ty = cx.ctors_for_ty(ty)?;
-        Ok(ctors_for_ty.split(column_ctors))
-    }
-
-    /// Does specialization: given a constructor, this takes the patterns from the column that match
-    /// the constructor, and outputs their fields.
-    /// This returns one column per field of the constructor. They usually all have the same length
-    /// (the number of patterns in `self` that matched `ctor`), except that we expand or-patterns
-    /// which may change the lengths.
-    fn specialize(
-        &self,
-        cx: &Cx,
-        ty: &Cx::Ty,
-        ctor: &Constructor<Cx>,
-    ) -> Vec<PatternColumn<'p, Cx>> {
-        let arity = ctor.arity(cx, ty);
-        if arity == 0 {
-            return Vec::new();
-        }
-
-        // We specialize the column by `ctor`. This gives us `arity`-many columns of patterns. These
-        // columns may have different lengths in the presence of or-patterns (this is why we can't
-        // reuse `Matrix`).
-        let mut specialized_columns: Vec<_> =
-            (0..arity).map(|_| Self { patterns: Vec::new() }).collect();
-        let relevant_patterns =
-            self.patterns.iter().filter(|pat| ctor.is_covered_by(cx, pat.ctor()));
-        for pat in relevant_patterns {
-            let specialized = pat.specialize(ctor, arity);
-            for (subpat, column) in specialized.into_iter().zip(&mut specialized_columns) {
-                column.expand_and_push(subpat);
-            }
-        }
-        specialized_columns
-    }
-}
+use crate::MatchArm;
 
 /// Traverse the patterns to collect any variants of a non_exhaustive enum that fail to be mentioned
 /// in a given column.
diff --git a/compiler/rustc_pattern_analysis/src/pat_column.rs b/compiler/rustc_pattern_analysis/src/pat_column.rs
new file mode 100644
index 00000000000..3cacfc491b9
--- /dev/null
+++ b/compiler/rustc_pattern_analysis/src/pat_column.rs
@@ -0,0 +1,90 @@
+use crate::constructor::{Constructor, SplitConstructorSet};
+use crate::pat::{DeconstructedPat, PatOrWild};
+use crate::{Captures, MatchArm, TypeCx};
+
+/// A column of patterns in a match, where a column is the intuitive notion of "subpatterns that
+/// inspect the same subvalue/place".
+/// This is used to traverse patterns column-by-column for lints. Despite similarities with the
+/// algorithm in [`crate::usefulness`], this does a different traversal. Notably this is linear in
+/// the depth of patterns, whereas `compute_exhaustiveness_and_usefulness` is worst-case exponential
+/// (exhaustiveness is NP-complete). The core difference is that we treat sub-columns separately.
+///
+/// This is not used in the usefulness algorithm; only in lints.
+#[derive(Debug)]
+pub struct PatternColumn<'p, Cx: TypeCx> {
+    /// This must not contain an or-pattern. `expand_and_push` takes care to expand them.
+    patterns: Vec<&'p DeconstructedPat<'p, Cx>>,
+}
+
+impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> {
+    pub fn new(arms: &[MatchArm<'p, Cx>]) -> Self {
+        let patterns = Vec::with_capacity(arms.len());
+        let mut column = PatternColumn { patterns };
+        for arm in arms {
+            column.expand_and_push(PatOrWild::Pat(arm.pat));
+        }
+        column
+    }
+    /// Pushes a pattern onto the column, expanding any or-patterns into its subpatterns.
+    /// Internal method, prefer [`PatternColumn::new`].
+    fn expand_and_push(&mut self, pat: PatOrWild<'p, Cx>) {
+        // We flatten or-patterns and skip algorithm-generated wildcards.
+        if pat.is_or_pat() {
+            self.patterns.extend(
+                pat.flatten_or_pat().into_iter().filter_map(|pat_or_wild| pat_or_wild.as_pat()),
+            )
+        } else if let Some(pat) = pat.as_pat() {
+            self.patterns.push(pat)
+        }
+    }
+
+    pub fn head_ty(&self) -> Option<&Cx::Ty> {
+        self.patterns.first().map(|pat| pat.ty())
+    }
+    pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'p DeconstructedPat<'p, Cx>> + Captures<'a> {
+        self.patterns.iter().copied()
+    }
+
+    /// Do constructor splitting on the constructors of the column.
+    pub fn analyze_ctors(
+        &self,
+        cx: &Cx,
+        ty: &Cx::Ty,
+    ) -> Result<SplitConstructorSet<Cx>, Cx::Error> {
+        let column_ctors = self.patterns.iter().map(|p| p.ctor());
+        let ctors_for_ty = cx.ctors_for_ty(ty)?;
+        Ok(ctors_for_ty.split(column_ctors))
+    }
+
+    /// Does specialization: given a constructor, this takes the patterns from the column that match
+    /// the constructor, and outputs their fields.
+    /// This returns one column per field of the constructor. They usually all have the same length
+    /// (the number of patterns in `self` that matched `ctor`), except that we expand or-patterns
+    /// which may change the lengths.
+    pub fn specialize(
+        &self,
+        cx: &Cx,
+        ty: &Cx::Ty,
+        ctor: &Constructor<Cx>,
+    ) -> Vec<PatternColumn<'p, Cx>> {
+        let arity = ctor.arity(cx, ty);
+        if arity == 0 {
+            return Vec::new();
+        }
+
+        // We specialize the column by `ctor`. This gives us `arity`-many columns of patterns. These
+        // columns may have different lengths in the presence of or-patterns (this is why we can't
+        // reuse `Matrix`).
+        let mut specialized_columns: Vec<_> =
+            (0..arity).map(|_| Self { patterns: Vec::new() }).collect();
+        let relevant_patterns =
+            self.patterns.iter().filter(|pat| ctor.is_covered_by(cx, pat.ctor()));
+        for pat in relevant_patterns {
+            let specialized = pat.specialize(ctor, arity);
+            for (subpat, column) in specialized.into_iter().zip(&mut specialized_columns) {
+                column.expand_and_push(subpat);
+            }
+        }
+        specialized_columns
+    }
+}