@@ -130,12 +130,11 @@ type ObligationTreeIdGenerator =
130130pub 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 ) ]
217242enum 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