]> git.proxmox.com Git - rustc.git/blame - src/librustc/hir/map/def_collector.rs
New upstream version 1.12.0+dfsg1
[rustc.git] / src / librustc / hir / map / def_collector.rs
CommitLineData
a7813a04
XL
1// Copyright 2016 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
11use super::*;
12
13use hir;
14use hir::intravisit;
15use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
16
17use middle::cstore::InlinedItem;
18
19use syntax::ast::*;
20use syntax::visit;
21use syntax::parse::token;
22
23/// Creates def ids for nodes in the HIR.
24pub struct DefCollector<'ast> {
25 // If we are walking HIR (c.f., AST), we need to keep a reference to the
26 // crate.
27 hir_crate: Option<&'ast hir::Crate>,
3157f602 28 definitions: &'ast mut Definitions,
a7813a04
XL
29 parent_def: Option<DefIndex>,
30}
31
32impl<'ast> DefCollector<'ast> {
3157f602 33 pub fn root(definitions: &'ast mut Definitions) -> DefCollector<'ast> {
a7813a04
XL
34 let mut collector = DefCollector {
35 hir_crate: None,
3157f602 36 definitions: definitions,
a7813a04
XL
37 parent_def: None,
38 };
39 let root = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
40 assert_eq!(root, CRATE_DEF_INDEX);
41 collector.parent_def = Some(root);
42
43 collector.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc);
44
45 collector
46 }
47
48 pub fn extend(parent_node: NodeId,
49 parent_def_path: DefPath,
50 parent_def_id: DefId,
3157f602 51 definitions: &'ast mut Definitions)
a7813a04
XL
52 -> DefCollector<'ast> {
53 let mut collector = DefCollector {
54 hir_crate: None,
55 parent_def: None,
56 definitions: definitions,
57 };
58
59 assert_eq!(parent_def_path.krate, parent_def_id.krate);
60 let root_path = Box::new(InlinedRootPath {
61 data: parent_def_path.data,
62 def_id: parent_def_id,
63 });
64
65 let def = collector.create_def(parent_node, DefPathData::InlinedRoot(root_path));
66 collector.parent_def = Some(def);
67
68 collector
69 }
70
71 pub fn walk_item(&mut self, ii: &'ast InlinedItem, krate: &'ast hir::Crate) {
72 self.hir_crate = Some(krate);
73 ii.visit(self);
74 }
75
76 fn parent_def(&self) -> Option<DefIndex> {
77 self.parent_def
78 }
79
80 fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex {
81 let parent_def = self.parent_def();
82 debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
83 self.definitions.create_def_with_parent(parent_def, node_id, data)
84 }
85
86 fn create_def_with_parent(&mut self,
87 parent: Option<DefIndex>,
88 node_id: NodeId,
89 data: DefPathData)
90 -> DefIndex {
91 self.definitions.create_def_with_parent(parent, node_id, data)
92 }
93
94 fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
95 let parent = self.parent_def;
96 self.parent_def = Some(parent_def);
97 f(self);
98 self.parent_def = parent;
99 }
100
3157f602 101 fn visit_ast_const_integer(&mut self, expr: &Expr) {
a7813a04
XL
102 // Find the node which will be used after lowering.
103 if let ExprKind::Paren(ref inner) = expr.node {
104 return self.visit_ast_const_integer(inner);
105 }
106
107 // FIXME(eddyb) Closures should have separate
108 // function definition IDs and expression IDs.
109 if let ExprKind::Closure(..) = expr.node {
110 return;
111 }
112
113 self.create_def(expr.id, DefPathData::Initializer);
114 }
115
116 fn visit_hir_const_integer(&mut self, expr: &'ast hir::Expr) {
117 // FIXME(eddyb) Closures should have separate
118 // function definition IDs and expression IDs.
119 if let hir::ExprClosure(..) = expr.node {
120 return;
121 }
122
123 self.create_def(expr.id, DefPathData::Initializer);
124 }
125}
126
3157f602
XL
127impl<'ast> visit::Visitor for DefCollector<'ast> {
128 fn visit_item(&mut self, i: &Item) {
a7813a04
XL
129 debug!("visit_item: {:?}", i);
130
131 // Pick the def data. This need not be unique, but the more
132 // information we encapsulate into
133 let def_data = match i.node {
134 ItemKind::DefaultImpl(..) | ItemKind::Impl(..) =>
135 DefPathData::Impl,
136 ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Trait(..) |
137 ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
5bcae85e
SL
138 DefPathData::TypeNs(i.ident.name.as_str()),
139 ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()),
a7813a04 140 ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
5bcae85e
SL
141 DefPathData::ValueNs(i.ident.name.as_str()),
142 ItemKind::Mac(..) => DefPathData::MacroDef(i.ident.name.as_str()),
a7813a04
XL
143 ItemKind::Use(..) => DefPathData::Misc,
144 };
145 let def = self.create_def(i.id, def_data);
146
147 self.with_parent(def, |this| {
148 match i.node {
149 ItemKind::Enum(ref enum_definition, _) => {
150 for v in &enum_definition.variants {
151 let variant_def_index =
152 this.create_def(v.node.data.id(),
5bcae85e 153 DefPathData::EnumVariant(v.node.name.name.as_str()));
a7813a04
XL
154 this.with_parent(variant_def_index, |this| {
155 for (index, field) in v.node.data.fields().iter().enumerate() {
156 let name = field.ident.map(|ident| ident.name)
157 .unwrap_or_else(|| token::intern(&index.to_string()));
5bcae85e 158 this.create_def(field.id, DefPathData::Field(name.as_str()));
a7813a04
XL
159 }
160
161 if let Some(ref expr) = v.node.disr_expr {
162 this.visit_ast_const_integer(expr);
163 }
164 });
165 }
166 }
167 ItemKind::Struct(ref struct_def, _) => {
168 // If this is a tuple-like struct, register the constructor.
169 if !struct_def.is_struct() {
170 this.create_def(struct_def.id(),
171 DefPathData::StructCtor);
172 }
173
174 for (index, field) in struct_def.fields().iter().enumerate() {
5bcae85e
SL
175 let name = field.ident.map(|ident| ident.name.as_str())
176 .unwrap_or(token::intern(&index.to_string()).as_str());
a7813a04
XL
177 this.create_def(field.id, DefPathData::Field(name));
178 }
179 }
180 _ => {}
181 }
182 visit::walk_item(this, i);
183 });
184 }
185
3157f602 186 fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
5bcae85e
SL
187 let def = self.create_def(foreign_item.id,
188 DefPathData::ValueNs(foreign_item.ident.name.as_str()));
a7813a04
XL
189
190 self.with_parent(def, |this| {
191 visit::walk_foreign_item(this, foreign_item);
192 });
193 }
194
3157f602 195 fn visit_generics(&mut self, generics: &Generics) {
a7813a04 196 for ty_param in generics.ty_params.iter() {
5bcae85e 197 self.create_def(ty_param.id, DefPathData::TypeParam(ty_param.ident.name.as_str()));
a7813a04
XL
198 }
199
200 visit::walk_generics(self, generics);
201 }
202
3157f602 203 fn visit_trait_item(&mut self, ti: &TraitItem) {
a7813a04
XL
204 let def_data = match ti.node {
205 TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
5bcae85e
SL
206 DefPathData::ValueNs(ti.ident.name.as_str()),
207 TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name.as_str()),
208 TraitItemKind::Macro(..) => DefPathData::MacroDef(ti.ident.name.as_str()),
a7813a04
XL
209 };
210
211 let def = self.create_def(ti.id, def_data);
212 self.with_parent(def, |this| {
213 if let TraitItemKind::Const(_, Some(ref expr)) = ti.node {
214 this.create_def(expr.id, DefPathData::Initializer);
215 }
216
217 visit::walk_trait_item(this, ti);
218 });
219 }
220
3157f602 221 fn visit_impl_item(&mut self, ii: &ImplItem) {
a7813a04
XL
222 let def_data = match ii.node {
223 ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
5bcae85e
SL
224 DefPathData::ValueNs(ii.ident.name.as_str()),
225 ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name.as_str()),
226 ImplItemKind::Macro(..) => DefPathData::MacroDef(ii.ident.name.as_str()),
a7813a04
XL
227 };
228
229 let def = self.create_def(ii.id, def_data);
230 self.with_parent(def, |this| {
231 if let ImplItemKind::Const(_, ref expr) = ii.node {
232 this.create_def(expr.id, DefPathData::Initializer);
233 }
234
235 visit::walk_impl_item(this, ii);
236 });
237 }
238
3157f602 239 fn visit_pat(&mut self, pat: &Pat) {
a7813a04
XL
240 let parent_def = self.parent_def;
241
242 if let PatKind::Ident(_, id, _) = pat.node {
5bcae85e 243 let def = self.create_def(pat.id, DefPathData::Binding(id.node.name.as_str()));
a7813a04
XL
244 self.parent_def = Some(def);
245 }
246
247 visit::walk_pat(self, pat);
248 self.parent_def = parent_def;
249 }
250
3157f602 251 fn visit_expr(&mut self, expr: &Expr) {
a7813a04
XL
252 let parent_def = self.parent_def;
253
254 if let ExprKind::Repeat(_, ref count) = expr.node {
255 self.visit_ast_const_integer(count);
256 }
257
258 if let ExprKind::Closure(..) = expr.node {
259 let def = self.create_def(expr.id, DefPathData::ClosureExpr);
260 self.parent_def = Some(def);
261 }
262
263 visit::walk_expr(self, expr);
264 self.parent_def = parent_def;
265 }
266
3157f602 267 fn visit_ty(&mut self, ty: &Ty) {
a7813a04
XL
268 if let TyKind::FixedLengthVec(_, ref length) = ty.node {
269 self.visit_ast_const_integer(length);
270 }
5bcae85e
SL
271 if let TyKind::ImplTrait(..) = ty.node {
272 self.create_def(ty.id, DefPathData::ImplTrait);
273 }
a7813a04
XL
274 visit::walk_ty(self, ty);
275 }
276
3157f602 277 fn visit_lifetime_def(&mut self, def: &LifetimeDef) {
5bcae85e 278 self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name.as_str()));
a7813a04
XL
279 }
280
3157f602 281 fn visit_macro_def(&mut self, macro_def: &MacroDef) {
5bcae85e 282 self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.ident.name.as_str()));
a7813a04
XL
283 }
284}
285
286// We walk the HIR rather than the AST when reading items from metadata.
287impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
288 /// Because we want to track parent items and so forth, enable
289 /// deep walking so that we walk nested items in the context of
290 /// their outer items.
291 fn visit_nested_item(&mut self, item_id: hir::ItemId) {
292 debug!("visit_nested_item: {:?}", item_id);
293 let item = self.hir_crate.unwrap().item(item_id.id);
294 self.visit_item(item)
295 }
296
297 fn visit_item(&mut self, i: &'ast hir::Item) {
298 debug!("visit_item: {:?}", i);
299
300 // Pick the def data. This need not be unique, but the more
301 // information we encapsulate into
302 let def_data = match i.node {
303 hir::ItemDefaultImpl(..) | hir::ItemImpl(..) =>
304 DefPathData::Impl,
305 hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemTrait(..) |
306 hir::ItemExternCrate(..) | hir::ItemMod(..) | hir::ItemForeignMod(..) |
307 hir::ItemTy(..) =>
5bcae85e 308 DefPathData::TypeNs(i.name.as_str()),
a7813a04 309 hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) =>
5bcae85e 310 DefPathData::ValueNs(i.name.as_str()),
a7813a04
XL
311 hir::ItemUse(..) => DefPathData::Misc,
312 };
313 let def = self.create_def(i.id, def_data);
314
315 self.with_parent(def, |this| {
316 match i.node {
317 hir::ItemEnum(ref enum_definition, _) => {
318 for v in &enum_definition.variants {
319 let variant_def_index =
320 this.create_def(v.node.data.id(),
5bcae85e 321 DefPathData::EnumVariant(v.node.name.as_str()));
a7813a04
XL
322
323 this.with_parent(variant_def_index, |this| {
324 for field in v.node.data.fields() {
325 this.create_def(field.id,
5bcae85e 326 DefPathData::Field(field.name.as_str()));
a7813a04
XL
327 }
328 if let Some(ref expr) = v.node.disr_expr {
329 this.visit_hir_const_integer(expr);
330 }
331 });
332 }
333 }
334 hir::ItemStruct(ref struct_def, _) => {
335 // If this is a tuple-like struct, register the constructor.
336 if !struct_def.is_struct() {
337 this.create_def(struct_def.id(),
338 DefPathData::StructCtor);
339 }
340
341 for field in struct_def.fields() {
5bcae85e 342 this.create_def(field.id, DefPathData::Field(field.name.as_str()));
a7813a04
XL
343 }
344 }
345 _ => {}
346 }
347 intravisit::walk_item(this, i);
348 });
349 }
350
351 fn visit_foreign_item(&mut self, foreign_item: &'ast hir::ForeignItem) {
5bcae85e
SL
352 let def = self.create_def(foreign_item.id,
353 DefPathData::ValueNs(foreign_item.name.as_str()));
a7813a04
XL
354
355 self.with_parent(def, |this| {
356 intravisit::walk_foreign_item(this, foreign_item);
357 });
358 }
359
360 fn visit_generics(&mut self, generics: &'ast hir::Generics) {
361 for ty_param in generics.ty_params.iter() {
5bcae85e 362 self.create_def(ty_param.id, DefPathData::TypeParam(ty_param.name.as_str()));
a7813a04
XL
363 }
364
365 intravisit::walk_generics(self, generics);
366 }
367
368 fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
369 let def_data = match ti.node {
370 hir::MethodTraitItem(..) | hir::ConstTraitItem(..) =>
5bcae85e
SL
371 DefPathData::ValueNs(ti.name.as_str()),
372 hir::TypeTraitItem(..) => DefPathData::TypeNs(ti.name.as_str()),
a7813a04
XL
373 };
374
375 let def = self.create_def(ti.id, def_data);
376 self.with_parent(def, |this| {
377 if let hir::ConstTraitItem(_, Some(ref expr)) = ti.node {
378 this.create_def(expr.id, DefPathData::Initializer);
379 }
380
381 intravisit::walk_trait_item(this, ti);
382 });
383 }
384
385 fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
386 let def_data = match ii.node {
387 hir::ImplItemKind::Method(..) | hir::ImplItemKind::Const(..) =>
5bcae85e
SL
388 DefPathData::ValueNs(ii.name.as_str()),
389 hir::ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name.as_str()),
a7813a04
XL
390 };
391
392 let def = self.create_def(ii.id, def_data);
393 self.with_parent(def, |this| {
394 if let hir::ImplItemKind::Const(_, ref expr) = ii.node {
395 this.create_def(expr.id, DefPathData::Initializer);
396 }
397
398 intravisit::walk_impl_item(this, ii);
399 });
400 }
401
402 fn visit_pat(&mut self, pat: &'ast hir::Pat) {
403 let parent_def = self.parent_def;
404
3157f602 405 if let hir::PatKind::Binding(_, name, _) = pat.node {
5bcae85e 406 let def = self.create_def(pat.id, DefPathData::Binding(name.node.as_str()));
a7813a04
XL
407 self.parent_def = Some(def);
408 }
409
410 intravisit::walk_pat(self, pat);
411 self.parent_def = parent_def;
412 }
413
414 fn visit_expr(&mut self, expr: &'ast hir::Expr) {
415 let parent_def = self.parent_def;
416
417 if let hir::ExprRepeat(_, ref count) = expr.node {
418 self.visit_hir_const_integer(count);
419 }
420
421 if let hir::ExprClosure(..) = expr.node {
422 let def = self.create_def(expr.id, DefPathData::ClosureExpr);
423 self.parent_def = Some(def);
424 }
425
426 intravisit::walk_expr(self, expr);
427 self.parent_def = parent_def;
428 }
429
430 fn visit_ty(&mut self, ty: &'ast hir::Ty) {
431 if let hir::TyFixedLengthVec(_, ref length) = ty.node {
432 self.visit_hir_const_integer(length);
433 }
5bcae85e
SL
434 if let hir::TyImplTrait(..) = ty.node {
435 self.create_def(ty.id, DefPathData::ImplTrait);
436 }
a7813a04
XL
437 intravisit::walk_ty(self, ty);
438 }
439
440 fn visit_lifetime_def(&mut self, def: &'ast hir::LifetimeDef) {
5bcae85e 441 self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name.as_str()));
a7813a04
XL
442 }
443
444 fn visit_macro_def(&mut self, macro_def: &'ast hir::MacroDef) {
5bcae85e 445 self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name.as_str()));
a7813a04
XL
446 }
447}