]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/hir/map/definitions.rs
Rollup merge of #41135 - japaric:unstable-docs, r=steveklabnik
[rust.git] / src / librustc / hir / map / definitions.rs
index 809d5db3071d7be75607974035a056b28ef3c377..6118df2ddfc899a527cf60077e86fb47ddbeb453 100644 (file)
@@ -21,7 +21,7 @@
 use rustc_data_structures::stable_hasher::StableHasher;
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 use std::fmt::Write;
-use std::hash::{Hash, Hasher};
+use std::hash::Hash;
 use syntax::ast;
 use syntax::symbol::{Symbol, InternedString};
 use ty::TyCtxt;
@@ -34,6 +34,7 @@
 pub struct DefPathTable {
     index_to_key: [Vec<DefKey>; 2],
     key_to_index: FxHashMap<DefKey, DefIndex>,
+    def_path_hashes: [Vec<u64>; 2],
 }
 
 // Unfortunately we have to provide a manual impl of Clone because of the
@@ -44,6 +45,8 @@ fn clone(&self) -> Self {
             index_to_key: [self.index_to_key[0].clone(),
                            self.index_to_key[1].clone()],
             key_to_index: self.key_to_index.clone(),
+            def_path_hashes: [self.def_path_hashes[0].clone(),
+                              self.def_path_hashes[1].clone()],
         }
     }
 }
