Skip to content

Commit cf3a562

Browse files
committed
Remove NodeIndex.
The size of the indices doesn't matter much here, and having a `newtype_index!` index type without also using `IndexVec` requires lots of conversions. So this commit removes `NodeIndex` in favour of uniform use of `usize` as the index type. As well as making the code slightly more concise, it also slightly speeds things up.
1 parent 476e75d commit cf3a562

File tree

2 files changed

+27
-36
lines changed

2 files changed

+27
-36
lines changed

src/librustc_data_structures/obligation_forest/graphviz.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ impl<'a, O: ForestObligation + 'a> dot::GraphWalk<'a> for &'a ObligationForest<O
7474
.flat_map(|i| {
7575
let node = &self.nodes[i];
7676

77-
node.dependents.iter().map(move |p| (p.index(), i))
77+
node.dependents.iter().map(move |&d| (d, i))
7878
})
7979
.collect()
8080
}

src/librustc_data_structures/obligation_forest/mod.rs

+26-35
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,6 @@
7373
//! aren't needed anymore.
7474
7575
use crate::fx::{FxHashMap, FxHashSet};
76-
use crate::indexed_vec::Idx;
77-
use crate::newtype_index;
7876

7977
use std::cell::{Cell, RefCell};
8078
use std::collections::hash_map::Entry;
@@ -87,10 +85,6 @@ mod graphviz;
8785
#[cfg(test)]
8886
mod tests;
8987

