Skip to content

Commit 43c0d2c

Browse files
committed
Redefine NodeIndex as a newtype_index!.
This commit removes the custom index implementation of `NodeIndex`, which probably predates `newtype_index!`. As well as eliminating code, it improves the debugging experience, because the custom implementation had the property of being incremented by 1 (so it could use `NonZeroU32`), which was incredibly confusing if you didn't expect it. For some reason, I also had to remove an `unsafe` block marker from `from_u32_unchecked()` that the compiler said was now unnecessary.
1 parent 04b1111 commit 43c0d2c

File tree

4 files changed

+35
-42
lines changed

4 files changed

+35
-42
lines changed

src/librustc_data_structures/indexed_vec.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ macro_rules! newtype_index {
149149

150150
#[inline]
151151
$v const unsafe fn from_u32_unchecked(value: u32) -> Self {
152-
unsafe { $type { private: value } }
152+
$type { private: value }
153153
}
154154

155155
/// Extracts the value of this index as an integer.

src/librustc_data_structures/obligation_forest/graphviz.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ 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.parent.iter().map(|p| p.get())
78-
.chain(node.dependents.iter().map(|p| p.get()))
79-
.map(move |p| (p, i))
77+
node.parent.iter()
78+
.chain(node.dependents.iter())
79+
.map(move |p| (p.index(), i))
8080
})
8181
.collect()
8282
}

src/librustc_data_structures/obligation_forest/mod.rs

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -81,21 +81,24 @@
8181
//! nodes, which aren't needed anymore.
8282
8383
use crate::fx::{FxHashMap, FxHashSet};
84+
use crate::indexed_vec::Idx;
85+
use crate::newtype_index;
8486

8587
use std::cell::Cell;
8688
use std::collections::hash_map::Entry;
8789
use std::fmt::Debug;
8890
use std::hash;
8991
use std::marker::PhantomData;
9092

91-
mod node_index;
92-
use self::node_index::NodeIndex;
93-
9493
mod graphviz;
9594

9695
#[cfg(test)]
9796
mod tests;
9897

98+
newtype_index! {
99+
pub struct NodeIndex { .. }
100+
}
101+
99102
pub trait ForestObligation : Clone + Debug {
100103
type Predicate : Clone + hash::Hash + Eq + Debug;
101104

@@ -151,6 +154,10 @@ pub struct ObligationForest<O: ForestObligation> {
151154
/// At all times we maintain the invariant that every node appears
152155
/// at a higher index than its parent. This is needed by the
153156
/// 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.
154161
nodes: Vec<Node<O>>,
155162

156163
/// A cache of predicates that have been successfully completed.
@@ -178,13 +185,19 @@ struct Node<O> {
178185
obligation: O,
179186
state: Cell<NodeState>,
180187

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.
184195
parent: Option<NodeIndex>,
185196

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`.
188201
dependents: Vec<NodeIndex>,
189202

190203
/// Identifier of the obligation tree to which this node belongs.
@@ -294,7 +307,7 @@ impl<O: ForestObligation> ObligationForest<O> {
294307
Entry::Occupied(o) => {
295308
debug!("register_obligation_at({:?}, {:?}) - duplicate of {:?}!",
296309
obligation, parent, o.get());
297-
let node = &mut self.nodes[o.get().get()];
310+
let node = &mut self.nodes[o.get().index()];
298311
if let Some(parent_index) = parent {
299312
// If the node is already in `waiting_cache`, it's already
300313
// been marked with a parent. (It's possible that parent
@@ -318,7 +331,7 @@ impl<O: ForestObligation> ObligationForest<O> {
318331

319332
let obligation_tree_id = match parent {
320333
Some(parent_index) => {
321-
self.nodes[parent_index.get()].obligation_tree_id
334+
self.nodes[parent_index.index()].obligation_tree_id
322335
}
323336
None => self.obligation_tree_id_generator.next().unwrap()
324337
};
@@ -506,7 +519,7 @@ impl<O: ForestObligation> ObligationForest<O> {
506519
node.state.set(NodeState::OnDfsStack);
507520
stack.push(i);
508521
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());
510523
}
511524
stack.pop();
512525
node.state.set(NodeState::Done);
@@ -531,11 +544,11 @@ impl<O: ForestObligation> ObligationForest<O> {
531544
let node = &self.nodes[i];
532545
node.state.set(NodeState::Error);
533546
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()));
535548

536549
// Loop to the parent.
537550
match node.parent {
538-
Some(parent_index) => i = parent_index.get(),
551+
Some(parent_index) => i = parent_index.index(),
539552
None => break
540553
}
541554
}
@@ -548,7 +561,7 @@ impl<O: ForestObligation> ObligationForest<O> {
548561
}
549562

550563
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())
552565
);
553566
}
554567

@@ -560,7 +573,7 @@ impl<O: ForestObligation> ObligationForest<O> {
560573
#[inline(always)]
561574
fn inlined_mark_neighbors_as_waiting_from(&self, node: &Node<O>) {
562575
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()]);
564577
}
565578
}
566579

@@ -686,7 +699,7 @@ impl<O: ForestObligation> ObligationForest<O> {
686699

687700
for node in &mut self.nodes {
688701
if let Some(index) = node.parent {
689-
let new_i = node_rewrites[index.get()];
702+
let new_i = node_rewrites[index.index()];
690703
if new_i >= nodes_len {
691704
// parent dead due to error
692705
node.parent = None;
@@ -697,7 +710,7 @@ impl<O: ForestObligation> ObligationForest<O> {
697710

698711
let mut i = 0;
699712
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()];
701714
if new_i >= nodes_len {
702715
node.dependents.swap_remove(i);
703716
} else {
@@ -709,7 +722,7 @@ impl<O: ForestObligation> ObligationForest<O> {
709722

710723
let mut kill_list = vec![];
711724
for (predicate, index) in &mut self.waiting_cache {
712-
let new_i = node_rewrites[index.get()];
725+
let new_i = node_rewrites[index.index()];
713726
if new_i >= nodes_len {
714727
kill_list.push(predicate.clone());
715728
} else {

src/librustc_data_structures/obligation_forest/node_index.rs

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)