]> git.proxmox.com Git - rustc.git/blame - src/librustc/front/map/definitions.rs
Imported Upstream version 1.8.0+dfsg1
[rustc.git] / src / librustc / front / map / definitions.rs
CommitLineData
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
92a42be0 11use middle::cstore::LOCAL_CRATE;
b039eaaf
SL
12use middle::def_id::{DefId, DefIndex};
13use rustc_data_structures::fnv::FnvHashMap;
14use rustc_front::hir;
15use syntax::ast;
16use syntax::parse::token::InternedString;
17use util::nodemap::NodeMap;
18
19#[derive(Clone)]
20pub struct Definitions {
21 data: Vec<DefData>,
22 key_map: FnvHashMap<DefKey, DefIndex>,
23 node_map: NodeMap<DefIndex>,
24}
25
26/// A unique identifier that we can use to lookup a definition
27/// precisely. It combines the index of the definition's parent (if
28/// any) with a `DisambiguatedDefPathData`.
29#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
30pub struct DefKey {
31 /// Parent path.
32 pub parent: Option<DefIndex>,
33
34 /// Identifier of this node.
35 pub disambiguated_data: DisambiguatedDefPathData,
36}
37
38/// Pair of `DefPathData` and an integer disambiguator. The integer is
39/// normally 0, but in the event that there are multiple defs with the
40/// same `parent` and `data`, we use this field to disambiguate
41/// between them. This introduces some artificial ordering dependency
42/// but means that if you have (e.g.) two impls for the same type in
43/// the same module, they do get distinct def-ids.
44#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
45pub struct DisambiguatedDefPathData {
46 pub data: DefPathData,
47 pub disambiguator: u32
48}
49
50/// For each definition, we track the following data. A definition
51/// here is defined somewhat circularly as "something with a def-id",
52/// but it generally corresponds to things like structs, enums, etc.
53/// There are also some rather random cases (like const initializer
54/// expressions) that are mostly just leftovers.
55#[derive(Clone, Debug)]
56pub struct DefData {
57 pub key: DefKey,
58
59 /// Local ID within the HIR.
60 pub node_id: ast::NodeId,
61}
62
63pub type DefPath = Vec<DisambiguatedDefPathData>;
64
65#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
66pub enum DefPathData {
67 // Root: these should only be used for the root nodes, because
68 // they are treated specially by the `def_path` function.
69 CrateRoot,
70 InlinedRoot(DefPath),
71
72 // Catch-all for random DefId things like DUMMY_NODE_ID
73 Misc,
74
75 // Different kinds of items and item-like things:
9cc50fc6 76 Impl(ast::Name),
b039eaaf
SL
77 Type(ast::Name),
78 Mod(ast::Name),
79 Value(ast::Name),
80 MacroDef(ast::Name),
81 ClosureExpr,
82
83 // Subportions of items
84 TypeParam(ast::Name),
85 LifetimeDef(ast::Name),
86 EnumVariant(ast::Name),
87 PositionalField,
88 Field(hir::StructFieldKind),
89 StructCtor, // implicit ctor for a tuple-like struct
90 Initializer, // initializer for a const
91 Binding(ast::Name), // pattern binding
92
93 // An external crate that does not have an `extern crate` in this
94 // crate.
95 DetachedCrate(ast::Name),
96}
97
98impl Definitions {
99 pub fn new() -> Definitions {
100 Definitions {
101 data: vec![],
102 key_map: FnvHashMap(),
103 node_map: NodeMap(),
104 }
105 }
106
107 pub fn len(&self) -> usize {
108 self.data.len()
109 }
110
111 pub fn def_key(&self, index: DefIndex) -> DefKey {
112 self.data[index.as_usize()].key.clone()
113 }
114
115 /// Returns the path from the crate root to `index`. The root
116 /// nodes are not included in the path (i.e., this will be an
117 /// empty vector for the crate root). For an inlined item, this
118 /// will be the path of the item in the external crate (but the
119 /// path will begin with the path to the external crate).
120 pub fn def_path(&self, index: DefIndex) -> DefPath {
121 make_def_path(index, |p| self.def_key(p))
122 }
123
124 pub fn opt_def_index(&self, node: ast::NodeId) -> Option<DefIndex> {
125 self.node_map.get(&node).cloned()
126 }
127
128 pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option<DefId> {
129 self.opt_def_index(node).map(DefId::local)
130 }
131
132 pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
133 if def_id.krate == LOCAL_CRATE {
134 assert!(def_id.index.as_usize() < self.data.len());
135 Some(self.data[def_id.index.as_usize()].node_id)
136 } else {
137 None
138 }
139 }
140
141 pub fn create_def_with_parent(&mut self,
142 parent: Option<DefIndex>,
143 node_id: ast::NodeId,
144 data: DefPathData)
145 -> DefIndex {
146 assert!(!self.node_map.contains_key(&node_id),
147 "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
148 node_id,
149 data,
150 self.data[self.node_map[&node_id].as_usize()]);
151
152 // Find a unique DefKey. This basically means incrementing the disambiguator
153 // until we get no match.
154 let mut key = DefKey {
155 parent: parent,
156 disambiguated_data: DisambiguatedDefPathData {
157 data: data,
158 disambiguator: 0
159 }
160 };
161
162 while self.key_map.contains_key(&key) {
163 key.disambiguated_data.disambiguator += 1;
164 }
165
166 // Create the definition.
167 let index = DefIndex::new(self.data.len());
168 self.data.push(DefData { key: key.clone(), node_id: node_id });
169 self.node_map.insert(node_id, index);
170 self.key_map.insert(key, index);
171
172 index
173 }
174}
175
176impl DefPathData {
177 pub fn as_interned_str(&self) -> InternedString {
178 use self::DefPathData::*;
179 match *self {
9cc50fc6 180 Impl(name) |
b039eaaf
SL
181 Type(name) |
182 Mod(name) |
183 Value(name) |
184 MacroDef(name) |
185 TypeParam(name) |
186 LifetimeDef(name) |
187 EnumVariant(name) |
188 DetachedCrate(name) |
189 Binding(name) => {
190 name.as_str()
191 }
192
193 Field(hir::StructFieldKind::NamedField(name, _)) => {
194 name.as_str()
195 }
196
197 PositionalField |
198 Field(hir::StructFieldKind::UnnamedField(_)) => {
7453a54e 199 InternedString::new("{{field}}")
b039eaaf
SL
200 }
201
202 // note that this does not show up in user printouts
203 CrateRoot => {
7453a54e 204 InternedString::new("{{root}}")
b039eaaf
SL
205 }
206
207 // note that this does not show up in user printouts
208 InlinedRoot(_) => {
7453a54e 209 InternedString::new("{{inlined-root}}")
b039eaaf
SL
210 }
211
212 Misc => {
7453a54e 213 InternedString::new("{{?}}")
b039eaaf
SL
214 }
215
b039eaaf 216 ClosureExpr => {
7453a54e 217 InternedString::new("{{closure}}")
b039eaaf
SL
218 }
219
220 StructCtor => {
7453a54e 221 InternedString::new("{{constructor}}")
b039eaaf
SL
222 }
223
224 Initializer => {
7453a54e 225 InternedString::new("{{initializer}}")
b039eaaf
SL
226 }
227 }
228 }
229
230 pub fn to_string(&self) -> String {
231 self.as_interned_str().to_string()
232 }
233}
234
235pub fn make_def_path<FN>(start_index: DefIndex, mut get_key: FN) -> DefPath
236 where FN: FnMut(DefIndex) -> DefKey
237{
238 let mut result = vec![];
239 let mut index = Some(start_index);
240 while let Some(p) = index {
241 let key = get_key(p);
242 match key.disambiguated_data.data {
243 DefPathData::CrateRoot => {
244 assert!(key.parent.is_none());
245 break;
246 }
247 DefPathData::InlinedRoot(ref p) => {
248 assert!(key.parent.is_none());
249 result.extend(p.iter().cloned().rev());
250 break;
251 }
252 _ => {
253 result.push(key.disambiguated_data);
254 index = key.parent;
255 }
256 }
257 }
258 result.reverse();
259 result
260}