@@ -185,6 +185,10 @@ impl CycleHeads {
185185 self . heads . last ( ) . copied ( )
186186 }
187187
188+ fn opt_lowest_cycle_head ( & self ) -> Option < StackDepth > {
189+ self . heads . first ( ) . copied ( )
190+ }
191+
188192 fn remove_highest_cycle_head ( & mut self ) {
189193 let last = self . heads . pop_last ( ) ;
190194 debug_assert_ne ! ( last, None ) ;
@@ -303,6 +307,7 @@ struct StackEntry<X: Cx> {
303307/// goals still on the stack.
304308#[ derive_where( Debug ; X : Cx ) ]
305309struct ProvisionalCacheEntry < X : Cx > {
310+ is_sus : bool ,
306311 heads : CycleHeads ,
307312 path_from_head : CycleKind ,
308313 nested_goals : NestedGoals < X > ,
@@ -411,7 +416,13 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
411416 let head = self . stack . next_index ( ) ;
412417 self . provisional_cache . retain ( |& input, entries| {
413418 entries. retain_mut ( |entry| {
414- let ProvisionalCacheEntry { heads, path_from_head, nested_goals, result } = entry;
419+ let ProvisionalCacheEntry {
420+ is_sus : _,
421+ heads,
422+ path_from_head,
423+ nested_goals,
424+ result,
425+ } = entry;
415426 if heads. highest_cycle_head ( ) != head {
416427 return true ;
417428 }
@@ -459,6 +470,10 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
459470 return self . handle_overflow ( cx, input, inspect) ;
460471 } ;
461472
473+ if let Some ( result) = self . lookup_provisional_cache ( cx, input) {
474+ return result;
475+ }
476+
462477 let validate_cache = if !D :: inspect_is_noop ( inspect) {
463478 None
464479 } else if let Some ( scope) = D :: enter_validation_scope ( cx, input) {
@@ -475,11 +490,6 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
475490 None
476491 } ;
477492
478- if let Some ( result) = self . lookup_provisional_cache ( cx, input) {
479- debug_assert ! ( validate_cache. is_none( ) , "global cache and provisional entry" ) ;
480- return result;
481- }
482-
483493 if let Some ( result) = self . check_cycle_on_stack ( cx, input) {
484494 debug_assert ! ( validate_cache. is_none( ) , "global cache and cycle on stack" ) ;
485495 return result;
@@ -531,9 +541,16 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
531541 } else if D :: ENABLE_PROVISIONAL_CACHE {
532542 debug_assert ! ( validate_cache. is_none( ) ) ;
533543 let entry = self . provisional_cache . entry ( input) . or_default ( ) ;
534- let StackEntry { heads, nested_goals, .. } = final_entry;
544+ let StackEntry { heads, nested_goals, encountered_overflow, .. } = final_entry;
545+ let is_sus = encountered_overflow;
535546 let path_from_head = Self :: stack_path_kind ( cx, & self . stack , heads. highest_cycle_head ( ) ) ;
536- entry. push ( ProvisionalCacheEntry { heads, path_from_head, nested_goals, result } ) ;
547+ entry. push ( ProvisionalCacheEntry {
548+ is_sus,
549+ heads,
550+ path_from_head,
551+ nested_goals,
552+ result,
553+ } ) ;
537554 } else {
538555 debug_assert ! ( validate_cache. is_none( ) ) ;
539556 }
@@ -587,8 +604,13 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
587604 debug ! ( ?input, ?path_from_global_entry, ?entries, "candidate_is_applicable" ) ;
588605 // A provisional cache entry is applicable if the path to
589606 // its highest cycle head is equal to the expected path.
590- for ProvisionalCacheEntry { heads, path_from_head, nested_goals : _, result : _ } in
591- entries
607+ for ProvisionalCacheEntry {
608+ is_sus : _,
609+ heads,
610+ path_from_head,
611+ nested_goals : _,
612+ result : _,
613+ } in entries. iter ( ) . filter ( |e| !e. is_sus )
592614 {
593615 let head = heads. highest_cycle_head ( ) ;
594616 let full_path = if Self :: stack_coinductive_from ( cx, stack, head) {
@@ -682,10 +704,22 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
682704 }
683705
684706 let entries = self . provisional_cache . get ( & input) ?;
685- for & ProvisionalCacheEntry { ref heads, path_from_head, ref nested_goals, result } in
686- entries
707+ for & ProvisionalCacheEntry {
708+ is_sus,
709+ ref heads,
710+ path_from_head,
711+ ref nested_goals,
712+ result,
713+ } in entries
687714 {
688715 let head = heads. highest_cycle_head ( ) ;
716+ if is_sus {
717+ let last = self . stack . raw . last ( ) . unwrap ( ) ;
718+ if !last. heads . opt_lowest_cycle_head ( ) . is_some_and ( |lowest| lowest <= head) {
719+ continue ;
720+ }
721+ }
722+
689723 if path_from_head == Self :: stack_path_kind ( cx, & self . stack , head) {
690724 // While we don't have to track the full depth of the provisional cache entry,
691725 // we do have to increment the required depth by one as we'd have already failed
0 commit comments