about summary refs log tree commit diff
path: root/compiler/rustc_pattern_analysis/src
diff options
context:
space:
mode:
authorNadrieril <nadrieril+git@gmail.com>2023-12-15 16:18:21 +0100
committerNadrieril <nadrieril+git@gmail.com>2023-12-15 16:58:38 +0100
commit1e89a38423ee1b562e3b10278d0097d88bc48f5f (patch)
tree4f9a1a59238d7c5b80020844b430bab6b6eb4de8 /compiler/rustc_pattern_analysis/src
parent8c5e89907c1f6312c8613b5d6851381bbcde8052 (diff)
downloadrust-1e89a38423ee1b562e3b10278d0097d88bc48f5f.tar.gz
rust-1e89a38423ee1b562e3b10278d0097d88bc48f5f.zip
`pattern_analysis` doesn't need to know what spans are
Diffstat (limited to 'compiler/rustc_pattern_analysis/src')
-rw-r--r--compiler/rustc_pattern_analysis/src/lib.rs5
-rw-r--r--compiler/rustc_pattern_analysis/src/lints.rs4
-rw-r--r--compiler/rustc_pattern_analysis/src/pat.rs36
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs4
-rw-r--r--compiler/rustc_pattern_analysis/src/usefulness.rs10
5 files changed, 31 insertions, 28 deletions
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index 36ec86eb5b3..12d2e0fc18b 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -37,14 +37,17 @@ use crate::rustc::RustcMatchCheckCtxt;
 use crate::usefulness::{compute_match_usefulness, ValidityConstraint};
 
 pub trait MatchCx: Sized + Clone + fmt::Debug {
+    /// The type of a pattern.
     type Ty: Copy + Clone + fmt::Debug; // FIXME: remove Copy
-    type Span: Clone + Default;
     /// The index of an enum variant.
     type VariantIdx: Clone + Idx;
     /// A string literal
     type StrLit: Clone + PartialEq + fmt::Debug;
     /// Extra data to store on a match arm.
     type ArmData: Copy + Clone + fmt::Debug;
+    /// Extra data to store on a pattern. `Default` needed when we create fictitious wildcard
+    /// patterns during analysis.
+    type PatData: Clone + Default;
 
     fn is_opaque_ty(ty: Self::Ty) -> bool;
     fn is_exhaustive_patterns_feature_on(&self) -> bool;
diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs
index 2391dd9096e..6c00a265b69 100644
--- a/compiler/rustc_pattern_analysis/src/lints.rs
+++ b/compiler/rustc_pattern_analysis/src/lints.rs
@@ -213,7 +213,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
                 };
 
                 use rustc_errors::DecorateLint;
-                let mut err = cx.tcx.sess.struct_span_warn(*arm.pat.span(), "");
+                let mut err = cx.tcx.sess.struct_span_warn(*arm.pat.data(), "");
                 err.set_primary_message(decorator.msg());
                 decorator.decorate_lint(&mut err);
                 err.emit();
