@@ -86,9 +86,13 @@ mod graphviz;
86
86
mod tests;
87
87
88
88
pub trait ForestObligation : Clone + Debug {
89
- type Predicate : Clone + hash:: Hash + Eq + Debug ;
89
+ type CacheKey : Clone + hash:: Hash + Eq + Debug ;
90
90
91
- fn as_predicate ( & self ) -> & Self :: Predicate ;
91
+ /// Converts this `ForestObligation` suitable for use as a cache key.
92
+ /// If two distinct `ForestObligations`s return the same cache key,
93
+ /// then it must be sound to use the result of processing one obligation
94
+ /// (e.g. success for error) for the other obligation
95
+ fn as_cache_key ( & self ) -> Self :: CacheKey ;
92
96
}
93
97
94
98
pub trait ObligationProcessor {
@@ -138,12 +142,12 @@ pub struct ObligationForest<O: ForestObligation> {
138
142
nodes : Vec < Node < O > > ,
139
143
140
144
/// A cache of predicates that have been successfully completed.
141
- done_cache : FxHashSet < O :: Predicate > ,
145
+ done_cache : FxHashSet < O :: CacheKey > ,
142
146
143
147
/// A cache of the nodes in `nodes`, indexed by predicate. Unfortunately,
144
148
/// its contents are not guaranteed to match those of `nodes`. See the
145
149
/// comments in `process_obligation` for details.
146
- active_cache : FxHashMap < O :: Predicate , usize > ,
150
+ active_cache : FxHashMap < O :: CacheKey , usize > ,
147
151
148
152
/// A vector reused in compress(), to avoid allocating new vectors.
149
153
node_rewrites : RefCell < Vec < usize > > ,
@@ -157,7 +161,7 @@ pub struct ObligationForest<O: ForestObligation> {
157
161
/// See [this][details] for details.
158
162
///
159
163
/// [details]: https://github.com/rust-lang/rust/pull/53255#issuecomment-421184780
160
- error_cache : FxHashMap < ObligationTreeId , FxHashSet < O :: Predicate > > ,
164
+ error_cache : FxHashMap < ObligationTreeId , FxHashSet < O :: CacheKey > > ,
161
165
}
162
166
163
167
#[ derive( Debug ) ]
@@ -305,11 +309,12 @@ impl<O: ForestObligation> ObligationForest<O> {
305
309
306
310
// Returns Err(()) if we already know this obligation failed.
307
311
fn register_obligation_at ( & mut self , obligation : O , parent : Option < usize > ) -> Result < ( ) , ( ) > {
308
- if self . done_cache . contains ( obligation. as_predicate ( ) ) {
312
+ if self . done_cache . contains ( & obligation. as_cache_key ( ) ) {
313
+ debug ! ( "register_obligation_at: ignoring already done obligation: {:?}" , obligation) ;
309
314
return Ok ( ( ) ) ;
310
315
}
311
316
312
- match self . active_cache . entry ( obligation. as_predicate ( ) . clone ( ) ) {
317
+ match self . active_cache . entry ( obligation. as_cache_key ( ) . clone ( ) ) {
313
318
Entry :: Occupied ( o) => {
314
319
let node = & mut self . nodes [ * o. get ( ) ] ;
315
320
if let Some ( parent_index) = parent {
@@ -333,7 +338,7 @@ impl<O: ForestObligation> ObligationForest<O> {
333
338
&& self
334
339
. error_cache
335
340
. get ( & obligation_tree_id)
336
- . map ( |errors| errors. contains ( obligation. as_predicate ( ) ) )
341
+ . map ( |errors| errors. contains ( & obligation. as_cache_key ( ) ) )
337
342
. unwrap_or ( false ) ;
338
343
339
344
if already_failed {
@@ -380,7 +385,7 @@ impl<O: ForestObligation> ObligationForest<O> {
380
385
self . error_cache
381
386
. entry ( node. obligation_tree_id )
382
387
. or_default ( )
383
- . insert ( node. obligation . as_predicate ( ) . clone ( ) ) ;
388
+ . insert ( node. obligation . as_cache_key ( ) . clone ( ) ) ;
384
389
}
385
390
386
391
/// Performs a pass through the obligation list. This must
@@ -618,11 +623,11 @@ impl<O: ForestObligation> ObligationForest<O> {
618
623
// `self.nodes`. See the comment in `process_obligation`
619
624
// for more details.
620
625
if let Some ( ( predicate, _) ) =
621
- self . active_cache . remove_entry ( node. obligation . as_predicate ( ) )
626
+ self . active_cache . remove_entry ( & node. obligation . as_cache_key ( ) )
622
627
{
623
628
self . done_cache . insert ( predicate) ;
624
629
} else {
625
- self . done_cache . insert ( node. obligation . as_predicate ( ) . clone ( ) ) ;
630
+ self . done_cache . insert ( node. obligation . as_cache_key ( ) . clone ( ) ) ;
626
631
}
627
632
if do_completed == DoCompleted :: Yes {
628
633
// Extract the success stories.
@@ -635,7 +640,7 @@ impl<O: ForestObligation> ObligationForest<O> {
635
640
// We *intentionally* remove the node from the cache at this point. Otherwise
636
641
// tests must come up with a different type on every type error they
637
642
// check against.
638
- self . active_cache . remove ( node. obligation . as_predicate ( ) ) ;
643
+ self . active_cache . remove ( & node. obligation . as_cache_key ( ) ) ;
639
644
self . insert_into_error_cache ( index) ;
640
645
node_rewrites[ index] = orig_nodes_len;
641
646
dead_nodes += 1 ;
0 commit comments