summary refs log tree commit diff
path: root/compiler/rustc_pattern_analysis/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_pattern_analysis/src')
-rw-r--r--compiler/rustc_pattern_analysis/src/constructor.rs16
-rw-r--r--compiler/rustc_pattern_analysis/src/lib.rs2
-rw-r--r--compiler/rustc_pattern_analysis/src/lints.rs34
-rw-r--r--compiler/rustc_pattern_analysis/src/pat.rs7
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs1
-rw-r--r--compiler/rustc_pattern_analysis/src/usefulness.rs34
6 files changed, 42 insertions, 52 deletions
diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs
index 4996015f863..df5bf3111ad 100644
--- a/compiler/rustc_pattern_analysis/src/constructor.rs
+++ b/compiler/rustc_pattern_analysis/src/constructor.rs
@@ -163,7 +163,6 @@ use self::MaybeInfiniteInt::*;
 use self::SliceKind::*;
 
 use crate::index;
-use crate::usefulness::PlaceCtxt;
 use crate::TypeCx;
 
 /// Whether we have seen a constructor in the column or not.
@@ -818,8 +817,8 @@ impl<Cx: TypeCx> Constructor<Cx> {
 
     /// The number of fields for this constructor. This must be kept in sync with
     /// `Fields::wildcards`.
-    pub(crate) fn arity(&self, pcx: &PlaceCtxt<'_, Cx>) -> usize {
-        pcx.ctor_arity(self)
+    pub(crate) fn arity(&self, cx: &Cx, ty: &Cx::Ty) -> usize {
+        cx.ctor_arity(self, ty)
     }
 
     /// Returns whether `self` is covered by `other`, i.e. whether `self` is a subset of `other`.
@@ -827,12 +826,11 @@ impl<Cx: TypeCx> Constructor<Cx> {
     /// this checks for inclusion.
     // We inline because this has a single call site in `Matrix::specialize_constructor`.
     #[inline]
-    pub(crate) fn is_covered_by(&self, pcx: &PlaceCtxt<'_, Cx>, other: &Self) -> bool {
+    pub(crate) fn is_covered_by(&self, cx: &Cx, other: &Self) -> bool {
         match (self, other) {
-            (Wildcard, _) => pcx
-                .mcx
-                .tycx
-                .bug(format_args!("Constructor splitting should not have returned `Wildcard`")),
+            (Wildcard, _) => {
+                cx.bug(format_args!("Constructor splitting should not have returned `Wildcard`"))
+            }
             // Wildcards cover anything
             (_, Wildcard) => true,
             // Only a wildcard pattern can match these special constructors.
@@ -873,7 +871,7 @@ impl<Cx: TypeCx> Constructor<Cx> {
             (Opaque(self_id), Opaque(other_id)) => self_id == other_id,
             (Opaque(..), _) | (_, Opaque(..)) => false,
 
-            _ => pcx.mcx.tycx.bug(format_args!(
+            _ => cx.bug(format_args!(
                 "trying to compare incompatible constructors {self:?} and {other:?}"
             )),
         }
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index a53d7a0d809..866eb67ea99 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -183,7 +183,7 @@ pub fn analyze_match<'p, 'tcx>(
     // `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
     if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() {
         let pat_column = PatternColumn::new(arms);
-        lint_nonexhaustive_missing_variants(cx, arms, &pat_column, scrut_ty)?;
+        lint_nonexhaustive_missing_variants(tycx, arms, &pat_column, scrut_ty)?;
     }
 
     Ok(report)
diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs
index e3d218d71c3..4cbd5e70189 100644
--- a/compiler/rustc_pattern_analysis/src/lints.rs
+++ b/compiler/rustc_pattern_analysis/src/lints.rs
@@ -4,8 +4,7 @@ use rustc_span::ErrorGuaranteed;
 use crate::constructor::{Constructor, SplitConstructorSet};
 use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered};
 use crate::pat::{DeconstructedPat, PatOrWild};
-use crate::rustc::{MatchCtxt, RevealedTy, RustcMatchCheckCtxt, WitnessPat};
-use crate::usefulness::PlaceCtxt;
+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
@@ -50,9 +49,9 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> {
     }
 
     /// Do constructor splitting on the constructors of the column.
-    fn analyze_ctors(&self, pcx: &PlaceCtxt<'_, Cx>) -> Result<SplitConstructorSet<Cx>, Cx::Error> {
+    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 = &pcx.ctors_for_ty()?;
+        let ctors_for_ty = cx.ctors_for_ty(ty)?;
         Ok(ctors_for_ty.split(column_ctors))
     }
 
@@ -63,10 +62,11 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> {
     /// which may change the lengths.
     fn specialize(
         &self,
-        pcx: &PlaceCtxt<'_, Cx>,
+        cx: &Cx,
+        ty: &Cx::Ty,
         ctor: &Constructor<Cx>,
     ) -> Vec<PatternColumn<'p, Cx>> {
-        let arity = ctor.arity(pcx);
+        let arity = ctor.arity(cx, ty);
         if arity == 0 {
             return Vec::new();
         }
@@ -77,7 +77,7 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> {
         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(pcx, pat.ctor()));
+            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) {
@@ -92,15 +92,14 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> {
 /// in a given column.
 #[instrument(level = "debug", skip(cx), ret)]
 fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
-    cx: MatchCtxt<'a, 'p, 'tcx>,
+    cx: &RustcMatchCheckCtxt<'p, 'tcx>,
     column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>,
 ) -> Result<Vec<WitnessPat<'p, 'tcx>>, ErrorGuaranteed> {
     let Some(&ty) = column.head_ty() else {
         return Ok(Vec::new());
     };
-    let pcx = &PlaceCtxt::new_dummy(cx, &ty);
 
-    let set = column.analyze_ctors(pcx)?;
+    let set = column.analyze_ctors(cx, &ty)?;
     if set.present.is_empty() {
         // We can't consistently handle the case where no constructors are present (since this would
         // require digging deep through any type in case there's a non_exhaustive enum somewhere),
@@ -109,20 +108,20 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
     }
 
     let mut witnesses = Vec::new();
-    if cx.tycx.is_foreign_non_exhaustive_enum(ty) {
+    if cx.is_foreign_non_exhaustive_enum(ty) {
         witnesses.extend(
             set.missing
                 .into_iter()
                 // This will list missing visible variants.
                 .filter(|c| !matches!(c, Constructor::Hidden | Constructor::NonExhaustive))
-                .map(|missing_ctor| WitnessPat::wild_from_ctor(pcx, missing_ctor)),
+                .map(|missing_ctor| WitnessPat::wild_from_ctor(cx, missing_ctor, ty)),
         )
     }
 
     // Recurse into the fields.
     for ctor in set.present {
-        let specialized_columns = column.specialize(pcx, &ctor);
-        let wild_pat = WitnessPat::wild_from_ctor(pcx, ctor);
+        let specialized_columns = column.specialize(cx, &ty, &ctor);
+        let wild_pat = WitnessPat::wild_from_ctor(cx, ctor, ty);
         for (i, col_i) in specialized_columns.iter().enumerate() {
             // Compute witnesses for each column.
             let wits_for_col_i = collect_nonexhaustive_missing_variants(cx, col_i)?;
@@ -138,18 +137,17 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
     Ok(witnesses)
 }
 
-pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
-    cx: MatchCtxt<'a, 'p, 'tcx>,
+pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>(
+    rcx: &RustcMatchCheckCtxt<'p, 'tcx>,
     arms: &[MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>],
     pat_column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>,
     scrut_ty: RevealedTy<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
-    let rcx: &RustcMatchCheckCtxt<'_, '_> = cx.tycx;
     if !matches!(
         rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, rcx.match_lint_level).0,
         rustc_session::lint::Level::Allow
     ) {
-        let witnesses = collect_nonexhaustive_missing_variants(cx, pat_column)?;
+        let witnesses = collect_nonexhaustive_missing_variants(rcx, pat_column)?;
         if !witnesses.is_empty() {
             // Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
             // is not exhaustive enough.
diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs
index d476766d466..c94d8b93535 100644
--- a/compiler/rustc_pattern_analysis/src/pat.rs
+++ b/compiler/rustc_pattern_analysis/src/pat.rs
@@ -6,7 +6,6 @@ use std::fmt;
 use smallvec::{smallvec, SmallVec};
 
 use crate::constructor::{Constructor, Slice, SliceKind};
-use crate::usefulness::PlaceCtxt;
 use crate::{Captures, TypeCx};
 
 use self::Constructor::*;
@@ -331,9 +330,9 @@ impl<Cx: TypeCx> WitnessPat<Cx> {
     /// Construct a pattern that matches everything that starts with this constructor.
     /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
     /// `Some(_)`.
-    pub(crate) fn wild_from_ctor(pcx: &PlaceCtxt<'_, Cx>, ctor: Constructor<Cx>) -> Self {
-        let fields = pcx.ctor_sub_tys(&ctor).map(|ty| Self::wildcard(ty)).collect();
-        Self::new(ctor, fields, pcx.ty.clone())
+    pub(crate) fn wild_from_ctor(cx: &Cx, ctor: Constructor<Cx>, ty: Cx::Ty) -> Self {
+        let fields = cx.ctor_sub_tys(&ctor, &ty).map(|ty| Self::wildcard(ty)).collect();
+        Self::new(ctor, fields, ty)
     }
 
     pub fn ctor(&self) -> &Constructor<Cx> {
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index 4fb76a891b5..ec37e202118 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -30,7 +30,6 @@ pub type ConstructorSet<'p, 'tcx> =
 pub type DeconstructedPat<'p, 'tcx> =
     crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
-pub type MatchCtxt<'a, 'p, 'tcx> = crate::MatchCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub type UsefulnessReport<'p, 'tcx> =
     crate::usefulness::UsefulnessReport<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs
index b15de1c0ca9..62d17ca4509 100644
--- a/compiler/rustc_pattern_analysis/src/usefulness.rs
+++ b/compiler/rustc_pattern_analysis/src/usefulness.rs
@@ -731,20 +731,19 @@ pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R {
 }
 
 /// Context that provides information local to a place under investigation.
-pub(crate) struct PlaceCtxt<'a, Cx: TypeCx> {
-    pub(crate) mcx: MatchCtxt<'a, Cx>,
+struct PlaceCtxt<'a, Cx: TypeCx> {
+    mcx: MatchCtxt<'a, Cx>,
     /// Type of the place under investigation.
-    pub(crate) ty: &'a Cx::Ty,
+    ty: &'a Cx::Ty,
 }
 
+impl<'a, Cx: TypeCx> Copy for PlaceCtxt<'a, Cx> {}
 impl<'a, Cx: TypeCx> Clone for PlaceCtxt<'a, Cx> {
     fn clone(&self) -> Self {
         Self { mcx: self.mcx, ty: self.ty }
     }
 }
 
-impl<'a, Cx: TypeCx> Copy for PlaceCtxt<'a, Cx> {}
-
 impl<'a, Cx: TypeCx> fmt::Debug for PlaceCtxt<'a, Cx> {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt.debug_struct("PlaceCtxt").field("ty", self.ty).finish()
@@ -752,24 +751,21 @@ impl<'a, Cx: TypeCx> fmt::Debug for PlaceCtxt<'a, Cx> {
 }
 
 impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> {
-    /// A `PlaceCtxt` when code other than `is_useful` needs one.
-    #[cfg_attr(not(feature = "rustc"), allow(dead_code))]
-    pub(crate) fn new_dummy(mcx: MatchCtxt<'a, Cx>, ty: &'a Cx::Ty) -> Self {
-        PlaceCtxt { mcx, ty }
-    }
-
-    pub(crate) fn ctor_arity(&self, ctor: &Constructor<Cx>) -> usize {
+    fn ctor_arity(&self, ctor: &Constructor<Cx>) -> usize {
         self.mcx.tycx.ctor_arity(ctor, self.ty)
     }
-    pub(crate) fn ctor_sub_tys(
+    fn ctor_sub_tys(
         &'a self,
         ctor: &'a Constructor<Cx>,
     ) -> impl Iterator<Item = Cx::Ty> + ExactSizeIterator + Captures<'a> {
         self.mcx.tycx.ctor_sub_tys(ctor, self.ty)
     }
-    pub(crate) fn ctors_for_ty(&self) -> Result<ConstructorSet<Cx>, Cx::Error> {
+    fn ctors_for_ty(&self) -> Result<ConstructorSet<Cx>, Cx::Error> {
         self.mcx.tycx.ctors_for_ty(self.ty)
     }
+    fn wild_from_ctor(&self, ctor: Constructor<Cx>) -> WitnessPat<Cx> {
+        WitnessPat::wild_from_ctor(self.mcx.tycx, ctor, self.ty.clone())
+    }
 }
 
 /// Serves two purposes:
@@ -1089,7 +1085,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
             wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant,
         };
         for (i, row) in self.rows().enumerate() {
-            if ctor.is_covered_by(pcx, row.head().ctor()) {
+            if ctor.is_covered_by(pcx.mcx.tycx, row.head().ctor()) {
                 let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i);
                 matrix.expand_and_push(new_row);
             }
@@ -1240,7 +1236,7 @@ impl<Cx: TypeCx> WitnessStack<Cx> {
     /// ```
     fn apply_constructor(&mut self, pcx: &PlaceCtxt<'_, Cx>, ctor: &Constructor<Cx>) {
         let len = self.0.len();
-        let arity = ctor.arity(pcx);
+        let arity = pcx.ctor_arity(ctor);
         let fields = self.0.drain((len - arity)..).rev().collect();
         let pat = WitnessPat::new(ctor.clone(), fields, pcx.ty.clone());
         self.0.push(pat);
@@ -1315,20 +1311,20 @@ impl<Cx: TypeCx> WitnessMatrix<Cx> {
                 *self = Self::empty();
             } else if !report_individual_missing_ctors {
                 // Report `_` as missing.
-                let pat = WitnessPat::wild_from_ctor(pcx, Constructor::Wildcard);
+                let pat = pcx.wild_from_ctor(Constructor::Wildcard);
                 self.push_pattern(pat);
             } else if missing_ctors.iter().any(|c| c.is_non_exhaustive()) {
                 // We need to report a `_` anyway, so listing other constructors would be redundant.
                 // `NonExhaustive` is displayed as `_` just like `Wildcard`, but it will be picked
                 // up by diagnostics to add a note about why `_` is required here.
-                let pat = WitnessPat::wild_from_ctor(pcx, Constructor::NonExhaustive);
+                let pat = pcx.wild_from_ctor(Constructor::NonExhaustive);
                 self.push_pattern(pat);
             } else {
                 // For each missing constructor `c`, we add a `c(_, _, _)` witness appropriately
                 // filled with wildcards.
                 let mut ret = Self::empty();
                 for ctor in missing_ctors {
-                    let pat = WitnessPat::wild_from_ctor(pcx, ctor.clone());
+                    let pat = pcx.wild_from_ctor(ctor.clone());
                     // Clone `self` and add `c(_, _, _)` to each of its witnesses.
                     let mut wit_matrix = self.clone();
                     wit_matrix.push_pattern(pat);