Skip to content

Commit 981b928

Browse files
committed
fix: Mark obligation forest nodes as "Done" after cycle checking them
This was lost in rust-lang#66405 , perhaps due to the added `dep_index >= min_index` check which attempts to avoid reprocessing in a different way. Unfortunately that does not cover the case where a node points to a higher index which can in degenerate cases where a lot of nodes point to a lot of higher indexed nodes end up with `O(N ^ 2)` complexity. With this fix restored it is `O(N)` again since nodes will never be reprocessed.
1 parent 0a58f58 commit 981b928

File tree

1 file changed

+20
-6
lines changed
  • src/librustc_data_structures/obligation_forest

1 file changed

+20
-6
lines changed

src/librustc_data_structures/obligation_forest/mod.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -563,12 +563,26 @@ impl<O: ForestObligation> ObligationForest<O> {
563563
P: ObligationProcessor<Obligation = O>,
564564
{
565565
let node = &self.nodes[index];
566-
if node.state.get() == NodeState::Success {
567-
match stack.iter().rposition(|&n| n == index) {
568-
None => {
569-
stack.push(index);
570-
for &dep_index in node.dependents.iter() {
571-
self.find_cycles_from_node(stack, processor, dep_index);
566+
if let NodeState::Success(waiting) = node.state.get() {
567+
if !self.is_still_waiting(waiting) {
568+
match stack.iter().rposition(|&n| n == index) {
569+
None => {
570+
stack.push(index);
571+
for &dep_index in node.dependents.iter() {
572+
// The index check avoids re-considering a node.
573+
if dep_index >= min_index {
574+
self.find_cycles_from_node(stack, processor, min_index, dep_index);
575+
}
576+
}
577+
stack.pop();
578+
node.state.set(NodeState::Success(Self::not_waiting()));
579+
}
580+
Some(rpos) => {
581+
// Cycle detected.
582+
processor.process_backedge(
583+
stack[rpos..].iter().map(GetObligation(&self.nodes)),
584+
PhantomData,
585+
);
572586
}
573587
stack.pop();
574588
node.state.set(NodeState::Done);

0 commit comments

Comments
 (0)