about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicholas Nethercote <nnethercote@mozilla.com>2019-09-16 11:53:12 +1000
committerNicholas Nethercote <nnethercote@mozilla.com>2019-09-16 11:53:12 +1000
commit43c0d2ce8eae322e0b1ffe945e356e30c808dbb3 (patch)
tree2137d29d9f4e87b827fd5ea458c47c774b4195e8
parent04b1111ae8dd97f3cf558654015b8101d270c634 (diff)
downloadrust-43c0d2ce8eae322e0b1ffe945e356e30c808dbb3.tar.gz
rust-43c0d2ce8eae322e0b1ffe945e356e30c808dbb3.zip
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.
-rw-r--r--src/librustc_data_structures/indexed_vec.rs2
-rw-r--r--src/librustc_data_structures/obligation_forest/graphviz.rs6
-rw-r--r--src/librustc_data_structures/obligation_forest/mod.rs49
-rw-r--r--src/librustc_data_structures/obligation_forest/node_index.rs20
4 files changed, 35 insertions, 42 deletions
diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs
index 6f40d059be2..6e80b48a685 100644
--- a/src/librustc_data_structures/indexed_vec.rs
+++ b/src/librustc_data_structures/indexed_vec.rs
@@ -149,7 +149,7 @@ macro_rules! newtype_index {
 
             #[inline]
             $v const unsafe fn from_u32_unchecked(value: u32) -> Self {
-                unsafe { $type { private: value } }
+                $type { private: value }
             }
 
             /// Extracts the value of this index as an integer.
diff --git a/src/librustc_data_structures/obligation_forest/graphviz.rs b/src/librustc_data_structures/obligation_forest/graphviz.rs
index a0363e165e0..b2120b182fa 100644
--- a/src/librustc_data_structures/obligation_forest/graphviz.rs
+++ b/src/librustc_data_structures/obligation_forest/graphviz.rs
@@ -74,9 +74,9 @@ impl<'a, O: ForestObligation + 'a> dot::GraphWalk<'a> for &'a ObligationForest<O
             .flat_map(|i| {
                 let node = &self.nodes[i];
 
-                node.parent.iter().map(|p| p.get())
-                    .chain(node.dependents.iter().map(|p| p.get()))
-                    .map(move |p| (p, i))
+                node.parent.iter()
+                    .chain(node.dependents.iter())
+                    .map(move |p| (p.index(), i))
             })
             .collect()
     }
diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs
index 7ef1953e2d8..cfc3b8194a6 100644
--- a/src/librustc_data_structures/obligation_forest/mod.rs
+++ b/src/librustc_data_structures/obligation_forest/mod.rs
@@ -81,6 +81,8 @@
 //! nodes, which aren't needed anymore.
 
 use crate::fx::{FxHashMap, FxHashSet};
+use crate::indexed_vec::Idx;
+use crate::newtype_index;
 
 use std::cell::Cell;
 use std::collections::hash_map::Entry;
@@ -88,14 +90,15 @@ use std::fmt::Debug;
 use std::hash;
 use std::marker::PhantomData;
 
-mod node_index;
-use self::node_index::NodeIndex;
-
 mod graphviz;
 
 #[cfg(test)]
 mod tests;
 
