@@ -137,13 +137,10 @@ pub struct ObligationForest<O: ForestObligation> {
137
137
/// significant, and space considerations are not important.
138
138
nodes : Vec < Node < O > > ,
139
139
140
- /// A cache of predicates that have been successfully completed.
141
- done_cache : FxHashSet < O :: Predicate > ,
142
-
143
140
/// A cache of the nodes in `nodes`, indexed by predicate. Unfortunately,
144
141
/// its contents are not guaranteed to match those of `nodes`. See the
145
142
/// comments in `process_obligation` for details.
146
- active_cache : FxHashMap < O :: Predicate , usize > ,
143
+ active_cache : FxHashMap < O :: Predicate , Option < usize > > ,
147
144
148
145
/// A vector reused in compress(), to avoid allocating new vectors.
149
146
node_rewrites : RefCell < Vec < usize > > ,
@@ -283,7 +280,6 @@ impl<O: ForestObligation> ObligationForest<O> {
283
280
pub fn new ( ) -> ObligationForest < O > {
284
281
ObligationForest {
285
282
nodes : vec ! [ ] ,
286
- done_cache : Default :: default ( ) ,
287
283
active_cache : Default :: default ( ) ,
288
284
node_rewrites : RefCell :: new ( vec ! [ ] ) ,
289
285
obligation_tree_id_generator : ( 0 ..) . map ( ObligationTreeId ) ,
@@ -305,13 +301,13 @@ impl<O: ForestObligation> ObligationForest<O> {
305
301
306
302
// Returns Err(()) if we already know this obligation failed.
307
303
fn register_obligation_at ( & mut self , obligation : O , parent : Option < usize > ) -> Result < ( ) , ( ) > {
308
- if self . done_cache . contains ( obligation. as_predicate ( ) ) {
309
- return Ok ( ( ) ) ;
310
- }
311
-
312
304
match self . active_cache . entry ( obligation. as_predicate ( ) . clone ( ) ) {
313
305
Entry :: Occupied ( o) => {
314
- let node = & mut self . nodes [ * o. get ( ) ] ;
306
+ let index = match o. get ( ) {
307
+ Some ( index) => * index,
308
+ None => return Ok ( ( ) ) , // Done!
309
+ } ;
310
+ let node = & mut self . nodes [ index] ;
315
311
if let Some ( parent_index) = parent {
316
312
// If the node is already in `active_cache`, it has already
317
313
// had its chance to be marked with a parent. So if it's
@@ -340,7 +336,7 @@ impl<O: ForestObligation> ObligationForest<O> {
340
336
Err ( ( ) )
341
337
} else {
342
338
let new_index = self . nodes . len ( ) ;
343
- v. insert ( new_index) ;
339
+ v. insert ( Some ( new_index) ) ;
344
340
self . nodes . push ( Node :: new ( parent, obligation, obligation_tree_id) ) ;
345
341
Ok ( ( ) )
346
342
}
@@ -576,7 +572,7 @@ impl<O: ForestObligation> ObligationForest<O> {
576
572
Some ( rpos) => {
577
573
// Cycle detected.
578
574
processor. process_backedge (
579
- stack[ rpos..] . iter ( ) . map ( GetObligation ( & self . nodes ) ) ,
575
+ stack[ rpos..] . iter ( ) . map ( |i| & self . nodes [ * i ] . obligation ) ,
580
576
PhantomData ,
581
577
) ;
582
578
}
@@ -590,6 +586,7 @@ impl<O: ForestObligation> ObligationForest<O> {
590
586
#[ inline( never) ]
591
587
fn compress ( & mut self , do_completed : DoCompleted ) -> Option < Vec < O > > {
592
588
let orig_nodes_len = self . nodes . len ( ) ;
589
+ let remove_node_marker = orig_nodes_len + 1 ;
593
590
let mut node_rewrites: Vec < _ > = self . node_rewrites . replace ( vec ! [ ] ) ;
594
591
debug_assert ! ( node_rewrites. is_empty( ) ) ;
595
592
node_rewrites. extend ( 0 ..orig_nodes_len) ;
@@ -613,17 +610,6 @@ impl<O: ForestObligation> ObligationForest<O> {
613
610
}
614
611
}
615
612
NodeState :: Done => {
616
- // This lookup can fail because the contents of
617
- // `self.active_cache` are not guaranteed to match those of
618
- // `self.nodes`. See the comment in `process_obligation`
619
- // for more details.
620
- if let Some ( ( predicate, _) ) =
621
- self . active_cache . remove_entry ( node. obligation . as_predicate ( ) )
622
- {
623
- self . done_cache . insert ( predicate) ;
624
- } else {
625
- self . done_cache . insert ( node. obligation . as_predicate ( ) . clone ( ) ) ;
626
- }
627
613
if do_completed == DoCompleted :: Yes {
628
614
// Extract the success stories.
629
615
removed_done_obligations. push ( node. obligation . clone ( ) ) ;
@@ -637,7 +623,7 @@ impl<O: ForestObligation> ObligationForest<O> {
637
623
// check against.
638
624
self . active_cache . remove ( node. obligation . as_predicate ( ) ) ;
639
625
self . insert_into_error_cache ( index) ;
640
- node_rewrites[ index] = orig_nodes_len ;
626
+ node_rewrites[ index] = remove_node_marker ;
641
627
dead_nodes += 1 ;
642
628
}
643
629
NodeState :: Success => unreachable ! ( ) ,
@@ -658,6 +644,7 @@ impl<O: ForestObligation> ObligationForest<O> {
658
644
659
645
fn apply_rewrites ( & mut self , node_rewrites : & [ usize ] ) {
660
646
let orig_nodes_len = node_rewrites. len ( ) ;
647
+ let remove_node_marker = orig_nodes_len + 1 ;
661
648
662
649
for node in & mut self . nodes {
663
650
let mut i = 0 ;
@@ -678,31 +665,21 @@ impl<O: ForestObligation> ObligationForest<O> {
678
665
679
666
// This updating of `self.active_cache` is necessary because the
680
667
// removal of nodes within `compress` can fail. See above.
681
- self . active_cache . retain ( |_predicate, index| {
682
- let new_index = node_rewrites[ * index] ;
683
- if new_index >= orig_nodes_len {
684
- false
668
+ self . active_cache . retain ( |_predicate, opt_index| {
669
+ if let Some ( index) = opt_index {
670
+ let new_index = node_rewrites[ * index] ;
671
+ if new_index == orig_nodes_len {
672
+ * opt_index = None ;
673
+ true
674
+ } else if new_index == remove_node_marker {
675
+ false
676
+ } else {
677
+ * index = new_index;
678
+ true
679
+ }
685
680
} else {
686
- * index = new_index;
687
681
true
688
682
}
689
683
} ) ;
690
684
}
691
685
}
692
-
693
- // I need a Clone closure.
694
- #[ derive( Clone ) ]
695
- struct GetObligation < ' a , O > ( & ' a [ Node < O > ] ) ;
696
-
697
- impl < ' a , ' b , O > FnOnce < ( & ' b usize , ) > for GetObligation < ' a , O > {
698
- type Output = & ' a O ;
699
- extern "rust-call" fn call_once ( self , args : ( & ' b usize , ) ) -> & ' a O {
700
- & self . 0 [ * args. 0 ] . obligation
701
- }
702
- }
703
-
704
- impl < ' a , ' b , O > FnMut < ( & ' b usize , ) > for GetObligation < ' a , O > {
705
- extern "rust-call" fn call_mut ( & mut self , args : ( & ' b usize , ) ) -> & ' a O {
706
- & self . 0 [ * args. 0 ] . obligation
707
- }
708
- }
0 commit comments