@@ -151,7 +151,9 @@ pub struct ObligationForest<O: ForestObligation> {
151
151
/// A cache of predicates that have been successfully completed.
152
152
done_cache : FxHashSet < O :: Predicate > ,
153
153
154
- /// An cache of the nodes in `nodes`, indexed by predicate.
154
+ /// A cache of the nodes in `nodes`, indexed by predicate. Unfortunately,
155
+ /// its contents are not guaranteed to match those of `nodes`. See the
156
+ /// comments in `process_obligation` for details.
155
157
waiting_cache : FxHashMap < O :: Predicate , NodeIndex > ,
156
158
157
159
scratch : Option < Vec < usize > > ,
@@ -394,6 +396,11 @@ impl<O: ForestObligation> ObligationForest<O> {
394
396
395
397
debug ! ( "process_obligations: node {} == {:?}" , i, node) ;
396
398
399
+ // `processor.process_obligation` can modify the predicate within
400
+ // `node.obligation`, and that predicate is the key used for
401
+ // `self.waiting_cache`. This means that `self.waiting_cache` can
402
+ // get out of sync with `nodes`. It's not very common, but it does
403
+ // happen, and code in `compress` has to allow for it.
397
404
let result = match node. state . get ( ) {
398
405
NodeState :: Pending => processor. process_obligation ( & mut node. obligation ) ,
399
406
_ => continue
@@ -621,7 +628,10 @@ impl<O: ForestObligation> ObligationForest<O> {
621
628
}
622
629
}
623
630
NodeState :: Done => {
624
- // Avoid cloning the key (predicate) in case it exists in the waiting cache
631
+ // This lookup can fail because the contents of
632
+ // `self.waiting_cache` is not guaranteed to match those of
633
+ // `self.nodes`. See the comment in `process_obligation`
634
+ // for more details.
625
635
if let Some ( ( predicate, _) ) = self . waiting_cache
626
636
. remove_entry ( node. obligation . as_predicate ( ) )
627
637
{
@@ -703,6 +713,8 @@ impl<O: ForestObligation> ObligationForest<O> {
703
713
}
704
714
}
705
715
716
+ // This updating of `self.waiting_cache` is necessary because the
717
+ // removal of nodes within `compress` can fail. See above.
706
718
let mut kill_list = vec ! [ ] ;
707
719
for ( predicate, index) in & mut self . waiting_cache {
708
720
let new_i = node_rewrites[ index. index ( ) ] ;
0 commit comments