@@ -220,6 +220,11 @@ impl Usages {
220
220
forced_ambiguity : if self . forced_ambiguity == 0 { 0 } else { 1 } ,
221
221
}
222
222
}
223
+
224
+ fn is_empty ( self ) -> bool {
225
+ let Usages { inductive, unknown, coinductive, forced_ambiguity } = self ;
226
+ inductive == 0 && unknown == 0 && coinductive == 0 && forced_ambiguity == 0
227
+ }
223
228
}
224
229
225
230
#[ derive( Debug , Default ) ]
@@ -280,15 +285,19 @@ impl CycleHeads {
280
285
self . heads . is_empty ( )
281
286
}
282
287
283
- fn highest_cycle_head ( & self ) -> StackDepth {
284
- self . opt_highest_cycle_head ( ) . unwrap ( )
288
+ fn highest_cycle_head ( & self ) -> ( StackDepth , CycleHead ) {
289
+ self . heads . last_key_value ( ) . map ( |( k, v) | ( * k, * v) ) . unwrap ( )
290
+ }
291
+
292
+ fn highest_cycle_head_index ( & self ) -> StackDepth {
293
+ self . opt_highest_cycle_head_index ( ) . unwrap ( )
285
294
}
286
295
287
- fn opt_highest_cycle_head ( & self ) -> Option < StackDepth > {
296
+ fn opt_highest_cycle_head_index ( & self ) -> Option < StackDepth > {
288
297
self . heads . last_key_value ( ) . map ( |( k, _) | * k)
289
298
}
290
299
291
- fn opt_lowest_cycle_head ( & self ) -> Option < StackDepth > {
300
+ fn opt_lowest_cycle_head_index ( & self ) -> Option < StackDepth > {
292
301
self . heads . first_key_value ( ) . map ( |( k, _) | * k)
293
302
}
294
303
@@ -580,7 +589,11 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
580
589
581
590
for ( head_index, head) in heads {
582
591
if let Some ( candidate_usages) = & mut parent. candidate_usages {
583
- candidate_usages. 0 . entry ( head_index) . or_default ( ) . add_usages ( head. usages . compressed ( ) ) ;
592
+ candidate_usages
593
+ . 0
594
+ . entry ( head_index)
595
+ . or_default ( )
596
+ . add_usages ( head. usages . compressed ( ) ) ;
584
597
}
585
598
match head_index. cmp ( & parent_index) {
586
599
Ordering :: Less => parent. heads . insert (
@@ -784,7 +797,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
784
797
let path_from_head = Self :: cycle_path_kind (
785
798
& self . stack ,
786
799
step_kind_from_parent,
787
- heads. highest_cycle_head ( ) ,
800
+ heads. highest_cycle_head_index ( ) ,
788
801
) ;
789
802
let provisional_cache_entry =
790
803
ProvisionalCacheEntry { encountered_overflow, heads, path_from_head, result } ;
@@ -822,11 +835,17 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
822
835
823
836
/// When reevaluating a goal with a changed provisional result, all provisional cache entry
824
837
/// which depend on this goal get invalidated.
825
- fn clear_dependent_provisional_results ( & mut self ) {
826
- let head = self . stack . next_index ( ) ;
838
+ ///
839
+ /// Note that we keep provisional cache entries which accessed this goal as a cycle head, but
840
+ /// don't depend on its value.
841
+ fn clear_dependent_provisional_results_for_rerun ( & mut self ) {
842
+ let rerun_index = self . stack . next_index ( ) ;
827
843
#[ allow( rustc:: potential_query_instability) ]
828
844
self . provisional_cache . retain ( |_, entries| {
829
- entries. retain ( |entry| entry. heads . highest_cycle_head ( ) != head) ;
845
+ entries. retain ( |entry| {
846
+ let ( head_index, head) = entry. heads . highest_cycle_head ( ) ;
847
+ head_index != rerun_index || head. usages . is_empty ( )
848
+ } ) ;
830
849
!entries. is_empty ( )
831
850
} ) ;
832
851
}
@@ -863,7 +882,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
863
882
path_from_head,
864
883
result,
865
884
} = entry;
866
- let popped_head = if heads. highest_cycle_head ( ) == popped_head_index {
885
+ let popped_head = if heads. highest_cycle_head_index ( ) == popped_head_index {
867
886
heads. remove_highest_cycle_head ( )
868
887
} else {
869
888
return true ;
@@ -907,7 +926,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
907
926
heads. insert ( head_index, eph, head. usages . compressed ( ) ) ;
908
927
}
909
928
910
- let Some ( head ) = heads. opt_highest_cycle_head ( ) else {
929
+ let Some ( head_index ) = heads. opt_highest_cycle_head_index ( ) else {
911
930
return false ;
912
931
} ;
913
932
@@ -916,7 +935,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
916
935
* path_from_head = path_from_head. extend ( Self :: cycle_path_kind (
917
936
& self . stack ,
918
937
stack_entry. step_kind_from_parent ,
919
- head ,
938
+ head_index ,
920
939
) ) ;
921
940
// Mutate the result of the provisional cache entry in case we did
922
941
// not reach a fixpoint.
@@ -940,7 +959,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
940
959
for & ProvisionalCacheEntry { encountered_overflow, ref heads, path_from_head, result } in
941
960
entries
942
961
{
943
- let head = heads. highest_cycle_head ( ) ;
962
+ let head_index = heads. highest_cycle_head_index ( ) ;
944
963
if encountered_overflow {
945
964
// This check is overly strict and very subtle. We need to make sure that if
946
965
// a global cache entry depends on some goal without adding it to its
@@ -952,14 +971,17 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
952
971
// current goal is already part of the same cycle. This check could be
953
972
// improved but seems to be good enough for now.
954
973
let last = self . stack . last ( ) . unwrap ( ) ;
955
- if last. heads . opt_lowest_cycle_head ( ) . is_none_or ( |lowest| lowest > head) {
974
+ if last. heads . opt_lowest_cycle_head_index ( ) . is_none_or ( |lowest| lowest > head_index)
975
+ {
956
976
continue ;
957
977
}
958
978
}
959
979
960
980
// A provisional cache entry is only valid if the current path from its
961
981
// highest cycle head to the goal is the same.
962
- if path_from_head == Self :: cycle_path_kind ( & self . stack , step_kind_from_parent, head) {
982
+ if path_from_head
983
+ == Self :: cycle_path_kind ( & self . stack , step_kind_from_parent, head_index)
984
+ {
963
985
Self :: update_parent_goal (
964
986
& mut self . stack ,
965
987
step_kind_from_parent,
@@ -968,7 +990,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
968
990
encountered_overflow,
969
991
UpdateParentGoalCtxt :: ProvisionalCacheHit ,
970
992
) ;
971
- debug ! ( ?head , ?path_from_head, "provisional cache hit" ) ;
993
+ debug ! ( ?head_index , ?path_from_head, "provisional cache hit" ) ;
972
994
return Some ( result) ;
973
995
}
974
996
}
@@ -1026,8 +1048,9 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
1026
1048
//
1027
1049
// We check if any of the paths taken while computing the global goal
1028
1050
// would end up with an applicable provisional cache entry.
1029
- let head = heads. highest_cycle_head ( ) ;
1030
- let head_to_curr = Self :: cycle_path_kind ( & self . stack , step_kind_from_parent, head) ;
1051
+ let head_index = heads. highest_cycle_head_index ( ) ;
1052
+ let head_to_curr =
1053
+ Self :: cycle_path_kind ( & self . stack , step_kind_from_parent, head_index) ;
1031
1054
let full_paths = path_from_global_entry. extend_with ( head_to_curr) ;
1032
1055
if full_paths. contains ( head_to_provisional. into ( ) ) {
1033
1056
debug ! (
@@ -1239,7 +1262,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
1239
1262
1240
1263
// Clear all provisional cache entries which depend on a previous provisional
1241
1264
// result of this goal and rerun.
1242
- self . clear_dependent_provisional_results ( ) ;
1265
+ self . clear_dependent_provisional_results_for_rerun ( ) ;
1243
1266
1244
1267
debug ! ( ?result, "fixpoint changed provisional results" ) ;
1245
1268
self . stack . push ( StackEntry {
0 commit comments