Skip to content

Commit

Permalink
Simplify lifetimes by allocating patterns on the arena
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
Nadrieril committed Dec 2, 2019
1 parent 21af89d commit e6aa962
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 49 deletions.
65 changes: 27 additions & 38 deletions src/librustc_mir/hair/pattern/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,16 +425,12 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
}

/// This computes `S(constructor, self)`. See top of the file for explanations.
fn specialize_constructor<'a, 'q>(
fn specialize_constructor(
&self,
cx: &mut MatchCheckCtxt<'a, 'tcx>,
cx: &mut MatchCheckCtxt<'p, 'tcx>,
constructor: &Constructor<'tcx>,
ctor_wild_subpatterns: &[&'q Pat<'tcx>],
) -> Option<PatStack<'q, 'tcx>>
where
'a: 'q,
'p: 'q,
{
ctor_wild_subpatterns: &'p [Pat<'tcx>],
) -> Option<PatStack<'p, 'tcx>> {
let new_heads = specialize_one_pattern(cx, self.head(), constructor, ctor_wild_subpatterns);
new_heads.map(|mut new_head| {
new_head.0.extend_from_slice(&self.0[1..]);
Expand Down Expand Up @@ -486,16 +482,12 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
}

/// This computes `S(constructor, self)`. See top of the file for explanations.
fn specialize_constructor<'a, 'q>(
fn specialize_constructor(
&self,
cx: &mut MatchCheckCtxt<'a, 'tcx>,
cx: &mut MatchCheckCtxt<'p, 'tcx>,
constructor: &Constructor<'tcx>,
ctor_wild_subpatterns: &[&'q Pat<'tcx>],
) -> Matrix<'q, 'tcx>
where
'a: 'q,
'p: 'q,
{
ctor_wild_subpatterns: &'p [Pat<'tcx>],
) -> Matrix<'p, 'tcx> {
self.0
.iter()
.filter_map(|r| r.specialize_constructor(cx, constructor, ctor_wild_subpatterns))
Expand Down Expand Up @@ -1604,10 +1596,10 @@ impl<'tcx> fmt::Debug for MissingConstructors<'tcx> {
/// relation to preceding patterns, it is not reachable) and exhaustiveness
/// checking (if a wildcard pattern is useful in relation to a matrix, the
/// matrix isn't exhaustive).
pub fn is_useful<'p, 'a, 'tcx>(
cx: &mut MatchCheckCtxt<'a, 'tcx>,
pub fn is_useful<'p, 'tcx>(
cx: &mut MatchCheckCtxt<'p, 'tcx>,
matrix: &Matrix<'p, 'tcx>,
v: &PatStack<'_, 'tcx>,
v: &PatStack<'p, 'tcx>,
witness_preference: WitnessPreference,
hir_id: HirId,
) -> Usefulness<'tcx> {
Expand Down Expand Up @@ -1768,21 +1760,21 @@ pub fn is_useful<'p, 'a, 'tcx>(

/// A shorthand for the `U(S(c, P), S(c, q))` operation from the paper. I.e., `is_useful` applied
/// to the specialised version of both the pattern matrix `P` and the new pattern `q`.
fn is_useful_specialized<'p, 'a, 'tcx>(
cx: &mut MatchCheckCtxt<'a, 'tcx>,
fn is_useful_specialized<'p, 'tcx>(
cx: &mut MatchCheckCtxt<'p, 'tcx>,
matrix: &Matrix<'p, 'tcx>,
v: &PatStack<'_, 'tcx>,
v: &PatStack<'p, 'tcx>,
ctor: Constructor<'tcx>,
lty: Ty<'tcx>,
witness_preference: WitnessPreference,
hir_id: HirId,
) -> Usefulness<'tcx> {
debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty);

let ctor_wild_subpatterns_owned: Vec<_> = ctor.wildcard_subpatterns(cx, lty);
let ctor_wild_subpatterns: Vec<_> = ctor_wild_subpatterns_owned.iter().collect();
let matrix = matrix.specialize_constructor(cx, &ctor, &ctor_wild_subpatterns);
v.specialize_constructor(cx, &ctor, &ctor_wild_subpatterns)
let ctor_wild_subpatterns =
cx.pattern_arena.alloc_from_iter(ctor.wildcard_subpatterns(cx, lty));
let matrix = matrix.specialize_constructor(cx, &ctor, ctor_wild_subpatterns);
v.specialize_constructor(cx, &ctor, ctor_wild_subpatterns)
.map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id))
.map(|u| u.apply_constructor(cx, &ctor, lty))
.unwrap_or(NotUseful)
Expand Down Expand Up @@ -2250,13 +2242,13 @@ fn constructor_covered_by_range<'tcx>(
if intersects { Some(()) } else { None }
}

fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
cx: &mut MatchCheckCtxt<'a, 'tcx>,
fn patterns_for_variant<'p, 'tcx>(
cx: &mut MatchCheckCtxt<'p, 'tcx>,
subpatterns: &'p [FieldPat<'tcx>],
ctor_wild_subpatterns: &[&'p Pat<'tcx>],
ctor_wild_subpatterns: &'p [Pat<'tcx>],
is_non_exhaustive: bool,
) -> PatStack<'p, 'tcx> {
let mut result = SmallVec::from_slice(ctor_wild_subpatterns);
let mut result: SmallVec<_> = ctor_wild_subpatterns.iter().collect();

for subpat in subpatterns {
if !is_non_exhaustive || !cx.is_uninhabited(subpat.pattern.ty) {
Expand All @@ -2280,11 +2272,11 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
/// different patterns.
/// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
/// fields filled with wild patterns.
fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
cx: &mut MatchCheckCtxt<'a, 'tcx>,
pat: &'q Pat<'tcx>,
fn specialize_one_pattern<'p, 'tcx>(
cx: &mut MatchCheckCtxt<'p, 'tcx>,
pat: &'p Pat<'tcx>,
constructor: &Constructor<'tcx>,
ctor_wild_subpatterns: &[&'p Pat<'tcx>],
ctor_wild_subpatterns: &'p [Pat<'tcx>],
) -> Option<PatStack<'p, 'tcx>> {
if let NonExhaustive = constructor {
// Only a wildcard pattern can match the special extra constructor
Expand All @@ -2294,9 +2286,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
let result = match *pat.kind {
PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`

PatKind::Binding { .. } | PatKind::Wild => {
Some(PatStack::from_slice(ctor_wild_subpatterns))
}
PatKind::Binding { .. } | PatKind::Wild => Some(ctor_wild_subpatterns.iter().collect()),

PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
let ref variant = adt_def.variants[variant_index];
Expand Down Expand Up @@ -2406,7 +2396,6 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
.chain(
ctor_wild_subpatterns
.iter()
.map(|p| *p)
.skip(prefix.len())
.take(slice_count)
.chain(suffix.iter()),
Expand Down
22 changes: 11 additions & 11 deletions src/librustc_mir/hair/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,8 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
patcx.include_lint_checks();
let pattern = patcx.lower_pattern(pat);
let pattern_ty = pattern.ty;
let pattern = expand_pattern(cx, pattern);
let pats: Matrix<'_, '_> = vec![PatStack::from_pattern(&pattern)].into_iter().collect();
let pattern = cx.pattern_arena.alloc(expand_pattern(cx, pattern));
let pats: Matrix<'_, '_> = vec![PatStack::from_pattern(pattern)].into_iter().collect();

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

// Check for unreachable patterns
fn check_arms<'p, 'tcx>(
cx: &mut MatchCheckCtxt<'_, 'tcx>,
cx: &mut MatchCheckCtxt<'p, 'tcx>,
arms: &[(Vec<(&'p super::Pat<'tcx>, &hir::Pat)>, Option<&hir::Expr>)],
source: hir::MatchSource,
) -> Matrix<'p, 'tcx> {
Expand Down Expand Up @@ -482,14 +482,14 @@ fn check_arms<'p, 'tcx>(
seen
}

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

fn check_exhaustive<'tcx>(
cx: &mut MatchCheckCtxt<'_, 'tcx>,
fn check_exhaustive<'p, 'tcx>(
cx: &mut MatchCheckCtxt<'p, 'tcx>,
scrut_ty: Ty<'tcx>,
sp: Span,
matrix: &Matrix<'_, 'tcx>,
matrix: &Matrix<'p, 'tcx>,
hir_id: HirId,
) {
let witnesses = match check_not_useful(cx, scrut_ty, matrix, hir_id) {
Expand Down

0 comments on commit e6aa962

Please sign in to comment.