Skip to content

Commit e6aa962

Browse files
committed
Simplify lifetimes by allocating patterns on the arena
We want the lifetimes of the patterns contained in the matrix and the candidate `PatStack` to be the same so that they can be mixed together. A lot of this would not be necessary if `SmallVec` was covariant in its type argument (see servo/rust-smallvec#146).
1 parent 21af89d commit e6aa962

File tree

2 files changed

+38
-49
lines changed

2 files changed

+38
-49
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 27 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -425,16 +425,12 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
425425
}
426426

427427
/// This computes `S(constructor, self)`. See top of the file for explanations.
428-
fn specialize_constructor<'a, 'q>(
428+
fn specialize_constructor(
429429
&self,
430-
cx: &mut MatchCheckCtxt<'a, 'tcx>,
430+
cx: &mut MatchCheckCtxt<'p, 'tcx>,
431431
constructor: &Constructor<'tcx>,
432-
ctor_wild_subpatterns: &[&'q Pat<'tcx>],
433-
) -> Option<PatStack<'q, 'tcx>>
434-
where
435-
'a: 'q,
436-
'p: 'q,
437-
{
432+
ctor_wild_subpatterns: &'p [Pat<'tcx>],
433+
) -> Option<PatStack<'p, 'tcx>> {
438434
let new_heads = specialize_one_pattern(cx, self.head(), constructor, ctor_wild_subpatterns);
439435
new_heads.map(|mut new_head| {
440436
new_head.0.extend_from_slice(&self.0[1..]);
@@ -486,16 +482,12 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
486482
}
487483

488484
/// This computes `S(constructor, self)`. See top of the file for explanations.
489-
fn specialize_constructor<'a, 'q>(
485+
fn specialize_constructor(
490486
&self,
491-
cx: &mut MatchCheckCtxt<'a, 'tcx>,
487+
cx: &mut MatchCheckCtxt<'p, 'tcx>,
492488
constructor: &Constructor<'tcx>,
493-
ctor_wild_subpatterns: &[&'q Pat<'tcx>],
494-
) -> Matrix<'q, 'tcx>
495-
where
496-
'a: 'q,
497-
'p: 'q,
498-
{
489+
ctor_wild_subpatterns: &'p [Pat<'tcx>],
490+
) -> Matrix<'p, 'tcx> {
499491
self.0
500492
.iter()
501493
.filter_map(|r| r.specialize_constructor(cx, constructor, ctor_wild_subpatterns))
@@ -1604,10 +1596,10 @@ impl<'tcx> fmt::Debug for MissingConstructors<'tcx> {
16041596
/// relation to preceding patterns, it is not reachable) and exhaustiveness
16051597
/// checking (if a wildcard pattern is useful in relation to a matrix, the
16061598
/// matrix isn't exhaustive).
1607-
pub fn is_useful<'p, 'a, 'tcx>(
1608-
cx: &mut MatchCheckCtxt<'a, 'tcx>,
1599+
pub fn is_useful<'p, 'tcx>(
1600+
cx: &mut MatchCheckCtxt<'p, 'tcx>,
16091601
matrix: &Matrix<'p, 'tcx>,
1610-
v: &PatStack<'_, 'tcx>,
1602+
v: &PatStack<'p, 'tcx>,
16111603
witness_preference: WitnessPreference,
16121604
hir_id: HirId,
16131605
) -> Usefulness<'tcx> {
@@ -1768,21 +1760,21 @@ pub fn is_useful<'p, 'a, 'tcx>(
17681760

17691761
/// A shorthand for the `U(S(c, P), S(c, q))` operation from the paper. I.e., `is_useful` applied
17701762
/// to the specialised version of both the pattern matrix `P` and the new pattern `q`.
1771-
fn is_useful_specialized<'p, 'a, 'tcx>(
1772-
cx: &mut MatchCheckCtxt<'a, 'tcx>,
1763+
fn is_useful_specialized<'p, 'tcx>(
1764+
cx: &mut MatchCheckCtxt<'p, 'tcx>,
17731765
matrix: &Matrix<'p, 'tcx>,
1774-
v: &PatStack<'_, 'tcx>,
1766+
v: &PatStack<'p, 'tcx>,
17751767
ctor: Constructor<'tcx>,
17761768
lty: Ty<'tcx>,
17771769
witness_preference: WitnessPreference,
17781770
hir_id: HirId,
17791771
) -> Usefulness<'tcx> {
17801772
debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty);
17811773

1782-
let ctor_wild_subpatterns_owned: Vec<_> = ctor.wildcard_subpatterns(cx, lty);
1783-
let ctor_wild_subpatterns: Vec<_> = ctor_wild_subpatterns_owned.iter().collect();
1784-
let matrix = matrix.specialize_constructor(cx, &ctor, &ctor_wild_subpatterns);
1785-
v.specialize_constructor(cx, &ctor, &ctor_wild_subpatterns)
1774+
let ctor_wild_subpatterns =
1775+
cx.pattern_arena.alloc_from_iter(ctor.wildcard_subpatterns(cx, lty));
1776+
let matrix = matrix.specialize_constructor(cx, &ctor, ctor_wild_subpatterns);
1777+
v.specialize_constructor(cx, &ctor, ctor_wild_subpatterns)
17861778
.map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id))
17871779
.map(|u| u.apply_constructor(cx, &ctor, lty))
17881780
.unwrap_or(NotUseful)
@@ -2250,13 +2242,13 @@ fn constructor_covered_by_range<'tcx>(
22502242
if intersects { Some(()) } else { None }
22512243
}
22522244

