1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! For each definition, we track the following data. A definition
12 //! here is defined somewhat circularly as "something with a def-id",
13 //! but it generally corresponds to things like structs, enums, etc.
14 //! There are also some rather random cases (like const initializer
15 //! expressions) that are mostly just leftovers.
18 use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, DefIndexAddressSpace};
20 use rustc_data_structures::fx::FxHashMap;
21 use rustc_data_structures::indexed_vec::IndexVec;
22 use rustc_data_structures::stable_hasher::StableHasher;
23 use serialize::{Encodable, Decodable, Encoder, Decoder};
26 use syntax::ast::{self, Ident};
27 use syntax::ext::hygiene::{Mark, SyntaxContext};
28 use syntax::symbol::{Symbol, InternedString};
30 use util::nodemap::NodeMap;
32 /// The DefPathTable maps DefIndexes to DefKeys and vice versa.
33 /// Internally the DefPathTable holds a tree of DefKeys, where each DefKey
34 /// stores the DefIndex of its parent.
35 /// There is one DefPathTable for each crate.
36 pub struct DefPathTable {
37 index_to_key: [Vec<DefKey>; 2],
38 key_to_index: FxHashMap<DefKey, DefIndex>,
39 def_path_hashes: [Vec<Fingerprint>; 2],
42 // Unfortunately we have to provide a manual impl of Clone because of the
43 // fixed-sized array field.
44 impl Clone for DefPathTable {
45 fn clone(&self) -> Self {
47 index_to_key: [self.index_to_key[0].clone(),
48 self.index_to_key[1].clone()],
49 key_to_index: self.key_to_index.clone(),
50 def_path_hashes: [self.def_path_hashes[0].clone(),
51 self.def_path_hashes[1].clone()],
58 fn allocate(&mut self,
60 def_path_hash: Fingerprint,
61 address_space: DefIndexAddressSpace)
64 let index_to_key = &mut self.index_to_key[address_space.index()];
65 let index = DefIndex::new(index_to_key.len() + address_space.start());
66 debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index);
67 index_to_key.push(key.clone());
70 self.key_to_index.insert(key, index);
71 self.def_path_hashes[address_space.index()].push(def_path_hash);
72 debug_assert!(self.def_path_hashes[address_space.index()].len() ==
73 self.index_to_key[address_space.index()].len());
78 pub fn def_key(&self, index: DefIndex) -> DefKey {
79 self.index_to_key[index.address_space().index()]
80 [index.as_array_index()].clone()
84 pub fn def_path_hash(&self, index: DefIndex) -> Fingerprint {
85 self.def_path_hashes[index.address_space().index()]
86 [index.as_array_index()]
90 pub fn def_index_for_def_key(&self, key: &DefKey) -> Option<DefIndex> {
91 self.key_to_index.get(key).cloned()
95 pub fn contains_key(&self, key: &DefKey) -> bool {
96 self.key_to_index.contains_key(key)
99 pub fn retrace_path(&self,
100 path_data: &[DisambiguatedDefPathData])
101 -> Option<DefIndex> {
102 let root_key = DefKey {
104 disambiguated_data: DisambiguatedDefPathData {
105 data: DefPathData::CrateRoot,
110 let root_index = self.key_to_index
112 .expect("no root key?")
115 debug!("retrace_path: root_index={:?}", root_index);
117 let mut index = root_index;
118 for data in path_data {
119 let key = DefKey { parent: Some(index), disambiguated_data: data.clone() };
120 debug!("retrace_path: key={:?}", key);
121 match self.key_to_index.get(&key) {
122 Some(&i) => index = i,
132 impl Encodable for DefPathTable {
133 fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
135 self.index_to_key[DefIndexAddressSpace::Low.index()].encode(s)?;
136 self.index_to_key[DefIndexAddressSpace::High.index()].encode(s)?;
139 self.def_path_hashes[DefIndexAddressSpace::Low.index()].encode(s)?;
140 self.def_path_hashes[DefIndexAddressSpace::High.index()].encode(s)?;
146 impl Decodable for DefPathTable {
147 fn decode<D: Decoder>(d: &mut D) -> Result<DefPathTable, D::Error> {
148 let index_to_key_lo: Vec<DefKey> = Decodable::decode(d)?;
149 let index_to_key_hi: Vec<DefKey> = Decodable::decode(d)?;
151 let def_path_hashes_lo: Vec<Fingerprint> = Decodable::decode(d)?;
152 let def_path_hashes_hi: Vec<Fingerprint> = Decodable::decode(d)?;
154 let index_to_key = [index_to_key_lo, index_to_key_hi];
155 let def_path_hashes = [def_path_hashes_lo, def_path_hashes_hi];
157 let mut key_to_index = FxHashMap();
159 for space in &[DefIndexAddressSpace::Low, DefIndexAddressSpace::High] {
160 key_to_index.extend(index_to_key[space.index()]
163 .map(|(index, key)| (key.clone(),
164 DefIndex::new(index + space.start()))))
168 index_to_key: index_to_key,
169 key_to_index: key_to_index,
170 def_path_hashes: def_path_hashes,
176 /// The definition table containing node definitions.
177 /// It holds the DefPathTable for local DefIds/DefPaths and it also stores a
178 /// mapping from NodeIds to local DefIds.
179 pub struct Definitions {
181 node_to_def_index: NodeMap<DefIndex>,
182 def_index_to_node: [Vec<ast::NodeId>; 2],
183 pub(super) node_to_hir_id: IndexVec<ast::NodeId, hir::HirId>,
184 macro_def_scopes: FxHashMap<Mark, DefId>,
185 expansions: FxHashMap<DefIndex, Mark>,
188 // Unfortunately we have to provide a manual impl of Clone because of the
189 // fixed-sized array field.
190 impl Clone for Definitions {
191 fn clone(&self) -> Self {
193 table: self.table.clone(),
194 node_to_def_index: self.node_to_def_index.clone(),
196 self.def_index_to_node[0].clone(),
197 self.def_index_to_node[1].clone(),
199 node_to_hir_id: self.node_to_hir_id.clone(),
200 macro_def_scopes: self.macro_def_scopes.clone(),
201 expansions: self.expansions.clone(),
206 /// A unique identifier that we can use to lookup a definition
207 /// precisely. It combines the index of the definition's parent (if
208 /// any) with a `DisambiguatedDefPathData`.
209 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
212 pub parent: Option<DefIndex>,
214 /// Identifier of this node.
215 pub disambiguated_data: DisambiguatedDefPathData,
219 fn compute_stable_hash(&self, parent_hash: Fingerprint) -> Fingerprint {
220 let mut hasher = StableHasher::new();
222 // We hash a 0u8 here to disambiguate between regular DefPath hashes,
223 // and the special "root_parent" below.
224 0u8.hash(&mut hasher);
225 parent_hash.hash(&mut hasher);
226 self.disambiguated_data.hash(&mut hasher);
230 fn root_parent_stable_hash(crate_name: &str, crate_disambiguator: &str) -> Fingerprint {
231 let mut hasher = StableHasher::new();
232 // Disambiguate this from a regular DefPath hash,
233 // see compute_stable_hash() above.
234 1u8.hash(&mut hasher);
235 crate_name.hash(&mut hasher);
236 crate_disambiguator.hash(&mut hasher);
241 /// Pair of `DefPathData` and an integer disambiguator. The integer is
242 /// normally 0, but in the event that there are multiple defs with the
243 /// same `parent` and `data`, we use this field to disambiguate
244 /// between them. This introduces some artificial ordering dependency
245 /// but means that if you have (e.g.) two impls for the same type in
246 /// the same module, they do get distinct def-ids.
247 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
248 pub struct DisambiguatedDefPathData {
249 pub data: DefPathData,
250 pub disambiguator: u32
253 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
255 /// the path leading from the crate root to the item
256 pub data: Vec<DisambiguatedDefPathData>,
258 /// what krate root is this path relative to?
263 pub fn is_local(&self) -> bool {
264 self.krate == LOCAL_CRATE
267 pub fn make<FN>(krate: CrateNum,
268 start_index: DefIndex,
269 mut get_key: FN) -> DefPath
270 where FN: FnMut(DefIndex) -> DefKey
272 let mut data = vec![];
273 let mut index = Some(start_index);
275 debug!("DefPath::make: krate={:?} index={:?}", krate, index);
276 let p = index.unwrap();
277 let key = get_key(p);
278 debug!("DefPath::make: key={:?}", key);
279 match key.disambiguated_data.data {
280 DefPathData::CrateRoot => {
281 assert!(key.parent.is_none());
285 data.push(key.disambiguated_data);
291 DefPath { data: data, krate: krate }
294 pub fn to_string(&self, tcx: TyCtxt) -> String {
295 let mut s = String::with_capacity(self.data.len() * 16);
297 s.push_str(&tcx.original_crate_name(self.krate).as_str());
299 s.push_str(&tcx.crate_disambiguator(self.krate).as_str());
301 for component in &self.data {
304 component.data.as_interned_str(),
305 component.disambiguator)
312 /// Returns a string representation of the DefPath without
313 /// the crate-prefix. This method is useful if you don't have
314 /// a TyCtxt available.
315 pub fn to_string_no_crate(&self) -> String {
316 let mut s = String::with_capacity(self.data.len() * 16);
318 for component in &self.data {
321 component.data.as_interned_str(),
322 component.disambiguator)
330 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
331 pub enum DefPathData {
332 // Root: these should only be used for the root nodes, because
333 // they are treated specially by the `def_path` function.
334 /// The crate root (marker)
337 // Catch-all for random DefId things like DUMMY_NODE_ID
340 // Different kinds of items and item-like things:
343 /// Something in the type NS
345 /// Something in the value NS
347 /// A module declaration
351 /// A closure expression
354 // Subportions of items
355 /// A type parameter (generic parameter)
357 /// A lifetime definition
359 /// A variant of a enum
363 /// Implicit ctor for a tuple-like struct
365 /// Initializer for a const
369 /// An `impl Trait` type node.
371 /// A `typeof` type node.
376 /// Create new empty definition map.
377 pub fn new() -> Definitions {
379 table: DefPathTable {
380 index_to_key: [vec![], vec![]],
381 key_to_index: FxHashMap(),
382 def_path_hashes: [vec![], vec![]],
384 node_to_def_index: NodeMap(),
385 def_index_to_node: [vec![], vec![]],
386 node_to_hir_id: IndexVec::new(),
387 macro_def_scopes: FxHashMap(),
388 expansions: FxHashMap(),
392 pub fn def_path_table(&self) -> &DefPathTable {
396 /// Get the number of definitions.
397 pub fn def_index_counts_lo_hi(&self) -> (usize, usize) {
398 (self.def_index_to_node[DefIndexAddressSpace::Low.index()].len(),
399 self.def_index_to_node[DefIndexAddressSpace::High.index()].len())
402 pub fn def_key(&self, index: DefIndex) -> DefKey {
403 self.table.def_key(index)
407 pub fn def_path_hash(&self, index: DefIndex) -> Fingerprint {
408 self.table.def_path_hash(index)
411 pub fn def_index_for_def_key(&self, key: DefKey) -> Option<DefIndex> {
412 self.table.def_index_for_def_key(&key)
415 /// Returns the path from the crate root to `index`. The root
416 /// nodes are not included in the path (i.e., this will be an
417 /// empty vector for the crate root). For an inlined item, this
418 /// will be the path of the item in the external crate (but the
419 /// path will begin with the path to the external crate).
420 pub fn def_path(&self, index: DefIndex) -> DefPath {
421 DefPath::make(LOCAL_CRATE, index, |p| self.def_key(p))
424 pub fn opt_def_index(&self, node: ast::NodeId) -> Option<DefIndex> {
425 self.node_to_def_index.get(&node).cloned()
428 pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option<DefId> {
429 self.opt_def_index(node).map(DefId::local)
432 pub fn local_def_id(&self, node: ast::NodeId) -> DefId {
433 self.opt_local_def_id(node).unwrap()
436 pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
437 if def_id.krate == LOCAL_CRATE {
438 let space_index = def_id.index.address_space().index();
439 let array_index = def_id.index.as_array_index();
440 Some(self.def_index_to_node[space_index][array_index])
446 pub fn node_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId {
447 self.node_to_hir_id[node_id]
450 /// Add a definition with a parent definition.
451 pub fn create_root_def(&mut self,
453 crate_disambiguator: &str)
457 disambiguated_data: DisambiguatedDefPathData {
458 data: DefPathData::CrateRoot,
463 let parent_hash = DefKey::root_parent_stable_hash(crate_name,
464 crate_disambiguator);
465 let def_path_hash = key.compute_stable_hash(parent_hash);
467 // Create the definition.
468 let address_space = super::ITEM_LIKE_SPACE;
469 let index = self.table.allocate(key, def_path_hash, address_space);
470 assert!(self.def_index_to_node[address_space.index()].is_empty());
471 self.def_index_to_node[address_space.index()].push(ast::CRATE_NODE_ID);
472 self.node_to_def_index.insert(ast::CRATE_NODE_ID, index);
477 /// Add a definition with a parent definition.
478 pub fn create_def_with_parent(&mut self,
480 node_id: ast::NodeId,
482 address_space: DefIndexAddressSpace,
485 debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
486 parent, node_id, data);
488 assert!(!self.node_to_def_index.contains_key(&node_id),
489 "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
492 self.table.def_key(self.node_to_def_index[&node_id]));
494 // The root node must be created with create_root_def()
495 assert!(data != DefPathData::CrateRoot);
497 // Find a unique DefKey. This basically means incrementing the disambiguator
498 // until we get no match.
499 let mut key = DefKey {
500 parent: Some(parent),
501 disambiguated_data: DisambiguatedDefPathData {
507 while self.table.contains_key(&key) {
508 key.disambiguated_data.disambiguator += 1;
511 let parent_hash = self.table.def_path_hash(parent);
512 let def_path_hash = key.compute_stable_hash(parent_hash);
514 debug!("create_def_with_parent: after disambiguation, key = {:?}", key);
516 // Create the definition.
517 let index = self.table.allocate(key, def_path_hash, address_space);
518 assert_eq!(index.as_array_index(),
519 self.def_index_to_node[address_space.index()].len());
520 self.def_index_to_node[address_space.index()].push(node_id);
521 if expansion.is_modern() {
522 self.expansions.insert(index, expansion);
525 debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id);
526 self.node_to_def_index.insert(node_id, index);
531 /// Initialize the ast::NodeId to HirId mapping once it has been generated during
532 /// AST to HIR lowering.
533 pub fn init_node_id_to_hir_id_mapping(&mut self,
534 mapping: IndexVec<ast::NodeId, hir::HirId>) {
535 assert!(self.node_to_hir_id.is_empty(),
536 "Trying initialize NodeId -> HirId mapping twice");
537 self.node_to_hir_id = mapping;
540 pub fn expansion(&self, index: DefIndex) -> Mark {
541 self.expansions.get(&index).cloned().unwrap_or(Mark::root())
544 pub fn macro_def_scope(&self, mark: Mark) -> DefId {
545 self.macro_def_scopes[&mark]
548 pub fn add_macro_def_scope(&mut self, mark: Mark, scope: DefId) {
549 self.macro_def_scopes.insert(mark, scope);
554 pub fn get_opt_ident(&self) -> Option<Ident> {
555 use self::DefPathData::*;
565 Field(ident) => Some(ident),
578 pub fn get_opt_name(&self) -> Option<ast::Name> {
579 self.get_opt_ident().map(|ident| ident.name)
582 pub fn as_interned_str(&self) -> InternedString {
583 use self::DefPathData::*;
584 let s = match *self {
594 return ident.name.as_str();
597 // note that this does not show up in user printouts
598 CrateRoot => "{{root}}",
602 ClosureExpr => "{{closure}}",
603 StructCtor => "{{constructor}}",
604 Initializer => "{{initializer}}",
605 ImplTrait => "{{impl-Trait}}",
606 Typeof => "{{typeof}}",
609 Symbol::intern(s).as_str()
612 pub fn to_string(&self) -> String {
613 self.as_interned_str().to_string()
617 impl Eq for DefPathData {}
618 impl PartialEq for DefPathData {
619 fn eq(&self, other: &DefPathData) -> bool {
620 ::std::mem::discriminant(self) == ::std::mem::discriminant(other) &&
621 self.get_opt_ident() == other.get_opt_ident()
625 impl ::std::hash::Hash for DefPathData {
626 fn hash<H: ::std::hash::Hasher>(&self, hasher: &mut H) {
627 ::std::mem::discriminant(self).hash(hasher);
628 if let Some(ident) = self.get_opt_ident() {
629 if ident.ctxt == SyntaxContext::empty() && ident.name == ident.name.interned() {
630 ident.name.as_str().hash(hasher)
632 // FIXME(jseyfried) implement stable hashing for idents with macros 2.0 hygiene info