90-
newtype_index! {
91-
pub struct NodeIndex { .. }
92-
}
93-
9488
pub trait ForestObligation : Clone + Debug {
9589
type Predicate : Clone + hash::Hash + Eq + Debug;
9690

@@ -143,9 +137,10 @@ pub struct ObligationForest<O: ForestObligation> {
143137
/// At the end of processing, those nodes will be removed by a
144138
/// call to `compress`.
145139
///
146-
/// Ideally, this would be an `IndexVec<NodeIndex, Node<O>>`. But that is
147-
/// slower, because this vector is accessed so often that the
148-
/// `u32`-to-`usize` conversions required for accesses are significant.
140+
/// `usize` indices are used here and throughout this module, rather than
141+
/// `newtype_index!` indices, because this code is hot enough that the
142+
/// `u32`-to-`usize` conversions that would be required are significant,
143+
/// and space considerations are not important.
149144
nodes: Vec<Node<O>>,
150145

151146
/// A cache of predicates that have been successfully completed.
@@ -154,7 +149,7 @@ pub struct ObligationForest<O: ForestObligation> {
154149
/// A cache of the nodes in `nodes`, indexed by predicate. Unfortunately,
155150
/// its contents are not guaranteed to match those of `nodes`. See the
156151
/// comments in `process_obligation` for details.
157-
waiting_cache: FxHashMap<O::Predicate, NodeIndex>,
152+
waiting_cache: FxHashMap<O::Predicate, usize>,
158153

159154
/// A scratch vector reused in various operations, to avoid allocating new
160155
/// vectors.
@@ -179,12 +174,12 @@ struct Node<O> {
179174

180175
/// Obligations that depend on this obligation for their completion. They
181176
/// must all be in a non-pending state.
182-
dependents: Vec<NodeIndex>,
177+
dependents: Vec<usize>,
183178

184179
/// If true, dependents[0] points to a "parent" node, which requires
185180
/// special treatment upon error but is otherwise treated the same.
186181
/// (It would be more idiomatic to store the parent node in a separate
187-
/// `Option<NodeIndex>` field, but that slows down the common case of
182+
/// `Option<usize>` field, but that slows down the common case of
188183
/// iterating over the parent and other descendants together.)
189184
has_parent: bool,
190185

@@ -194,7 +189,7 @@ struct Node<O> {
194189

195190
impl<O> Node<O> {
196191
fn new(
197-
parent: Option<NodeIndex>,
192+
parent: Option<usize>,
198193
obligation: O,
199194
obligation_tree_id: ObligationTreeId
200195
) -> Node<O> {
@@ -303,9 +298,7 @@ impl<O: ForestObligation> ObligationForest<O> {
303298
}
304299

305300
// Returns Err(()) if we already know this obligation failed.
306-
fn register_obligation_at(&mut self, obligation: O, parent: Option<NodeIndex>)
307-
-> Result<(), ()>
308-
{
301+
fn register_obligation_at(&mut self, obligation: O, parent: Option<usize>) -> Result<(), ()> {
309302
if self.done_cache.contains(obligation.as_predicate()) {
310303
return Ok(());
311304
}
@@ -314,7 +307,7 @@ impl<O: ForestObligation> ObligationForest<O> {
314307
Entry::Occupied(o) => {
315308
debug!("register_obligation_at({:?}, {:?}) - duplicate of {:?}!",
316309
obligation, parent, o.get());
317-
let node = &mut self.nodes[o.get().index()];
310+
let node = &mut self.nodes[*o.get()];
318311
if let Some(parent_index) = parent {
319312
// If the node is already in `waiting_cache`, it has
320313
// already had its chance to be marked with a parent. So if
@@ -335,10 +328,8 @@ impl<O: ForestObligation> ObligationForest<O> {
335328
obligation, parent, self.nodes.len());
336329

337330
let obligation_tree_id = match parent {
338-
Some(parent_index) => {
339-
self.nodes[parent_index.index()].obligation_tree_id
340-
}
341-
None => self.obligation_tree_id_generator.next().unwrap()
331+
Some(parent_index) => self.nodes[parent_index].obligation_tree_id,
332+
None => self.obligation_tree_id_generator.next().unwrap(),
342333
};
343334

344335
let already_failed =
@@ -351,7 +342,7 @@ impl<O: ForestObligation> ObligationForest<O> {
351342
if already_failed {
352343
Err(())
353344
} else {
354-
v.insert(NodeIndex::new(self.nodes.len()));
345+
v.insert(self.nodes.len());
355346
self.nodes.push(Node::new(parent, obligation, obligation_tree_id));
356347
Ok(())
357348
}
@@ -437,7 +428,7 @@ impl<O: ForestObligation> ObligationForest<O> {
437428
for child in children {
438429
let st = self.register_obligation_at(
439430
child,
440-
Some(NodeIndex::new(i))
431+
Some(i)
441432
);
442433
if let Err(()) = st {
443434
// Error already reported - propagate it
@@ -522,8 +513,8 @@ impl<O: ForestObligation> ObligationForest<O> {
522513
NodeState::Success => {
523514
node.state.set(NodeState::OnDfsStack);
524515
stack.push(i);
525-
for index in node.dependents.iter() {
526-
self.find_cycles_from_node(stack, processor, index.index());
516+
for &index in node.dependents.iter() {
517+
self.find_cycles_from_node(stack, processor, index);
527518
}
528519
stack.pop();
529520
node.state.set(NodeState::Done);
@@ -551,11 +542,11 @@ impl<O: ForestObligation> ObligationForest<O> {
551542
if node.has_parent {
552543
// The first dependent is the parent, which is treated
553544
// specially.
554-
error_stack.extend(node.dependents.iter().skip(1).map(|index| index.index()));
555-
i = node.dependents[0].index();
545+
error_stack.extend(node.dependents.iter().skip(1));
546+
i = node.dependents[0];
556547
} else {
557548
// No parent; treat all dependents non-specially.
558-
error_stack.extend(node.dependents.iter().map(|index| index.index()));
549+
error_stack.extend(node.dependents.iter());
559550
break;
560551
}
561552
}
@@ -567,7 +558,7 @@ impl<O: ForestObligation> ObligationForest<O> {
567558
_ => node.state.set(NodeState::Error),
568559
}
569560

570-
error_stack.extend(node.dependents.iter().map(|index| index.index()));
561+
error_stack.extend(node.dependents.iter());
571562
}
572563

573564
self.scratch.replace(error_stack);
@@ -577,8 +568,8 @@ impl<O: ForestObligation> ObligationForest<O> {
577568
// This always-inlined function is for the hot call site.
578569
#[inline(always)]
579570
fn inlined_mark_neighbors_as_waiting_from(&self, node: &Node<O>) {
580-
for dependent in node.dependents.iter() {
581-
self.mark_as_waiting_from(&self.nodes[dependent.index()]);
571+
for &dependent in node.dependents.iter() {
572+
self.mark_as_waiting_from(&self.nodes[dependent]);
582573
}
583574
}
584575

@@ -708,15 +699,15 @@ impl<O: ForestObligation> ObligationForest<O> {
708699
for node in &mut self.nodes {
709700
let mut i = 0;
710701
while i < node.dependents.len() {
711-
let new_i = node_rewrites[node.dependents[i].index()];
702+
let new_i = node_rewrites[node.dependents[i]];
712703
if new_i >= nodes_len {
713704
node.dependents.swap_remove(i);
714705
if i == 0 && node.has_parent {
715706
// We just removed the parent.
716707
node.has_parent = false;
717708
}
718709
} else {
719-
node.dependents[i] = NodeIndex::new(new_i);
710+
node.dependents[i] = new_i;
720711
i += 1;
721712
}
722713
}
@@ -725,11 +716,11 @@ impl<O: ForestObligation> ObligationForest<O> {
725716
// This updating of `self.waiting_cache` is necessary because the
726717
// removal of nodes within `compress` can fail. See above.
727718
self.waiting_cache.retain(|_predicate, index| {
728-
let new_i = node_rewrites[index.index()];
719+
let new_i = node_rewrites[*index];
729720
if new_i >= nodes_len {
730721
false
731722
} else {
732-
*index = NodeIndex::new(new_i);
723+
*index = new_i;
733724
true
734725
}
735726
});

0 commit comments

Comments
 (0)