@@ -248,7 +248,6 @@ use syntax_pos::{Span, DUMMY_SP};
248248use arena:: TypedArena ;
249249
250250use smallvec:: { smallvec, SmallVec } ;
251- use std:: cell:: RefCell ;
252251use std:: cmp:: { self , max, min, Ordering } ;
253252use std:: convert:: TryInto ;
254253use std:: fmt;
@@ -341,25 +340,30 @@ impl PatternFolder<'tcx> for LiteralExpander<'tcx> {
341340pub 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
348348impl < ' 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.
437423pub struct Matrix < ' p , ' tcx > ( Vec < PatStack < ' p , ' tcx > > ) ;
438424
@@ -1987,6 +1973,7 @@ fn constructor_intersects_pattern<'p, 'tcx>(
19871973}
19881974
19891975fn 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 }
0 commit comments