81
81
//! nodes, which aren't needed anymore.
82
82
83
83
use crate :: fx:: { FxHashMap , FxHashSet } ;
84
+ use crate :: indexed_vec:: Idx ;
85
+ use crate :: newtype_index;
84
86
85
87
use std:: cell:: Cell ;
86
88
use std:: collections:: hash_map:: Entry ;
87
89
use std:: fmt:: Debug ;
88
90
use std:: hash;
89
91
use std:: marker:: PhantomData ;
90
92
91
- mod node_index;
92
- use self :: node_index:: NodeIndex ;
93
-
94
93
mod graphviz;
95
94
96
95
#[ cfg( test) ]
97
96
mod tests;
98
97
98
+ newtype_index ! {
99
+ pub struct NodeIndex { .. }
100
+ }
101
+
99
102
pub trait ForestObligation : Clone + Debug {
100
103
type Predicate : Clone + hash:: Hash + Eq + Debug ;
101
104
@@ -151,6 +154,10 @@ pub struct ObligationForest<O: ForestObligation> {
151
154
/// At all times we maintain the invariant that every node appears
152
155
/// at a higher index than its parent. This is needed by the
153
156
/// backtrace iterator (which uses `split_at`).
157
+ ///
158
+ /// Ideally, this would be an `IndexVec<NodeIndex, Node<O>>`. But that is
159
+ /// slower, because this vector is accessed so often that the
160
+ /// `u32`-to-`usize` conversions required for accesses are significant.
154
161
nodes : Vec < Node < O > > ,
155
162
156
163
/// A cache of predicates that have been successfully completed.
@@ -178,13 +185,19 @@ struct Node<O> {
178
185
obligation : O ,
179
186
state : Cell < NodeState > ,
180
187
181
- /// The parent of a node - the original obligation of
182
- /// which it is a subobligation. Except for error reporting,
183
- /// it is just like any member of `dependents`.
188
+ /// The parent of a node - the original obligation of which it is a
189
+ /// subobligation. Except for error reporting, it is just like any member
190
+ /// of `dependents`.
191
+ ///
192
+ /// Unlike `ObligationForest::nodes`, this uses `NodeIndex` rather than
193
+ /// `usize` for the index, because keeping the size down is more important
194
+ /// than the cost of converting to a `usize` for indexing.
184
195
parent : Option < NodeIndex > ,
185
196
186
- /// Obligations that depend on this obligation for their
187
- /// completion. They must all be in a non-pending state.
197
+ /// Obligations that depend on this obligation for their completion. They
198
+ /// must all be in a non-pending state.
199
+ ///
200
+ /// This uses `NodeIndex` for the same reason as `parent`.
188
201
dependents : Vec < NodeIndex > ,
189
202
190
203
/// Identifier of the obligation tree to which this node belongs.
@@ -294,7 +307,7 @@ impl<O: ForestObligation> ObligationForest<O> {
294
307
Entry :: Occupied ( o) => {
295
308
debug ! ( "register_obligation_at({:?}, {:?}) - duplicate of {:?}!" ,
296
309
obligation, parent, o. get( ) ) ;
297
- let node = & mut self . nodes [ o. get ( ) . get ( ) ] ;
310
+ let node = & mut self . nodes [ o. get ( ) . index ( ) ] ;
298
311
if let Some ( parent_index) = parent {
299
312
// If the node is already in `waiting_cache`, it's already
300
313
// been marked with a parent. (It's possible that parent
@@ -318,7 +331,7 @@ impl<O: ForestObligation> ObligationForest<O> {
318
331
319
332
let obligation_tree_id = match parent {
320
333
Some ( parent_index) => {
321
- self . nodes [ parent_index. get ( ) ] . obligation_tree_id
334
+ self . nodes [ parent_index. index ( ) ] . obligation_tree_id
322
335
}
323
336
None => self . obligation_tree_id_generator . next ( ) . unwrap ( )
324
337
} ;
@@ -506,7 +519,7 @@ impl<O: ForestObligation> ObligationForest<O> {
506
519
node. state . set ( NodeState :: OnDfsStack ) ;
507
520
stack. push ( i) ;
508
521
for index in node. parent . iter ( ) . chain ( node. dependents . iter ( ) ) {
509
- self . find_cycles_from_node ( stack, processor, index. get ( ) ) ;
522
+ self . find_cycles_from_node ( stack, processor, index. index ( ) ) ;
510
523
}
511
524
stack. pop ( ) ;
512
525
node. state . set ( NodeState :: Done ) ;
@@ -531,11 +544,11 @@ impl<O: ForestObligation> ObligationForest<O> {
531
544
let node = & self . nodes [ i] ;
532
545
node. state . set ( NodeState :: Error ) ;
533
546
trace. push ( node. obligation . clone ( ) ) ;
534
- error_stack. extend ( node. dependents . iter ( ) . map ( |index| index. get ( ) ) ) ;
547
+ error_stack. extend ( node. dependents . iter ( ) . map ( |index| index. index ( ) ) ) ;
535
548
536
549
// Loop to the parent.
537
550
match node. parent {
538
- Some ( parent_index) => i = parent_index. get ( ) ,
551
+ Some ( parent_index) => i = parent_index. index ( ) ,
539
552
None => break
540
553
}
541
554
}
@@ -548,7 +561,7 @@ impl<O: ForestObligation> ObligationForest<O> {
548
561
}
549
562
550
563
error_stack. extend (
551
- node. parent . iter ( ) . chain ( node. dependents . iter ( ) ) . map ( |index| index. get ( ) )
564
+ node. parent . iter ( ) . chain ( node. dependents . iter ( ) ) . map ( |index| index. index ( ) )
552
565
) ;
553
566
}
554
567
@@ -560,7 +573,7 @@ impl<O: ForestObligation> ObligationForest<O> {
560
573
#[ inline( always) ]
561
574
fn inlined_mark_neighbors_as_waiting_from ( & self , node : & Node < O > ) {
562
575
for dependent in node. parent . iter ( ) . chain ( node. dependents . iter ( ) ) {
563
- self . mark_as_waiting_from ( & self . nodes [ dependent. get ( ) ] ) ;
576
+ self . mark_as_waiting_from ( & self . nodes [ dependent. index ( ) ] ) ;
564
577
}
565
578
}
566
579
@@ -686,7 +699,7 @@ impl<O: ForestObligation> ObligationForest<O> {
686
699
687
700
for node in & mut self . nodes {
688
701
if let Some ( index) = node. parent {
689
- let new_i = node_rewrites[ index. get ( ) ] ;
702
+ let new_i = node_rewrites[ index. index ( ) ] ;
690
703
if new_i >= nodes_len {
691
704
// parent dead due to error
692
705
node. parent = None ;
@@ -697,7 +710,7 @@ impl<O: ForestObligation> ObligationForest<O> {
697
710
698
711
let mut i = 0 ;
699
712
while i < node. dependents . len ( ) {
700
- let new_i = node_rewrites[ node. dependents [ i] . get ( ) ] ;
713
+ let new_i = node_rewrites[ node. dependents [ i] . index ( ) ] ;
701
714
if new_i >= nodes_len {
702
715
node. dependents . swap_remove ( i) ;
703
716
} else {
@@ -709,7 +722,7 @@ impl<O: ForestObligation> ObligationForest<O> {
709
722
710
723
let mut kill_list = vec ! [ ] ;
711
724
for ( predicate, index) in & mut self . waiting_cache {
712
- let new_i = node_rewrites[ index. get ( ) ] ;
725
+ let new_i = node_rewrites[ index. index ( ) ] ;
713
726
if new_i >= nodes_len {
714
727
kill_list. push ( predicate. clone ( ) ) ;
715
728
} else {
0 commit comments