diff options
| author | Nadrieril <nadrieril+git@gmail.com> | 2023-12-15 16:18:21 +0100 |
|---|---|---|
| committer | Nadrieril <nadrieril+git@gmail.com> | 2023-12-15 16:58:38 +0100 |
| commit | 1e89a38423ee1b562e3b10278d0097d88bc48f5f (patch) | |
| tree | 4f9a1a59238d7c5b80020844b430bab6b6eb4de8 /compiler/rustc_pattern_analysis/src | |
| parent | 8c5e89907c1f6312c8613b5d6851381bbcde8052 (diff) | |
| download | rust-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.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/lints.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/pat.rs | 36 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/rustc.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/usefulness.rs | 10 |
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 }; |
