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 use middle
::cstore
::LOCAL_CRATE
;
12 use hir
::def_id
::{DefId, DefIndex}
;
13 use hir
::map
::def_collector
::DefCollector
;
14 use rustc_data_structures
::fnv
::FnvHashMap
;
15 use syntax
::{ast, visit}
;
16 use syntax
::parse
::token
::InternedString
;
17 use util
::nodemap
::NodeMap
;
19 /// The definition table containing node definitions
21 pub struct Definitions
{
23 key_map
: FnvHashMap
<DefKey
, DefIndex
>,
24 node_map
: NodeMap
<DefIndex
>,
27 /// A unique identifier that we can use to lookup a definition
28 /// precisely. It combines the index of the definition's parent (if
29 /// any) with a `DisambiguatedDefPathData`.
30 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
33 pub parent
: Option
<DefIndex
>,
35 /// Identifier of this node.
36 pub disambiguated_data
: DisambiguatedDefPathData
,
39 /// Pair of `DefPathData` and an integer disambiguator. The integer is
40 /// normally 0, but in the event that there are multiple defs with the
41 /// same `parent` and `data`, we use this field to disambiguate
42 /// between them. This introduces some artificial ordering dependency
43 /// but means that if you have (e.g.) two impls for the same type in
44 /// the same module, they do get distinct def-ids.
45 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
46 pub struct DisambiguatedDefPathData
{
47 pub data
: DefPathData
,
48 pub disambiguator
: u32
51 /// For each definition, we track the following data. A definition
52 /// here is defined somewhat circularly as "something with a def-id",
53 /// but it generally corresponds to things like structs, enums, etc.
54 /// There are also some rather random cases (like const initializer
55 /// expressions) that are mostly just leftovers.
56 #[derive(Clone, Debug)]
60 /// Local ID within the HIR.
61 pub node_id
: ast
::NodeId
,
64 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
66 /// the path leading from the crate root to the item
67 pub data
: Vec
<DisambiguatedDefPathData
>,
69 /// what krate root is this path relative to?
70 pub krate
: ast
::CrateNum
,
74 pub fn is_local(&self) -> bool
{
75 self.krate
== LOCAL_CRATE
78 pub fn make
<FN
>(start_krate
: ast
::CrateNum
,
79 start_index
: DefIndex
,
80 mut get_key
: FN
) -> DefPath
81 where FN
: FnMut(DefIndex
) -> DefKey
83 let mut krate
= start_krate
;
84 let mut data
= vec
![];
85 let mut index
= Some(start_index
);
87 debug
!("DefPath::make: krate={:?} index={:?}", krate
, index
);
88 let p
= index
.unwrap();
90 debug
!("DefPath::make: key={:?}", key
);
91 match key
.disambiguated_data
.data
{
92 DefPathData
::CrateRoot
=> {
93 assert
!(key
.parent
.is_none());
96 DefPathData
::InlinedRoot(ref p
) => {
97 assert
!(key
.parent
.is_none());
98 assert
!(!p
.def_id
.is_local());
99 data
.extend(p
.data
.iter().cloned().rev());
100 krate
= p
.def_id
.krate
;
104 data
.push(key
.disambiguated_data
);
110 DefPath { data: data, krate: krate }
114 /// Root of an inlined item. We track the `DefPath` of the item within
115 /// the original crate but also its def-id. This is kind of an
116 /// augmented version of a `DefPath` that includes a `DefId`. This is
117 /// all sort of ugly but the hope is that inlined items will be going
118 /// away soon anyway.
120 /// Some of the constraints that led to the current approach:
122 /// - I don't want to have a `DefId` in the main `DefPath` because
123 /// that gets serialized for incr. comp., and when reloaded the
124 /// `DefId` is no longer valid. I'd rather maintain the invariant
125 /// that every `DefId` is valid, and a potentially outdated `DefId` is
126 /// represented as a `DefPath`.
127 /// - (We don't serialize def-paths from inlined items, so it's ok to have one here.)
128 /// - We need to be able to extract the def-id from inline items to
129 /// make the symbol name. In theory we could retrace it from the
130 /// data, but the metadata doesn't have the required indices, and I
131 /// don't want to write the code to create one just for this.
132 /// - It may be that we don't actually need `data` at all. We'll have
133 /// to see about that.
134 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
135 pub struct InlinedRootPath
{
136 pub data
: Vec
<DisambiguatedDefPathData
>,
140 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
141 pub enum DefPathData
{
142 // Root: these should only be used for the root nodes, because
143 // they are treated specially by the `def_path` function.
144 /// The crate root (marker)
147 InlinedRoot(Box
<InlinedRootPath
>),
149 // Catch-all for random DefId things like DUMMY_NODE_ID
152 // Different kinds of items and item-like things:
155 /// Something in the type NS
157 /// Something in the value NS
159 /// A module declaration
163 /// A closure expression
166 // Subportions of items
167 /// A type parameter (generic parameter)
168 TypeParam(ast
::Name
),
169 /// A lifetime definition
170 LifetimeDef(ast
::Name
),
171 /// A variant of a enum
172 EnumVariant(ast
::Name
),
175 /// Implicit ctor for a tuple-like struct
177 /// Initializer for a const
184 /// Create new empty definition map.
185 pub fn new() -> Definitions
{
188 key_map
: FnvHashMap(),
193 pub fn collect(&mut self, krate
: &ast
::Crate
) {
194 let mut def_collector
= DefCollector
::root(self);
195 visit
::walk_crate(&mut def_collector
, krate
);
198 /// Get the number of definitions.
199 pub fn len(&self) -> usize {
203 pub fn def_key(&self, index
: DefIndex
) -> DefKey
{
204 self.data
[index
.as_usize()].key
.clone()
207 pub fn def_index_for_def_key(&self, key
: DefKey
) -> Option
<DefIndex
> {
208 self.key_map
.get(&key
).cloned()
211 /// Returns the path from the crate root to `index`. The root
212 /// nodes are not included in the path (i.e., this will be an
213 /// empty vector for the crate root). For an inlined item, this
214 /// will be the path of the item in the external crate (but the
215 /// path will begin with the path to the external crate).
216 pub fn def_path(&self, index
: DefIndex
) -> DefPath
{
217 DefPath
::make(LOCAL_CRATE
, index
, |p
| self.def_key(p
))
220 pub fn opt_def_index(&self, node
: ast
::NodeId
) -> Option
<DefIndex
> {
221 self.node_map
.get(&node
).cloned()
224 pub fn opt_local_def_id(&self, node
: ast
::NodeId
) -> Option
<DefId
> {
225 self.opt_def_index(node
).map(DefId
::local
)
228 pub fn local_def_id(&self, node
: ast
::NodeId
) -> DefId
{
229 self.opt_local_def_id(node
).unwrap()
232 pub fn as_local_node_id(&self, def_id
: DefId
) -> Option
<ast
::NodeId
> {
233 if def_id
.krate
== LOCAL_CRATE
{
234 assert
!(def_id
.index
.as_usize() < self.data
.len());
235 Some(self.data
[def_id
.index
.as_usize()].node_id
)
241 /// Add a definition with a parent definition.
242 pub fn create_def_with_parent(&mut self,
243 parent
: Option
<DefIndex
>,
244 node_id
: ast
::NodeId
,
247 debug
!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
248 parent
, node_id
, data
);
250 assert
!(!self.node_map
.contains_key(&node_id
),
251 "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
254 self.data
[self.node_map
[&node_id
].as_usize()]);
256 assert
!(parent
.is_some() ^
match data
{
257 DefPathData
::CrateRoot
| DefPathData
::InlinedRoot(_
) => true,
261 // Find a unique DefKey. This basically means incrementing the disambiguator
262 // until we get no match.
263 let mut key
= DefKey
{
265 disambiguated_data
: DisambiguatedDefPathData
{
271 while self.key_map
.contains_key(&key
) {
272 key
.disambiguated_data
.disambiguator
+= 1;
275 debug
!("create_def_with_parent: after disambiguation, key = {:?}", key
);
277 // Create the definition.
278 let index
= DefIndex
::new(self.data
.len());
279 self.data
.push(DefData { key: key.clone(), node_id: node_id }
);
280 debug
!("create_def_with_parent: node_map[{:?}] = {:?}", node_id
, index
);
281 self.node_map
.insert(node_id
, index
);
282 debug
!("create_def_with_parent: key_map[{:?}] = {:?}", key
, index
);
283 self.key_map
.insert(key
, index
);
291 pub fn as_interned_str(&self) -> InternedString
{
292 use self::DefPathData
::*;
307 InternedString
::new("{{impl}}")
310 // note that this does not show up in user printouts
312 InternedString
::new("{{root}}")
315 // note that this does not show up in user printouts
317 InternedString
::new("{{inlined-root}}")
321 InternedString
::new("{{?}}")
325 InternedString
::new("{{closure}}")
329 InternedString
::new("{{constructor}}")
333 InternedString
::new("{{initializer}}")
338 pub fn to_string(&self) -> String
{
339 self.as_interned_str().to_string()