2253-
fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
2254-
cx: &mut MatchCheckCtxt<'a, 'tcx>,
2245+
fn patterns_for_variant<'p, 'tcx>(
2246+
cx: &mut MatchCheckCtxt<'p, 'tcx>,
22552247
subpatterns: &'p [FieldPat<'tcx>],
2256-
ctor_wild_subpatterns: &[&'p Pat<'tcx>],
2248+
ctor_wild_subpatterns: &'p [Pat<'tcx>],
22572249
is_non_exhaustive: bool,
22582250
) -> PatStack<'p, 'tcx> {
2259-
let mut result = SmallVec::from_slice(ctor_wild_subpatterns);
2251+
let mut result: SmallVec<_> = ctor_wild_subpatterns.iter().collect();
22602252

22612253
for subpat in subpatterns {
22622254
if !is_non_exhaustive || !cx.is_uninhabited(subpat.pattern.ty) {
@@ -2280,11 +2272,11 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
22802272
/// different patterns.
22812273
/// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
22822274
/// fields filled with wild patterns.
2283-
fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
2284-
cx: &mut MatchCheckCtxt<'a, 'tcx>,
2285-
pat: &'q Pat<'tcx>,
2275+
fn specialize_one_pattern<'p, 'tcx>(
2276+
cx: &mut MatchCheckCtxt<'p, 'tcx>,
2277+
pat: &'p Pat<'tcx>,
22862278
constructor: &Constructor<'tcx>,
2287-
ctor_wild_subpatterns: &[&'p Pat<'tcx>],
2279+
ctor_wild_subpatterns: &'p [Pat<'tcx>],
22882280
) -> Option<PatStack<'p, 'tcx>> {
22892281
if let NonExhaustive = constructor {
22902282
// Only a wildcard pattern can match the special extra constructor
@@ -2294,9 +2286,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
22942286
let result = match *pat.kind {
22952287
PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`
22962288

2297-
PatKind::Binding { .. } | PatKind::Wild => {
2298-
Some(PatStack::from_slice(ctor_wild_subpatterns))
2299-
}
2289+
PatKind::Binding { .. } | PatKind::Wild => Some(ctor_wild_subpatterns.iter().collect()),
23002290

23012291
PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
23022292
let ref variant = adt_def.variants[variant_index];
@@ -2406,7 +2396,6 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
24062396
.chain(
24072397
ctor_wild_subpatterns
24082398
.iter()
2409-
.map(|p| *p)
24102399
.skip(prefix.len())
24112400
.take(slice_count)
24122401
.chain(suffix.iter()),

src/librustc_mir/hair/pattern/check_match.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,8 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
261261
patcx.include_lint_checks();
262262
let pattern = patcx.lower_pattern(pat);
263263
let pattern_ty = pattern.ty;
264-
let pattern = expand_pattern(cx, pattern);
265-
let pats: Matrix<'_, '_> = vec![PatStack::from_pattern(&pattern)].into_iter().collect();
264+
let pattern = cx.pattern_arena.alloc(expand_pattern(cx, pattern));
265+
let pats: Matrix<'_, '_> = vec![PatStack::from_pattern(pattern)].into_iter().collect();
266266

267267
let witnesses = match check_not_useful(cx, pattern_ty, &pats, pat.hir_id) {
268268
Ok(_) => return,
@@ -398,7 +398,7 @@ fn pat_is_catchall(pat: &Pat) -> bool {
398398

399399
// Check for unreachable patterns
400400
fn check_arms<'p, 'tcx>(
401-
cx: &mut MatchCheckCtxt<'_, 'tcx>,
401+
cx: &mut MatchCheckCtxt<'p, 'tcx>,
402402
arms: &[(Vec<(&'p super::Pat<'tcx>, &hir::Pat)>, Option<&hir::Expr>)],
403403
source: hir::MatchSource,
404404
) -> Matrix<'p, 'tcx> {
@@ -482,14 +482,14 @@ fn check_arms<'p, 'tcx>(
482482
seen
483483
}
484484

485-
fn check_not_useful(
486-
cx: &mut MatchCheckCtxt<'_, 'tcx>,
485+
fn check_not_useful<'p, 'tcx>(
486+
cx: &mut MatchCheckCtxt<'p, 'tcx>,
487487
ty: Ty<'tcx>,
488-
matrix: &Matrix<'_, 'tcx>,
488+
matrix: &Matrix<'p, 'tcx>,
489489
hir_id: HirId,
490490
) -> Result<(), Vec<super::Pat<'tcx>>> {
491-
let wild_pattern = super::Pat::wildcard_from_ty(ty);
492-
match is_useful(cx, matrix, &PatStack::from_pattern(&wild_pattern), ConstructWitness, hir_id) {
491+
let wild_pattern = cx.pattern_arena.alloc(super::Pat::wildcard_from_ty(ty));
492+
match is_useful(cx, matrix, &PatStack::from_pattern(wild_pattern), ConstructWitness, hir_id) {
493493
NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable.
494494
UsefulWithWitness(pats) => Err(if pats.is_empty() {
495495
bug!("Exhaustiveness check returned no witnesses")
@@ -500,11 +500,11 @@ fn check_not_useful(
500500
}
501501
}
502502

503-
fn check_exhaustive<'tcx>(
504-
cx: &mut MatchCheckCtxt<'_, 'tcx>,
503+
fn check_exhaustive<'p, 'tcx>(
504+
cx: &mut MatchCheckCtxt<'p, 'tcx>,
505505
scrut_ty: Ty<'tcx>,
506506
sp: Span,
507-
matrix: &Matrix<'_, 'tcx>,
507+
matrix: &Matrix<'p, 'tcx>,
508508
hir_id: HirId,
509509
) {
510510
let witnesses = match check_not_useful(cx, scrut_ty, matrix, hir_id) {

0 commit comments

Comments
 (0)