blob: 673429b49f79038e2b048ec041a52ad2c1a30c6c [file] [log] [blame]
Niko Matsakis01f32ac2015-09-17 18:29:591// 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
Eduard Burtescufc363cb2016-08-31 11:00:2911use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
Nicholas Nethercote00e48af2016-11-08 03:02:5512use rustc_data_structures::fx::FxHashMap;
Niko Matsakis2e7df802016-08-01 23:55:2013use std::fmt::Write;
Alex Crichton10c31342016-09-29 00:23:3614use std::hash::{Hash, Hasher};
15use std::collections::hash_map::DefaultHasher;
Jeffrey Seyfriedebaaafc2016-09-14 09:55:2016use syntax::ast;
Jeffrey Seyfriedd2f8fb02016-11-16 08:21:5217use syntax::symbol::{Symbol, InternedString};
Niko Matsakis2e7df802016-08-01 23:55:2018use ty::TyCtxt;
Niko Matsakis01f32ac2015-09-17 18:29:5919use util::nodemap::NodeMap;
20
Tickida55fd72015-12-21 21:24:1521/// The definition table containing node definitions
Niko Matsakis01f32ac2015-09-17 18:29:5922#[derive(Clone)]
23pub struct Definitions {
24 data: Vec<DefData>,
Nicholas Nethercote00e48af2016-11-08 03:02:5525 key_map: FxHashMap<DefKey, DefIndex>,
Niko Matsakis01f32ac2015-09-17 18:29:5926 node_map: NodeMap<DefIndex>,
27}
28
29/// A unique identifier that we can use to lookup a definition
30/// precisely. It combines the index of the definition's parent (if
31/// any) with a `DisambiguatedDefPathData`.
32#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
33pub struct DefKey {
34 /// Parent path.
35 pub parent: Option<DefIndex>,
36
37 /// Identifier of this node.
38 pub disambiguated_data: DisambiguatedDefPathData,
39}
40
41/// Pair of `DefPathData` and an integer disambiguator. The integer is
42/// normally 0, but in the event that there are multiple defs with the
43/// same `parent` and `data`, we use this field to disambiguate
44/// between them. This introduces some artificial ordering dependency
45/// but means that if you have (e.g.) two impls for the same type in
46/// the same module, they do get distinct def-ids.
47#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
48pub struct DisambiguatedDefPathData {
49 pub data: DefPathData,
50 pub disambiguator: u32
51}
52
53/// For each definition, we track the following data. A definition
54/// here is defined somewhat circularly as "something with a def-id",
55/// but it generally corresponds to things like structs, enums, etc.
56/// There are also some rather random cases (like const initializer
57/// expressions) that are mostly just leftovers.
58#[derive(Clone, Debug)]
59pub struct DefData {
60 pub key: DefKey,
61
62 /// Local ID within the HIR.
63 pub node_id: ast::NodeId,
64}
65
Niko Matsakis7b6270b2016-03-16 09:40:1466#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
67pub struct DefPath {
68 /// the path leading from the crate root to the item
69 pub data: Vec<DisambiguatedDefPathData>,
70
71 /// what krate root is this path relative to?
Eduard Burtescufc363cb2016-08-31 11:00:2972 pub krate: CrateNum,
Niko Matsakis7b6270b2016-03-16 09:40:1473}
74
75impl DefPath {
76 pub fn is_local(&self) -> bool {
77 self.krate == LOCAL_CRATE
78 }
79
Eduard Burtescufc363cb2016-08-31 11:00:2980 pub fn make<FN>(start_krate: CrateNum,
Niko Matsakis7b6270b2016-03-16 09:40:1481 start_index: DefIndex,
82 mut get_key: FN) -> DefPath
83 where FN: FnMut(DefIndex) -> DefKey
84 {
85 let mut krate = start_krate;
86 let mut data = vec![];
87 let mut index = Some(start_index);
88 loop {
Niko Matsakisb01919a2016-05-06 18:52:5789 debug!("DefPath::make: krate={:?} index={:?}", krate, index);
Niko Matsakis7b6270b2016-03-16 09:40:1490 let p = index.unwrap();
91 let key = get_key(p);
Niko Matsakisb01919a2016-05-06 18:52:5792 debug!("DefPath::make: key={:?}", key);
Niko Matsakis7b6270b2016-03-16 09:40:1493 match key.disambiguated_data.data {
94 DefPathData::CrateRoot => {
95 assert!(key.parent.is_none());
96 break;
97 }
98 DefPathData::InlinedRoot(ref p) => {
99 assert!(key.parent.is_none());
100 assert!(!p.def_id.is_local());
101 data.extend(p.data.iter().cloned().rev());
102 krate = p.def_id.krate;
103 break;
104 }
105 _ => {
106 data.push(key.disambiguated_data);
107 index = key.parent;
108 }
109 }
110 }
111 data.reverse();
112 DefPath { data: data, krate: krate }
113 }
Niko Matsakis2e7df802016-08-01 23:55:20114
115 pub fn to_string(&self, tcx: TyCtxt) -> String {
116 let mut s = String::with_capacity(self.data.len() * 16);
117
Jeffrey Seyfriede85a0d72016-11-16 10:52:37118 s.push_str(&tcx.original_crate_name(self.krate).as_str());
Niko Matsakis2e7df802016-08-01 23:55:20119 s.push_str("/");
Jeffrey Seyfriede85a0d72016-11-16 10:52:37120 s.push_str(&tcx.crate_disambiguator(self.krate).as_str());
Niko Matsakis2e7df802016-08-01 23:55:20121
122 for component in &self.data {
123 write!(s,
124 "::{}[{}]",
125 component.data.as_interned_str(),
126 component.disambiguator)
127 .unwrap();
128 }
129
130 s
131 }
Niko Matsakis81504942016-08-06 00:12:20132
133 pub fn deterministic_hash(&self, tcx: TyCtxt) -> u64 {
Alex Crichton10c31342016-09-29 00:23:36134 let mut state = DefaultHasher::new();
Niko Matsakis81504942016-08-06 00:12:20135 self.deterministic_hash_to(tcx, &mut state);
136 state.finish()
137 }
138
139 pub fn deterministic_hash_to<H: Hasher>(&self, tcx: TyCtxt, state: &mut H) {
Jeffrey Seyfriede85a0d72016-11-16 10:52:37140 tcx.original_crate_name(self.krate).as_str().hash(state);
141 tcx.crate_disambiguator(self.krate).as_str().hash(state);
Niko Matsakis81504942016-08-06 00:12:20142 self.data.hash(state);
143 }
Niko Matsakis7b6270b2016-03-16 09:40:14144}
145
Niko Matsakis65c0b7c2016-03-16 09:31:51146/// Root of an inlined item. We track the `DefPath` of the item within
147/// the original crate but also its def-id. This is kind of an
148/// augmented version of a `DefPath` that includes a `DefId`. This is
149/// all sort of ugly but the hope is that inlined items will be going
150/// away soon anyway.
151///
152/// Some of the constraints that led to the current approach:
153///
154/// - I don't want to have a `DefId` in the main `DefPath` because
155/// that gets serialized for incr. comp., and when reloaded the
156/// `DefId` is no longer valid. I'd rather maintain the invariant
157/// that every `DefId` is valid, and a potentially outdated `DefId` is
158/// represented as a `DefPath`.
159/// - (We don't serialize def-paths from inlined items, so it's ok to have one here.)
160/// - We need to be able to extract the def-id from inline items to
161/// make the symbol name. In theory we could retrace it from the
162/// data, but the metadata doesn't have the required indices, and I
163/// don't want to write the code to create one just for this.
164/// - It may be that we don't actually need `data` at all. We'll have
165/// to see about that.
166#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
167pub struct InlinedRootPath {
168 pub data: Vec<DisambiguatedDefPathData>,
169 pub def_id: DefId,
170}
Niko Matsakis01f32ac2015-09-17 18:29:59171
172#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
173pub enum DefPathData {
174 // Root: these should only be used for the root nodes, because
175 // they are treated specially by the `def_path` function.
Tickida55fd72015-12-21 21:24:15176 /// The crate root (marker)
Niko Matsakis01f32ac2015-09-17 18:29:59177 CrateRoot,
Tickida55fd72015-12-21 21:24:15178 /// An inlined root
Niko Matsakis65c0b7c2016-03-16 09:31:51179 InlinedRoot(Box<InlinedRootPath>),
Niko Matsakis01f32ac2015-09-17 18:29:59180
181 // Catch-all for random DefId things like DUMMY_NODE_ID
182 Misc,
183
184 // Different kinds of items and item-like things:
Tickida55fd72015-12-21 21:24:15185 /// An impl
Niko Matsakis5e265082016-03-16 09:47:18186 Impl,
Tickida55fd72015-12-21 21:24:15187 /// Something in the type NS
Niko Matsakis571010b2016-08-06 00:10:04188 TypeNs(InternedString),
Tickida55fd72015-12-21 21:24:15189 /// Something in the value NS
Niko Matsakis571010b2016-08-06 00:10:04190 ValueNs(InternedString),
Tickida55fd72015-12-21 21:24:15191 /// A module declaration
Niko Matsakis571010b2016-08-06 00:10:04192 Module(InternedString),
Tickida55fd72015-12-21 21:24:15193 /// A macro rule
Niko Matsakis571010b2016-08-06 00:10:04194 MacroDef(InternedString),
Tickida55fd72015-12-21 21:24:15195 /// A closure expression
Niko Matsakis01f32ac2015-09-17 18:29:59196 ClosureExpr,
197
198 // Subportions of items
Tickida55fd72015-12-21 21:24:15199 /// A type parameter (generic parameter)
Niko Matsakis571010b2016-08-06 00:10:04200 TypeParam(InternedString),
Tickida55fd72015-12-21 21:24:15201 /// A lifetime definition
Niko Matsakis571010b2016-08-06 00:10:04202 LifetimeDef(InternedString),
Tickida55fd72015-12-21 21:24:15203 /// A variant of a enum
Niko Matsakis571010b2016-08-06 00:10:04204 EnumVariant(InternedString),
Tickida55fd72015-12-21 21:24:15205 /// A struct field
Niko Matsakis571010b2016-08-06 00:10:04206 Field(InternedString),
Tickida55fd72015-12-21 21:24:15207 /// Implicit ctor for a tuple-like struct
208 StructCtor,
209 /// Initializer for a const
210 Initializer,
211 /// Pattern binding
Niko Matsakis571010b2016-08-06 00:10:04212 Binding(InternedString),
Eduard Burtescuef11d4e2016-07-22 15:56:22213 /// An `impl Trait` type node.
214 ImplTrait
Niko Matsakis01f32ac2015-09-17 18:29:59215}
216
217impl Definitions {
Tickida55fd72015-12-21 21:24:15218 /// Create new empty definition map.
Niko Matsakis01f32ac2015-09-17 18:29:59219 pub fn new() -> Definitions {
220 Definitions {
221 data: vec![],
Nicholas Nethercote00e48af2016-11-08 03:02:55222 key_map: FxHashMap(),
Niko Matsakis01f32ac2015-09-17 18:29:59223 node_map: NodeMap(),
224 }
225 }
226
Tickida55fd72015-12-21 21:24:15227 /// Get the number of definitions.
Niko Matsakis01f32ac2015-09-17 18:29:59228 pub fn len(&self) -> usize {
229 self.data.len()
230 }
231
232 pub fn def_key(&self, index: DefIndex) -> DefKey {
233 self.data[index.as_usize()].key.clone()
234 }
235
Niko Matsakisb01919a2016-05-06 18:52:57236 pub fn def_index_for_def_key(&self, key: DefKey) -> Option<DefIndex> {
237 self.key_map.get(&key).cloned()
238 }
239
Niko Matsakis01f32ac2015-09-17 18:29:59240 /// Returns the path from the crate root to `index`. The root
241 /// nodes are not included in the path (i.e., this will be an
242 /// empty vector for the crate root). For an inlined item, this
243 /// will be the path of the item in the external crate (but the
244 /// path will begin with the path to the external crate).
245 pub fn def_path(&self, index: DefIndex) -> DefPath {
Niko Matsakis7b6270b2016-03-16 09:40:14246 DefPath::make(LOCAL_CRATE, index, |p| self.def_key(p))
Niko Matsakis01f32ac2015-09-17 18:29:59247 }
248
249 pub fn opt_def_index(&self, node: ast::NodeId) -> Option<DefIndex> {
250 self.node_map.get(&node).cloned()
251 }
252
253 pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option<DefId> {
254 self.opt_def_index(node).map(DefId::local)
255 }
256
Jeffrey Seyfried84284472016-04-24 03:26:10257 pub fn local_def_id(&self, node: ast::NodeId) -> DefId {
258 self.opt_local_def_id(node).unwrap()
259 }
260
Niko Matsakis01f32ac2015-09-17 18:29:59261 pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
262 if def_id.krate == LOCAL_CRATE {
263 assert!(def_id.index.as_usize() < self.data.len());
264 Some(self.data[def_id.index.as_usize()].node_id)
265 } else {
266 None
267 }
268 }
269
Tickida55fd72015-12-21 21:24:15270 /// Add a definition with a parent definition.
Niko Matsakis01f32ac2015-09-17 18:29:59271 pub fn create_def_with_parent(&mut self,
272 parent: Option<DefIndex>,
273 node_id: ast::NodeId,
274 data: DefPathData)
275 -> DefIndex {
Niko Matsakisd8263c42016-03-28 21:39:57276 debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
277 parent, node_id, data);
278
Niko Matsakis01f32ac2015-09-17 18:29:59279 assert!(!self.node_map.contains_key(&node_id),
280 "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
281 node_id,
282 data,
283 self.data[self.node_map[&node_id].as_usize()]);
284
Niko Matsakisd8263c42016-03-28 21:39:57285 assert!(parent.is_some() ^ match data {
286 DefPathData::CrateRoot | DefPathData::InlinedRoot(_) => true,
287 _ => false,
288 });
289
Niko Matsakis01f32ac2015-09-17 18:29:59290 // Find a unique DefKey. This basically means incrementing the disambiguator
291 // until we get no match.
292 let mut key = DefKey {
293 parent: parent,
294 disambiguated_data: DisambiguatedDefPathData {
295 data: data,
296 disambiguator: 0
297 }
298 };
299
300 while self.key_map.contains_key(&key) {
301 key.disambiguated_data.disambiguator += 1;
302 }
303
Niko Matsakisd8263c42016-03-28 21:39:57304 debug!("create_def_with_parent: after disambiguation, key = {:?}", key);
305
Niko Matsakis01f32ac2015-09-17 18:29:59306 // Create the definition.
307 let index = DefIndex::new(self.data.len());
308 self.data.push(DefData { key: key.clone(), node_id: node_id });
Niko Matsakisd8263c42016-03-28 21:39:57309 debug!("create_def_with_parent: node_map[{:?}] = {:?}", node_id, index);
Niko Matsakis01f32ac2015-09-17 18:29:59310 self.node_map.insert(node_id, index);
Niko Matsakisd8263c42016-03-28 21:39:57311 debug!("create_def_with_parent: key_map[{:?}] = {:?}", key, index);
Niko Matsakis01f32ac2015-09-17 18:29:59312 self.key_map.insert(key, index);
313
Niko Matsakisd8263c42016-03-28 21:39:57314
Niko Matsakis01f32ac2015-09-17 18:29:59315 index
316 }
317}
318
319impl DefPathData {
Eduard Burtescudadbaa42016-09-17 10:34:55320 pub fn get_opt_name(&self) -> Option<ast::Name> {
321 use self::DefPathData::*;
322 match *self {
323 TypeNs(ref name) |
324 ValueNs(ref name) |
325 Module(ref name) |
326 MacroDef(ref name) |
327 TypeParam(ref name) |
328 LifetimeDef(ref name) |
329 EnumVariant(ref name) |
330 Binding(ref name) |
Jeffrey Seyfriedd2f8fb02016-11-16 08:21:52331 Field(ref name) => Some(Symbol::intern(name)),
Eduard Burtescudadbaa42016-09-17 10:34:55332
333 Impl |
334 CrateRoot |
335 InlinedRoot(_) |
336 Misc |
337 ClosureExpr |
338 StructCtor |
339 Initializer |
340 ImplTrait => None
341 }
342 }
343
Niko Matsakis01f32ac2015-09-17 18:29:59344 pub fn as_interned_str(&self) -> InternedString {
345 use self::DefPathData::*;
346 match *self {
Niko Matsakis571010b2016-08-06 00:10:04347 TypeNs(ref name) |
348 ValueNs(ref name) |
349 Module(ref name) |
350 MacroDef(ref name) |
351 TypeParam(ref name) |
352 LifetimeDef(ref name) |
353 EnumVariant(ref name) |
354 Binding(ref name) |
355 Field(ref name) => {
356 name.clone()
Niko Matsakis01f32ac2015-09-17 18:29:59357 }
358
Niko Matsakis5e265082016-03-16 09:47:18359 Impl => {
360 InternedString::new("{{impl}}")
361 }
362
Niko Matsakis01f32ac2015-09-17 18:29:59363 // note that this does not show up in user printouts
364 CrateRoot => {
Michael Woerister862911d2015-11-02 13:46:39365 InternedString::new("{{root}}")
Niko Matsakis01f32ac2015-09-17 18:29:59366 }
367
368 // note that this does not show up in user printouts
369 InlinedRoot(_) => {
Michael Woerister862911d2015-11-02 13:46:39370 InternedString::new("{{inlined-root}}")
Niko Matsakis01f32ac2015-09-17 18:29:59371 }
372
373 Misc => {
Michael Woerister862911d2015-11-02 13:46:39374 InternedString::new("{{?}}")
Niko Matsakis01f32ac2015-09-17 18:29:59375 }
376
Niko Matsakis01f32ac2015-09-17 18:29:59377 ClosureExpr => {
Michael Woerister862911d2015-11-02 13:46:39378 InternedString::new("{{closure}}")
Niko Matsakis01f32ac2015-09-17 18:29:59379 }
380
381 StructCtor => {
Michael Woerister862911d2015-11-02 13:46:39382 InternedString::new("{{constructor}}")
Niko Matsakis01f32ac2015-09-17 18:29:59383 }
384
385 Initializer => {
Michael Woerister862911d2015-11-02 13:46:39386 InternedString::new("{{initializer}}")
Niko Matsakis01f32ac2015-09-17 18:29:59387 }
Eduard Burtescuef11d4e2016-07-22 15:56:22388
389 ImplTrait => {
390 InternedString::new("{{impl-Trait}}")
391 }
Niko Matsakis01f32ac2015-09-17 18:29:59392 }
393 }
394
395 pub fn to_string(&self) -> String {
396 self.as_interned_str().to_string()
397 }
398}
399