@@ -248,6 +248,7 @@ use syntax_pos::{Span, DUMMY_SP};
248248use arena:: TypedArena ;
249249
250250use smallvec:: { smallvec, SmallVec } ;
251+ use std:: cell:: RefCell ;
251252use std:: cmp:: { self , max, min, Ordering } ;
252253use std:: convert:: TryInto ;
253254use std:: fmt;
@@ -339,6 +340,9 @@ impl PatternFolder<'tcx> for LiteralExpander<'tcx> {
339340#[ derive( Debug , Clone ) ]
340341pub struct PatStack < ' p , ' tcx > {
341342 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 ] > > > ,
342346}
343347
344348impl < ' p , ' tcx > PatStack < ' p , ' tcx > {
@@ -351,7 +355,7 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
351355 }
352356
353357 fn from_vec ( vec : SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ) -> Self {
354- PatStack { patterns : vec }
358+ PatStack { patterns : vec, head_ctors_cache : RefCell :: new ( None ) }
355359 }
356360
357361 fn from_slice ( s : & [ & ' p Pat < ' tcx > ] ) -> Self {
@@ -371,7 +375,18 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
371375 }
372376
373377 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
375390 }
376391
377392 fn iter ( & self ) -> impl Iterator < Item = & Pat < ' tcx > > {
@@ -392,9 +407,10 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
392407 let new_heads = specialize_one_pattern ( cx, self . head ( ) , constructor, ctor_wild_subpatterns) ;
393408 let result = new_heads
394409 . 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)
398414 } )
399415 . collect ( ) ;
400416 debug ! ( "specialize({:#?}, {:#?}) = {:#?}" , self , constructor, result) ;
0 commit comments