]> git.proxmox.com Git - rustc.git/blame - src/librustc/hir/map/def_collector.rs
New upstream version 1.22.1+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
476ff2be 11use hir::map::definitions::*;
cc61c64b 12use hir::def_id::{CRATE_DEF_INDEX, DefIndex, DefIndexAddressSpace};
a7813a04
XL
13
14use syntax::ast::*;
c30ab7b3 15use syntax::ext::hygiene::Mark;
a7813a04 16use syntax::visit;
7cac9316 17use syntax::symbol::keywords;
041b39d2 18use syntax::symbol::Symbol;
a7813a04 19
cc61c64b
XL
20use hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE};
21
32a655c1 22/// Creates def ids for nodes in the AST.
c30ab7b3 23pub struct DefCollector<'a> {
c30ab7b3 24 definitions: &'a mut Definitions,
a7813a04 25 parent_def: Option<DefIndex>,
7cac9316 26 expansion: Mark,
c30ab7b3 27 pub visit_macro_invoc: Option<&'a mut FnMut(MacroInvocationData)>,
a7813a04
XL
28}
29
c30ab7b3
SL
30pub struct MacroInvocationData {
31 pub mark: Mark,
32 pub def_index: DefIndex,
32a655c1 33 pub const_expr: bool,
c30ab7b3
SL
34}
35
36impl<'a> DefCollector<'a> {
7cac9316 37 pub fn new(definitions: &'a mut Definitions, expansion: Mark) -> Self {
9e0c209e 38 DefCollector {
041b39d2
XL
39 definitions,
40 expansion,
a7813a04 41 parent_def: None,
c30ab7b3 42 visit_macro_invoc: None,
9e0c209e 43 }
a7813a04
XL
44 }
45
cc61c64b
XL
46 pub fn collect_root(&mut self, crate_name: &str, crate_disambiguator: &str) {
47 let root = self.definitions.create_root_def(crate_name,
48 crate_disambiguator);
9e0c209e
SL
49 assert_eq!(root, CRATE_DEF_INDEX);
50 self.parent_def = Some(root);
a7813a04
XL
51 }
52
cc61c64b
XL
53 fn create_def(&mut self,
54 node_id: NodeId,
55 data: DefPathData,
56 address_space: DefIndexAddressSpace)
57 -> DefIndex {
58 let parent_def = self.parent_def.unwrap();
a7813a04 59 debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
7cac9316
XL
60 self.definitions
61 .create_def_with_parent(parent_def, node_id, data, address_space, self.expansion)
a7813a04
XL
62 }
63
c30ab7b3 64 pub fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
a7813a04
XL
65 let parent = self.parent_def;
66 self.parent_def = Some(parent_def);
67 f(self);
68 self.parent_def = parent;
69 }
70
32a655c1 71 pub fn visit_const_expr(&mut self, expr: &Expr) {
c30ab7b3
SL
72 match expr.node {
73 // Find the node which will be used after lowering.
32a655c1 74 ExprKind::Paren(ref inner) => return self.visit_const_expr(inner),
c30ab7b3
SL
75 ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, true),
76 // FIXME(eddyb) Closures should have separate
77 // function definition IDs and expression IDs.
78 ExprKind::Closure(..) => return,
79 _ => {}
a7813a04
XL
80 }
81
cc61c64b 82 self.create_def(expr.id, DefPathData::Initializer, REGULAR_SPACE);
a7813a04
XL
83 }
84
32a655c1 85 fn visit_macro_invoc(&mut self, id: NodeId, const_expr: bool) {
c30ab7b3
SL
86 if let Some(ref mut visit) = self.visit_macro_invoc {
87 visit(MacroInvocationData {
cc61c64b 88 mark: id.placeholder_to_mark(),
041b39d2 89 const_expr,
c30ab7b3
SL
90 def_index: self.parent_def.unwrap(),
91 })
92 }
93 }
a7813a04
XL
94}
95
476ff2be
SL
96impl<'a> visit::Visitor<'a> for DefCollector<'a> {
97 fn visit_item(&mut self, i: &'a Item) {
a7813a04
XL
98 debug!("visit_item: {:?}", i);
99
100 // Pick the def data. This need not be unique, but the more
101 // information we encapsulate into
102 let def_data = match i.node {
103 ItemKind::DefaultImpl(..) | ItemKind::Impl(..) =>
104 DefPathData::Impl,
9e0c209e 105 ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) |
a7813a04 106 ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
ea8adc8c 107 DefPathData::TypeNs(i.ident.name.as_str()),
c30ab7b3
SL
108 ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
109 return visit::walk_item(self, i);
110 }
ea8adc8c 111 ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()),
a7813a04 112 ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
ea8adc8c
XL
113 DefPathData::ValueNs(i.ident.name.as_str()),
114 ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()),
c30ab7b3 115 ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
cc61c64b 116 ItemKind::GlobalAsm(..) => DefPathData::Misc,
476ff2be
SL
117 ItemKind::Use(ref view_path) => {
118 match view_path.node {
119 ViewPathGlob(..) => {}
120
121 // FIXME(eddyb) Should use the real name. Which namespace?
122 ViewPathSimple(..) => {}
123 ViewPathList(_, ref imports) => {
124 for import in imports {
cc61c64b
XL
125 self.create_def(import.node.id,
126 DefPathData::Misc,
127 ITEM_LIKE_SPACE);
476ff2be
SL
128 }
129 }
130 }
131 DefPathData::Misc
132 }
a7813a04 133 };
cc61c64b 134 let def = self.create_def(i.id, def_data, ITEM_LIKE_SPACE);
a7813a04
XL
135
136 self.with_parent(def, |this| {
137 match i.node {
138 ItemKind::Enum(ref enum_definition, _) => {
139 for v in &enum_definition.variants {
140 let variant_def_index =
141 this.create_def(v.node.data.id(),
ea8adc8c 142 DefPathData::EnumVariant(v.node.name.name.as_str()),
cc61c64b 143 REGULAR_SPACE);
a7813a04
XL
144 this.with_parent(variant_def_index, |this| {
145 for (index, field) in v.node.data.fields().iter().enumerate() {
041b39d2
XL
146 let name = field.ident.map(|ident| ident.name)
147 .unwrap_or_else(|| Symbol::intern(&index.to_string()));
ea8adc8c
XL
148 this.create_def(field.id,
149 DefPathData::Field(name.as_str()),
150 REGULAR_SPACE);
a7813a04
XL
151 }
152
153 if let Some(ref expr) = v.node.disr_expr {
32a655c1 154 this.visit_const_expr(expr);
a7813a04
XL
155 }
156 });
157 }
158 }
9e0c209e 159 ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
a7813a04
XL
160 // If this is a tuple-like struct, register the constructor.
161 if !struct_def.is_struct() {
162 this.create_def(struct_def.id(),
cc61c64b
XL
163 DefPathData::StructCtor,
164 REGULAR_SPACE);
a7813a04
XL
165 }
166
167 for (index, field) in struct_def.fields().iter().enumerate() {
041b39d2
XL
168 let name = field.ident.map(|ident| ident.name)
169 .unwrap_or_else(|| Symbol::intern(&index.to_string()));
ea8adc8c 170 this.create_def(field.id, DefPathData::Field(name.as_str()), REGULAR_SPACE);
a7813a04
XL
171 }
172 }
173 _ => {}
174 }
175 visit::walk_item(this, i);
176 });
177 }
178
476ff2be 179 fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
5bcae85e 180 let def = self.create_def(foreign_item.id,
ea8adc8c 181 DefPathData::ValueNs(foreign_item.ident.name.as_str()),
cc61c64b 182 REGULAR_SPACE);
a7813a04
XL
183
184 self.with_parent(def, |this| {
185 visit::walk_foreign_item(this, foreign_item);
186 });
187 }
188
476ff2be 189 fn visit_generics(&mut self, generics: &'a Generics) {
a7813a04 190 for ty_param in generics.ty_params.iter() {
cc61c64b 191 self.create_def(ty_param.id,
ea8adc8c 192 DefPathData::TypeParam(ty_param.ident.name.as_str()),
cc61c64b 193 REGULAR_SPACE);
a7813a04
XL
194 }
195
196 visit::walk_generics(self, generics);
197 }
198
476ff2be 199 fn visit_trait_item(&mut self, ti: &'a TraitItem) {
a7813a04
XL
200 let def_data = match ti.node {
201 TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
ea8adc8c
XL
202 DefPathData::ValueNs(ti.ident.name.as_str()),
203 TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name.as_str()),
c30ab7b3 204 TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
a7813a04
XL
205 };
206
cc61c64b 207 let def = self.create_def(ti.id, def_data, ITEM_LIKE_SPACE);
a7813a04
XL
208 self.with_parent(def, |this| {
209 if let TraitItemKind::Const(_, Some(ref expr)) = ti.node {
32a655c1 210 this.visit_const_expr(expr);
a7813a04
XL
211 }
212
213 visit::walk_trait_item(this, ti);
214 });
215 }
216
476ff2be 217 fn visit_impl_item(&mut self, ii: &'a ImplItem) {
a7813a04
XL
218 let def_data = match ii.node {
219 ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
ea8adc8c
XL
220 DefPathData::ValueNs(ii.ident.name.as_str()),
221 ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name.as_str()),
c30ab7b3 222 ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
a7813a04
XL
223 };
224
cc61c64b 225 let def = self.create_def(ii.id, def_data, ITEM_LIKE_SPACE);
a7813a04
XL
226 self.with_parent(def, |this| {
227 if let ImplItemKind::Const(_, ref expr) = ii.node {
32a655c1 228 this.visit_const_expr(expr);
a7813a04
XL
229 }
230
231 visit::walk_impl_item(this, ii);
232 });
233 }
234
476ff2be 235 fn visit_pat(&mut self, pat: &'a Pat) {
c30ab7b3
SL
236 match pat.node {
237 PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false),
ea8adc8c 238 _ => visit::walk_pat(self, pat),
a7813a04 239 }
a7813a04
XL
240 }
241
476ff2be 242 fn visit_expr(&mut self, expr: &'a Expr) {
a7813a04
XL
243 let parent_def = self.parent_def;
244
c30ab7b3
SL
245 match expr.node {
246 ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, false),
32a655c1 247 ExprKind::Repeat(_, ref count) => self.visit_const_expr(count),
c30ab7b3 248 ExprKind::Closure(..) => {
cc61c64b
XL
249 let def = self.create_def(expr.id,
250 DefPathData::ClosureExpr,
251 REGULAR_SPACE);
c30ab7b3
SL
252 self.parent_def = Some(def);
253 }
254 _ => {}
a7813a04
XL
255 }
256
257 visit::walk_expr(self, expr);
258 self.parent_def = parent_def;
259 }
260
476ff2be 261 fn visit_ty(&mut self, ty: &'a Ty) {
c30ab7b3
SL
262 match ty.node {
263 TyKind::Mac(..) => return self.visit_macro_invoc(ty.id, false),
32a655c1 264 TyKind::Array(_, ref length) => self.visit_const_expr(length),
c30ab7b3 265 TyKind::ImplTrait(..) => {
cc61c64b 266 self.create_def(ty.id, DefPathData::ImplTrait, REGULAR_SPACE);
c30ab7b3 267 }
32a655c1 268 TyKind::Typeof(ref expr) => self.visit_const_expr(expr),
c30ab7b3 269 _ => {}
5bcae85e 270 }
a7813a04
XL
271 visit::walk_ty(self, ty);
272 }
273
476ff2be 274 fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) {
cc61c64b 275 self.create_def(def.lifetime.id,
ea8adc8c 276 DefPathData::LifetimeDef(def.lifetime.ident.name.as_str()),
cc61c64b 277 REGULAR_SPACE);
a7813a04
XL
278 }
279
476ff2be 280 fn visit_stmt(&mut self, stmt: &'a Stmt) {
c30ab7b3
SL
281 match stmt.node {
282 StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id, false),
283 _ => visit::walk_stmt(self, stmt),
284 }
285 }
a7813a04 286}