@@ -263,7 +263,7 @@ pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>(
                 let mut suffixes: SmallVec<[_; 1]> = Default::default();
                 // Iterate on patterns that contained `overlap`.
                 for pat in column.iter() {
-                    let this_span = *pat.span();
+                    let this_span = *pat.data();
                     let Constructor::IntRange(this_range) = pat.ctor() else { continue };
                     if this_range.is_singleton() {
                         // Don't lint when one of the ranges is a singleton.
diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs
index f719cc511fb..daaf62dca3d 100644
--- a/compiler/rustc_pattern_analysis/src/pat.rs
+++ b/compiler/rustc_pattern_analysis/src/pat.rs
@@ -26,23 +26,23 @@ pub struct DeconstructedPat<'p, Cx: MatchCx> {
     ctor: Constructor<Cx>,
     fields: &'p [DeconstructedPat<'p, Cx>],
     ty: Cx::Ty,
-    span: Cx::Span,
+    data: Cx::PatData,
     /// Whether removing this arm would change the behavior of the match expression.
     useful: Cell<bool>,
 }
 
 impl<'p, Cx: MatchCx> DeconstructedPat<'p, Cx> {
-    pub fn wildcard(ty: Cx::Ty, span: Cx::Span) -> Self {
-        Self::new(Wildcard, &[], ty, span)
+    pub fn wildcard(ty: Cx::Ty, data: Cx::PatData) -> Self {
+        Self::new(Wildcard, &[], ty, data)
     }
 
     pub fn new(
         ctor: Constructor<Cx>,
         fields: &'p [DeconstructedPat<'p, Cx>],
         ty: Cx::Ty,
-        span: Cx::Span,
+        data: Cx::PatData,
     ) -> Self {
-        DeconstructedPat { ctor, fields, ty, span, useful: Cell::new(false) }
+        DeconstructedPat { ctor, fields, ty, data, useful: Cell::new(false) }
     }
 
     pub(crate) fn is_or_pat(&self) -> bool {
@@ -63,8 +63,8 @@ impl<'p, Cx: MatchCx> DeconstructedPat<'p, Cx> {
     pub fn ty(&self) -> Cx::Ty {
         self.ty
     }
-    pub fn span(&self) -> &Cx::Span {
-        &self.span
+    pub fn data(&self) -> &Cx::PatData {
+        &self.data
     }
 
     pub fn iter_fields<'a>(
@@ -83,7 +83,7 @@ impl<'p, Cx: MatchCx> DeconstructedPat<'p, Cx> {
         let wildcard_sub_tys = || {
             let tys = pcx.cx.ctor_sub_tys(other_ctor, pcx.ty);
             tys.iter()
-                .map(|ty| DeconstructedPat::wildcard(*ty, Cx::Span::default()))
+                .map(|ty| DeconstructedPat::wildcard(*ty, Cx::PatData::default()))
                 .map(|pat| pcx.wildcard_arena.alloc(pat) as &_)
                 .collect()
         };
@@ -113,8 +113,8 @@ impl<'p, Cx: MatchCx> DeconstructedPat<'p, Cx> {
         }
     }
 
-    /// We keep track for each pattern if it was ever useful during the analysis. This is used
-    /// with `redundant_spans` to report redundant subpatterns arising from or patterns.
+    /// We keep track for each pattern if it was ever useful during the analysis. This is used with
+    /// `redundant_subpatterns` to report redundant subpatterns arising from or patterns.
     pub(crate) fn set_useful(&self) {
         self.useful.set(true)
     }
@@ -132,19 +132,19 @@ impl<'p, Cx: MatchCx> DeconstructedPat<'p, Cx> {
         }
     }
 
-    /// Report the spans of subpatterns that were not useful, if any.
-    pub(crate) fn redundant_spans(&self) -> Vec<Cx::Span> {
-        let mut spans = Vec::new();
-        self.collect_redundant_spans(&mut spans);
-        spans
+    /// Report the subpatterns that were not useful, if any.
+    pub(crate) fn redundant_subpatterns(&self) -> Vec<&Self> {
+        let mut subpats = Vec::new();
+        self.collect_redundant_subpatterns(&mut subpats);
+        subpats
     }
-    fn collect_redundant_spans(&self, spans: &mut Vec<Cx::Span>) {
+    fn collect_redundant_subpatterns<'a>(&'a self, subpats: &mut Vec<&'a Self>) {
         // We don't look at subpatterns if we already reported the whole pattern as redundant.
         if !self.is_useful() {
-            spans.push(self.span.clone());
+            subpats.push(self);
         } else {
             for p in self.iter_fields() {
-                p.collect_redundant_spans(spans);
+                p.collect_redundant_subpatterns(subpats);
             }
         }
     }
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index 1d08d2efef3..e5347ce6363 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -35,7 +35,7 @@ pub(crate) type PatCtxt<'a, 'p, 'tcx> =
     crate::usefulness::PatCtxt<'a, 'p, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub(crate) type SplitConstructorSet<'p, 'tcx> =
     crate::constructor::SplitConstructorSet<RustcMatchCheckCtxt<'p, 'tcx>>;
-pub type Usefulness = crate::usefulness::Usefulness<Span>;
+pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub type UsefulnessReport<'p, 'tcx> =
     crate::usefulness::UsefulnessReport<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub type WitnessPat<'p, 'tcx> = crate::pat::WitnessPat<RustcMatchCheckCtxt<'p, 'tcx>>;
@@ -864,10 +864,10 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
 
 impl<'p, 'tcx> MatchCx for RustcMatchCheckCtxt<'p, 'tcx> {
     type Ty = Ty<'tcx>;
-    type Span = Span;
     type VariantIdx = VariantIdx;
     type StrLit = Const<'tcx>;
     type ArmData = HirId;
+    type PatData = Span;
 
     fn is_exhaustive_patterns_feature_on(&self) -> bool {
         self.tcx.features().exhaustive_patterns
diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs
index 3141e992f33..88d28c8f483 100644
--- a/compiler/rustc_pattern_analysis/src/usefulness.rs
+++ b/compiler/rustc_pattern_analysis/src/usefulness.rs
@@ -849,7 +849,7 @@ impl<'a, 'p, Cx: MatchCx> Matrix<'a, 'p, Cx> {
         scrut_validity: ValidityConstraint,
     ) -> Self {
         let wild_pattern =
-            wildcard_arena.alloc(DeconstructedPat::wildcard(scrut_ty, Cx::Span::default()));
+            wildcard_arena.alloc(DeconstructedPat::wildcard(scrut_ty, Default::default()));
         let wildcard_row = PatStack::from_pattern(wild_pattern);
         let mut matrix = Matrix {
             rows: Vec::with_capacity(arms.len()),
@@ -1287,11 +1287,11 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: MatchCx>(
 
 /// Indicates whether or not a given arm is useful.
 #[derive(Clone, Debug)]
-pub enum Usefulness<Span> {
+pub enum Usefulness<'p, Cx: MatchCx> {
     /// The arm is useful. This additionally carries a set of or-pattern branches that have been
     /// found to be redundant despite the overall arm being useful. Used only in the presence of
     /// or-patterns, otherwise it stays empty.
-    Useful(Vec<Span>),
+    Useful(Vec<&'p DeconstructedPat<'p, Cx>>),
     /// The arm is redundant and can be removed without changing the behavior of the match
     /// expression.
     Redundant,
@@ -1300,7 +1300,7 @@ pub enum Usefulness<Span> {
 /// The output of checking a match for exhaustiveness and arm usefulness.
 pub struct UsefulnessReport<'p, Cx: MatchCx> {
     /// For each arm of the input, whether that arm is useful after the arms above it.
-    pub arm_usefulness: Vec<(MatchArm<'p, Cx>, Usefulness<Cx::Span>)>,
+    pub arm_usefulness: Vec<(MatchArm<'p, Cx>, Usefulness<'p, Cx>)>,
     /// If the match is exhaustive, this is empty. If not, this contains witnesses for the lack of
     /// exhaustiveness.
     pub non_exhaustiveness_witnesses: Vec<WitnessPat<Cx>>,
@@ -1327,7 +1327,7 @@ pub fn compute_match_usefulness<'p, Cx: MatchCx>(
             debug!(?arm);
             // We warn when a pattern is not useful.
             let usefulness = if arm.pat.is_useful() {
-                Usefulness::Useful(arm.pat.redundant_spans())
+                Usefulness::Useful(arm.pat.redundant_subpatterns())
             } else {
                 Usefulness::Redundant
             };