Skip to content

Commit 2f2243c

Browse files
committed
Auto merge of #99843 - oli-obk:is_useful_perf, r=compiler-errors
Some `is_useful` cleanups #98582 was reverted because it was a perf regression. #99806 reintroduces the changes, but this PR picks individual ones that have no regressions.
2 parents caee496 + 803d374 commit 2f2243c

File tree

2 files changed

+43
-46
lines changed

2 files changed

+43
-46
lines changed

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

+30-33
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ impl IntRange {
261261
/// Lint on likely incorrect range patterns (#63987)
262262
pub(super) fn lint_overlapping_range_endpoints<'a, 'p: 'a, 'tcx: 'a>(
263263
&self,
264-
pcx: PatCtxt<'_, 'p, 'tcx>,
264+
pcx: &PatCtxt<'_, 'p, 'tcx>,
265265
pats: impl Iterator<Item = &'a DeconstructedPat<'p, 'tcx>>,
266266
column_count: usize,
267267
hir_id: HirId,
@@ -696,7 +696,7 @@ impl<'tcx> Constructor<'tcx> {
696696
/// `EvalResult::Deny { .. }`.
697697
///
698698
/// This means that the variant has a stdlib unstable feature marking it.
699-
pub(super) fn is_unstable_variant(&self, pcx: PatCtxt<'_, '_, 'tcx>) -> bool {
699+
pub(super) fn is_unstable_variant(&self, pcx: &PatCtxt<'_, '_, 'tcx>) -> bool {
700700
if let Constructor::Variant(idx) = self && let ty::Adt(adt, _) = pcx.ty.kind() {
701701
let variant_def_id = adt.variant(*idx).def_id;
702702
// Filter variants that depend on a disabled unstable feature.
@@ -710,7 +710,7 @@ impl<'tcx> Constructor<'tcx> {
710710

711711
/// Checks if the `Constructor` is a `Constructor::Variant` with a `#[doc(hidden)]`
712712
/// attribute from a type not local to the current crate.
713-
pub(super) fn is_doc_hidden_variant(&self, pcx: PatCtxt<'_, '_, 'tcx>) -> bool {
713+
pub(super) fn is_doc_hidden_variant(&self, pcx: &PatCtxt<'_, '_, 'tcx>) -> bool {
714714
if let Constructor::Variant(idx) = self && let ty::Adt(adt, _) = pcx.ty.kind() {
715715
let variant_def_id = adt.variants()[*idx].def_id;
716716
return pcx.cx.tcx.is_doc_hidden(variant_def_id) && !variant_def_id.is_local();
@@ -731,7 +731,7 @@ impl<'tcx> Constructor<'tcx> {
731731

732732
/// The number of fields for this constructor. This must be kept in sync with
733733
/// `Fields::wildcards`.
734-
pub(super) fn arity(&self, pcx: PatCtxt<'_, '_, 'tcx>) -> usize {
734+
pub(super) fn arity(&self, pcx: &PatCtxt<'_, '_, 'tcx>) -> usize {
735735
match self {
736736
Single | Variant(_) => match pcx.ty.kind() {
737737
ty::Tuple(fs) => fs.len(),
@@ -775,7 +775,7 @@ impl<'tcx> Constructor<'tcx> {
775775
/// matrix, unless all of them are.
776776
pub(super) fn split<'a>(
777777
&self,
778-
pcx: PatCtxt<'_, '_, 'tcx>,
778+
pcx: &PatCtxt<'_, '_, 'tcx>,
779779
ctors: impl Iterator<Item = &'a Constructor<'tcx>> + Clone,
780780
) -> SmallVec<[Self; 1]>
781781
where
@@ -811,7 +811,7 @@ impl<'tcx> Constructor<'tcx> {
811811
/// this checks for inclusion.
812812
// We inline because this has a single call site in `Matrix::specialize_constructor`.
813813
#[inline]
814-
pub(super) fn is_covered_by<'p>(&self, pcx: PatCtxt<'_, 'p, 'tcx>, other: &Self) -> bool {
814+
pub(super) fn is_covered_by<'p>(&self, pcx: &PatCtxt<'_, 'p, 'tcx>, other: &Self) -> bool {
815815
// This must be kept in sync with `is_covered_by_any`.
816816
match (self, other) {
817817
// Wildcards cover anything
@@ -865,7 +865,7 @@ impl<'tcx> Constructor<'tcx> {
865865
/// assumed to have been split from a wildcard.
866866
fn is_covered_by_any<'p>(
867867
&self,
868-
pcx: PatCtxt<'_, 'p, 'tcx>,
868+
pcx: &PatCtxt<'_, 'p, 'tcx>,
869869
used_ctors: &[Constructor<'tcx>],
870870
) -> bool {
871871
if used_ctors.is_empty() {
@@ -918,7 +918,7 @@ pub(super) struct SplitWildcard<'tcx> {
918918
}
919919

920920
impl<'tcx> SplitWildcard<'tcx> {
921-
pub(super) fn new<'p>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Self {
921+
pub(super) fn new<'p>(pcx: &PatCtxt<'_, 'p, 'tcx>) -> Self {
922922
debug!("SplitWildcard::new({:?})", pcx.ty);
923923
let cx = pcx.cx;
924924
let make_range = |start, end| {
@@ -1044,7 +1044,7 @@ impl<'tcx> SplitWildcard<'tcx> {
10441044
/// do what you want.
10451045
pub(super) fn split<'a>(
10461046
&mut self,
1047-
pcx: PatCtxt<'_, '_, 'tcx>,
1047+
pcx: &PatCtxt<'_, '_, 'tcx>,
10481048
ctors: impl Iterator<Item = &'a Constructor<'tcx>> + Clone,
10491049
) where
10501050
'tcx: 'a,
@@ -1056,21 +1056,21 @@ impl<'tcx> SplitWildcard<'tcx> {
10561056
}
10571057

10581058
/// Whether there are any value constructors for this type that are not present in the matrix.
1059-
fn any_missing(&self, pcx: PatCtxt<'_, '_, 'tcx>) -> bool {
1059+
fn any_missing(&self, pcx: &PatCtxt<'_, '_, 'tcx>) -> bool {
10601060
self.iter_missing(pcx).next().is_some()
10611061
}
10621062

10631063
/// Iterate over the constructors for this type that are not present in the matrix.
10641064
pub(super) fn iter_missing<'a, 'p>(
10651065
&'a self,
1066-
pcx: PatCtxt<'a, 'p, 'tcx>,
1066+
pcx: &'a PatCtxt<'a, 'p, 'tcx>,
10671067
) -> impl Iterator<Item = &'a Constructor<'tcx>> + Captures<'p> {
10681068
self.all_ctors.iter().filter(move |ctor| !ctor.is_covered_by_any(pcx, &self.matrix_ctors))
10691069
}
10701070

10711071
/// Return the set of constructors resulting from splitting the wildcard. As explained at the
10721072
/// top of the file, if any constructors are missing we can ignore the present ones.
1073-
fn into_ctors(self, pcx: PatCtxt<'_, '_, 'tcx>) -> SmallVec<[Constructor<'tcx>; 1]> {
1073+
fn into_ctors(self, pcx: &PatCtxt<'_, '_, 'tcx>) -> SmallVec<[Constructor<'tcx>; 1]> {
10741074
if self.any_missing(pcx) {
10751075
// Some constructors are missing, thus we can specialize with the special `Missing`
10761076
// constructor, which stands for those constructors that are not seen in the matrix,
@@ -1202,35 +1202,32 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
12021202

12031203
/// Creates a new list of wildcard fields for a given constructor. The result must have a
12041204
/// length of `constructor.arity()`.
1205-
pub(super) fn wildcards(
1206-
cx: &MatchCheckCtxt<'p, 'tcx>,
1207-
ty: Ty<'tcx>,
1208-
constructor: &Constructor<'tcx>,
1209-
) -> Self {
1205+
#[instrument(level = "trace")]
1206+
pub(super) fn wildcards(pcx: &PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'tcx>) -> Self {
12101207
let ret = match constructor {
1211-
Single | Variant(_) => match ty.kind() {
1212-
ty::Tuple(fs) => Fields::wildcards_from_tys(cx, fs.iter()),
1213-
ty::Ref(_, rty, _) => Fields::wildcards_from_tys(cx, once(*rty)),
1208+
Single | Variant(_) => match pcx.ty.kind() {
1209+
ty::Tuple(fs) => Fields::wildcards_from_tys(pcx.cx, fs.iter()),
1210+
ty::Ref(_, rty, _) => Fields::wildcards_from_tys(pcx.cx, once(*rty)),
12141211
ty::Adt(adt, substs) => {
12151212
if adt.is_box() {
12161213
// The only legal patterns of type `Box` (outside `std`) are `_` and box
12171214
// patterns. If we're here we can assume this is a box pattern.
1218-
Fields::wildcards_from_tys(cx, once(substs.type_at(0)))
1215+
Fields::wildcards_from_tys(pcx.cx, once(substs.type_at(0)))
12191216
} else {
12201217
let variant = &adt.variant(constructor.variant_index_for_adt(*adt));
1221-
let tys = Fields::list_variant_nonhidden_fields(cx, ty, variant)
1218+
let tys = Fields::list_variant_nonhidden_fields(pcx.cx, pcx.ty, variant)
12221219
.map(|(_, ty)| ty);
1223-
Fields::wildcards_from_tys(cx, tys)
1220+
Fields::wildcards_from_tys(pcx.cx, tys)
12241221
}
12251222
}
1226-
_ => bug!("Unexpected type for `Single` constructor: {:?}", ty),
1223+
_ => bug!("Unexpected type for `Single` constructor: {:?}", pcx),
12271224
},
1228-
Slice(slice) => match *ty.kind() {
1225+
Slice(slice) => match *pcx.ty.kind() {
12291226
ty::Slice(ty) | ty::Array(ty, _) => {
12301227
let arity = slice.arity();
1231-
Fields::wildcards_from_tys(cx, (0..arity).map(|_| ty))
1228+
Fields::wildcards_from_tys(pcx.cx, (0..arity).map(|_| ty))
12321229
}
1233-
_ => bug!("bad slice pattern {:?} {:?}", constructor, ty),
1230+
_ => bug!("bad slice pattern {:?} {:?}", constructor, pcx),
12341231
},
12351232
Str(..)
12361233
| FloatRange(..)
@@ -1243,7 +1240,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
12431240
bug!("called `Fields::wildcards` on an `Or` ctor")
12441241
}
12451242
};
1246-
debug!("Fields::wildcards({:?}, {:?}) = {:#?}", constructor, ty, ret);
1243+
debug!(?ret);
12471244
ret
12481245
}
12491246

@@ -1285,8 +1282,8 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
12851282
/// Construct a pattern that matches everything that starts with this constructor.
12861283
/// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
12871284
/// `Some(_)`.
1288-
pub(super) fn wild_from_ctor(pcx: PatCtxt<'_, 'p, 'tcx>, ctor: Constructor<'tcx>) -> Self {
1289-
let fields = Fields::wildcards(pcx.cx, pcx.ty, &ctor);
1285+
pub(super) fn wild_from_ctor(pcx: &PatCtxt<'_, 'p, 'tcx>, ctor: Constructor<'tcx>) -> Self {
1286+
let fields = Fields::wildcards(pcx, &ctor);
12901287
DeconstructedPat::new(ctor, fields, pcx.ty, DUMMY_SP)
12911288
}
12921289

@@ -1553,13 +1550,13 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
15531550
/// `other_ctor` can be different from `self.ctor`, but must be covered by it.
15541551
pub(super) fn specialize<'a>(
15551552
&'a self,
1556-
cx: &MatchCheckCtxt<'p, 'tcx>,
1553+
pcx: &PatCtxt<'_, 'p, 'tcx>,
15571554
other_ctor: &Constructor<'tcx>,
15581555
) -> SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]> {
15591556
match (&self.ctor, other_ctor) {
15601557
(Wildcard, _) => {
15611558
// We return a wildcard for each field of `other_ctor`.
1562-
Fields::wildcards(cx, self.ty, other_ctor).iter_patterns().collect()
1559+
Fields::wildcards(pcx, other_ctor).iter_patterns().collect()
15631560
}
15641561
(Slice(self_slice), Slice(other_slice))
15651562
if self_slice.arity() != other_slice.arity() =>
@@ -1578,7 +1575,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
15781575
let prefix = &self.fields.fields[..prefix];
15791576
let suffix = &self.fields.fields[self_slice.arity() - suffix..];
15801577
let wildcard: &_ =
1581-
cx.pattern_arena.alloc(DeconstructedPat::wildcard(inner_ty));
1578+
pcx.cx.pattern_arena.alloc(DeconstructedPat::wildcard(inner_ty));
15821579
let extra_wildcards = other_slice.arity() - self_slice.arity();
15831580
let extra_wildcards = (0..extra_wildcards).map(|_| wildcard);
15841581
prefix.iter().chain(extra_wildcards).chain(suffix).collect()

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

+13-13
Original file line numberDiff line numberDiff line change
@@ -411,12 +411,12 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
411411
/// This is roughly the inverse of `Constructor::apply`.
412412
fn pop_head_constructor(
413413
&self,
414-
cx: &MatchCheckCtxt<'p, 'tcx>,
414+
pcx: &PatCtxt<'_, 'p, 'tcx>,
415415
ctor: &Constructor<'tcx>,
416416
) -> PatStack<'p, 'tcx> {
417417
// We pop the head pattern and push the new fields extracted from the arguments of
418418
// `self.head()`.
419-
let mut new_fields: SmallVec<[_; 2]> = self.head().specialize(cx, ctor);
419+
let mut new_fields: SmallVec<[_; 2]> = self.head().specialize(pcx, ctor);
420420
new_fields.extend_from_slice(&self.pats[1..]);
421421
PatStack::from_vec(new_fields)
422422
}
@@ -469,13 +469,13 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
469469
/// This computes `S(constructor, self)`. See top of the file for explanations.
470470
fn specialize_constructor(
471471
&self,
472-
pcx: PatCtxt<'_, 'p, 'tcx>,
472+
pcx: &PatCtxt<'_, 'p, 'tcx>,
473473
ctor: &Constructor<'tcx>,
474474
) -> Matrix<'p, 'tcx> {
475475
let mut matrix = Matrix::empty();
476476
for row in &self.patterns {
477477
if ctor.is_covered_by(pcx, row.head().ctor()) {
478-
let new_row = row.pop_head_constructor(pcx.cx, ctor);
478+
let new_row = row.pop_head_constructor(pcx, ctor);
479479
matrix.push(new_row);
480480
}
481481
}
@@ -575,7 +575,7 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
575575
/// with the results of specializing with the other constructors.
576576
fn apply_constructor(
577577
self,
578-
pcx: PatCtxt<'_, 'p, 'tcx>,
578+
pcx: &PatCtxt<'_, 'p, 'tcx>,
579579
matrix: &Matrix<'p, 'tcx>, // used to compute missing ctors
580580
ctor: &Constructor<'tcx>,
581581
) -> Self {
@@ -713,7 +713,7 @@ impl<'p, 'tcx> Witness<'p, 'tcx> {
713713
///
714714
/// left_ty: struct X { a: (bool, &'static str), b: usize}
715715
/// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 }
716-
fn apply_constructor(mut self, pcx: PatCtxt<'_, 'p, 'tcx>, ctor: &Constructor<'tcx>) -> Self {
716+
fn apply_constructor(mut self, pcx: &PatCtxt<'_, 'p, 'tcx>, ctor: &Constructor<'tcx>) -> Self {
717717
let pat = {
718718
let len = self.0.len();
719719
let arity = ctor.arity(pcx);
@@ -786,7 +786,7 @@ fn is_useful<'p, 'tcx>(
786786
is_under_guard: bool,
787787
is_top_level: bool,
788788
) -> Usefulness<'p, 'tcx> {
789-
debug!("matrix,v={:?}{:?}", matrix, v);
789+
debug!(?matrix, ?v);
790790
let Matrix { patterns: rows, .. } = matrix;
791791

792792
// The base case. We are pattern-matching on () and the return value is
@@ -806,11 +806,6 @@ fn is_useful<'p, 'tcx>(
806806

807807
debug_assert!(rows.iter().all(|r| r.len() == v.len()));
808808

809-
let ty = v.head().ty();
810-
let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
811-
debug!("v.head: {:?}, v.span: {:?}", v.head(), v.head().span());
812-
let pcx = PatCtxt { cx, ty, span: v.head().span(), is_top_level, is_non_exhaustive };
813-
814809
// If the first pattern is an or-pattern, expand it.
815810
let mut ret = Usefulness::new_not_useful(witness_preference);
816811
if v.head().is_or_pat() {
@@ -832,6 +827,11 @@ fn is_useful<'p, 'tcx>(
832827
}
833828
}
834829
} else {
830+
let ty = v.head().ty();
831+
let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
832+
debug!("v.head: {:?}, v.span: {:?}", v.head(), v.head().span());
833+
let pcx = &PatCtxt { cx, ty, span: v.head().span(), is_top_level, is_non_exhaustive };
834+
835835
let v_ctor = v.head().ctor();
836836
debug!(?v_ctor);
837837
if let Constructor::IntRange(ctor_range) = &v_ctor {
@@ -853,7 +853,7 @@ fn is_useful<'p, 'tcx>(
853853
debug!("specialize({:?})", ctor);
854854
// We cache the result of `Fields::wildcards` because it is used a lot.
855855
let spec_matrix = start_matrix.specialize_constructor(pcx, &ctor);
856-
let v = v.pop_head_constructor(cx, &ctor);
856+
let v = v.pop_head_constructor(pcx, &ctor);
857857
let usefulness = ensure_sufficient_stack(|| {
858858
is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false)
859859
});

0 commit comments

Comments
 (0)