]> git.lizzy.rs Git - rust.git/blob - src/librustc/hir/map/definitions.rs
5322d24e38934cddaaab784fc6915cd955f866fa
[rust.git] / src / librustc / hir / map / definitions.rs
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.
4 //
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.
10
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.
16
17 use hir;
18 use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, DefIndexAddressSpace,
19                   CRATE_DEF_INDEX};
20 use ich::Fingerprint;
21 use rustc_data_structures::fx::FxHashMap;
22 use rustc_data_structures::indexed_vec::IndexVec;
23 use rustc_data_structures::stable_hasher::StableHasher;
24 use serialize::{Encodable, Decodable, Encoder, Decoder};
25 use std::fmt::Write;
26 use std::hash::Hash;
27 use syntax::ast;
28 use syntax::ext::hygiene::Mark;
29 use syntax::symbol::{Symbol, InternedString};
30 use ty::TyCtxt;
31 use util::nodemap::NodeMap;
32
33 /// The DefPathTable maps DefIndexes to DefKeys and vice versa.
34 /// Internally the DefPathTable holds a tree of DefKeys, where each DefKey
35 /// stores the DefIndex of its parent.
36 /// There is one DefPathTable for each crate.
37 pub struct DefPathTable {
38     index_to_key: [Vec<DefKey>; 2],
39     key_to_index: FxHashMap<DefKey, DefIndex>,
40     def_path_hashes: [Vec<DefPathHash>; 2],
41 }
42
43 // Unfortunately we have to provide a manual impl of Clone because of the
44 // fixed-sized array field.
45 impl Clone for DefPathTable {
46     fn clone(&self) -> Self {
47         DefPathTable {
48             index_to_key: [self.index_to_key[0].clone(),
49                            self.index_to_key[1].clone()],
50             key_to_index: self.key_to_index.clone(),
51             def_path_hashes: [self.def_path_hashes[0].clone(),
52                               self.def_path_hashes[1].clone()],
53         }
54     }
55 }
56
57 impl DefPathTable {
58     pub fn new() -> Self {
59         DefPathTable {
60             index_to_key: [vec![], vec![]],
61             key_to_index: FxHashMap(),
62             def_path_hashes: [vec![], vec![]],
63         }
64     }
65
66     pub fn allocate(&mut self,
67                     key: DefKey,
68                     def_path_hash: DefPathHash,
69                     address_space: DefIndexAddressSpace)
70                     -> DefIndex {
71         let index = {
72             let index_to_key = &mut self.index_to_key[address_space.index()];
73             let index = DefIndex::new(index_to_key.len() + address_space.start());
74             debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index);
75             index_to_key.push(key.clone());
76             index
77         };
78         self.key_to_index.insert(key, index);
79         self.def_path_hashes[address_space.index()].push(def_path_hash);
80         debug_assert!(self.def_path_hashes[address_space.index()].len() ==
81                       self.index_to_key[address_space.index()].len());
82         index
83     }
84
85     #[inline(always)]
86     pub fn def_key(&self, index: DefIndex) -> DefKey {
87         self.index_to_key[index.address_space().index()]
88                          [index.as_array_index()].clone()
89     }
90
91     #[inline(always)]
92     pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
93         self.def_path_hashes[index.address_space().index()]
94                             [index.as_array_index()]
95     }
96
97     #[inline(always)]
98     pub fn def_index_for_def_key(&self, key: &DefKey) -> Option<DefIndex> {
99         self.key_to_index.get(key).cloned()
100     }
101
102     #[inline(always)]
103     pub fn contains_key(&self, key: &DefKey) -> bool {
104         self.key_to_index.contains_key(key)
105     }
106
107     pub fn retrace_path(&self,
108                         path_data: &[DisambiguatedDefPathData])
109                         -> Option<DefIndex> {
110         let root_key = DefKey {
111             parent: None,
112             disambiguated_data: DisambiguatedDefPathData {
113                 data: DefPathData::CrateRoot,
114                 disambiguator: 0,
115             },
116         };
117
118         let root_index = self.key_to_index
119                              .get(&root_key)
120                              .expect("no root key?")
121                              .clone();
122
123         debug!("retrace_path: root_index={:?}", root_index);
124
125         let mut index = root_index;
126         for data in path_data {
127             let key = DefKey { parent: Some(index), disambiguated_data: data.clone() };
128             debug!("retrace_path: key={:?}", key);
129             match self.key_to_index.get(&key) {
130                 Some(&i) => index = i,
131                 None => return None,
132             }
133         }
134
135         Some(index)
136     }
137
138     pub fn add_def_path_hashes_to(&self,
139                                   cnum: CrateNum,
140                                   out: &mut FxHashMap<DefPathHash, DefId>) {
141         for address_space in &[DefIndexAddressSpace::Low, DefIndexAddressSpace::High] {
142             let start_index = address_space.start();
143             out.extend(
144                 (&self.def_path_hashes[address_space.index()])
145                     .iter()
146                     .enumerate()
147                     .map(|(index, &hash)| {
148                         let def_id = DefId {
149                             krate: cnum,
150                             index: DefIndex::new(index + start_index),
151                         };
152                         (hash, def_id)
153                     })
154             );
155         }
156     }
157
158     pub fn size(&self) -> usize {
159         self.key_to_index.len()
160     }
161 }
162
163
164 impl Encodable for DefPathTable {
165     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
166         // Index to key
167         self.index_to_key[DefIndexAddressSpace::Low.index()].encode(s)?;
168         self.index_to_key[DefIndexAddressSpace::High.index()].encode(s)?;
169
170         // DefPath hashes
171         self.def_path_hashes[DefIndexAddressSpace::Low.index()].encode(s)?;
172         self.def_path_hashes[DefIndexAddressSpace::High.index()].encode(s)?;
173
174         Ok(())
175     }
176 }
177
178 impl Decodable for DefPathTable {
179     fn decode<D: Decoder>(d: &mut D) -> Result<DefPathTable, D::Error> {
180         let index_to_key_lo: Vec<DefKey> = Decodable::decode(d)?;
181         let index_to_key_hi: Vec<DefKey> = Decodable::decode(d)?;
182
183         let def_path_hashes_lo: Vec<DefPathHash> = Decodable::decode(d)?;
184         let def_path_hashes_hi: Vec<DefPathHash> = Decodable::decode(d)?;
185
186         let index_to_key = [index_to_key_lo, index_to_key_hi];
187         let def_path_hashes = [def_path_hashes_lo, def_path_hashes_hi];
188
189         let mut key_to_index = FxHashMap();
190
191         for space in &[DefIndexAddressSpace::Low, DefIndexAddressSpace::High] {
192             key_to_index.extend(index_to_key[space.index()]
193                 .iter()
194                 .enumerate()
195                 .map(|(index, key)| (key.clone(),
196                                      DefIndex::new(index + space.start()))))
197         }
198
199         Ok(DefPathTable {
200             index_to_key: index_to_key,
201             key_to_index: key_to_index,
202             def_path_hashes: def_path_hashes,
203         })
204     }
205 }
206
207
208 /// The definition table containing node definitions.
209 /// It holds the DefPathTable for local DefIds/DefPaths and it also stores a
210 /// mapping from NodeIds to local DefIds.
211 pub struct Definitions {
212     table: DefPathTable,
213     node_to_def_index: NodeMap<DefIndex>,
214     def_index_to_node: [Vec<ast::NodeId>; 2],
215     pub(super) node_to_hir_id: IndexVec<ast::NodeId, hir::HirId>,
216     macro_def_scopes: FxHashMap<Mark, DefId>,
217     expansions: FxHashMap<DefIndex, Mark>,
218 }
219
220 // Unfortunately we have to provide a manual impl of Clone because of the
221 // fixed-sized array field.
222 impl Clone for Definitions {
223     fn clone(&self) -> Self {
224         Definitions {
225             table: self.table.clone(),
226             node_to_def_index: self.node_to_def_index.clone(),
227             def_index_to_node: [
228                 self.def_index_to_node[0].clone(),
229                 self.def_index_to_node[1].clone(),
230             ],
231             node_to_hir_id: self.node_to_hir_id.clone(),
232             macro_def_scopes: self.macro_def_scopes.clone(),
233             expansions: self.expansions.clone(),
234         }
235     }
236 }
237
238 /// A unique identifier that we can use to lookup a definition
239 /// precisely. It combines the index of the definition's parent (if
240 /// any) with a `DisambiguatedDefPathData`.
241 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
242 pub struct DefKey {
243     /// Parent path.
244     pub parent: Option<DefIndex>,
245
246     /// Identifier of this node.
247     pub disambiguated_data: DisambiguatedDefPathData,
248 }
249
250 impl DefKey {
251     pub fn compute_stable_hash(&self, parent_hash: DefPathHash) -> DefPathHash {
252         let mut hasher = StableHasher::new();
253
254         // We hash a 0u8 here to disambiguate between regular DefPath hashes,
255         // and the special "root_parent" below.
256         0u8.hash(&mut hasher);
257         parent_hash.hash(&mut hasher);
258
259         let DisambiguatedDefPathData {
260             ref data,
261             disambiguator,
262         } = self.disambiguated_data;
263
264         ::std::mem::discriminant(data).hash(&mut hasher);
265         match *data {
266             DefPathData::TypeNs(name) |
267             DefPathData::ValueNs(name) |
268             DefPathData::Module(name) |
269             DefPathData::MacroDef(name) |
270             DefPathData::TypeParam(name) |
271             DefPathData::LifetimeDef(name) |
272             DefPathData::EnumVariant(name) |
273             DefPathData::Binding(name) |
274             DefPathData::Field(name) |
275             DefPathData::GlobalMetaData(name) => {
276                 (*name.as_str()).hash(&mut hasher);
277             }
278
279             DefPathData::Impl |
280             DefPathData::CrateRoot |
281             DefPathData::Misc |
282             DefPathData::ClosureExpr |
283             DefPathData::StructCtor |
284             DefPathData::Initializer |
285             DefPathData::ImplTrait |
286             DefPathData::Typeof => {}
287         };
288
289         disambiguator.hash(&mut hasher);
290
291         DefPathHash(hasher.finish())
292     }
293
294     pub fn root_parent_stable_hash(crate_name: &str, crate_disambiguator: &str) -> DefPathHash {
295         let mut hasher = StableHasher::new();
296         // Disambiguate this from a regular DefPath hash,
297         // see compute_stable_hash() above.
298         1u8.hash(&mut hasher);
299         crate_name.hash(&mut hasher);
300         crate_disambiguator.hash(&mut hasher);
301         DefPathHash(hasher.finish())
302     }
303 }
304
305 /// Pair of `DefPathData` and an integer disambiguator. The integer is
306 /// normally 0, but in the event that there are multiple defs with the
307 /// same `parent` and `data`, we use this field to disambiguate
308 /// between them. This introduces some artificial ordering dependency
309 /// but means that if you have (e.g.) two impls for the same type in
310 /// the same module, they do get distinct def-ids.
311 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
312 pub struct DisambiguatedDefPathData {
313     pub data: DefPathData,
314     pub disambiguator: u32
315 }
316
317 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
318 pub struct DefPath {
319     /// the path leading from the crate root to the item
320     pub data: Vec<DisambiguatedDefPathData>,
321
322     /// what krate root is this path relative to?
323     pub krate: CrateNum,
324 }
325
326 impl DefPath {
327     pub fn is_local(&self) -> bool {
328         self.krate == LOCAL_CRATE
329     }
330
331     pub fn make<FN>(krate: CrateNum,
332                     start_index: DefIndex,
333                     mut get_key: FN) -> DefPath
334         where FN: FnMut(DefIndex) -> DefKey
335     {
336         let mut data = vec![];
337         let mut index = Some(start_index);
338         loop {
339             debug!("DefPath::make: krate={:?} index={:?}", krate, index);
340             let p = index.unwrap();
341             let key = get_key(p);
342             debug!("DefPath::make: key={:?}", key);
343             match key.disambiguated_data.data {
344                 DefPathData::CrateRoot => {
345                     assert!(key.parent.is_none());
346                     break;
347                 }
348                 _ => {
349                     data.push(key.disambiguated_data);
350                     index = key.parent;
351                 }
352             }
353         }
354         data.reverse();
355         DefPath { data: data, krate: krate }
356     }
357
358     pub fn to_string(&self, tcx: TyCtxt) -> String {
359         let mut s = String::with_capacity(self.data.len() * 16);
360
361         s.push_str(&tcx.original_crate_name(self.krate).as_str());
362         s.push_str("/");
363         // Don't print the whole crate disambiguator. That's just annoying in
364         // debug output.
365         s.push_str(&tcx.crate_disambiguator(self.krate).as_str()[..7]);
366
367         for component in &self.data {
368             write!(s,
369                    "::{}[{}]",
370                    component.data.as_interned_str(),
371                    component.disambiguator)
372                 .unwrap();
373         }
374
375         s
376     }
377
378     /// Returns a string representation of the DefPath without
379     /// the crate-prefix. This method is useful if you don't have
380     /// a TyCtxt available.
381     pub fn to_string_no_crate(&self) -> String {
382         let mut s = String::with_capacity(self.data.len() * 16);
383
384         for component in &self.data {
385             write!(s,
386                    "::{}[{}]",
387                    component.data.as_interned_str(),
388                    component.disambiguator)
389                 .unwrap();
390         }
391
392         s
393     }
394 }
395
396 #[derive(Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable)]
397 pub enum DefPathData {
398     // Root: these should only be used for the root nodes, because
399     // they are treated specially by the `def_path` function.
400     /// The crate root (marker)
401     CrateRoot,
402
403     // Catch-all for random DefId things like DUMMY_NODE_ID
404     Misc,
405
406     // Different kinds of items and item-like things:
407     /// An impl
408     Impl,
409     /// Something in the type NS
410     TypeNs(Symbol),
411     /// Something in the value NS
412     ValueNs(Symbol),
413     /// A module declaration
414     Module(Symbol),
415     /// A macro rule
416     MacroDef(Symbol),
417     /// A closure expression
418     ClosureExpr,
419
420     // Subportions of items
421     /// A type parameter (generic parameter)
422     TypeParam(Symbol),
423     /// A lifetime definition
424     LifetimeDef(Symbol),
425     /// A variant of a enum
426     EnumVariant(Symbol),
427     /// A struct field
428     Field(Symbol),
429     /// Implicit ctor for a tuple-like struct
430     StructCtor,
431     /// Initializer for a const
432     Initializer,
433     /// Pattern binding
434     Binding(Symbol),
435     /// An `impl Trait` type node.
436     ImplTrait,
437     /// A `typeof` type node.
438     Typeof,
439
440     /// GlobalMetaData identifies a piece of crate metadata that is global to
441     /// a whole crate (as opposed to just one item). GlobalMetaData components
442     /// are only supposed to show up right below the crate root.
443     GlobalMetaData(Symbol)
444 }
445
446 #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug,
447          RustcEncodable, RustcDecodable)]
448 pub struct DefPathHash(pub Fingerprint);
449
450 impl_stable_hash_for!(tuple_struct DefPathHash { fingerprint });
451
452 impl Definitions {
453     /// Create new empty definition map.
454     pub fn new() -> Definitions {
455         Definitions {
456             table: DefPathTable::new(),
457             node_to_def_index: NodeMap(),
458             def_index_to_node: [vec![], vec![]],
459             node_to_hir_id: IndexVec::new(),
460             macro_def_scopes: FxHashMap(),
461             expansions: FxHashMap(),
462         }
463     }
464
465     pub fn def_path_table(&self) -> &DefPathTable {
466         &self.table
467     }
468
469     /// Get the number of definitions.
470     pub fn def_index_counts_lo_hi(&self) -> (usize, usize) {
471         (self.table.index_to_key[DefIndexAddressSpace::Low.index()].len(),
472          self.table.index_to_key[DefIndexAddressSpace::High.index()].len())
473     }
474
475     pub fn def_key(&self, index: DefIndex) -> DefKey {
476         self.table.def_key(index)
477     }
478
479     #[inline(always)]
480     pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
481         self.table.def_path_hash(index)
482     }
483
484     pub fn def_index_for_def_key(&self, key: DefKey) -> Option<DefIndex> {
485         self.table.def_index_for_def_key(&key)
486     }
487
488     /// Returns the path from the crate root to `index`. The root
489     /// nodes are not included in the path (i.e., this will be an
490     /// empty vector for the crate root). For an inlined item, this
491     /// will be the path of the item in the external crate (but the
492     /// path will begin with the path to the external crate).
493     pub fn def_path(&self, index: DefIndex) -> DefPath {
494         DefPath::make(LOCAL_CRATE, index, |p| self.def_key(p))
495     }
496
497     pub fn opt_def_index(&self, node: ast::NodeId) -> Option<DefIndex> {
498         self.node_to_def_index.get(&node).cloned()
499     }
500
501     pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option<DefId> {
502         self.opt_def_index(node).map(DefId::local)
503     }
504
505     pub fn local_def_id(&self, node: ast::NodeId) -> DefId {
506         self.opt_local_def_id(node).unwrap()
507     }
508
509     pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
510         if def_id.krate == LOCAL_CRATE {
511             let space_index = def_id.index.address_space().index();
512             let array_index = def_id.index.as_array_index();
513             let node_id = self.def_index_to_node[space_index][array_index];
514             if node_id != ast::DUMMY_NODE_ID {
515                 Some(node_id)
516             } else {
517                 None
518             }
519         } else {
520             None
521         }
522     }
523
524     pub fn node_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId {
525         self.node_to_hir_id[node_id]
526     }
527
528     /// Add a definition with a parent definition.
529     pub fn create_root_def(&mut self,
530                            crate_name: &str,
531                            crate_disambiguator: &str)
532                            -> DefIndex {
533         let key = DefKey {
534             parent: None,
535             disambiguated_data: DisambiguatedDefPathData {
536                 data: DefPathData::CrateRoot,
537                 disambiguator: 0
538             }
539         };
540
541         let parent_hash = DefKey::root_parent_stable_hash(crate_name,
542                                                           crate_disambiguator);
543         let def_path_hash = key.compute_stable_hash(parent_hash);
544
545         // Create the definition.
546         let address_space = super::ITEM_LIKE_SPACE;
547         let root_index = self.table.allocate(key, def_path_hash, address_space);
548         assert_eq!(root_index, CRATE_DEF_INDEX);
549         assert!(self.def_index_to_node[address_space.index()].is_empty());
550         self.def_index_to_node[address_space.index()].push(ast::CRATE_NODE_ID);
551         self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index);
552
553         // Allocate some other DefIndices that always must exist.
554         GlobalMetaDataKind::allocate_def_indices(self);
555
556         root_index
557     }
558
559     /// Add a definition with a parent definition.
560     pub fn create_def_with_parent(&mut self,
561                                   parent: DefIndex,
562                                   node_id: ast::NodeId,
563                                   data: DefPathData,
564                                   address_space: DefIndexAddressSpace,
565                                   expansion: Mark)
566                                   -> DefIndex {
567         debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
568                parent, node_id, data);
569
570         assert!(!self.node_to_def_index.contains_key(&node_id),
571                 "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
572                 node_id,
573                 data,
574                 self.table.def_key(self.node_to_def_index[&node_id]));
575
576         // The root node must be created with create_root_def()
577         assert!(data != DefPathData::CrateRoot);
578
579         // Find a unique DefKey. This basically means incrementing the disambiguator
580         // until we get no match.
581         let mut key = DefKey {
582             parent: Some(parent),
583             disambiguated_data: DisambiguatedDefPathData {
584                 data: data,
585                 disambiguator: 0
586             }
587         };
588
589         while self.table.contains_key(&key) {
590             key.disambiguated_data.disambiguator += 1;
591         }
592
593         let parent_hash = self.table.def_path_hash(parent);
594         let def_path_hash = key.compute_stable_hash(parent_hash);
595
596         debug!("create_def_with_parent: after disambiguation, key = {:?}", key);
597
598         // Create the definition.
599         let index = self.table.allocate(key, def_path_hash, address_space);
600         assert_eq!(index.as_array_index(),
601                    self.def_index_to_node[address_space.index()].len());
602         self.def_index_to_node[address_space.index()].push(node_id);
603
604         // Some things for which we allocate DefIndices don't correspond to
605         // anything in the AST, so they don't have a NodeId. For these cases
606         // we don't need a mapping from NodeId to DefIndex.
607         if node_id != ast::DUMMY_NODE_ID {
608             debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id);
609             self.node_to_def_index.insert(node_id, index);
610         }
611
612         if expansion.is_modern() {
613             self.expansions.insert(index, expansion);
614         }
615
616         index
617     }
618
619     /// Initialize the ast::NodeId to HirId mapping once it has been generated during
620     /// AST to HIR lowering.
621     pub fn init_node_id_to_hir_id_mapping(&mut self,
622                                           mapping: IndexVec<ast::NodeId, hir::HirId>) {
623         assert!(self.node_to_hir_id.is_empty(),
624                 "Trying initialize NodeId -> HirId mapping twice");
625         self.node_to_hir_id = mapping;
626     }
627
628     pub fn expansion(&self, index: DefIndex) -> Mark {
629         self.expansions.get(&index).cloned().unwrap_or(Mark::root())
630     }
631
632     pub fn macro_def_scope(&self, mark: Mark) -> DefId {
633         self.macro_def_scopes[&mark]
634     }
635
636     pub fn add_macro_def_scope(&mut self, mark: Mark, scope: DefId) {
637         self.macro_def_scopes.insert(mark, scope);
638     }
639 }
640
641 impl DefPathData {
642     pub fn get_opt_name(&self) -> Option<Symbol> {
643         use self::DefPathData::*;
644         match *self {
645             TypeNs(name) |
646             ValueNs(name) |
647             Module(name) |
648             MacroDef(name) |
649             TypeParam(name) |
650             LifetimeDef(name) |
651             EnumVariant(name) |
652             Binding(name) |
653             Field(name) |
654             GlobalMetaData(name) => Some(name),
655
656             Impl |
657             CrateRoot |
658             Misc |
659             ClosureExpr |
660             StructCtor |
661             Initializer |
662             ImplTrait |
663             Typeof => None
664         }
665     }
666
667     pub fn as_interned_str(&self) -> InternedString {
668         use self::DefPathData::*;
669         let s = match *self {
670             TypeNs(name) |
671             ValueNs(name) |
672             Module(name) |
673             MacroDef(name) |
674             TypeParam(name) |
675             LifetimeDef(name) |
676             EnumVariant(name) |
677             Binding(name) |
678             Field(name) |
679             GlobalMetaData(name) => {
680                 return name.as_str();
681             }
682
683             // note that this does not show up in user printouts
684             CrateRoot => "{{root}}",
685
686             Impl => "{{impl}}",
687             Misc => "{{?}}",
688             ClosureExpr => "{{closure}}",
689             StructCtor => "{{constructor}}",
690             Initializer => "{{initializer}}",
691             ImplTrait => "{{impl-Trait}}",
692             Typeof => "{{typeof}}",
693         };
694
695         Symbol::intern(s).as_str()
696     }
697
698     pub fn to_string(&self) -> String {
699         self.as_interned_str().to_string()
700     }
701 }
702
703 // We define the GlobalMetaDataKind enum with this macro because we want to
704 // make sure that we exhaustively iterate over all variants when registering
705 // the corresponding DefIndices in the DefTable.
706 macro_rules! define_global_metadata_kind {
707     (pub enum GlobalMetaDataKind {
708         $($variant:ident),*
709     }) => (
710         #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash,
711                  RustcEncodable, RustcDecodable)]
712         pub enum GlobalMetaDataKind {
713             $($variant),*
714         }
715
716         impl GlobalMetaDataKind {
717             fn allocate_def_indices(definitions: &mut Definitions) {
718                 $({
719                     let instance = GlobalMetaDataKind::$variant;
720                     definitions.create_def_with_parent(
721                         CRATE_DEF_INDEX,
722                         ast::DUMMY_NODE_ID,
723                         DefPathData::GlobalMetaData(instance.name()),
724                         DefIndexAddressSpace::High,
725                         Mark::root()
726                     );
727
728                     // Make sure calling def_index does not crash.
729                     instance.def_index(&definitions.table);
730                 })*
731             }
732
733             pub fn def_index(&self, def_path_table: &DefPathTable) -> DefIndex {
734                 let def_key = DefKey {
735                     parent: Some(CRATE_DEF_INDEX),
736                     disambiguated_data: DisambiguatedDefPathData {
737                         data: DefPathData::GlobalMetaData(self.name()),
738                         disambiguator: 0,
739                     }
740                 };
741
742                 def_path_table.key_to_index[&def_key]
743             }
744
745             fn name(&self) -> Symbol {
746
747                 let string = match *self {
748                     $(
749                         GlobalMetaDataKind::$variant => {
750                             concat!("{{GlobalMetaData::", stringify!($variant), "}}")
751                         }
752                     )*
753                 };
754
755                 Symbol::intern(string)
756             }
757         }
758     )
759 }
760
761 define_global_metadata_kind!(pub enum GlobalMetaDataKind {
762     Krate,
763     CrateDeps,
764     DylibDependencyFormats,
765     LangItems,
766     LangItemsMissing,
767     NativeLibraries,
768     CodeMap,
769     Impls,
770     ExportedSymbols
771 });