Skip to content

Commit d49499e

Browse files
committed
gaming
1 parent 53dd192 commit d49499e

File tree

1 file changed

+42
-19
lines changed
  • compiler/rustc_type_ir/src/search_graph

1 file changed

+42
-19
lines changed

compiler/rustc_type_ir/src/search_graph/mod.rs

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,11 @@ impl Usages {
220220
forced_ambiguity: if self.forced_ambiguity == 0 { 0 } else { 1 },
221221
}
222222
}
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+
}
223228
}
224229

225230
#[derive(Debug, Default)]
@@ -280,15 +285,19 @@ impl CycleHeads {
280285
self.heads.is_empty()
281286
}
282287

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()
285294
}
286295

287-
fn opt_highest_cycle_head(&self) -> Option<StackDepth> {
296+
fn opt_highest_cycle_head_index(&self) -> Option<StackDepth> {
288297
self.heads.last_key_value().map(|(k, _)| *k)
289298
}
290299

291-
fn opt_lowest_cycle_head(&self) -> Option<StackDepth> {
300+
fn opt_lowest_cycle_head_index(&self) -> Option<StackDepth> {
292301
self.heads.first_key_value().map(|(k, _)| *k)
293302
}
294303

@@ -580,7 +589,11 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
580589

581590
for (head_index, head) in heads {
582591
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());
584597
}
585598
match head_index.cmp(&parent_index) {
586599
Ordering::Less => parent.heads.insert(
@@ -784,7 +797,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
784797
let path_from_head = Self::cycle_path_kind(
785798
&self.stack,
786799
step_kind_from_parent,
787-
heads.highest_cycle_head(),
800+
heads.highest_cycle_head_index(),
788801
);
789802
let provisional_cache_entry =
790803
ProvisionalCacheEntry { encountered_overflow, heads, path_from_head, result };
@@ -822,11 +835,17 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
822835

823836
/// When reevaluating a goal with a changed provisional result, all provisional cache entry
824837
/// 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();
827843
#[allow(rustc::potential_query_instability)]
828844
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+
});
830849
!entries.is_empty()
831850
});
832851
}
@@ -863,7 +882,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
863882
path_from_head,
864883
result,
865884
} = 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 {
867886
heads.remove_highest_cycle_head()
868887
} else {
869888
return true;
@@ -907,7 +926,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
907926
heads.insert(head_index, eph, head.usages.compressed());
908927
}
909928

910-
let Some(head) = heads.opt_highest_cycle_head() else {
929+
let Some(head_index) = heads.opt_highest_cycle_head_index() else {
911930
return false;
912931
};
913932

@@ -916,7 +935,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
916935
*path_from_head = path_from_head.extend(Self::cycle_path_kind(
917936
&self.stack,
918937
stack_entry.step_kind_from_parent,
919-
head,
938+
head_index,
920939
));
921940
// Mutate the result of the provisional cache entry in case we did
922941
// not reach a fixpoint.
@@ -940,7 +959,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
940959
for &ProvisionalCacheEntry { encountered_overflow, ref heads, path_from_head, result } in
941960
entries
942961
{
943-
let head = heads.highest_cycle_head();
962+
let head_index = heads.highest_cycle_head_index();
944963
if encountered_overflow {
945964
// This check is overly strict and very subtle. We need to make sure that if
946965
// 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> {
952971
// current goal is already part of the same cycle. This check could be
953972
// improved but seems to be good enough for now.
954973
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+
{
956976
continue;
957977
}
958978
}
959979

960980
// A provisional cache entry is only valid if the current path from its
961981
// 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+
{
963985
Self::update_parent_goal(
964986
&mut self.stack,
965987
step_kind_from_parent,
@@ -968,7 +990,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
968990
encountered_overflow,
969991
UpdateParentGoalCtxt::ProvisionalCacheHit,
970992
);
971-
debug!(?head, ?path_from_head, "provisional cache hit");
993+
debug!(?head_index, ?path_from_head, "provisional cache hit");
972994
return Some(result);
973995
}
974996
}
@@ -1026,8 +1048,9 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
10261048
//
10271049
// We check if any of the paths taken while computing the global goal
10281050
// 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);
10311054
let full_paths = path_from_global_entry.extend_with(head_to_curr);
10321055
if full_paths.contains(head_to_provisional.into()) {
10331056
debug!(
@@ -1239,7 +1262,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
12391262

12401263
// Clear all provisional cache entries which depend on a previous provisional
12411264
// result of this goal and rerun.
1242-
self.clear_dependent_provisional_results();
1265+
self.clear_dependent_provisional_results_for_rerun();
12431266

12441267
debug!(?result, "fixpoint changed provisional results");
12451268
self.stack.push(StackEntry {

0 commit comments

Comments
 (0)