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 https://github.com/servo/rust-smallvec/issues/146).
This commit is contained in:
parent
21af89d773
commit
e6aa96246f
2 changed files with 38 additions and 49 deletions
|
@ -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..]);
|
||||
|
@ -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))
|
||||
|
@ -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> {
|
||||
|
@ -1768,10 +1760,10 @@ 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,
|
||||
|
@ -1779,10 +1771,10 @@ fn is_useful_specialized<'p, 'a, 'tcx>(
|
|||
) -> 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)
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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()),
|
||||
|
|
|
@ -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,
|
||||
|
@ -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> {
|
||||
|
@ -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")
|
||||
|
@ -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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue