]>
Commit | Line | Data |
---|---|---|
9fa01778 XL |
1 | use crate::hir::map::definitions::*; |
2 | use crate::hir::def_id::{CRATE_DEF_INDEX, DefIndex, DefIndexAddressSpace}; | |
3 | use crate::session::CrateDisambiguator; | |
a7813a04 XL |
4 | |
5 | use syntax::ast::*; | |
c30ab7b3 | 6 | use syntax::ext::hygiene::Mark; |
a7813a04 | 7 | use syntax::visit; |
7cac9316 | 8 | use syntax::symbol::keywords; |
041b39d2 | 9 | use syntax::symbol::Symbol; |
abe05a73 | 10 | use syntax::parse::token::{self, Token}; |
0531ce1d | 11 | use syntax_pos::Span; |
a7813a04 | 12 | |
9fa01778 | 13 | use crate::hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE}; |
cc61c64b | 14 | |
9fa01778 | 15 | /// Creates `DefId`s for nodes in the AST. |
c30ab7b3 | 16 | pub struct DefCollector<'a> { |
c30ab7b3 | 17 | definitions: &'a mut Definitions, |
a7813a04 | 18 | parent_def: Option<DefIndex>, |
7cac9316 | 19 | expansion: Mark, |
0531ce1d | 20 | pub visit_macro_invoc: Option<&'a mut dyn FnMut(MacroInvocationData)>, |
a7813a04 XL |
21 | } |
22 | ||
c30ab7b3 SL |
23 | pub struct MacroInvocationData { |
24 | pub mark: Mark, | |
25 | pub def_index: DefIndex, | |
c30ab7b3 SL |
26 | } |
27 | ||
28 | impl<'a> DefCollector<'a> { | |
7cac9316 | 29 | pub fn new(definitions: &'a mut Definitions, expansion: Mark) -> Self { |
9e0c209e | 30 | DefCollector { |
041b39d2 XL |
31 | definitions, |
32 | expansion, | |
a7813a04 | 33 | parent_def: None, |
c30ab7b3 | 34 | visit_macro_invoc: None, |
9e0c209e | 35 | } |
a7813a04 XL |
36 | } |
37 | ||
abe05a73 XL |
38 | pub fn collect_root(&mut self, |
39 | crate_name: &str, | |
40 | crate_disambiguator: CrateDisambiguator) { | |
cc61c64b XL |
41 | let root = self.definitions.create_root_def(crate_name, |
42 | crate_disambiguator); | |
9e0c209e SL |
43 | assert_eq!(root, CRATE_DEF_INDEX); |
44 | self.parent_def = Some(root); | |
a7813a04 XL |
45 | } |
46 | ||
cc61c64b XL |
47 | fn create_def(&mut self, |
48 | node_id: NodeId, | |
49 | data: DefPathData, | |
0531ce1d XL |
50 | address_space: DefIndexAddressSpace, |
51 | span: Span) | |
cc61c64b XL |
52 | -> DefIndex { |
53 | let parent_def = self.parent_def.unwrap(); | |
a7813a04 | 54 | debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def); |
7cac9316 | 55 | self.definitions |
0531ce1d | 56 | .create_def_with_parent(parent_def, node_id, data, address_space, self.expansion, span) |
a7813a04 XL |
57 | } |
58 | ||
c30ab7b3 | 59 | pub fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) { |
a7813a04 XL |
60 | let parent = self.parent_def; |
61 | self.parent_def = Some(parent_def); | |
62 | f(self); | |
63 | self.parent_def = parent; | |
64 | } | |
65 | ||
8faf50e0 XL |
66 | fn visit_async_fn( |
67 | &mut self, | |
68 | id: NodeId, | |
8faf50e0 XL |
69 | name: Name, |
70 | span: Span, | |
b7449926 XL |
71 | header: &FnHeader, |
72 | generics: &'a Generics, | |
73 | decl: &'a FnDecl, | |
74 | body: &'a Block, | |
8faf50e0 | 75 | ) { |
b7449926 XL |
76 | let (closure_id, return_impl_trait_id) = match header.asyncness { |
77 | IsAsync::Async { | |
78 | closure_id, | |
79 | return_impl_trait_id, | |
80 | } => (closure_id, return_impl_trait_id), | |
81 | _ => unreachable!(), | |
82 | }; | |
83 | ||
8faf50e0 XL |
84 | // For async functions, we need to create their inner defs inside of a |
85 | // closure to match their desugared representation. | |
86 | let fn_def_data = DefPathData::ValueNs(name.as_interned_str()); | |
87 | let fn_def = self.create_def(id, fn_def_data, ITEM_LIKE_SPACE, span); | |
88 | return self.with_parent(fn_def, |this| { | |
89 | this.create_def(return_impl_trait_id, DefPathData::ImplTrait, REGULAR_SPACE, span); | |
b7449926 XL |
90 | |
91 | visit::walk_generics(this, generics); | |
92 | visit::walk_fn_decl(this, decl); | |
93 | ||
94 | let closure_def = this.create_def(closure_id, | |
0bf4aa26 XL |
95 | DefPathData::ClosureExpr, |
96 | REGULAR_SPACE, | |
97 | span); | |
b7449926 XL |
98 | this.with_parent(closure_def, |this| { |
99 | visit::walk_block(this, body); | |
100 | }) | |
8faf50e0 XL |
101 | }) |
102 | } | |
103 | ||
94b46f34 | 104 | fn visit_macro_invoc(&mut self, id: NodeId) { |
c30ab7b3 SL |
105 | if let Some(ref mut visit) = self.visit_macro_invoc { |
106 | visit(MacroInvocationData { | |
cc61c64b | 107 | mark: id.placeholder_to_mark(), |
c30ab7b3 SL |
108 | def_index: self.parent_def.unwrap(), |
109 | }) | |
110 | } | |
111 | } | |
a7813a04 XL |
112 | } |
113 | ||
476ff2be SL |
114 | impl<'a> visit::Visitor<'a> for DefCollector<'a> { |
115 | fn visit_item(&mut self, i: &'a Item) { | |
a7813a04 XL |
116 | debug!("visit_item: {:?}", i); |
117 | ||
118 | // Pick the def data. This need not be unique, but the more | |
94b46f34 | 119 | // information we encapsulate into, the better |
a7813a04 | 120 | let def_data = match i.node { |
2c00a5a8 | 121 | ItemKind::Impl(..) => DefPathData::Impl, |
8faf50e0 | 122 | ItemKind::Trait(..) => DefPathData::Trait(i.ident.as_interned_str()), |
9fa01778 | 123 | ItemKind::TraitAlias(..) => DefPathData::TraitAlias(i.ident.as_interned_str()), |
ff7c6d11 | 124 | ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | |
9fa01778 XL |
125 | ItemKind::Existential(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | |
126 | ItemKind::Ty(..) => DefPathData::TypeNs(i.ident.as_interned_str()), | |
c30ab7b3 SL |
127 | ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => { |
128 | return visit::walk_item(self, i); | |
129 | } | |
b7449926 XL |
130 | ItemKind::Fn( |
131 | ref decl, | |
132 | ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. }, | |
133 | ref generics, | |
134 | ref body, | |
135 | ) => { | |
8faf50e0 XL |
136 | return self.visit_async_fn( |
137 | i.id, | |
8faf50e0 XL |
138 | i.ident.name, |
139 | i.span, | |
b7449926 XL |
140 | header, |
141 | generics, | |
142 | decl, | |
143 | body, | |
8faf50e0 XL |
144 | ) |
145 | } | |
146 | ItemKind::Mod(..) => DefPathData::Module(i.ident.as_interned_str()), | |
a7813a04 | 147 | ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => |
8faf50e0 XL |
148 | DefPathData::ValueNs(i.ident.as_interned_str()), |
149 | ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.as_interned_str()), | |
94b46f34 | 150 | ItemKind::Mac(..) => return self.visit_macro_invoc(i.id), |
cc61c64b | 151 | ItemKind::GlobalAsm(..) => DefPathData::Misc, |
ff7c6d11 XL |
152 | ItemKind::Use(..) => { |
153 | return visit::walk_item(self, i); | |
476ff2be | 154 | } |
a7813a04 | 155 | }; |
0531ce1d | 156 | let def = self.create_def(i.id, def_data, ITEM_LIKE_SPACE, i.span); |
a7813a04 XL |
157 | |
158 | self.with_parent(def, |this| { | |
159 | match i.node { | |
9e0c209e | 160 | ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => { |
a7813a04 XL |
161 | // If this is a tuple-like struct, register the constructor. |
162 | if !struct_def.is_struct() { | |
163 | this.create_def(struct_def.id(), | |
cc61c64b | 164 | DefPathData::StructCtor, |
0531ce1d XL |
165 | REGULAR_SPACE, |
166 | i.span); | |
a7813a04 | 167 | } |
a7813a04 XL |
168 | } |
169 | _ => {} | |
170 | } | |
171 | visit::walk_item(this, i); | |
172 | }); | |
173 | } | |
174 | ||
ff7c6d11 | 175 | fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) { |
0531ce1d | 176 | self.create_def(id, DefPathData::Misc, ITEM_LIKE_SPACE, use_tree.span); |
ff7c6d11 XL |
177 | visit::walk_use_tree(self, use_tree, id); |
178 | } | |
179 | ||
476ff2be | 180 | fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) { |
83c7162d | 181 | if let ForeignItemKind::Macro(_) = foreign_item.node { |
94b46f34 | 182 | return self.visit_macro_invoc(foreign_item.id); |
83c7162d XL |
183 | } |
184 | ||
5bcae85e | 185 | let def = self.create_def(foreign_item.id, |
8faf50e0 | 186 | DefPathData::ValueNs(foreign_item.ident.as_interned_str()), |
0531ce1d XL |
187 | REGULAR_SPACE, |
188 | foreign_item.span); | |
a7813a04 XL |
189 | |
190 | self.with_parent(def, |this| { | |
191 | visit::walk_foreign_item(this, foreign_item); | |
192 | }); | |
193 | } | |
194 | ||
94b46f34 XL |
195 | fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) { |
196 | let def = self.create_def(v.node.data.id(), | |
8faf50e0 | 197 | DefPathData::EnumVariant(v.node.ident.as_interned_str()), |
94b46f34 XL |
198 | REGULAR_SPACE, |
199 | v.span); | |
200 | self.with_parent(def, |this| visit::walk_variant(this, v, g, item_id)); | |
201 | } | |
202 | ||
203 | fn visit_variant_data(&mut self, data: &'a VariantData, _: Ident, | |
204 | _: &'a Generics, _: NodeId, _: Span) { | |
205 | for (index, field) in data.fields().iter().enumerate() { | |
206 | let name = field.ident.map(|ident| ident.name) | |
207 | .unwrap_or_else(|| Symbol::intern(&index.to_string())); | |
208 | let def = self.create_def(field.id, | |
209 | DefPathData::Field(name.as_interned_str()), | |
210 | REGULAR_SPACE, | |
211 | field.span); | |
212 | self.with_parent(def, |this| this.visit_struct_field(field)); | |
213 | } | |
214 | } | |
215 | ||
ff7c6d11 | 216 | fn visit_generic_param(&mut self, param: &'a GenericParam) { |
8faf50e0 XL |
217 | let name = param.ident.as_interned_str(); |
218 | let def_path_data = match param.kind { | |
219 | GenericParamKind::Lifetime { .. } => DefPathData::LifetimeParam(name), | |
220 | GenericParamKind::Type { .. } => DefPathData::TypeParam(name), | |
9fa01778 | 221 | GenericParamKind::Const { .. } => DefPathData::ConstParam(name), |
8faf50e0 XL |
222 | }; |
223 | self.create_def(param.id, def_path_data, REGULAR_SPACE, param.ident.span); | |
a7813a04 | 224 | |
ff7c6d11 | 225 | visit::walk_generic_param(self, param); |
a7813a04 XL |
226 | } |
227 | ||
476ff2be | 228 | fn visit_trait_item(&mut self, ti: &'a TraitItem) { |
a7813a04 XL |
229 | let def_data = match ti.node { |
230 | TraitItemKind::Method(..) | TraitItemKind::Const(..) => | |
8faf50e0 | 231 | DefPathData::ValueNs(ti.ident.as_interned_str()), |
83c7162d | 232 | TraitItemKind::Type(..) => { |
8faf50e0 | 233 | DefPathData::AssocTypeInTrait(ti.ident.as_interned_str()) |
83c7162d | 234 | }, |
94b46f34 | 235 | TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id), |
a7813a04 XL |
236 | }; |
237 | ||
0531ce1d | 238 | let def = self.create_def(ti.id, def_data, ITEM_LIKE_SPACE, ti.span); |
94b46f34 | 239 | self.with_parent(def, |this| visit::walk_trait_item(this, ti)); |
a7813a04 XL |
240 | } |
241 | ||
476ff2be | 242 | fn visit_impl_item(&mut self, ii: &'a ImplItem) { |
a7813a04 | 243 | let def_data = match ii.node { |
8faf50e0 | 244 | ImplItemKind::Method(MethodSig { |
b7449926 XL |
245 | header: ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. }, |
246 | ref decl, | |
247 | }, ref body) => { | |
8faf50e0 XL |
248 | return self.visit_async_fn( |
249 | ii.id, | |
8faf50e0 XL |
250 | ii.ident.name, |
251 | ii.span, | |
b7449926 XL |
252 | header, |
253 | &ii.generics, | |
254 | decl, | |
255 | body, | |
8faf50e0 XL |
256 | ) |
257 | } | |
a7813a04 | 258 | ImplItemKind::Method(..) | ImplItemKind::Const(..) => |
8faf50e0 XL |
259 | DefPathData::ValueNs(ii.ident.as_interned_str()), |
260 | ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.as_interned_str()), | |
261 | ImplItemKind::Existential(..) => { | |
262 | DefPathData::AssocExistentialInImpl(ii.ident.as_interned_str()) | |
263 | }, | |
94b46f34 | 264 | ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id), |
a7813a04 XL |
265 | }; |
266 | ||
0531ce1d | 267 | let def = self.create_def(ii.id, def_data, ITEM_LIKE_SPACE, ii.span); |
94b46f34 | 268 | self.with_parent(def, |this| visit::walk_impl_item(this, ii)); |
a7813a04 XL |
269 | } |
270 | ||
476ff2be | 271 | fn visit_pat(&mut self, pat: &'a Pat) { |
c30ab7b3 | 272 | match pat.node { |
94b46f34 | 273 | PatKind::Mac(..) => return self.visit_macro_invoc(pat.id), |
ea8adc8c | 274 | _ => visit::walk_pat(self, pat), |
a7813a04 | 275 | } |
a7813a04 XL |
276 | } |
277 | ||
94b46f34 XL |
278 | fn visit_anon_const(&mut self, constant: &'a AnonConst) { |
279 | let def = self.create_def(constant.id, | |
280 | DefPathData::AnonConst, | |
281 | REGULAR_SPACE, | |
282 | constant.value.span); | |
283 | self.with_parent(def, |this| visit::walk_anon_const(this, constant)); | |
284 | } | |
285 | ||
476ff2be | 286 | fn visit_expr(&mut self, expr: &'a Expr) { |
a7813a04 XL |
287 | let parent_def = self.parent_def; |
288 | ||
c30ab7b3 | 289 | match expr.node { |
94b46f34 | 290 | ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id), |
8faf50e0 XL |
291 | ExprKind::Closure(_, asyncness, ..) => { |
292 | let closure_def = self.create_def(expr.id, | |
cc61c64b | 293 | DefPathData::ClosureExpr, |
0531ce1d XL |
294 | REGULAR_SPACE, |
295 | expr.span); | |
8faf50e0 XL |
296 | self.parent_def = Some(closure_def); |
297 | ||
298 | // Async closures desugar to closures inside of closures, so | |
299 | // we must create two defs. | |
300 | if let IsAsync::Async { closure_id, .. } = asyncness { | |
301 | let async_def = self.create_def(closure_id, | |
302 | DefPathData::ClosureExpr, | |
303 | REGULAR_SPACE, | |
304 | expr.span); | |
305 | self.parent_def = Some(async_def); | |
306 | } | |
307 | } | |
308 | ExprKind::Async(_, async_id, _) => { | |
309 | let async_def = self.create_def(async_id, | |
310 | DefPathData::ClosureExpr, | |
311 | REGULAR_SPACE, | |
312 | expr.span); | |
313 | self.parent_def = Some(async_def); | |
c30ab7b3 SL |
314 | } |
315 | _ => {} | |
8faf50e0 | 316 | }; |
a7813a04 XL |
317 | |
318 | visit::walk_expr(self, expr); | |
319 | self.parent_def = parent_def; | |
320 | } | |
321 | ||
476ff2be | 322 | fn visit_ty(&mut self, ty: &'a Ty) { |
c30ab7b3 | 323 | match ty.node { |
94b46f34 | 324 | TyKind::Mac(..) => return self.visit_macro_invoc(ty.id), |
8faf50e0 XL |
325 | TyKind::ImplTrait(node_id, _) => { |
326 | self.create_def(node_id, DefPathData::ImplTrait, REGULAR_SPACE, ty.span); | |
327 | } | |
c30ab7b3 | 328 | _ => {} |
5bcae85e | 329 | } |
a7813a04 XL |
330 | visit::walk_ty(self, ty); |
331 | } | |
332 | ||
476ff2be | 333 | fn visit_stmt(&mut self, stmt: &'a Stmt) { |
c30ab7b3 | 334 | match stmt.node { |
94b46f34 | 335 | StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id), |
c30ab7b3 SL |
336 | _ => visit::walk_stmt(self, stmt), |
337 | } | |
338 | } | |
abe05a73 XL |
339 | |
340 | fn visit_token(&mut self, t: Token) { | |
341 | if let Token::Interpolated(nt) = t { | |
9fa01778 | 342 | if let token::NtExpr(ref expr) = *nt { |
b7449926 XL |
343 | if let ExprKind::Mac(..) = expr.node { |
344 | self.visit_macro_invoc(expr.id); | |
abe05a73 | 345 | } |
abe05a73 XL |
346 | } |
347 | } | |
348 | } | |
a7813a04 | 349 | } |