@@ -76,7 +76,7 @@ use crate::fx::{FxHashMap, FxHashSet};
7676use crate :: indexed_vec:: Idx ;
7777use crate :: newtype_index;
7878
79- use std:: cell:: Cell ;
79+ use std:: cell:: { Cell , RefCell } ;
8080use std:: collections:: hash_map:: Entry ;
8181use std:: fmt:: Debug ;
8282use std:: hash;
@@ -156,7 +156,9 @@ pub struct ObligationForest<O: ForestObligation> {
156156 /// comments in `process_obligation` for details.
157157 waiting_cache : FxHashMap < O :: Predicate , NodeIndex > ,
158158
159- scratch : Option < Vec < usize > > ,
159+ /// A scratch vector reused in various operations, to avoid allocating new
160+ /// vectors.
161+ scratch : RefCell < Vec < usize > > ,
160162
161163 obligation_tree_id_generator : ObligationTreeIdGenerator ,
162164
@@ -265,7 +267,7 @@ impl<O: ForestObligation> ObligationForest<O> {
265267 nodes : vec ! [ ] ,
266268 done_cache : Default :: default ( ) ,
267269 waiting_cache : Default :: default ( ) ,
268- scratch : Some ( vec ! [ ] ) ,
270+ scratch : RefCell :: new ( vec ! [ ] ) ,
269271 obligation_tree_id_generator : ( 0 ..) . map ( ObligationTreeId ) ,
270272 error_cache : Default :: default ( ) ,
271273 }
@@ -345,8 +347,8 @@ impl<O: ForestObligation> ObligationForest<O> {
345347 /// Converts all remaining obligations to the given error.
346348 pub fn to_errors < E : Clone > ( & mut self , error : E ) -> Vec < Error < O , E > > {
347349 let mut errors = vec ! [ ] ;
348- for i in 0 .. self . nodes . len ( ) {
349- if let NodeState :: Pending = self . nodes [ i ] . state . get ( ) {
350+ for ( i , node ) in self . nodes . iter ( ) . enumerate ( ) {
351+ if let NodeState :: Pending = node . state . get ( ) {
350352 let backtrace = self . error_at ( i) ;
351353 errors. push ( Error {
352354 error : error. clone ( ) ,
@@ -469,20 +471,20 @@ impl<O: ForestObligation> ObligationForest<O> {
469471 /// report all cycles between them. This should be called
470472 /// after `mark_as_waiting` marks all nodes with pending
471473 /// subobligations as NodeState::Waiting.
472- fn process_cycles < P > ( & mut self , processor : & mut P )
474+ fn process_cycles < P > ( & self , processor : & mut P )
473475 where P : ObligationProcessor < Obligation =O >
474476 {
475- let mut stack = self . scratch . take ( ) . unwrap ( ) ;
477+ let mut stack = self . scratch . replace ( vec ! [ ] ) ;
476478 debug_assert ! ( stack. is_empty( ) ) ;
477479
478480 debug ! ( "process_cycles()" ) ;
479481
480- for i in 0 .. self . nodes . len ( ) {
482+ for ( i , node ) in self . nodes . iter ( ) . enumerate ( ) {
481483 // For rustc-benchmarks/inflate-0.1.0 this state test is extremely
482484 // hot and the state is almost always `Pending` or `Waiting`. It's
483485 // a win to handle the no-op cases immediately to avoid the cost of
484486 // the function call.
485- match self . nodes [ i ] . state . get ( ) {
487+ match node . state . get ( ) {
486488 NodeState :: Waiting | NodeState :: Pending | NodeState :: Done | NodeState :: Error => { } ,
487489 _ => self . find_cycles_from_node ( & mut stack, processor, i) ,
488490 }
@@ -491,7 +493,7 @@ impl<O: ForestObligation> ObligationForest<O> {
491493 debug ! ( "process_cycles: complete" ) ;
492494
493495 debug_assert ! ( stack. is_empty( ) ) ;
494- self . scratch = Some ( stack) ;
496+ self . scratch . replace ( stack) ;
495497 }
496498
497499 fn find_cycles_from_node < P > ( & self , stack : & mut Vec < usize > , processor : & mut P , i : usize )
@@ -525,8 +527,8 @@ impl<O: ForestObligation> ObligationForest<O> {
525527
526528 /// Returns a vector of obligations for `p` and all of its
527529 /// ancestors, putting them into the error state in the process.
528- fn error_at ( & mut self , mut i : usize ) -> Vec < O > {
529- let mut error_stack = self . scratch . take ( ) . unwrap ( ) ;
530+ fn error_at ( & self , mut i : usize ) -> Vec < O > {
531+ let mut error_stack = self . scratch . replace ( vec ! [ ] ) ;
530532 let mut trace = vec ! [ ] ;
531533
532534 loop {
@@ -554,7 +556,7 @@ impl<O: ForestObligation> ObligationForest<O> {
554556 ) ;
555557 }
556558
557- self . scratch = Some ( error_stack) ;
559+ self . scratch . replace ( error_stack) ;
558560 trace
559561 }
560562
@@ -608,7 +610,7 @@ impl<O: ForestObligation> ObligationForest<O> {
608610 #[ inline( never) ]
609611 fn compress ( & mut self , do_completed : DoCompleted ) -> Option < Vec < O > > {
610612 let nodes_len = self . nodes . len ( ) ;
611- let mut node_rewrites: Vec < _ > = self . scratch . take ( ) . unwrap ( ) ;
613+ let mut node_rewrites: Vec < _ > = self . scratch . replace ( vec ! [ ] ) ;
612614 node_rewrites. extend ( 0 ..nodes_len) ;
613615 let mut dead_nodes = 0 ;
614616
@@ -658,7 +660,7 @@ impl<O: ForestObligation> ObligationForest<O> {
658660 // No compression needed.
659661 if dead_nodes == 0 {
660662 node_rewrites. truncate ( 0 ) ;
661- self . scratch = Some ( node_rewrites) ;
663+ self . scratch . replace ( node_rewrites) ;
662664 return if do_completed == DoCompleted :: Yes { Some ( vec ! [ ] ) } else { None } ;
663665 }
664666
@@ -682,7 +684,7 @@ impl<O: ForestObligation> ObligationForest<O> {
682684 self . apply_rewrites ( & node_rewrites) ;
683685
684686 node_rewrites. truncate ( 0 ) ;
685- self . scratch = Some ( node_rewrites) ;
687+ self . scratch . replace ( node_rewrites) ;
686688
687689 successful
688690 }
0 commit comments