Skip to content

Commit 6df1815

Browse files
committed
Compute constructors on PatStack construction
All the constructed PatStacks end up having `head_ctors` called on them, so this does not unnecessarily precompute anything.
1 parent 368c71b commit 6df1815

File tree

2 files changed

+34
-43
lines changed

2 files changed

+34
-43
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 30 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@ use syntax_pos::{Span, DUMMY_SP};
248248
use arena::TypedArena;
249249

250250
use smallvec::{smallvec, SmallVec};
251-
use std::cell::RefCell;
252251
use std::cmp::{self, max, min, Ordering};
253252
use std::convert::TryInto;
254253
use std::fmt;
@@ -341,25 +340,30 @@ impl PatternFolder<'tcx> for LiteralExpander<'tcx> {
341340
pub struct PatStack<'p, 'tcx> {
342341
patterns: SmallVec<[&'p Pat<'tcx>; 2]>,
343342
// This caches the invocation of `pat_constructors` on the head of the stack. We avoid mutating
344-
// `self` to be sure we don't keep an invalid cache around.
345-
head_ctors_cache: RefCell<Option<SmallVec<[Constructor<'tcx>; 1]>>>,
343+
// `self` to be sure we don't keep an invalid cache around. Must be non-empty unless `patterns`
344+
// is empty.
345+
head_ctors_cache: SmallVec<[Constructor<'tcx>; 1]>,
346346
}
347347

348348
impl<'p, 'tcx> PatStack<'p, 'tcx> {
349-
pub fn from_pattern(pat: &'p Pat<'tcx>) -> Self {
350-
PatStack::from_vec(smallvec![pat])
349+
pub fn from_pattern(cx: &MatchCheckCtxt<'_, 'tcx>, pat: &'p Pat<'tcx>) -> Self {
350+
PatStack::from_vec(cx, smallvec![pat])
351351
}
352352

353353
fn empty() -> Self {
354-
PatStack::from_vec(smallvec![])
354+
PatStack { patterns: smallvec![], head_ctors_cache: smallvec![] }
355355
}
356356

357-
fn from_vec(vec: SmallVec<[&'p Pat<'tcx>; 2]>) -> Self {
358-
PatStack { patterns: vec, head_ctors_cache: RefCell::new(None) }
357+
fn from_vec(cx: &MatchCheckCtxt<'_, 'tcx>, patterns: SmallVec<[&'p Pat<'tcx>; 2]>) -> Self {
358+
if patterns.is_empty() {
359+
return PatStack::empty();
360+
}
361+
let head_ctors_cache = pat_constructors(cx.tcx, cx.param_env, patterns[0]);
362+
PatStack { patterns, head_ctors_cache }
359363
}
360364

361-
fn from_slice(s: &[&'p Pat<'tcx>]) -> Self {
362-
PatStack::from_vec(SmallVec::from_slice(s))
365+
fn from_slice(cx: &MatchCheckCtxt<'_, 'tcx>, s: &[&'p Pat<'tcx>]) -> Self {
366+
PatStack::from_vec(cx, SmallVec::from_slice(s))
363367
}
364368

365369
fn is_empty(&self) -> bool {
@@ -376,16 +380,7 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
376380

377381
fn head_ctors(&self, cx: &MatchCheckCtxt<'_, 'tcx>) -> SmallVec<[Constructor<'tcx>; 1]> {
378382
let new_ctors = pat_constructors(cx.tcx, cx.param_env, self.head());
379-
let borrow = self.head_ctors_cache.borrow();
380-
match *borrow {
381-
Some(ref cached_ctors) => {
382-
assert_eq!(cached_ctors, &new_ctors);
383-
}
384-
None => {
385-
drop(borrow);
386-
*self.head_ctors_cache.borrow_mut() = Some(new_ctors.clone());
387-
}
388-
}
383+
assert_eq!(self.head_ctors_cache, new_ctors);
389384
new_ctors
390385
}
391386

@@ -410,7 +405,7 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
410405
.map(|new_head| {
411406
let mut pats = new_head.patterns;
412407
pats.extend_from_slice(&self.patterns[1..]);
413-
PatStack::from_vec(pats)
408+
PatStack::from_vec(cx, pats)
414409
})
415410
.collect();
416411
debug!("specialize({:#?}, {:#?}) = {:#?}", self, constructor, result);
@@ -424,15 +419,6 @@ impl<'p, 'tcx> Default for PatStack<'p, 'tcx> {
424419
}
425420
}
426421

427-
impl<'p, 'tcx> FromIterator<&'p Pat<'tcx>> for PatStack<'p, 'tcx> {
428-
fn from_iter<T>(iter: T) -> Self
429-
where
430-
T: IntoIterator<Item = &'p Pat<'tcx>>,
431-
{
432-
PatStack::from_vec(iter.into_iter().collect())
433-
}
434-
}
435-
436422
/// A 2D matrix.
437423
pub struct Matrix<'p, 'tcx>(Vec<PatStack<'p, 'tcx>>);
438424

@@ -1987,6 +1973,7 @@ fn constructor_intersects_pattern<'p, 'tcx>(
19871973
}
19881974

19891975
fn patterns_for_variant<'p, 'tcx>(
1976+
cx: &MatchCheckCtxt<'_, 'tcx>,
19901977
subpatterns: &'p [FieldPat<'tcx>],
19911978
ctor_wild_subpatterns: &[&'p Pat<'tcx>],
19921979
) -> PatStack<'p, 'tcx> {
@@ -2000,7 +1987,7 @@ fn patterns_for_variant<'p, 'tcx>(
20001987
"patterns_for_variant({:#?}, {:#?}) = {:#?}",
20011988
subpatterns, ctor_wild_subpatterns, result
20021989
);
2003-
PatStack::from_vec(result)
1990+
PatStack::from_vec(cx, result)
20041991
}
20051992

20061993
/// This is the main specialization step. It expands the pattern into `arity` patterns based on the
@@ -2037,23 +2024,23 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
20372024
PatKind::AscribeUserType { .. } => unreachable!(), // Handled above
20382025

20392026
PatKind::Binding { .. } | PatKind::Wild => {
2040-
smallvec![PatStack::from_slice(ctor_wild_subpatterns)]
2027+
smallvec![PatStack::from_slice(cx, ctor_wild_subpatterns)]
20412028
}
20422029

20432030
PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
20442031
let ref variant = adt_def.variants[variant_index];
20452032
if Variant(variant.def_id) == *constructor {
2046-
smallvec![patterns_for_variant(subpatterns, ctor_wild_subpatterns)]
2033+
smallvec![patterns_for_variant(cx, subpatterns, ctor_wild_subpatterns)]
20472034
} else {
20482035
smallvec![]
20492036
}
20502037
}
20512038

20522039
PatKind::Leaf { ref subpatterns } => {
2053-
smallvec![patterns_for_variant(subpatterns, ctor_wild_subpatterns)]
2040+
smallvec![patterns_for_variant(cx, subpatterns, ctor_wild_subpatterns)]
20542041
}
20552042

2056-
PatKind::Deref { ref subpattern } => smallvec![PatStack::from_pattern(subpattern)],
2043+
PatKind::Deref { ref subpattern } => smallvec![PatStack::from_pattern(cx, subpattern)],
20572044

20582045
PatKind::Constant { value } if constructor.is_slice() => {
20592046
// We extract an `Option` for the pointer because slices of zero
@@ -2098,7 +2085,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
20982085
return smallvec![];
20992086
};
21002087
let ptr = Pointer::new(AllocId(0), offset);
2101-
let stack: Option<PatStack<'_, '_>> = (0..n)
2088+
let stack: Option<SmallVec<_>> = (0..n)
21022089
.map(|i| {
21032090
let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?;
21042091
let scalar = alloc.read_scalar(&cx.tcx, ptr, layout.size).ok()?;
@@ -2109,7 +2096,10 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
21092096
Some(&*cx.pattern_arena.alloc(pattern))
21102097
})
21112098
.collect();
2112-
stack.into_iter().collect()
2099+
match stack {
2100+
Some(v) => smallvec![PatStack::from_vec(cx, v)],
2101+
None => smallvec![],
2102+
}
21132103
} else {
21142104
smallvec![]
21152105
}
@@ -2132,7 +2122,8 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
21322122
let pat_len = prefix.len() + suffix.len();
21332123
if let Some(slice_count) = ctor_wild_subpatterns.len().checked_sub(pat_len) {
21342124
if slice_count == 0 || slice.is_some() {
2135-
smallvec![
2125+
smallvec![PatStack::from_vec(
2126+
cx,
21362127
prefix
21372128
.iter()
21382129
.chain(
@@ -2144,7 +2135,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
21442135
.chain(suffix.iter()),
21452136
)
21462137
.collect(),
2147-
]
2138+
)]
21482139
} else {
21492140
smallvec![]
21502141
}

src/librustc_mir/hair/pattern/check_match.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
246246
.iter()
247247
.filter(|&&(_, guard)| guard.is_none())
248248
.flat_map(|arm| &arm.0)
249-
.map(|pat| PatStack::from_pattern(pat.0))
249+
.map(|pat| PatStack::from_pattern(cx, pat.0))
250250
.collect();
251251
let scrut_ty = self.tables.node_type(scrut.hir_id);
252252
check_exhaustive(cx, scrut_ty, scrut.span, &matrix);
@@ -262,7 +262,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
262262
let pattern = patcx.lower_pattern(pat);
263263
let pattern_ty = pattern.ty;
264264
let pats: Matrix<'_, '_> =
265-
vec![PatStack::from_pattern(expand_pattern(cx, pattern))].into_iter().collect();
265+
vec![PatStack::from_pattern(cx, expand_pattern(cx, pattern))].into_iter().collect();
266266

267267
let witnesses = match check_not_useful(cx, pattern_ty, &pats) {
268268
Ok(_) => return,
@@ -406,7 +406,7 @@ fn check_arms<'tcx>(
406406
let mut catchall = None;
407407
for (arm_index, &(ref pats, guard)) in arms.iter().enumerate() {
408408
for &(pat, hir_pat) in pats {
409-
let v = PatStack::from_pattern(pat);
409+
let v = PatStack::from_pattern(cx, pat);
410410

411411
match is_useful(cx, &seen, &v, LeaveOutWitness) {
412412
NotUseful => {
@@ -487,7 +487,7 @@ fn check_not_useful(
487487
matrix: &Matrix<'_, 'tcx>,
488488
) -> Result<(), Vec<super::Pat<'tcx>>> {
489489
let wild_pattern = super::Pat { ty, span: DUMMY_SP, kind: box PatKind::Wild };
490-
match is_useful(cx, matrix, &PatStack::from_pattern(&wild_pattern), ConstructWitness) {
490+
match is_useful(cx, matrix, &PatStack::from_pattern(cx, &wild_pattern), ConstructWitness) {
491491
NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable.
492492
UsefulWithWitness(pats) => Err(if pats.is_empty() {
493493
vec![wild_pattern]

0 commit comments

Comments
 (0)