+newtype_index! {
+    pub struct NodeIndex { .. }
+}
+
 pub trait ForestObligation : Clone + Debug {
     type Predicate : Clone + hash::Hash + Eq + Debug;
 
@@ -151,6 +154,10 @@ pub struct ObligationForest<O: ForestObligation> {
     /// At all times we maintain the invariant that every node appears
     /// at a higher index than its parent. This is needed by the
     /// backtrace iterator (which uses `split_at`).
+    ///
+    /// Ideally, this would be an `IndexVec<NodeIndex, Node<O>>`. But that is
+    /// slower, because this vector is accessed so often that the
+    /// `u32`-to-`usize` conversions required for accesses are significant.
     nodes: Vec<Node<O>>,
 
     /// A cache of predicates that have been successfully completed.
@@ -178,13 +185,19 @@ struct Node<O> {
     obligation: O,
     state: Cell<NodeState>,
 
-    /// The parent of a node - the original obligation of
-    /// which it is a subobligation. Except for error reporting,
-    /// it is just like any member of `dependents`.
+    /// The parent of a node - the original obligation of which it is a
+    /// subobligation. Except for error reporting, it is just like any member
+    /// of `dependents`.
+    ///
+    /// Unlike `ObligationForest::nodes`, this uses `NodeIndex` rather than
+    /// `usize` for the index, because keeping the size down is more important
+    /// than the cost of converting to a `usize` for indexing.
     parent: Option<NodeIndex>,
 
-    /// Obligations that depend on this obligation for their
-    /// completion. They must all be in a non-pending state.
+    /// Obligations that depend on this obligation for their completion. They
+    /// must all be in a non-pending state.
+    ///
+    /// This uses `NodeIndex` for the same reason as `parent`.
     dependents: Vec<NodeIndex>,
 
     /// Identifier of the obligation tree to which this node belongs.
@@ -294,7 +307,7 @@ impl<O: ForestObligation> ObligationForest<O> {
             Entry::Occupied(o) => {
                 debug!("register_obligation_at({:?}, {:?}) - duplicate of {:?}!",
                        obligation, parent, o.get());
-                let node = &mut self.nodes[o.get().get()];
+                let node = &mut self.nodes[o.get().index()];
                 if let Some(parent_index) = parent {
                     // If the node is already in `waiting_cache`, it's already
                     // been marked with a parent. (It's possible that parent
@@ -318,7 +331,7 @@ impl<O: ForestObligation> ObligationForest<O> {
 
                 let obligation_tree_id = match parent {
                     Some(parent_index) => {
-                        self.nodes[parent_index.get()].obligation_tree_id
+                        self.nodes[parent_index.index()].obligation_tree_id
                     }
                     None => self.obligation_tree_id_generator.next().unwrap()
                 };
@@ -506,7 +519,7 @@ impl<O: ForestObligation> ObligationForest<O> {
                 node.state.set(NodeState::OnDfsStack);
                 stack.push(i);
                 for index in node.parent.iter().chain(node.dependents.iter()) {
-                    self.find_cycles_from_node(stack, processor, index.get());
+                    self.find_cycles_from_node(stack, processor, index.index());
                 }
                 stack.pop();
                 node.state.set(NodeState::Done);
@@ -531,11 +544,11 @@ impl<O: ForestObligation> ObligationForest<O> {
             let node = &self.nodes[i];
             node.state.set(NodeState::Error);
             trace.push(node.obligation.clone());
-            error_stack.extend(node.dependents.iter().map(|index| index.get()));
+            error_stack.extend(node.dependents.iter().map(|index| index.index()));
 
             // Loop to the parent.
             match node.parent {
-                Some(parent_index) => i = parent_index.get(),
+                Some(parent_index) => i = parent_index.index(),
                 None => break
             }
         }
@@ -548,7 +561,7 @@ impl<O: ForestObligation> ObligationForest<O> {
             }
 
             error_stack.extend(
-                node.parent.iter().chain(node.dependents.iter()).map(|index| index.get())
+                node.parent.iter().chain(node.dependents.iter()).map(|index| index.index())
             );
         }
 
@@ -560,7 +573,7 @@ impl<O: ForestObligation> ObligationForest<O> {
     #[inline(always)]
     fn inlined_mark_neighbors_as_waiting_from(&self, node: &Node<O>) {
         for dependent in node.parent.iter().chain(node.dependents.iter()) {
-            self.mark_as_waiting_from(&self.nodes[dependent.get()]);
+            self.mark_as_waiting_from(&self.nodes[dependent.index()]);
         }
     }
 
@@ -686,7 +699,7 @@ impl<O: ForestObligation> ObligationForest<O> {
 
         for node in &mut self.nodes {
             if let Some(index) = node.parent {
-                let new_i = node_rewrites[index.get()];
+                let new_i = node_rewrites[index.index()];
                 if new_i >= nodes_len {
                     // parent dead due to error
                     node.parent = None;
@@ -697,7 +710,7 @@ impl<O: ForestObligation> ObligationForest<O> {
 
             let mut i = 0;
             while i < node.dependents.len() {
-                let new_i = node_rewrites[node.dependents[i].get()];
+                let new_i = node_rewrites[node.dependents[i].index()];
                 if new_i >= nodes_len {
                     node.dependents.swap_remove(i);
                 } else {
@@ -709,7 +722,7 @@ impl<O: ForestObligation> ObligationForest<O> {
 
         let mut kill_list = vec![];
         for (predicate, index) in &mut self.waiting_cache {
-            let new_i = node_rewrites[index.get()];
+            let new_i = node_rewrites[index.index()];
             if new_i >= nodes_len {
                 kill_list.push(predicate.clone());
             } else {
diff --git a/src/librustc_data_structures/obligation_forest/node_index.rs b/src/librustc_data_structures/obligation_forest/node_index.rs
deleted file mode 100644
index 69ea473e054..00000000000
--- a/src/librustc_data_structures/obligation_forest/node_index.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use std::num::NonZeroU32;
-use std::u32;
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub struct NodeIndex {
-    index: NonZeroU32,
-}
-
-impl NodeIndex {
-    #[inline]
-    pub fn new(value: usize) -> NodeIndex {
-        assert!(value < (u32::MAX as usize));
-        NodeIndex { index: NonZeroU32::new((value as u32) + 1).unwrap() }
-    }
-
-    #[inline]
-    pub fn get(self) -> usize {
-        (self.index.get() - 1) as usize
-    }
-}