Skip to content

Commit 0cd8141

Browse files
authored
Rollup merge of rust-lang#66405 - nnethercote:tweak-ObligForest-NodeStates, r=nikomatsakis
Tweak `ObligationForest` `NodeState`s These two commits improve comments and function names. r? @nikomatsakis
2 parents 6d77e45 + c45fc6b commit 0cd8141

File tree

1 file changed

+60
-29
lines changed
  • src/librustc_data_structures/obligation_forest

1 file changed

+60
-29
lines changed

src/librustc_data_structures/obligation_forest/mod.rs

+60-29
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,11 @@ type ObligationTreeIdGenerator =
130130
pub struct ObligationForest<O: ForestObligation> {
131131
/// The list of obligations. In between calls to
132132
/// `process_obligations`, this list only contains nodes in the
133-
/// `Pending` or `Success` state (with a non-zero number of
133+
/// `Pending` or `Waiting` state (with a non-zero number of
134134
/// incomplete children). During processing, some of those nodes
135135
/// may be changed to the error state, or we may find that they
136-
/// are completed (That is, `num_incomplete_children` drops to 0).
137-
/// At the end of processing, those nodes will be removed by a
138-
/// call to `compress`.
136+
/// are completed. At the end of processing, those nodes will be
137+
/// removed by a call to `compress`.
139138
///
140139
/// `usize` indices are used here and throughout this module, rather than
141140
/// `rustc_index::newtype_index!` indices, because this code is hot enough that the
@@ -211,28 +210,56 @@ impl<O> Node<O> {
211210
/// represents the current state of processing for the obligation (of
212211
/// type `O`) associated with this node.
213212
///
214-
/// Outside of ObligationForest methods, nodes should be either Pending
215-
/// or Waiting.
213+
/// The non-`Error` state transitions are as follows.
214+
/// ```
215+
/// (Pre-creation)
216+
/// |
217+
/// | register_obligation_at() (called by process_obligations() and
218+
/// v from outside the crate)
219+
/// Pending
220+
/// |
221+
/// | process_obligations()
222+
/// v
223+
/// Success
224+
/// | ^
225+
/// | | update_waiting_and_success_states()
226+
/// | v
227+
/// | Waiting
228+
/// |
229+
/// | process_cycles()
230+
/// v
231+
/// Done
232+
/// |
233+
/// | compress()
234+
/// v
235+
/// (Removed)
236+
/// ```
237+
/// The `Error` state can be introduced in several places, via `error_at()`.
238+
///
239+
/// Outside of `ObligationForest` methods, nodes should be either `Pending` or
240+
/// `Waiting`.
216241
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
217242
enum NodeState {
218-
/// Obligations for which selection had not yet returned a
219-
/// non-ambiguous result.
243+
/// This obligation has not yet been selected successfully. Cannot have
244+
/// subobligations.
220245
Pending,
221246

222-
/// This obligation was selected successfully, but may or
223-
/// may not have subobligations.
247+
/// This obligation was selected successfully, but the state of any
248+
/// subobligations are current unknown. It will be converted to `Waiting`
249+
/// or `Done` once the states of the subobligations become known.
224250
Success,
225251

226-
/// This obligation was selected successfully, but it has
227-
/// a pending subobligation.
252+
/// This obligation was selected successfully, but it has one or more
253+
/// pending subobligations.
228254
Waiting,
229255

230-
/// This obligation, along with its subobligations, are complete,
231-
/// and will be removed in the next collection.
256+
/// This obligation was selected successfully, as were all of its
257+
/// subobligations (of which there may be none). It will be removed by the
258+
/// next compression step.
232259
Done,
233260

234-
/// This obligation was resolved to an error. Error nodes are
235-
/// removed from the vector by the compression step.
261+
/// This obligation was resolved to an error. It will be removed by the
262+
/// next compression step.
236263
Error,
237264
}
238265

@@ -464,7 +491,7 @@ impl<O: ForestObligation> ObligationForest<O> {
464491
};
465492
}
466493

467-
self.mark_as_waiting();
494+
self.update_waiting_and_success_states();
468495
self.process_cycles(processor);
469496
let completed = self.compress(do_completed);
470497

@@ -477,10 +504,9 @@ impl<O: ForestObligation> ObligationForest<O> {
477504
}
478505
}
479506

480-
/// Mark all `NodeState::Success` nodes as `NodeState::Done` and
481-
/// report all cycles between them. This should be called
482-
/// after `mark_as_waiting` marks all nodes with pending
483-
/// subobligations as NodeState::Waiting.
507+
/// Mark all `Success` nodes as `Done` and report all cycles between them.
508+
/// This should be called after `update_waiting_and_success_states` updates
509+
/// the status of all `Waiting` and `Success` nodes.
484510
fn process_cycles<P>(&self, processor: &mut P)
485511
where P: ObligationProcessor<Obligation=O>
486512
{
@@ -562,42 +588,47 @@ impl<O: ForestObligation> ObligationForest<O> {
562588

563589
// This always-inlined function is for the hot call site.
564590
#[inline(always)]
565-
fn inlined_mark_neighbors_as_waiting_from(&self, node: &Node<O>) {
591+
fn inlined_mark_dependents_as_waiting(&self, node: &Node<O>) {
566592
for &index in node.dependents.iter() {
567593
let node = &self.nodes[index];
568594
match node.state.get() {
569595
NodeState::Waiting | NodeState::Error => {}
570596
NodeState::Success => {
571597
node.state.set(NodeState::Waiting);
572598
// This call site is cold.
573-
self.uninlined_mark_neighbors_as_waiting_from(node);
599+
self.uninlined_mark_dependents_as_waiting(node);
574600
}
575601
NodeState::Pending | NodeState::Done => {
576602
// This call site is cold.
577-
self.uninlined_mark_neighbors_as_waiting_from(node);
603+
self.uninlined_mark_dependents_as_waiting(node);
578604
}
579605
}
580606
}
581607
}
582608

583609
// This never-inlined function is for the cold call site.
584610
#[inline(never)]
585-
fn uninlined_mark_neighbors_as_waiting_from(&self, node: &Node<O>) {
586-
self.inlined_mark_neighbors_as_waiting_from(node)
611+
fn uninlined_mark_dependents_as_waiting(&self, node: &Node<O>) {
612+
self.inlined_mark_dependents_as_waiting(node)
587613
}
588614

589-
/// Marks all nodes that depend on a pending node as `NodeState::Waiting`.
590-
fn mark_as_waiting(&self) {
615+
/// Updates the states of all `Waiting` and `Success` nodes. Upon
616+
/// completion, all such nodes that depend on a pending node will be marked
617+
/// as `Waiting`, and all others will be marked as `Success`.
618+
fn update_waiting_and_success_states(&self) {
619+
// Optimistically mark all `Waiting` nodes as `Success`.
591620
for node in &self.nodes {
592621
if node.state.get() == NodeState::Waiting {
593622
node.state.set(NodeState::Success);
594623
}
595624
}
596625

626+
// Convert all `Success` nodes that still depend on a pending node to
627+
// `Waiting`. This may undo some of the changes done in the loop above.
597628
for node in &self.nodes {
598629
if node.state.get() == NodeState::Pending {
599630
// This call site is hot.
600-
self.inlined_mark_neighbors_as_waiting_from(node);
631+
self.inlined_mark_dependents_as_waiting(node);
601632
}
602633
}
603634
}

0 commit comments

Comments
 (0)