@@ -76,7 +76,7 @@ use crate::fx::{FxHashMap, FxHashSet};
76
76
use crate :: indexed_vec:: Idx ;
77
77
use crate :: newtype_index;
78
78
79
- use std:: cell:: Cell ;
79
+ use std:: cell:: { Cell , RefCell } ;
80
80
use std:: collections:: hash_map:: Entry ;
81
81
use std:: fmt:: Debug ;
82
82
use std:: hash;
@@ -156,7 +156,9 @@ pub struct ObligationForest<O: ForestObligation> {
156
156
/// comments in `process_obligation` for details.
157
157
waiting_cache : FxHashMap < O :: Predicate , NodeIndex > ,
158
158
159
- scratch : Option < Vec < usize > > ,
159
+ /// A scratch vector reused in various operations, to avoid allocating new
160
+ /// vectors.
161
+ scratch : RefCell < Vec < usize > > ,
160
162
161
163
obligation_tree_id_generator : ObligationTreeIdGenerator ,
162
164
@@ -265,7 +267,7 @@ impl<O: ForestObligation> ObligationForest<O> {
265
267
nodes : vec ! [ ] ,
266
268
done_cache : Default :: default ( ) ,
267
269
waiting_cache : Default :: default ( ) ,
268
- scratch : Some ( vec ! [ ] ) ,
270
+ scratch : RefCell :: new ( vec ! [ ] ) ,
269
271
obligation_tree_id_generator : ( 0 ..) . map ( ObligationTreeId ) ,
270
272
error_cache : Default :: default ( ) ,
271
273
}
@@ -345,8 +347,8 @@ impl<O: ForestObligation> ObligationForest<O> {
345
347
/// Converts all remaining obligations to the given error.
346
348
pub fn to_errors < E : Clone > ( & mut self , error : E ) -> Vec < Error < O , E > > {
347
349
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 ( ) {
350
352
let backtrace = self . error_at ( i) ;
351
353
errors. push ( Error {
352
354
error : error. clone ( ) ,
@@ -469,20 +471,20 @@ impl<O: ForestObligation> ObligationForest<O> {
469
471
/// report all cycles between them. This should be called
470
472
/// after `mark_as_waiting` marks all nodes with pending
471
473
/// subobligations as NodeState::Waiting.
472
- fn process_cycles < P > ( & mut self , processor : & mut P )
474
+ fn process_cycles < P > ( & self , processor : & mut P )
473
475
where P : ObligationProcessor < Obligation =O >
474
476
{
475
- let mut stack = self . scratch . take ( ) . unwrap ( ) ;
477
+ let mut stack = self . scratch . replace ( vec ! [ ] ) ;
476
478
debug_assert ! ( stack. is_empty( ) ) ;
477
479
478
480
debug ! ( "process_cycles()" ) ;
479
481
480
- for i in 0 .. self . nodes . len ( ) {
482
+ for ( i , node ) in self . nodes . iter ( ) . enumerate ( ) {
481
483
// For rustc-benchmarks/inflate-0.1.0 this state test is extremely
482
484
// hot and the state is almost always `Pending` or `Waiting`. It's
483
485
// a win to handle the no-op cases immediately to avoid the cost of
484
486
// the function call.
485
- match self . nodes [ i ] . state . get ( ) {
487
+ match node . state . get ( ) {
486
488
NodeState :: Waiting | NodeState :: Pending | NodeState :: Done | NodeState :: Error => { } ,
487
489
_ => self . find_cycles_from_node ( & mut stack, processor, i) ,
488
490
}
@@ -491,7 +493,7 @@ impl<O: ForestObligation> ObligationForest<O> {
491
493
debug ! ( "process_cycles: complete" ) ;
492
494
493
495
debug_assert ! ( stack. is_empty( ) ) ;
494
- self . scratch = Some ( stack) ;
496
+ self . scratch . replace ( stack) ;
495
497
}
496
498
497
499
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> {
525
527
526
528
/// Returns a vector of obligations for `p` and all of its
527
529
/// 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 ! [ ] ) ;
530
532
let mut trace = vec ! [ ] ;
531
533
532
534
loop {
@@ -554,7 +556,7 @@ impl<O: ForestObligation> ObligationForest<O> {
554
556
) ;
555
557
}
556
558
557
- self . scratch = Some ( error_stack) ;
559
+ self . scratch . replace ( error_stack) ;
558
560
trace
559
561
}
560
562
@@ -608,7 +610,7 @@ impl<O: ForestObligation> ObligationForest<O> {
608
610
#[ inline( never) ]
609
611
fn compress ( & mut self , do_completed : DoCompleted ) -> Option < Vec < O > > {
610
612
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 ! [ ] ) ;
612
614
node_rewrites. extend ( 0 ..nodes_len) ;
613
615
let mut dead_nodes = 0 ;
614
616
@@ -658,7 +660,7 @@ impl<O: ForestObligation> ObligationForest<O> {
658
660
// No compression needed.
659
661
if dead_nodes == 0 {
660
662
node_rewrites. truncate ( 0 ) ;
661
- self . scratch = Some ( node_rewrites) ;
663
+ self . scratch . replace ( node_rewrites) ;
662
664
return if do_completed == DoCompleted :: Yes { Some ( vec ! [ ] ) } else { None } ;
663
665
}
664
666
@@ -682,7 +684,7 @@ impl<O: ForestObligation> ObligationForest<O> {
682
684
self . apply_rewrites ( & node_rewrites) ;
683
685
684
686
node_rewrites. truncate ( 0 ) ;
685
- self . scratch = Some ( node_rewrites) ;
687
+ self . scratch . replace ( node_rewrites) ;
686
688
687
689
successful
688
690
}
0 commit comments