Skip to content

Commit cde64b3

Browse files
committed
overwhelm
1 parent d372c6c commit cde64b3

File tree

2 files changed

+177
-55
lines changed

2 files changed

+177
-55
lines changed

compiler/rustc_type_ir/src/search_graph/mod.rs

Lines changed: 99 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -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)

compiler/rustc_type_ir/src/search_graph/tree.rs

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,34 @@ rustc_index::newtype_index! {
2626
pub(super) struct CycleId {}
2727
}
2828

29+
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
30+
pub(super) enum RebaseEntriesKind {
31+
Normal,
32+
Ambiguity,
33+
Overflow,
34+
}
35+
2936
#[derive_where(Debug; X: Cx)]
3037
pub(super) enum NodeKind<X: Cx> {
31-
InProgress { cycles_start: CycleId },
32-
Finished { encountered_overflow: bool, heads: CycleHeads, result: X::Result },
33-
CycleOnStack { entry_node_id: NodeId, result: X::Result },
34-
ProvisionalCacheHit { entry_node_id: NodeId },
38+
InProgress {
39+
cycles_start: CycleId,
40+
last_iteration_provisional_result: Option<X::Result>,
41+
rebase_entries_kind: Option<RebaseEntriesKind>,
42+
},
43+
Finished {
44+
encountered_overflow: bool,
45+
heads: CycleHeads,
46+
last_iteration_provisional_result: Option<X::Result>,
47+
rebase_entries_kind: Option<RebaseEntriesKind>,
48+
result: X::Result,
49+
},
50+
CycleOnStack {
51+
entry_node_id: NodeId,
52+
result: X::Result,
53+
},
54+
ProvisionalCacheHit {
55+
entry_node_id: NodeId,
56+
},
3557
}
3658

3759
#[derive_where(Debug; X: Cx)]
@@ -66,7 +88,11 @@ impl<X: Cx> SearchTree<X> {
6688
self.nodes.push(Node {
6789
info,
6890
parent,
69-
kind: NodeKind::InProgress { cycles_start: self.cycles.next_index() },
91+
kind: NodeKind::InProgress {
92+
cycles_start: self.cycles.next_index(),
93+
last_iteration_provisional_result: None,
94+
rebase_entries_kind: None,
95+
},
7096
})
7197
}
7298

@@ -108,10 +134,21 @@ impl<X: Cx> SearchTree<X> {
108134
heads: CycleHeads,
109135
result: X::Result,
110136
) {
111-
let NodeKind::InProgress { cycles_start: _ } = self.nodes[node_id].kind else {
137+
let NodeKind::InProgress {
138+
cycles_start: _,
139+
last_iteration_provisional_result,
140+
rebase_entries_kind,
141+
} = self.nodes[node_id].kind
142+
else {
112143
panic!("unexpected node kind: {:?}", self.nodes[node_id]);
113144
};
114-
self.nodes[node_id].kind = NodeKind::Finished { encountered_overflow, heads, result }
145+
self.nodes[node_id].kind = NodeKind::Finished {
146+
encountered_overflow,
147+
heads,
148+
result,
149+
last_iteration_provisional_result,
150+
rebase_entries_kind,
151+
}
115152
}
116153

117154
pub(super) fn get_cycle(&self, cycle_id: CycleId) -> &Cycle<X> {
@@ -129,15 +166,22 @@ impl<X: Cx> SearchTree<X> {
129166
encountered_overflow: prev_overflow,
130167
heads: prev_heads,
131168
result: prev_result,
169+
rebase_entries_kind: prev_rebase_entries_kind,
170+
last_iteration_provisional_result: prev_last_iteration_provisional_result,
132171
},
133172
NodeKind::Finished {
134173
encountered_overflow: new_overflow,
135174
heads: new_heads,
136175
result: new_result,
176+
rebase_entries_kind: new_rebase_entries_kind,
177+
last_iteration_provisional_result: new_last_iteration_provisional_result,
137178
},
138179
) => {
139180
prev_result == new_result
140181
&& (*prev_overflow || !*new_overflow)
182+
&& prev_rebase_entries_kind == new_rebase_entries_kind
183+
&& prev_last_iteration_provisional_result
184+
== new_last_iteration_provisional_result
141185
&& prev_heads.contains(new_heads)
142186
}
143187
(
@@ -157,10 +201,35 @@ impl<X: Cx> SearchTree<X> {
157201
}
158202
}
159203

160-
pub(super) fn rerun_get_and_reset_cycles(&mut self, node_id: NodeId) -> Range<CycleId> {
161-
if let NodeKind::InProgress { cycles_start, .. } = &mut self.nodes[node_id].kind {
204+
pub(super) fn set_rebase_kind(&mut self, node_id: NodeId, rebase_kind: RebaseEntriesKind) {
205+
if let NodeKind::InProgress {
206+
cycles_start: _,
207+
last_iteration_provisional_result: _,
208+
rebase_entries_kind,
209+
} = &mut self.nodes[node_id].kind
210+
{
211+
let prev = rebase_entries_kind.replace(rebase_kind);
212+
debug_assert!(prev.is_none());
213+
} else {
214+
panic!("unexpected node kind: {:?}", self.nodes[node_id]);
215+
}
216+
}
217+
218+
pub(super) fn rerun_get_and_reset_cycles(
219+
&mut self,
220+
node_id: NodeId,
221+
provisional_result: X::Result,
222+
) -> Range<CycleId> {
223+
if let NodeKind::InProgress {
224+
cycles_start,
225+
last_iteration_provisional_result,
226+
rebase_entries_kind,
227+
} = &mut self.nodes[node_id].kind
228+
{
229+
debug_assert!(rebase_entries_kind.is_none());
162230
let prev = *cycles_start;
163231
*cycles_start = self.cycles.next_index();
232+
*last_iteration_provisional_result = Some(provisional_result);
164233
prev..self.cycles.next_index()
165234
} else {
166235
panic!("unexpected node kind: {:?}", self.nodes[node_id]);

0 commit comments

Comments
 (0)