From e6aa96246fe6125dae72d2840749f2859b49a47f Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 28 Nov 2019 13:03:02 +0000 Subject: [PATCH] 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). --- src/librustc_mir/hair/pattern/_match.rs | 65 ++++++++------------ src/librustc_mir/hair/pattern/check_match.rs | 22 +++---- 2 files changed, 38 insertions(+), 49 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index f2c5bf1bf6d55..e2ed925047442 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -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> - where - 'a: 'q, - 'p: 'q, - { + ctor_wild_subpatterns: &'p [Pat<'tcx>], + ) -> Option> { 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> { 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()), diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 56f0ace489180..62bc04b65f34f 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -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>> { - 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) {