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