@@ -21,7 +21,7 @@ use std::marker::PhantomData;
2121use derive_where:: derive_where;
2222#[ cfg( feature = "nightly" ) ]
2323use rustc_macros:: { Decodable_NoContext , Encodable_NoContext , HashStable_NoContext } ;
24- use rustc_type_ir:: data_structures:: HashMap ;
24+ use rustc_type_ir:: data_structures:: { HashMap , HashSet } ;
2525use tracing:: { debug, instrument} ;
2626
2727mod stack;
@@ -1113,7 +1113,6 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
11131113
11141114 /// Whether we've reached a fixpoint when evaluating a cycle head.
11151115 fn reached_fixpoint (
1116- & mut self ,
11171116 cx : X ,
11181117 stack_entry : & StackEntry < X > ,
11191118 usage_kind : UsageKind ,
@@ -1161,7 +1160,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
11611160 // is equal to the provisional result of the previous iteration, or because
11621161 // this was only the root of either coinductive or inductive cycles, and the
11631162 // final result is equal to the initial response for that case.
1164- if self . reached_fixpoint ( cx, & stack_entry, usage_kind, result) {
1163+ if Self :: reached_fixpoint ( cx, & stack_entry, usage_kind, result) {
11651164 Self :: rebase_provisional_cache_entries (
11661165 & self . stack ,
11671166 & mut self . provisional_cache ,
@@ -1270,7 +1269,9 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
12701269 let truncate_stack = |stack : & mut Stack < X > , provisional_cache : & mut _ , depth| {
12711270 while stack. next_index ( ) > depth {
12721271 let reeval_entry = stack. pop ( ) ;
1273- // TODO
1272+ // TODO: How can we tell whether this entry was the final revision.
1273+ //
1274+ // We should be able to rebase provisional entries in most cases.
12741275 Self :: clear_dependent_provisional_results ( stack, provisional_cache) ;
12751276 Self :: update_parent_goal (
12761277 stack,
@@ -1286,6 +1287,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
12861287 let cycles = self . tree . rerun_get_and_reset_cycles ( prev_stack_entry. node_id ) ;
12871288 let current_stack_len = self . stack . len ( ) ;
12881289 let mut first_cycle = true ;
1290+ let mut has_changed = HashSet :: default ( ) ;
12891291 ' outer: for cycle in cycles {
12901292 let & tree:: Cycle { node_id : cycle_node_id, ref provisional_results } =
12911293 self . tree . get_cycle ( cycle) ;
@@ -1310,6 +1312,13 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
13101312 if !self . tree . get_heads ( entry_node_id) . contains_stack_entry ( current_depth) {
13111313 continue ;
13121314 }
1315+
1316+ // We've evaluated the `entry_node_id` before evaluating this goal. In case
1317+ // that node and its parents has not changed, we can reinsert the cache entry
1318+ // before starting to reevaluate it.
1319+ if !self . tree . goal_or_parent_has_changed ( node_id, & has_changed, entry_node_id) {
1320+ continue ;
1321+ }
13131322 }
13141323 } ;
13151324
@@ -1345,8 +1354,6 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
13451354 while let Some ( & ( stack_depth, node_id, info) ) = added_goals. peek ( ) {
13461355 if let Some ( existing_entry) = self . stack . get ( stack_depth) {
13471356 let provisional_result = provisional_results. get ( & stack_depth) . copied ( ) ;
1348- // Issue: changing the provisional result means we must not rebase, but instead
1349- // invalidate.
13501357 if existing_entry. node_id == node_id
13511358 && provisional_result == existing_entry. provisional_result
13521359 {
@@ -1410,10 +1417,10 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
14101417 debug ! ( input = ?current_goal. 1 . input, ?result, "goal did not change" ) ;
14111418 continue ' outer;
14121419 } else {
1420+ has_changed. insert ( current_goal. 0 ) ;
14131421 debug ! ( input = ?current_goal. 1 . input, ?result, "goal did change" ) ;
14141422 if self . stack . len ( ) > current_stack_len {
14151423 let parent = self . stack . pop ( ) ;
1416- // TODO
14171424 Self :: clear_dependent_provisional_results (
14181425 & self . stack ,
14191426 & mut self . provisional_cache ,
0 commit comments