@@ -52,6 +55,7 @@ impl DefPathTable {
 
     fn allocate(&mut self,
                 key: DefKey,
+                def_path_hash: u64,
                 address_space: DefIndexAddressSpace)
                 -> DefIndex {
         let index = {
@@ -62,6 +66,9 @@ fn allocate(&mut self,
             index
         };
         self.key_to_index.insert(key, index);
+        self.def_path_hashes[address_space.index()].push(def_path_hash);
+        debug_assert!(self.def_path_hashes[address_space.index()].len() ==
+                      self.index_to_key[address_space.index()].len());
         index
     }
 
@@ -71,6 +78,12 @@ pub fn def_key(&self, index: DefIndex) -> DefKey {
                          [index.as_array_index()].clone()
     }
 
+    #[inline(always)]
+    pub fn def_path_hash(&self, index: DefIndex) -> u64 {
+        self.def_path_hashes[index.address_space().index()]
+                            [index.as_array_index()]
+    }
+
     #[inline(always)]
     pub fn def_index_for_def_key(&self, key: &DefKey) -> Option<DefIndex> {
         self.key_to_index.get(key).cloned()
@@ -116,17 +129,28 @@ pub fn retrace_path(&self,
 
 impl Encodable for DefPathTable {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        // Index to key
         self.index_to_key[DefIndexAddressSpace::Low.index()].encode(s)?;
-        self.index_to_key[DefIndexAddressSpace::High.index()].encode(s)
+        self.index_to_key[DefIndexAddressSpace::High.index()].encode(s)?;
+
+        // DefPath hashes
+        self.def_path_hashes[DefIndexAddressSpace::Low.index()].encode(s)?;
+        self.def_path_hashes[DefIndexAddressSpace::High.index()].encode(s)?;
+
+        Ok(())
     }
 }
 
 impl Decodable for DefPathTable {
     fn decode<D: Decoder>(d: &mut D) -> Result<DefPathTable, D::Error> {
         let index_to_key_lo: Vec<DefKey> = Decodable::decode(d)?;
-        let index_to_key_high: Vec<DefKey> = Decodable::decode(d)?;
+        let index_to_key_hi: Vec<DefKey> = Decodable::decode(d)?;
 
-        let index_to_key = [index_to_key_lo, index_to_key_high];
+        let def_path_hashes_lo: Vec<u64> = Decodable::decode(d)?;
+        let def_path_hashes_hi: Vec<u64> = Decodable::decode(d)?;
+
+        let index_to_key = [index_to_key_lo, index_to_key_hi];
+        let def_path_hashes = [def_path_hashes_lo, def_path_hashes_hi];
 
         let mut key_to_index = FxHashMap();
 
@@ -141,6 +165,7 @@ fn decode<D: Decoder>(d: &mut D) -> Result<DefPathTable, D::Error> {
         Ok(DefPathTable {
             index_to_key: index_to_key,
             key_to_index: key_to_index,
+            def_path_hashes: def_path_hashes,
         })
     }
 }
@@ -184,6 +209,29 @@ pub struct DefKey {
     pub disambiguated_data: DisambiguatedDefPathData,
 }
 
+impl DefKey {
+    fn compute_stable_hash(&self, parent_hash: u64) -> u64 {
+        let mut hasher = StableHasher::new();
+
+        // We hash a 0u8 here to disambiguate between regular DefPath hashes,
+        // and the special "root_parent" below.
+        0u8.hash(&mut hasher);
+        parent_hash.hash(&mut hasher);
+        self.disambiguated_data.hash(&mut hasher);
+        hasher.finish()
+    }
+
+    fn root_parent_stable_hash(crate_name: &str, crate_disambiguator: &str) -> u64 {
+        let mut hasher = StableHasher::new();
+        // Disambiguate this from a regular DefPath hash,
+        // see compute_stable_hash() above.
+        1u8.hash(&mut hasher);
+        crate_name.hash(&mut hasher);
+        crate_disambiguator.hash(&mut hasher);
+        hasher.finish()
+    }
+}
+
 /// Pair of `DefPathData` and an integer disambiguator. The integer is
 /// normally 0, but in the event that there are multiple defs with the
 /// same `parent` and `data`, we use this field to disambiguate
@@ -271,19 +319,6 @@ pub fn to_string_no_crate(&self) -> String {
 
         s
     }
-
-    pub fn deterministic_hash(&self, tcx: TyCtxt) -> u64 {
-        debug!("deterministic_hash({:?})", self);
-        let mut state = StableHasher::new();
-        self.deterministic_hash_to(tcx, &mut state);
-        state.finish()
-    }
-
-    pub fn deterministic_hash_to<H: Hasher>(&self, tcx: TyCtxt, state: &mut H) {
-        tcx.original_crate_name(self.krate).as_str().hash(state);
-        tcx.crate_disambiguator(self.krate).as_str().hash(state);
-        self.data.hash(state);
-    }
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
@@ -338,6 +373,7 @@ pub fn new() -> Definitions {
             table: DefPathTable {
                 index_to_key: [vec![], vec![]],
                 key_to_index: FxHashMap(),
+                def_path_hashes: [vec![], vec![]],
             },
             node_to_def_index: NodeMap(),
             def_index_to_node: [vec![], vec![]],
@@ -359,6 +395,11 @@ pub fn def_key(&self, index: DefIndex) -> DefKey {
         self.table.def_key(index)
     }
 
+    #[inline(always)]
+    pub fn def_path_hash(&self, index: DefIndex) -> u64 {
+        self.table.def_path_hash(index)
+    }
+
     pub fn def_index_for_def_key(&self, key: DefKey) -> Option<DefIndex> {
         self.table.def_index_for_def_key(&key)
     }
@@ -394,12 +435,42 @@ pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
         }
     }
 
+    pub fn node_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId {
+        self.node_to_hir_id[node_id]
+    }
+
+    /// Add a definition with a parent definition.
+    pub fn create_root_def(&mut self,
+                           crate_name: &str,
+                           crate_disambiguator: &str)
+                           -> DefIndex {
+        let key = DefKey {
+            parent: None,
+            disambiguated_data: DisambiguatedDefPathData {
+                data: DefPathData::CrateRoot,
+                disambiguator: 0
+            }
+        };
+
+        let parent_hash = DefKey::root_parent_stable_hash(crate_name,
+                                                          crate_disambiguator);
+        let def_path_hash = key.compute_stable_hash(parent_hash);
+
+        // Create the definition.
+        let address_space = super::ITEM_LIKE_SPACE;
+        let index = self.table.allocate(key, def_path_hash, address_space);
+        assert!(self.def_index_to_node[address_space.index()].is_empty());
+        self.def_index_to_node[address_space.index()].push(ast::CRATE_NODE_ID);
+        self.node_to_def_index.insert(ast::CRATE_NODE_ID, index);
+
+        index
+    }
+
     /// Add a definition with a parent definition.
     pub fn create_def_with_parent(&mut self,
-                                  parent: Option<DefIndex>,
+                                  parent: DefIndex,
                                   node_id: ast::NodeId,
                                   data: DefPathData,
-                                  // is_owner: bool)
                                   address_space: DefIndexAddressSpace)
                                   -> DefIndex {
         debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
@@ -411,12 +482,13 @@ pub fn create_def_with_parent(&mut self,
                 data,
                 self.table.def_key(self.node_to_def_index[&node_id]));
 
-        assert_eq!(parent.is_some(), data != DefPathData::CrateRoot);
+        // The root node must be created with create_root_def()
+        assert!(data != DefPathData::CrateRoot);
 
         // Find a unique DefKey. This basically means incrementing the disambiguator
         // until we get no match.
         let mut key = DefKey {
-            parent: parent,
+            parent: Some(parent),
             disambiguated_data: DisambiguatedDefPathData {
                 data: data,
                 disambiguator: 0
@@ -427,10 +499,13 @@ pub fn create_def_with_parent(&mut self,
             key.disambiguated_data.disambiguator += 1;
         }
 
+        let parent_hash = self.table.def_path_hash(parent);
+        let def_path_hash = key.compute_stable_hash(parent_hash);
+
         debug!("create_def_with_parent: after disambiguation, key = {:?}", key);
 
         // Create the definition.
-        let index = self.table.allocate(key, address_space);
+        let index = self.table.allocate(key, def_path_hash, address_space);
         assert_eq!(index.as_array_index(),
                    self.def_index_to_node[address_space.index()].len());
         self.def_index_to_node[address_space.index()].push(node_id);