Skip to content

Commit cf4982a

Browse files
committed
Limit the use of PlaceCtxt
1 parent 4371b3e commit cf4982a

File tree

6 files changed

+39
-48
lines changed

6 files changed

+39
-48
lines changed

compiler/rustc_pattern_analysis/src/constructor.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ use self::MaybeInfiniteInt::*;
162162
use self::SliceKind::*;
163163

164164
use crate::index;
165-
use crate::usefulness::PlaceCtxt;
166165
use crate::TypeCx;
167166

168167
/// Whether we have seen a constructor in the column or not.
@@ -718,21 +717,20 @@ impl<Cx: TypeCx> Constructor<Cx> {
718717

719718
/// The number of fields for this constructor. This must be kept in sync with
720719
/// `Fields::wildcards`.
721-
pub(crate) fn arity(&self, pcx: &PlaceCtxt<'_, Cx>) -> usize {
722-
pcx.ctor_arity(self)
720+
pub(crate) fn arity(&self, cx: &Cx, ty: &Cx::Ty) -> usize {
721+
cx.ctor_arity(self, ty)
723722
}
724723

725724
/// Returns whether `self` is covered by `other`, i.e. whether `self` is a subset of `other`.
726725
/// For the simple cases, this is simply checking for equality. For the "grouped" constructors,
727726
/// this checks for inclusion.
728727
// We inline because this has a single call site in `Matrix::specialize_constructor`.
729728
#[inline]
730-
pub(crate) fn is_covered_by(&self, pcx: &PlaceCtxt<'_, Cx>, other: &Self) -> bool {
729+
pub(crate) fn is_covered_by(&self, cx: &Cx, other: &Self) -> bool {
731730
match (self, other) {
732-
(Wildcard, _) => pcx
733-
.mcx
734-
.tycx
735-
.bug(format_args!("Constructor splitting should not have returned `Wildcard`")),
731+
(Wildcard, _) => {
732+
cx.bug(format_args!("Constructor splitting should not have returned `Wildcard`"))
733+
}
736734
// Wildcards cover anything
737735
(_, Wildcard) => true,
738736
// Only a wildcard pattern can match these special constructors.
@@ -773,7 +771,7 @@ impl<Cx: TypeCx> Constructor<Cx> {
773771
(Opaque(self_id), Opaque(other_id)) => self_id == other_id,
774772
(Opaque(..), _) | (_, Opaque(..)) => false,
775773

776-
_ => pcx.mcx.tycx.bug(format_args!(
774+
_ => cx.bug(format_args!(
777775
"trying to compare incompatible constructors {self:?} and {other:?}"
778776
)),
779777
}

compiler/rustc_pattern_analysis/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ pub fn analyze_match<'p, 'tcx>(
162162
// `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
163163
if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() {
164164
let pat_column = PatternColumn::new(arms);
165-
lint_nonexhaustive_missing_variants(cx, arms, &pat_column, scrut_ty)?;
165+
lint_nonexhaustive_missing_variants(tycx, arms, &pat_column, scrut_ty)?;
166166
}
167167

168168
Ok(report)

compiler/rustc_pattern_analysis/src/lints.rs

+16-18
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ use rustc_span::ErrorGuaranteed;
44
use crate::constructor::{Constructor, SplitConstructorSet};
55
use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered};
66
use crate::pat::{DeconstructedPat, PatOrWild};
7-
use crate::rustc::{MatchCtxt, RevealedTy, RustcMatchCheckCtxt, WitnessPat};
8-
use crate::usefulness::PlaceCtxt;
7+
use crate::rustc::{RevealedTy, RustcMatchCheckCtxt, WitnessPat};
98
use crate::{MatchArm, TypeCx};
109

1110
/// 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> {
5049
}
5150

5251
/// Do constructor splitting on the constructors of the column.
53-
fn analyze_ctors(&self, pcx: &PlaceCtxt<'_, Cx>) -> Result<SplitConstructorSet<Cx>, Cx::Error> {
52+
fn analyze_ctors(&self, cx: &Cx, ty: &Cx::Ty) -> Result<SplitConstructorSet<Cx>, Cx::Error> {
5453
let column_ctors = self.patterns.iter().map(|p| p.ctor());
55-
let ctors_for_ty = &pcx.ctors_for_ty()?;
54+
let ctors_for_ty = cx.ctors_for_ty(ty)?;
5655
Ok(ctors_for_ty.split(column_ctors))
5756
}
5857

@@ -63,10 +62,11 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> {
6362
/// which may change the lengths.
6463
fn specialize(
6564
&self,
66-
pcx: &PlaceCtxt<'_, Cx>,
65+
cx: &Cx,
66+
ty: &Cx::Ty,
6767
ctor: &Constructor<Cx>,
6868
) -> Vec<PatternColumn<'p, Cx>> {
69-
let arity = ctor.arity(pcx);
69+
let arity = ctor.arity(cx, ty);
7070
if arity == 0 {
7171
return Vec::new();
7272
}
@@ -77,7 +77,7 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> {
7777
let mut specialized_columns: Vec<_> =
7878
(0..arity).map(|_| Self { patterns: Vec::new() }).collect();
7979
let relevant_patterns =
80-
self.patterns.iter().filter(|pat| ctor.is_covered_by(pcx, pat.ctor()));
80+
self.patterns.iter().filter(|pat| ctor.is_covered_by(cx, pat.ctor()));
8181
for pat in relevant_patterns {
8282
let specialized = pat.specialize(ctor, arity);
8383
for (subpat, column) in specialized.into_iter().zip(&mut specialized_columns) {
@@ -92,15 +92,14 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> {
9292
/// in a given column.
9393
#[instrument(level = "debug", skip(cx), ret)]
9494
fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
95-
cx: MatchCtxt<'a, 'p, 'tcx>,
95+
cx: &RustcMatchCheckCtxt<'p, 'tcx>,
9696
column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>,
9797
) -> Result<Vec<WitnessPat<'p, 'tcx>>, ErrorGuaranteed> {
9898
let Some(&ty) = column.head_ty() else {
9999
return Ok(Vec::new());
100100
};
101-
let pcx = &PlaceCtxt::new_dummy(cx, &ty);
102101

103-
let set = column.analyze_ctors(pcx)?;
102+
let set = column.analyze_ctors(cx, &ty)?;
104103
if set.present.is_empty() {
105104
// We can't consistently handle the case where no constructors are present (since this would
106105
// 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>(
109108
}
110109

111110
let mut witnesses = Vec::new();
112-
if cx.tycx.is_foreign_non_exhaustive_enum(ty) {
111+
if cx.is_foreign_non_exhaustive_enum(ty) {
113112
witnesses.extend(
114113
set.missing
115114
.into_iter()
116115
// This will list missing visible variants.
117116
.filter(|c| !matches!(c, Constructor::Hidden | Constructor::NonExhaustive))
118-
.map(|missing_ctor| WitnessPat::wild_from_ctor(pcx, missing_ctor)),
117+
.map(|missing_ctor| WitnessPat::wild_from_ctor(cx, missing_ctor, ty)),
119118
)
120119
}
121120

122121
// Recurse into the fields.
123122
for ctor in set.present {
124-
let specialized_columns = column.specialize(pcx, &ctor);
125-
let wild_pat = WitnessPat::wild_from_ctor(pcx, ctor);
123+
let specialized_columns = column.specialize(cx, &ty, &ctor);
124+
let wild_pat = WitnessPat::wild_from_ctor(cx, ctor, ty);
126125
for (i, col_i) in specialized_columns.iter().enumerate() {
127126
// Compute witnesses for each column.
128127
let wits_for_col_i = collect_nonexhaustive_missing_variants(cx, col_i)?;
@@ -138,18 +137,17 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
138137
Ok(witnesses)
139138
}
140139

141-
pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
142-
cx: MatchCtxt<'a, 'p, 'tcx>,
140+
pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>(
141+
rcx: &RustcMatchCheckCtxt<'p, 'tcx>,
143142
arms: &[MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>],
144143
pat_column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>,
145144
scrut_ty: RevealedTy<'tcx>,
146145
) -> Result<(), ErrorGuaranteed> {
147-
let rcx: &RustcMatchCheckCtxt<'_, '_> = cx.tycx;
148146
if !matches!(
149147
rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, rcx.match_lint_level).0,
150148
rustc_session::lint::Level::Allow
151149
) {
152-
let witnesses = collect_nonexhaustive_missing_variants(cx, pat_column)?;
150+
let witnesses = collect_nonexhaustive_missing_variants(rcx, pat_column)?;
153151
if !witnesses.is_empty() {
154152
// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
155153
// is not exhaustive enough.

compiler/rustc_pattern_analysis/src/pat.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use std::fmt;
66
use smallvec::{smallvec, SmallVec};
77

88
use crate::constructor::{Constructor, Slice, SliceKind};
9-
use crate::usefulness::PlaceCtxt;
109
use crate::{Captures, TypeCx};
1110

1211
use self::Constructor::*;
@@ -240,10 +239,10 @@ impl<Cx: TypeCx> WitnessPat<Cx> {
240239
/// Construct a pattern that matches everything that starts with this constructor.
241240
/// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
242241
/// `Some(_)`.
243-
pub(crate) fn wild_from_ctor(pcx: &PlaceCtxt<'_, Cx>, ctor: Constructor<Cx>) -> Self {
244-
let field_tys = pcx.ctor_sub_tys(&ctor);
242+
pub(crate) fn wild_from_ctor(cx: &Cx, ctor: Constructor<Cx>, ty: Cx::Ty) -> Self {
243+
let field_tys = cx.ctor_sub_tys(&ctor, &ty);
245244
let fields = field_tys.iter().cloned().map(|ty| Self::wildcard(ty)).collect();
246-
Self::new(ctor, fields, pcx.ty.clone())
245+
Self::new(ctor, fields, ty)
247246
}
248247

249248
pub fn ctor(&self) -> &Constructor<Cx> {

compiler/rustc_pattern_analysis/src/rustc.rs

-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ pub type ConstructorSet<'p, 'tcx> =
3131
pub type DeconstructedPat<'p, 'tcx> =
3232
crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
3333
pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
34-
pub type MatchCtxt<'a, 'p, 'tcx> = crate::MatchCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>;
3534
pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
3635
pub type UsefulnessReport<'p, 'tcx> =
3736
crate::usefulness::UsefulnessReport<'p, RustcMatchCheckCtxt<'p, 'tcx>>;

compiler/rustc_pattern_analysis/src/usefulness.rs

+12-15
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,7 @@ pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R {
732732
/// Context that provides information local to a place under investigation.
733733
#[derive(derivative::Derivative)]
734734
#[derivative(Debug(bound = ""), Clone(bound = ""), Copy(bound = ""))]
735-
pub(crate) struct PlaceCtxt<'a, Cx: TypeCx> {
735+
struct PlaceCtxt<'a, Cx: TypeCx> {
736736
#[derivative(Debug = "ignore")]
737737
pub(crate) mcx: MatchCtxt<'a, Cx>,
738738
/// Type of the place under investigation.
@@ -741,21 +741,18 @@ pub(crate) struct PlaceCtxt<'a, Cx: TypeCx> {
741741
}
742742

743743
impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> {
744-
/// A `PlaceCtxt` when code other than `is_useful` needs one.
745-
#[cfg_attr(not(feature = "rustc"), allow(dead_code))]
746-
pub(crate) fn new_dummy(mcx: MatchCtxt<'a, Cx>, ty: &'a Cx::Ty) -> Self {
747-
PlaceCtxt { mcx, ty }
748-
}
749-
750-
pub(crate) fn ctor_arity(&self, ctor: &Constructor<Cx>) -> usize {
744+
fn ctor_arity(&self, ctor: &Constructor<Cx>) -> usize {
751745
self.mcx.tycx.ctor_arity(ctor, self.ty)
752746
}
753-
pub(crate) fn ctor_sub_tys(&self, ctor: &Constructor<Cx>) -> &[Cx::Ty] {
747+
fn ctor_sub_tys(&self, ctor: &Constructor<Cx>) -> &[Cx::Ty] {
754748
self.mcx.tycx.ctor_sub_tys(ctor, self.ty)
755749
}
756-
pub(crate) fn ctors_for_ty(&self) -> Result<ConstructorSet<Cx>, Cx::Error> {
750+
fn ctors_for_ty(&self) -> Result<ConstructorSet<Cx>, Cx::Error> {
757751
self.mcx.tycx.ctors_for_ty(self.ty)
758752
}
753+
fn wild_from_ctor(&self, ctor: Constructor<Cx>) -> WitnessPat<Cx> {
754+
WitnessPat::wild_from_ctor(self.mcx.tycx, ctor, self.ty.clone())
755+
}
759756
}
760757

761758
/// Serves two purposes:
@@ -1072,7 +1069,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
10721069
wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant,
10731070
};
10741071
for (i, row) in self.rows().enumerate() {
1075-
if ctor.is_covered_by(pcx, row.head().ctor()) {
1072+
if ctor.is_covered_by(pcx.mcx.tycx, row.head().ctor()) {
10761073
let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i);
10771074
matrix.expand_and_push(new_row);
10781075
}
@@ -1213,7 +1210,7 @@ impl<Cx: TypeCx> WitnessStack<Cx> {
12131210
/// ```
12141211
fn apply_constructor(&mut self, pcx: &PlaceCtxt<'_, Cx>, ctor: &Constructor<Cx>) {
12151212
let len = self.0.len();
1216-
let arity = ctor.arity(pcx);
1213+
let arity = pcx.ctor_arity(ctor);
12171214
let fields = self.0.drain((len - arity)..).rev().collect();
12181215
let pat = WitnessPat::new(ctor.clone(), fields, pcx.ty.clone());
12191216
self.0.push(pat);
@@ -1278,20 +1275,20 @@ impl<Cx: TypeCx> WitnessMatrix<Cx> {
12781275
*self = Self::empty();
12791276
} else if !report_individual_missing_ctors {
12801277
// Report `_` as missing.
1281-
let pat = WitnessPat::wild_from_ctor(pcx, Constructor::Wildcard);
1278+
let pat = pcx.wild_from_ctor(Constructor::Wildcard);
12821279
self.push_pattern(pat);
12831280
} else if missing_ctors.iter().any(|c| c.is_non_exhaustive()) {
12841281
// We need to report a `_` anyway, so listing other constructors would be redundant.
12851282
// `NonExhaustive` is displayed as `_` just like `Wildcard`, but it will be picked
12861283
// up by diagnostics to add a note about why `_` is required here.
1287-
let pat = WitnessPat::wild_from_ctor(pcx, Constructor::NonExhaustive);
1284+
let pat = pcx.wild_from_ctor(Constructor::NonExhaustive);
12881285
self.push_pattern(pat);
12891286
} else {
12901287
// For each missing constructor `c`, we add a `c(_, _, _)` witness appropriately
12911288
// filled with wildcards.
12921289
let mut ret = Self::empty();
12931290
for ctor in missing_ctors {
1294-
let pat = WitnessPat::wild_from_ctor(pcx, ctor.clone());
1291+
let pat = pcx.wild_from_ctor(ctor.clone());
12951292
// Clone `self` and add `c(_, _, _)` to each of its witnesses.
12961293
let mut wit_matrix = self.clone();
12971294
wit_matrix.push_pattern(pat);

0 commit comments

Comments
 (0)