Skip to content

Commit 4cbab2b

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 fdc0011 + c45fc6b commit 4cbab2b

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

@@ -453,7 +480,7 @@ impl<O: ForestObligation> ObligationForest<O> {
453480
};
454481
}
455482

456-
self.mark_as_waiting();
483+
self.update_waiting_and_success_states();
457484
self.process_cycles(processor);
458485
let completed = self.compress(do_completed);
459486

@@ -466,10 +493,9 @@ impl<O: ForestObligation> ObligationForest<O> {
466493
}
467494
}
468495

469-
/// Mark all `NodeState::Success` nodes as `NodeState::Done` and
470-
/// report all cycles between them. This should be called
471-
/// after `mark_as_waiting` marks all nodes with pending
472-
/// subobligations as NodeState::Waiting.
496+
/// Mark all `Success` nodes as `Done` and report all cycles between them.
497+
/// This should be called after `update_waiting_and_success_states` updates
498+
/// the status of all `Waiting` and `Success` nodes.
473499
fn process_cycles<P>(&self, processor: &mut P)
474500
where P: ObligationProcessor<Obligation=O>
475501
{
@@ -551,42 +577,47 @@ impl<O: ForestObligation> ObligationForest<O> {
551577

552578
// This always-inlined function is for the hot call site.
553579
#[inline(always)]
554-
fn inlined_mark_neighbors_as_waiting_from(&self, node: &Node<O>) {
580+
fn inlined_mark_dependents_as_waiting(&self, node: &Node<O>) {
555581
for &index in node.dependents.iter() {
556582
let node = &self.nodes[index];
557583
match node.state.get() {
558584
NodeState::Waiting | NodeState::Error => {}
559585
NodeState::Success => {
560586
node.state.set(NodeState::Waiting);
561587
// This call site is cold.
562-
self.uninlined_mark_neighbors_as_waiting_from(node);
588+
self.uninlined_mark_dependents_as_waiting(node);
563589
}
564590
NodeState::Pending | NodeState::Done => {
565591
// This call site is cold.
566-
self.uninlined_mark_neighbors_as_waiting_from(node);
592+
self.uninlined_mark_dependents_as_waiting(node);
567593
}
568594
}
569595
}
570596
}
571597

572598
// This never-inlined function is for the cold call site.
573599
#[inline(never)]
574-
fn uninlined_mark_neighbors_as_waiting_from(&self, node: &Node<O>) {
575-
self.inlined_mark_neighbors_as_waiting_from(node)
600+
fn uninlined_mark_dependents_as_waiting(&self, node: &Node<O>) {
601+
self.inlined_mark_dependents_as_waiting(node)
576602
}
577603

578-
/// Marks all nodes that depend on a pending node as `NodeState::Waiting`.
579-
fn mark_as_waiting(&self) {
604+
/// Updates the states of all `Waiting` and `Success` nodes. Upon
605+
/// completion, all such nodes that depend on a pending node will be marked
606+
/// as `Waiting`, and all others will be marked as `Success`.
607+
fn update_waiting_and_success_states(&self) {
608+
// Optimistically mark all `Waiting` nodes as `Success`.
580609
for node in &self.nodes {
581610
if node.state.get() == NodeState::Waiting {
582611
node.state.set(NodeState::Success);
583612
}
584613
}
585614

615+
// Convert all `Success` nodes that still depend on a pending node to
616+
// `Waiting`. This may undo some of the changes done in the loop above.
586617
for node in &self.nodes {
587618
if node.state.get() == NodeState::Pending {
588619
// This call site is hot.
589-
self.inlined_mark_neighbors_as_waiting_from(node);
620+
self.inlined_mark_dependents_as_waiting(node);
590621
}
591622
}
592623
}

0 commit comments

Comments
 (0)