@@ -785,14 +785,11 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
785785 fn clear_dependent_provisional_results (
786786 stack : & Stack < X > ,
787787 provisional_cache : & mut HashMap < X :: Input , Vec < ProvisionalCacheEntry < X > > > ,
788- mut handle_removed_entry : impl FnMut ( X :: Input , ProvisionalCacheEntry < X > ) ,
789788 ) {
790789 let head = stack. next_index ( ) ;
791790 #[ allow( rustc:: potential_query_instability) ]
792- provisional_cache. retain ( |& input, entries| {
793- for e in entries. extract_if ( .., |entry| entry. heads . highest_cycle_head ( ) == head) {
794- handle_removed_entry ( input, e)
795- }
791+ provisional_cache. retain ( |_, entries| {
792+ entries. retain ( |entry| entry. heads . highest_cycle_head ( ) != head) ;
796793 !entries. is_empty ( )
797794 } ) ;
798795 }
@@ -1171,6 +1168,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
11711168 & stack_entry,
11721169 |_, result| result,
11731170 ) ;
1171+ self . tree . set_rebase_kind ( stack_entry. node_id , tree:: RebaseEntriesKind :: Normal ) ;
11741172 return EvaluationResult :: finalize ( stack_entry, encountered_overflow, result) ;
11751173 }
11761174
@@ -1195,6 +1193,8 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
11951193 & stack_entry,
11961194 |input, _| D :: propagate_ambiguity ( cx, input, result) ,
11971195 ) ;
1196+
1197+ self . tree . set_rebase_kind ( stack_entry. node_id , tree:: RebaseEntriesKind :: Ambiguity ) ;
11981198 return EvaluationResult :: finalize ( stack_entry, encountered_overflow, result) ;
11991199 } ;
12001200
@@ -1210,6 +1210,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
12101210 & stack_entry,
12111211 |input, _| D :: on_fixpoint_overflow ( cx, input) ,
12121212 ) ;
1213+ self . tree . set_rebase_kind ( stack_entry. node_id , tree:: RebaseEntriesKind :: Overflow ) ;
12131214 return EvaluationResult :: finalize ( stack_entry, encountered_overflow, result) ;
12141215 }
12151216
@@ -1223,6 +1224,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
12231224 & new_stack_entry,
12241225 |_, result| result,
12251226 ) ;
1227+ self . tree . set_rebase_kind ( new_stack_entry. node_id , tree:: RebaseEntriesKind :: Normal ) ;
12261228 return EvaluationResult :: finalize (
12271229 new_stack_entry,
12281230 encountered_overflow,
@@ -1247,20 +1249,9 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
12471249 ) -> ( StackEntry < X > , X :: Result ) {
12481250 let node_id = prev_stack_entry. node_id ;
12491251 let current_depth = self . stack . next_index ( ) ;
1250-
1251- let mut removed_entries = BTreeMap :: new ( ) ;
12521252 // Clear all provisional cache entries which depend on a previous provisional
12531253 // result of this goal and rerun.
1254- Self :: clear_dependent_provisional_results (
1255- & self . stack ,
1256- & mut self . provisional_cache ,
1257- |input, entry| {
1258- let prev = removed_entries. insert ( entry. entry_node_id , ( input, entry) ) ;
1259- if let Some ( prev) = prev {
1260- unreachable ! ( "duplicate entries for the same `NodeId`: {prev:?}" ) ;
1261- }
1262- } ,
1263- ) ;
1254+ Self :: clear_dependent_provisional_results ( & self . stack , & mut self . provisional_cache ) ;
12641255 self . stack . push ( StackEntry {
12651256 node_id,
12661257 input : prev_stack_entry. input ,
@@ -1280,13 +1271,58 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
12801271 return ( reeval_entry, result) ;
12811272 }
12821273
1283- let truncate_stack = |stack : & mut Stack < X > , provisional_cache : & mut _ , depth| {
1274+ let truncate_unchanged_stack = |stack : & mut Stack < X > ,
1275+ provisional_cache : & mut _ ,
1276+ tree : & SearchTree < X > ,
1277+ depth| {
12841278 while stack. next_index ( ) > depth {
1285- let reeval_entry = stack. pop ( ) ;
1286- // TODO: How can we tell whether this entry was the final revision.
1287- //
1288- // We should be able to rebase provisional entries in most cases.
1289- Self :: clear_dependent_provisional_results ( stack, provisional_cache, |_, _| ( ) ) ;
1279+ let mut reeval_entry = stack. pop ( ) ;
1280+ let & tree:: NodeKind :: Finished {
1281+ encountered_overflow,
1282+ ref heads,
1283+ last_iteration_provisional_result,
1284+ rebase_entries_kind,
1285+ result,
1286+ } = tree. node_kind_raw ( reeval_entry. node_id )
1287+ else {
1288+ unreachable ! ( ) ;
1289+ } ;
1290+ if last_iteration_provisional_result == reeval_entry. provisional_result {
1291+ reeval_entry. heads = heads. clone ( ) ;
1292+ match rebase_entries_kind {
1293+ Some ( tree:: RebaseEntriesKind :: Normal ) => {
1294+ debug ! ( ?reeval_entry. input, "rebase entries while truncating stack" ) ;
1295+ Self :: rebase_provisional_cache_entries (
1296+ stack,
1297+ provisional_cache,
1298+ & reeval_entry,
1299+ |_, result| result,
1300+ )
1301+ }
1302+ Some ( tree:: RebaseEntriesKind :: Ambiguity ) => {
1303+ Self :: rebase_provisional_cache_entries (
1304+ stack,
1305+ provisional_cache,
1306+ & reeval_entry,
1307+ |input, result| D :: propagate_ambiguity ( cx, input, result) ,
1308+ )
1309+ }
1310+ Some ( tree:: RebaseEntriesKind :: Overflow ) => {
1311+ Self :: rebase_provisional_cache_entries (
1312+ stack,
1313+ provisional_cache,
1314+ & reeval_entry,
1315+ |input, _| D :: on_fixpoint_overflow ( cx, input) ,
1316+ )
1317+ }
1318+ None | _ => {
1319+ Self :: clear_dependent_provisional_results ( stack, provisional_cache)
1320+ }
1321+ }
1322+ } else {
1323+ Self :: clear_dependent_provisional_results ( stack, provisional_cache) ;
1324+ }
1325+
12901326 Self :: update_parent_goal (
12911327 stack,
12921328 reeval_entry. step_kind_from_parent ,
@@ -1295,10 +1331,39 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
12951331 reeval_entry. encountered_overflow ,
12961332 UpdateParentGoalCtxt :: Ordinary ( & reeval_entry. nested_goals ) ,
12971333 ) ;
1334+ let entry = provisional_cache. entry ( reeval_entry. input ) . or_default ( ) ;
1335+
1336+ for ( head, path_to_nested) in heads. iter ( ) {
1337+ let path_from_head =
1338+ Self :: cycle_path_kind ( & stack, reeval_entry. step_kind_from_parent , head) ;
1339+ for path_kind in path_to_nested. extend_with ( path_from_head) . iter_paths ( ) {
1340+ let usage_kind = UsageKind :: Single ( path_kind) ;
1341+ stack[ head] . has_been_used = Some (
1342+ stack[ head]
1343+ . has_been_used
1344+ . map_or ( usage_kind, |prev| prev. merge ( usage_kind) ) ,
1345+ ) ;
1346+ }
1347+ }
1348+ let path_from_head = Self :: cycle_path_kind (
1349+ & stack,
1350+ reeval_entry. step_kind_from_parent ,
1351+ heads. highest_cycle_head ( ) ,
1352+ ) ;
1353+ let provisional_cache_entry = ProvisionalCacheEntry {
1354+ entry_node_id : reeval_entry. node_id ,
1355+ encountered_overflow,
1356+ heads : heads. clone ( ) ,
1357+ path_from_head,
1358+ result,
1359+ } ;
1360+ debug ! ( ?provisional_cache_entry) ;
1361+ entry. push ( provisional_cache_entry) ;
12981362 }
12991363 } ;
13001364
1301- let cycles = self . tree . rerun_get_and_reset_cycles ( prev_stack_entry. node_id ) ;
1365+ let cycles =
1366+ self . tree . rerun_get_and_reset_cycles ( prev_stack_entry. node_id , provisional_result) ;
13021367 let current_stack_len = self . stack . len ( ) ;
13031368 let mut was_reevaluated = HashSet :: default ( ) ;
13041369 ' outer: for cycle in cycles {
@@ -1364,9 +1429,10 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
13641429 ) ;
13651430 let _ = added_goals. next ( ) . unwrap ( ) ;
13661431 } else {
1367- truncate_stack (
1432+ truncate_unchanged_stack (
13681433 & mut self . stack ,
13691434 & mut self . provisional_cache ,
1435+ & self . tree ,
13701436 stack_depth,
13711437 ) ;
13721438 break ;
@@ -1381,7 +1447,12 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
13811447 }
13821448 }
13831449 ( None , Some ( _) ) => {
1384- truncate_stack ( & mut self . stack , & mut self . provisional_cache , stack_depth) ;
1450+ truncate_unchanged_stack (
1451+ & mut self . stack ,
1452+ & mut self . provisional_cache ,
1453+ & self . tree ,
1454+ stack_depth,
1455+ ) ;
13851456 break ;
13861457 }
13871458 ( None , None ) => break ,
@@ -1406,18 +1477,6 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
14061477 } ) ;
14071478 }
14081479
1409- /*
1410- while let Some((&entry_node_id, _)) = removed_entries.first_key_value() {
1411- if entry_node_id < current_goal.0
1412- && self.stack.iter().all(|e| e.node_id != entry_node_id)
1413- {
1414- let (entry_node_id, (input, entry)) = removed_entries.pop_first().unwrap();
1415- if !self.tree.goal_or_parent_has_changed(node_id, &has_changed, entry_node_id) {
1416- self.provisional_cache.entry(input).or_default().push(entry);
1417- }
1418- }
1419- }*/
1420-
14211480 loop {
14221481 let span = tracing:: debug_span!(
14231482 "reevaluate_canonical_goal" ,
@@ -1443,7 +1502,6 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
14431502 Self :: clear_dependent_provisional_results (
14441503 & self . stack ,
14451504 & mut self . provisional_cache ,
1446- |_, _| ( ) ,
14471505 ) ;
14481506 Self :: update_parent_goal (
14491507 & mut self . stack ,
@@ -1475,18 +1533,13 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
14751533 return ( reeval_entry, result) ;
14761534 }
14771535
1478- truncate_stack (
1536+ truncate_unchanged_stack (
14791537 & mut self . stack ,
14801538 & mut self . provisional_cache ,
1539+ & self . tree ,
14811540 StackDepth :: from_usize ( current_stack_len) ,
14821541 ) ;
14831542
1484- for ( entry_node_id, ( input, entry) ) in removed_entries {
1485- if !self . tree . goal_or_parent_was_reevaluated ( node_id, & was_reevaluated, entry_node_id) {
1486- self . provisional_cache . entry ( input) . or_default ( ) . push ( entry) ;
1487- }
1488- }
1489-
14901543 debug_assert_eq ! ( self . stack. len( ) , current_stack_len) ;
14911544 let reeval_entry = self . stack . pop ( ) ;
14921545 ( reeval_entry, provisional_result)
0 commit comments