Skip to content

Commit 1e89a38

Browse files
committed
pattern_analysis doesn't need to know what spans are
1 parent 8c5e899 commit 1e89a38

File tree

6 files changed

+39
-36
lines changed

6 files changed

+39
-36
lines changed

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -856,21 +856,21 @@ fn report_arm_reachability<'p, 'tcx>(
856856
for (arm, is_useful) in report.arm_usefulness.iter() {
857857
match is_useful {
858858
Usefulness::Redundant => {
859-
report_unreachable_pattern(*arm.pat.span(), arm.arm_data, catchall)
859+
report_unreachable_pattern(*arm.pat.data(), arm.arm_data, catchall)
860860
}
861-
Usefulness::Useful(redundant_spans) if redundant_spans.is_empty() => {}
861+
Usefulness::Useful(redundant_subpats) if redundant_subpats.is_empty() => {}
862862
// The arm is reachable, but contains redundant subpatterns (from or-patterns).
863-
Usefulness::Useful(redundant_spans) => {
864-
let mut redundant_spans = redundant_spans.clone();
863+
Usefulness::Useful(redundant_subpats) => {
864+
let mut redundant_subpats = redundant_subpats.clone();
865865
// Emit lints in the order in which they occur in the file.
866-
redundant_spans.sort_unstable();
867-
for span in redundant_spans {
868-
report_unreachable_pattern(span, arm.arm_data, None);
866+
redundant_subpats.sort_unstable_by_key(|pat| pat.data());
867+
for pat in redundant_subpats {
868+
report_unreachable_pattern(*pat.data(), arm.arm_data, None);
869869
}
870870
}
871871
}
872872
if !arm.has_guard && catchall.is_none() && pat_is_catchall(arm.pat) {
873-
catchall = Some(*arm.pat.span());
873+
catchall = Some(*arm.pat.data());
874874
}
875875
}
876876
}

compiler/rustc_pattern_analysis/src/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,17 @@ use crate::rustc::RustcMatchCheckCtxt;
3737
use crate::usefulness::{compute_match_usefulness, ValidityConstraint};
3838

3939
pub trait MatchCx: Sized + Clone + fmt::Debug {
40+
/// The type of a pattern.
4041
type Ty: Copy + Clone + fmt::Debug; // FIXME: remove Copy
41-
type Span: Clone + Default;
4242
/// The index of an enum variant.
4343
type VariantIdx: Clone + Idx;
4444
/// A string literal
4545
type StrLit: Clone + PartialEq + fmt::Debug;
4646
/// Extra data to store on a match arm.
4747
type ArmData: Copy + Clone + fmt::Debug;
48+
/// Extra data to store on a pattern. `Default` needed when we create fictitious wildcard
49+
/// patterns during analysis.
50+
type PatData: Clone + Default;
4851

4952
fn is_opaque_ty(ty: Self::Ty) -> bool;
5053
fn is_exhaustive_patterns_feature_on(&self) -> bool;

compiler/rustc_pattern_analysis/src/lints.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
213213
};
214214

215215
use rustc_errors::DecorateLint;
216-
let mut err = cx.tcx.sess.struct_span_warn(*arm.pat.span(), "");
216+
let mut err = cx.tcx.sess.struct_span_warn(*arm.pat.data(), "");
217217
err.set_primary_message(decorator.msg());
218218
decorator.decorate_lint(&mut err);
219219
err.emit();
@@ -263,7 +263,7 @@ pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>(
263263
let mut suffixes: SmallVec<[_; 1]> = Default::default();
264264
// Iterate on patterns that contained `overlap`.
265265
for pat in column.iter() {
266-
let this_span = *pat.span();
266+
let this_span = *pat.data();
267267
let Constructor::IntRange(this_range) = pat.ctor() else { continue };
268268
if this_range.is_singleton() {
269269
// Don't lint when one of the ranges is a singleton.

compiler/rustc_pattern_analysis/src/pat.rs

+18-18
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,23 @@ pub struct DeconstructedPat<'p, Cx: MatchCx> {
2626
ctor: Constructor<Cx>,
2727
fields: &'p [DeconstructedPat<'p, Cx>],
2828
ty: Cx::Ty,
29-
span: Cx::Span,
29+
data: Cx::PatData,
3030
/// Whether removing this arm would change the behavior of the match expression.
3131
useful: Cell<bool>,
3232
}
3333

3434
impl<'p, Cx: MatchCx> DeconstructedPat<'p, Cx> {
35-
pub fn wildcard(ty: Cx::Ty, span: Cx::Span) -> Self {
36-
Self::new(Wildcard, &[], ty, span)
35+
pub fn wildcard(ty: Cx::Ty, data: Cx::PatData) -> Self {
36+
Self::new(Wildcard, &[], ty, data)
3737
}
3838

3939
pub fn new(
4040
ctor: Constructor<Cx>,
4141
fields: &'p [DeconstructedPat<'p, Cx>],
4242
ty: Cx::Ty,
43-
span: Cx::Span,
43+
data: Cx::PatData,
4444
) -> Self {
45-
DeconstructedPat { ctor, fields, ty, span, useful: Cell::new(false) }
45+
DeconstructedPat { ctor, fields, ty, data, useful: Cell::new(false) }
4646
}
4747

4848
pub(crate) fn is_or_pat(&self) -> bool {
@@ -63,8 +63,8 @@ impl<'p, Cx: MatchCx> DeconstructedPat<'p, Cx> {
6363
pub fn ty(&self) -> Cx::Ty {
6464
self.ty
6565
}
66-
pub fn span(&self) -> &Cx::Span {
67-
&self.span
66+
pub fn data(&self) -> &Cx::PatData {
67+
&self.data
6868
}
6969

7070
pub fn iter_fields<'a>(
@@ -83,7 +83,7 @@ impl<'p, Cx: MatchCx> DeconstructedPat<'p, Cx> {
8383
let wildcard_sub_tys = || {
8484
let tys = pcx.cx.ctor_sub_tys(other_ctor, pcx.ty);
8585
tys.iter()
86-
.map(|ty| DeconstructedPat::wildcard(*ty, Cx::Span::default()))
86+
.map(|ty| DeconstructedPat::wildcard(*ty, Cx::PatData::default()))
8787
.map(|pat| pcx.wildcard_arena.alloc(pat) as &_)
8888
.collect()
8989
};
@@ -113,8 +113,8 @@ impl<'p, Cx: MatchCx> DeconstructedPat<'p, Cx> {
113113
}
114114
}
115115

116-
/// We keep track for each pattern if it was ever useful during the analysis. This is used
117-
/// with `redundant_spans` to report redundant subpatterns arising from or patterns.
116+
/// We keep track for each pattern if it was ever useful during the analysis. This is used with
117+
/// `redundant_subpatterns` to report redundant subpatterns arising from or patterns.
118118
pub(crate) fn set_useful(&self) {
119119
self.useful.set(true)
120120
}
@@ -132,19 +132,19 @@ impl<'p, Cx: MatchCx> DeconstructedPat<'p, Cx> {
132132
}
133133
}
134134

135-
/// Report the spans of subpatterns that were not useful, if any.
136-
pub(crate) fn redundant_spans(&self) -> Vec<Cx::Span> {
137-
let mut spans = Vec::new();
138-
self.collect_redundant_spans(&mut spans);
139-
spans
135+
/// Report the subpatterns that were not useful, if any.
136+
pub(crate) fn redundant_subpatterns(&self) -> Vec<&Self> {
137+
let mut subpats = Vec::new();
138+
self.collect_redundant_subpatterns(&mut subpats);
139+
subpats
140140
}
141-
fn collect_redundant_spans(&self, spans: &mut Vec<Cx::Span>) {
141+
fn collect_redundant_subpatterns<'a>(&'a self, subpats: &mut Vec<&'a Self>) {
142142
// We don't look at subpatterns if we already reported the whole pattern as redundant.
143143
if !self.is_useful() {
144-
spans.push(self.span.clone());
144+
subpats.push(self);
145145
} else {
146146
for p in self.iter_fields() {
147-
p.collect_redundant_spans(spans);
147+
p.collect_redundant_subpatterns(subpats);
148148
}
149149
}
150150
}

compiler/rustc_pattern_analysis/src/rustc.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub(crate) type PatCtxt<'a, 'p, 'tcx> =
3535
crate::usefulness::PatCtxt<'a, 'p, RustcMatchCheckCtxt<'p, 'tcx>>;
3636
pub(crate) type SplitConstructorSet<'p, 'tcx> =
3737
crate::constructor::SplitConstructorSet<RustcMatchCheckCtxt<'p, 'tcx>>;
38-
pub type Usefulness = crate::usefulness::Usefulness<Span>;
38+
pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
3939
pub type UsefulnessReport<'p, 'tcx> =
4040
crate::usefulness::UsefulnessReport<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
4141
pub type WitnessPat<'p, 'tcx> = crate::pat::WitnessPat<RustcMatchCheckCtxt<'p, 'tcx>>;
@@ -864,10 +864,10 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
864864

865865
impl<'p, 'tcx> MatchCx for RustcMatchCheckCtxt<'p, 'tcx> {
866866
type Ty = Ty<'tcx>;
867-
type Span = Span;
868867
type VariantIdx = VariantIdx;
869868
type StrLit = Const<'tcx>;
870869
type ArmData = HirId;
870+
type PatData = Span;
871871

872872
fn is_exhaustive_patterns_feature_on(&self) -> bool {
873873
self.tcx.features().exhaustive_patterns

compiler/rustc_pattern_analysis/src/usefulness.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,7 @@ impl<'a, 'p, Cx: MatchCx> Matrix<'a, 'p, Cx> {
849849
scrut_validity: ValidityConstraint,
850850
) -> Self {
851851
let wild_pattern =
852-
wildcard_arena.alloc(DeconstructedPat::wildcard(scrut_ty, Cx::Span::default()));
852+
wildcard_arena.alloc(DeconstructedPat::wildcard(scrut_ty, Default::default()));
853853
let wildcard_row = PatStack::from_pattern(wild_pattern);
854854
let mut matrix = Matrix {
855855
rows: Vec::with_capacity(arms.len()),
@@ -1287,11 +1287,11 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: MatchCx>(
12871287

12881288
/// Indicates whether or not a given arm is useful.
12891289
#[derive(Clone, Debug)]
1290-
pub enum Usefulness<Span> {
1290+
pub enum Usefulness<'p, Cx: MatchCx> {
12911291
/// The arm is useful. This additionally carries a set of or-pattern branches that have been
12921292
/// found to be redundant despite the overall arm being useful. Used only in the presence of
12931293
/// or-patterns, otherwise it stays empty.
1294-
Useful(Vec<Span>),
1294+
Useful(Vec<&'p DeconstructedPat<'p, Cx>>),
12951295
/// The arm is redundant and can be removed without changing the behavior of the match
12961296
/// expression.
12971297
Redundant,
@@ -1300,7 +1300,7 @@ pub enum Usefulness<Span> {
13001300
/// The output of checking a match for exhaustiveness and arm usefulness.
13011301
pub struct UsefulnessReport<'p, Cx: MatchCx> {
13021302
/// For each arm of the input, whether that arm is useful after the arms above it.
1303-
pub arm_usefulness: Vec<(MatchArm<'p, Cx>, Usefulness<Cx::Span>)>,
1303+
pub arm_usefulness: Vec<(MatchArm<'p, Cx>, Usefulness<'p, Cx>)>,
13041304
/// If the match is exhaustive, this is empty. If not, this contains witnesses for the lack of
13051305
/// exhaustiveness.
13061306
pub non_exhaustiveness_witnesses: Vec<WitnessPat<Cx>>,
@@ -1327,7 +1327,7 @@ pub fn compute_match_usefulness<'p, Cx: MatchCx>(
13271327
debug!(?arm);
13281328
// We warn when a pattern is not useful.
13291329
let usefulness = if arm.pat.is_useful() {
1330-
Usefulness::Useful(arm.pat.redundant_spans())
1330+
Usefulness::Useful(arm.pat.redundant_subpatterns())
13311331
} else {
13321332
Usefulness::Redundant
13331333
};

0 commit comments

Comments
 (0)