@@ -248,6 +248,7 @@ use syntax_pos::{Span, DUMMY_SP};
248
248
use arena:: TypedArena ;
249
249
250
250
use smallvec:: { smallvec, SmallVec } ;
251
+ use std:: cell:: RefCell ;
251
252
use std:: cmp:: { self , max, min, Ordering } ;
252
253
use std:: convert:: TryInto ;
253
254
use std:: fmt;
@@ -339,6 +340,9 @@ impl PatternFolder<'tcx> for LiteralExpander<'tcx> {
339
340
#[ derive( Debug , Clone ) ]
340
341
pub struct PatStack < ' p , ' tcx > {
341
342
patterns : SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ,
343
+ // 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 ] > > > ,
342
346
}
343
347
344
348
impl < ' p , ' tcx > PatStack < ' p , ' tcx > {
@@ -351,7 +355,7 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
351
355
}
352
356
353
357
fn from_vec ( vec : SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ) -> Self {
354
- PatStack { patterns : vec }
358
+ PatStack { patterns : vec, head_ctors_cache : RefCell :: new ( None ) }
355
359
}
356
360
357
361
fn from_slice ( s : & [ & ' p Pat < ' tcx > ] ) -> Self {
@@ -371,7 +375,18 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
371
375
}
372
376
373
377
fn head_ctors ( & self , cx : & MatchCheckCtxt < ' _ , ' tcx > ) -> SmallVec < [ Constructor < ' tcx > ; 1 ] > {
374
- pat_constructors ( cx. tcx , cx. param_env , self . head ( ) )
378
+ 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
+ }
389
+ new_ctors
375
390
}
376
391
377
392
fn iter ( & self ) -> impl Iterator < Item = & Pat < ' tcx > > {
@@ -392,9 +407,10 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
392
407
let new_heads = specialize_one_pattern ( cx, self . head ( ) , constructor, ctor_wild_subpatterns) ;
393
408
let result = new_heads
394
409
. into_iter ( )
395
- . map ( |mut new_head| {
396
- new_head. patterns . extend_from_slice ( & self . patterns [ 1 ..] ) ;
397
- new_head
410
+ . map ( |new_head| {
411
+ let mut pats = new_head. patterns ;
412
+ pats. extend_from_slice ( & self . patterns [ 1 ..] ) ;
413
+ PatStack :: from_vec ( pats)
398
414
} )
399
415
. collect ( ) ;
400
416
debug ! ( "specialize({:#?}, {:#?}) = {:#?}" , self , constructor, result) ;
0 commit comments