@@ -248,7 +248,6 @@ use syntax_pos::{Span, DUMMY_SP};
248
248
use arena:: TypedArena ;
249
249
250
250
use smallvec:: { smallvec, SmallVec } ;
251
- use std:: cell:: RefCell ;
252
251
use std:: cmp:: { self , max, min, Ordering } ;
253
252
use std:: convert:: TryInto ;
254
253
use std:: fmt;
@@ -341,25 +340,30 @@ impl PatternFolder<'tcx> for LiteralExpander<'tcx> {
341
340
pub struct PatStack < ' p , ' tcx > {
342
341
patterns : SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ,
343
342
// 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 ] > ,
346
346
}
347
347
348
348
impl < ' 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] )
351
351
}
352
352
353
353
fn empty ( ) -> Self {
354
- PatStack :: from_vec ( smallvec ! [ ] )
354
+ PatStack { patterns : smallvec ! [ ] , head_ctors_cache : smallvec ! [ ] }
355
355
}
356
356
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 }
359
363
}
360
364
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) )
363
367
}
364
368
365
369
fn is_empty ( & self ) -> bool {
@@ -376,16 +380,7 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
376
380
377
381
fn head_ctors ( & self , cx : & MatchCheckCtxt < ' _ , ' tcx > ) -> SmallVec < [ Constructor < ' tcx > ; 1 ] > {
378
382
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) ;
389
384
new_ctors
390
385
}
391
386
@@ -410,7 +405,7 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
410
405
. map ( |new_head| {
411
406
let mut pats = new_head. patterns ;
412
407
pats. extend_from_slice ( & self . patterns [ 1 ..] ) ;
413
- PatStack :: from_vec ( pats)
408
+ PatStack :: from_vec ( cx , pats)
414
409
} )
415
410
. collect ( ) ;
416
411
debug ! ( "specialize({:#?}, {:#?}) = {:#?}" , self , constructor, result) ;
@@ -424,15 +419,6 @@ impl<'p, 'tcx> Default for PatStack<'p, 'tcx> {
424
419
}
425
420
}
426
421
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
-
436
422
/// A 2D matrix.
437
423
pub struct Matrix < ' p , ' tcx > ( Vec < PatStack < ' p , ' tcx > > ) ;
438
424
@@ -1987,6 +1973,7 @@ fn constructor_intersects_pattern<'p, 'tcx>(
1987
1973
}
1988
1974
1989
1975
fn patterns_for_variant < ' p , ' tcx > (
1976
+ cx : & MatchCheckCtxt < ' _ , ' tcx > ,
1990
1977
subpatterns : & ' p [ FieldPat < ' tcx > ] ,
1991
1978
ctor_wild_subpatterns : & [ & ' p Pat < ' tcx > ] ,
1992
1979
) -> PatStack < ' p , ' tcx > {
@@ -2000,7 +1987,7 @@ fn patterns_for_variant<'p, 'tcx>(
2000
1987
"patterns_for_variant({:#?}, {:#?}) = {:#?}" ,
2001
1988
subpatterns, ctor_wild_subpatterns, result
2002
1989
) ;
2003
- PatStack :: from_vec ( result)
1990
+ PatStack :: from_vec ( cx , result)
2004
1991
}
2005
1992
2006
1993
/// 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>(
2037
2024
PatKind :: AscribeUserType { .. } => unreachable ! ( ) , // Handled above
2038
2025
2039
2026
PatKind :: Binding { .. } | PatKind :: Wild => {
2040
- smallvec ! [ PatStack :: from_slice( ctor_wild_subpatterns) ]
2027
+ smallvec ! [ PatStack :: from_slice( cx , ctor_wild_subpatterns) ]
2041
2028
}
2042
2029
2043
2030
PatKind :: Variant { adt_def, variant_index, ref subpatterns, .. } => {
2044
2031
let ref variant = adt_def. variants [ variant_index] ;
2045
2032
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) ]
2047
2034
} else {
2048
2035
smallvec ! [ ]
2049
2036
}
2050
2037
}
2051
2038
2052
2039
PatKind :: Leaf { ref subpatterns } => {
2053
- smallvec ! [ patterns_for_variant( subpatterns, ctor_wild_subpatterns) ]
2040
+ smallvec ! [ patterns_for_variant( cx , subpatterns, ctor_wild_subpatterns) ]
2054
2041
}
2055
2042
2056
- PatKind :: Deref { ref subpattern } => smallvec ! [ PatStack :: from_pattern( subpattern) ] ,
2043
+ PatKind :: Deref { ref subpattern } => smallvec ! [ PatStack :: from_pattern( cx , subpattern) ] ,
2057
2044
2058
2045
PatKind :: Constant { value } if constructor. is_slice ( ) => {
2059
2046
// 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>(
2098
2085
return smallvec ! [ ] ;
2099
2086
} ;
2100
2087
let ptr = Pointer :: new ( AllocId ( 0 ) , offset) ;
2101
- let stack: Option < PatStack < ' _ , ' _ > > = ( 0 ..n)
2088
+ let stack: Option < SmallVec < _ > > = ( 0 ..n)
2102
2089
. map ( |i| {
2103
2090
let ptr = ptr. offset ( layout. size * i, & cx. tcx ) . ok ( ) ?;
2104
2091
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>(
2109
2096
Some ( & * cx. pattern_arena . alloc ( pattern) )
2110
2097
} )
2111
2098
. collect ( ) ;
2112
- stack. into_iter ( ) . collect ( )
2099
+ match stack {
2100
+ Some ( v) => smallvec ! [ PatStack :: from_vec( cx, v) ] ,
2101
+ None => smallvec ! [ ] ,
2102
+ }
2113
2103
} else {
2114
2104
smallvec ! [ ]
2115
2105
}
@@ -2132,7 +2122,8 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
2132
2122
let pat_len = prefix. len ( ) + suffix. len ( ) ;
2133
2123
if let Some ( slice_count) = ctor_wild_subpatterns. len ( ) . checked_sub ( pat_len) {
2134
2124
if slice_count == 0 || slice. is_some ( ) {
2135
- smallvec ! [
2125
+ smallvec ! [ PatStack :: from_vec(
2126
+ cx,
2136
2127
prefix
2137
2128
. iter( )
2138
2129
. chain(
@@ -2144,7 +2135,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
2144
2135
. chain( suffix. iter( ) ) ,
2145
2136
)
2146
2137
. collect( ) ,
2147
- ]
2138
+ ) ]
2148
2139
} else {
2149
2140
smallvec ! [ ]
2150
2141
}
0 commit comments