]>
Commit | Line | Data |
---|---|---|
6a06907d | 1 | use crate::{ImplTraitContext, Resolver}; |
ba9703b0 | 2 | use rustc_ast::visit::{self, FnKind}; |
3dfed10e | 3 | use rustc_ast::*; |
dfeec247 | 4 | use rustc_expand::expand::AstFragment; |
ba9703b0 XL |
5 | use rustc_hir::def_id::LocalDefId; |
6 | use rustc_hir::definitions::*; | |
136023e0 | 7 | use rustc_span::hygiene::LocalExpnId; |
a2a8927a | 8 | use rustc_span::symbol::sym; |
dfeec247 | 9 | use rustc_span::Span; |
a7813a04 | 10 | |
923072b8 | 11 | pub(crate) fn collect_definitions( |
9ffffee4 | 12 | resolver: &mut Resolver<'_, '_>, |
60c5eb7d | 13 | fragment: &AstFragment, |
136023e0 | 14 | expansion: LocalExpnId, |
60c5eb7d | 15 | ) { |
6a06907d XL |
16 | let (parent_def, impl_trait_context) = resolver.invocation_parents[&expansion]; |
17 | fragment.visit_with(&mut DefCollector { resolver, parent_def, expansion, impl_trait_context }); | |
60c5eb7d XL |
18 | } |
19 | ||
9fa01778 | 20 | /// Creates `DefId`s for nodes in the AST. |
9ffffee4 FG |
21 | struct DefCollector<'a, 'b, 'tcx> { |
22 | resolver: &'a mut Resolver<'b, 'tcx>, | |
ba9703b0 | 23 | parent_def: LocalDefId, |
6a06907d | 24 | impl_trait_context: ImplTraitContext, |
136023e0 | 25 | expansion: LocalExpnId, |
c30ab7b3 SL |
26 | } |
27 | ||
9ffffee4 | 28 | impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> { |
ba9703b0 | 29 | fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> LocalDefId { |
416331ca | 30 | let parent_def = self.parent_def; |
a7813a04 | 31 | debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def); |
c295e0f8 XL |
32 | self.resolver.create_def( |
33 | parent_def, | |
34 | node_id, | |
35 | data, | |
36 | self.expansion.to_expn_id(), | |
37 | span.with_parent(None), | |
38 | ) | |
a7813a04 XL |
39 | } |
40 | ||
ba9703b0 | 41 | fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) { |
416331ca | 42 | let orig_parent_def = std::mem::replace(&mut self.parent_def, parent_def); |
a7813a04 | 43 | f(self); |
416331ca | 44 | self.parent_def = orig_parent_def; |
a7813a04 XL |
45 | } |
46 | ||
6a06907d XL |
47 | fn with_impl_trait<F: FnOnce(&mut Self)>( |
48 | &mut self, | |
49 | impl_trait_context: ImplTraitContext, | |
50 | f: F, | |
51 | ) { | |
52 | let orig_itc = std::mem::replace(&mut self.impl_trait_context, impl_trait_context); | |
53 | f(self); | |
54 | self.impl_trait_context = orig_itc; | |
55 | } | |
56 | ||
57 | fn collect_field(&mut self, field: &'a FieldDef, index: Option<usize>) { | |
dfeec247 XL |
58 | let index = |this: &Self| { |
59 | index.unwrap_or_else(|| { | |
60 | let node_id = NodeId::placeholder_from_expn_id(this.expansion); | |
f035d41b | 61 | this.resolver.placeholder_field_indices[&node_id] |
dfeec247 XL |
62 | }) |
63 | }; | |
e74abb32 | 64 | |
e1599b0c | 65 | if field.is_placeholder { |
f035d41b XL |
66 | let old_index = self.resolver.placeholder_field_indices.insert(field.id, index(self)); |
67 | assert!(old_index.is_none(), "placeholder field index is reset for a node ID"); | |
e1599b0c XL |
68 | self.visit_macro_invoc(field.id); |
69 | } else { | |
e74abb32 | 70 | let name = field.ident.map_or_else(|| sym::integer(index(self)), |ident| ident.name); |
e1599b0c | 71 | let def = self.create_def(field.id, DefPathData::ValueNs(name), field.span); |
6a06907d | 72 | self.with_parent(def, |this| visit::walk_field_def(this, field)); |
e1599b0c XL |
73 | } |
74 | } | |
75 | ||
e74abb32 | 76 | fn visit_macro_invoc(&mut self, id: NodeId) { |
6a06907d | 77 | let id = id.placeholder_to_expn_id(); |
f035d41b | 78 | let old_parent = |
6a06907d | 79 | self.resolver.invocation_parents.insert(id, (self.parent_def, self.impl_trait_context)); |
f035d41b | 80 | assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation"); |
c30ab7b3 | 81 | } |
a7813a04 XL |
82 | } |
83 | ||
9ffffee4 | 84 | impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { |
476ff2be | 85 | fn visit_item(&mut self, i: &'a Item) { |
a7813a04 XL |
86 | debug!("visit_item: {:?}", i); |
87 | ||
88 | // Pick the def data. This need not be unique, but the more | |
94b46f34 | 89 | // information we encapsulate into, the better |
60c5eb7d | 90 | let def_data = match &i.kind { |
dfeec247 | 91 | ItemKind::Impl { .. } => DefPathData::Impl, |
a2a8927a | 92 | ItemKind::ForeignMod(..) => DefPathData::ForeignMod, |
dfeec247 XL |
93 | ItemKind::Mod(..) |
94 | | ItemKind::Trait(..) | |
95 | | ItemKind::TraitAlias(..) | |
96 | | ItemKind::Enum(..) | |
97 | | ItemKind::Struct(..) | |
98 | | ItemKind::Union(..) | |
99 | | ItemKind::ExternCrate(..) | |
dfeec247 | 100 | | ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name), |
dfeec247 XL |
101 | ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => { |
102 | DefPathData::ValueNs(i.ident.name) | |
8faf50e0 | 103 | } |
e74abb32 | 104 | ItemKind::MacroDef(..) => DefPathData::MacroNs(i.ident.name), |
5869c6ff XL |
105 | ItemKind::MacCall(..) => { |
106 | visit::walk_item(self, i); | |
107 | return self.visit_macro_invoc(i.id); | |
108 | } | |
04454e1e | 109 | ItemKind::GlobalAsm(..) => DefPathData::GlobalAsm, |
ff7c6d11 XL |
110 | ItemKind::Use(..) => { |
111 | return visit::walk_item(self, i); | |
476ff2be | 112 | } |
a7813a04 | 113 | }; |
48663c56 | 114 | let def = self.create_def(i.id, def_data, i.span); |
a7813a04 XL |
115 | |
116 | self.with_parent(def, |this| { | |
6a06907d XL |
117 | this.with_impl_trait(ImplTraitContext::Existential, |this| { |
118 | match i.kind { | |
119 | ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => { | |
120 | // If this is a unit or tuple-like struct, register the constructor. | |
487cf647 FG |
121 | if let Some(ctor_node_id) = struct_def.ctor_node_id() { |
122 | this.create_def(ctor_node_id, DefPathData::Ctor, i.span); | |
6a06907d | 123 | } |
a7813a04 | 124 | } |
6a06907d | 125 | _ => {} |
a7813a04 | 126 | } |
6a06907d XL |
127 | visit::walk_item(this, i); |
128 | }) | |
a7813a04 XL |
129 | }); |
130 | } | |
131 | ||
ba9703b0 | 132 | fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) { |
04454e1e | 133 | if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind { |
487cf647 | 134 | if let Async::Yes { closure_id, .. } = sig.header.asyncness { |
04454e1e FG |
135 | self.visit_generics(generics); |
136 | ||
ba9703b0 XL |
137 | // For async functions, we need to create their inner defs inside of a |
138 | // closure to match their desugared representation. Besides that, | |
139 | // we must mirror everything that `visit::walk_fn` below does. | |
140 | self.visit_fn_header(&sig.header); | |
6a06907d XL |
141 | for param in &sig.decl.inputs { |
142 | self.visit_param(param); | |
143 | } | |
487cf647 | 144 | self.visit_fn_ret_ty(&sig.decl.output); |
2b03887a FG |
145 | // If this async fn has no body (i.e. it's an async fn signature in a trait) |
146 | // then the closure_def will never be used, and we should avoid generating a | |
147 | // def-id for it. | |
148 | if let Some(body) = body { | |
149 | let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span); | |
150 | self.with_parent(closure_def, |this| this.visit_block(body)); | |
151 | } | |
ba9703b0 XL |
152 | return; |
153 | } | |
154 | } | |
155 | ||
f2b60f7d | 156 | visit::walk_fn(self, fn_kind); |
ba9703b0 XL |
157 | } |
158 | ||
ff7c6d11 | 159 | fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) { |
04454e1e | 160 | self.create_def(id, DefPathData::Use, use_tree.span); |
ff7c6d11 XL |
161 | visit::walk_use_tree(self, use_tree, id); |
162 | } | |
163 | ||
476ff2be | 164 | fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) { |
ba9703b0 | 165 | if let ForeignItemKind::MacCall(_) = foreign_item.kind { |
94b46f34 | 166 | return self.visit_macro_invoc(foreign_item.id); |
83c7162d XL |
167 | } |
168 | ||
dfeec247 XL |
169 | let def = self.create_def( |
170 | foreign_item.id, | |
171 | DefPathData::ValueNs(foreign_item.ident.name), | |
172 | foreign_item.span, | |
173 | ); | |
a7813a04 XL |
174 | |
175 | self.with_parent(def, |this| { | |
176 | visit::walk_foreign_item(this, foreign_item); | |
177 | }); | |
178 | } | |
179 | ||
e1599b0c XL |
180 | fn visit_variant(&mut self, v: &'a Variant) { |
181 | if v.is_placeholder { | |
182 | return self.visit_macro_invoc(v.id); | |
183 | } | |
dfeec247 | 184 | let def = self.create_def(v.id, DefPathData::TypeNs(v.ident.name), v.span); |
532ac7d7 | 185 | self.with_parent(def, |this| { |
487cf647 FG |
186 | if let Some(ctor_node_id) = v.data.ctor_node_id() { |
187 | this.create_def(ctor_node_id, DefPathData::Ctor, v.span); | |
532ac7d7 | 188 | } |
e1599b0c | 189 | visit::walk_variant(this, v) |
532ac7d7 | 190 | }); |
94b46f34 XL |
191 | } |
192 | ||
e1599b0c XL |
193 | fn visit_variant_data(&mut self, data: &'a VariantData) { |
194 | // The assumption here is that non-`cfg` macro expansion cannot change field indices. | |
195 | // It currently holds because only inert attributes are accepted on fields, | |
196 | // and every such attribute expands into a single field after it's resolved. | |
94b46f34 | 197 | for (index, field) in data.fields().iter().enumerate() { |
e1599b0c | 198 | self.collect_field(field, Some(index)); |
94b46f34 XL |
199 | } |
200 | } | |
201 | ||
ff7c6d11 | 202 | fn visit_generic_param(&mut self, param: &'a GenericParam) { |
e1599b0c XL |
203 | if param.is_placeholder { |
204 | self.visit_macro_invoc(param.id); | |
205 | return; | |
206 | } | |
e74abb32 | 207 | let name = param.ident.name; |
8faf50e0 | 208 | let def_path_data = match param.kind { |
48663c56 XL |
209 | GenericParamKind::Lifetime { .. } => DefPathData::LifetimeNs(name), |
210 | GenericParamKind::Type { .. } => DefPathData::TypeNs(name), | |
211 | GenericParamKind::Const { .. } => DefPathData::ValueNs(name), | |
8faf50e0 | 212 | }; |
48663c56 | 213 | self.create_def(param.id, def_path_data, param.ident.span); |
a7813a04 | 214 | |
6a06907d XL |
215 | // impl-Trait can happen inside generic parameters, like |
216 | // ``` | |
217 | // fn foo<U: Iterator<Item = impl Clone>>() {} | |
218 | // ``` | |
219 | // | |
220 | // In that case, the impl-trait is lowered as an additional generic parameter. | |
221 | self.with_impl_trait(ImplTraitContext::Universal(self.parent_def), |this| { | |
222 | visit::walk_generic_param(this, param) | |
223 | }); | |
a7813a04 XL |
224 | } |
225 | ||
74b04a01 XL |
226 | fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) { |
227 | let def_data = match &i.kind { | |
74b04a01 | 228 | AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(i.ident.name), |
2b03887a | 229 | AssocItemKind::Type(..) => DefPathData::TypeNs(i.ident.name), |
ba9703b0 | 230 | AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id), |
a7813a04 XL |
231 | }; |
232 | ||
74b04a01 XL |
233 | let def = self.create_def(i.id, def_data, i.span); |
234 | self.with_parent(def, |this| visit::walk_assoc_item(this, i, ctxt)); | |
a7813a04 XL |
235 | } |
236 | ||
476ff2be | 237 | fn visit_pat(&mut self, pat: &'a Pat) { |
e74abb32 | 238 | match pat.kind { |
ba9703b0 | 239 | PatKind::MacCall(..) => self.visit_macro_invoc(pat.id), |
ea8adc8c | 240 | _ => visit::walk_pat(self, pat), |
a7813a04 | 241 | } |
a7813a04 XL |
242 | } |
243 | ||
94b46f34 | 244 | fn visit_anon_const(&mut self, constant: &'a AnonConst) { |
dfeec247 | 245 | let def = self.create_def(constant.id, DefPathData::AnonConst, constant.value.span); |
94b46f34 XL |
246 | self.with_parent(def, |this| visit::walk_anon_const(this, constant)); |
247 | } | |
248 | ||
476ff2be | 249 | fn visit_expr(&mut self, expr: &'a Expr) { |
e74abb32 | 250 | let parent_def = match expr.kind { |
ba9703b0 | 251 | ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id), |
487cf647 | 252 | ExprKind::Closure(ref closure) => { |
8faf50e0 XL |
253 | // Async closures desugar to closures inside of closures, so |
254 | // we must create two defs. | |
416331ca | 255 | let closure_def = self.create_def(expr.id, DefPathData::ClosureExpr, expr.span); |
487cf647 | 256 | match closure.asyncness { |
74b04a01 | 257 | Async::Yes { closure_id, .. } => { |
dfeec247 XL |
258 | self.create_def(closure_id, DefPathData::ClosureExpr, expr.span) |
259 | } | |
74b04a01 | 260 | Async::No => closure_def, |
8faf50e0 XL |
261 | } |
262 | } | |
353b0b11 | 263 | ExprKind::Async(_, _) => self.create_def(expr.id, DefPathData::ClosureExpr, expr.span), |
416331ca | 264 | _ => self.parent_def, |
8faf50e0 | 265 | }; |
a7813a04 | 266 | |
416331ca | 267 | self.with_parent(parent_def, |this| visit::walk_expr(this, expr)); |
a7813a04 XL |
268 | } |
269 | ||
476ff2be | 270 | fn visit_ty(&mut self, ty: &'a Ty) { |
e74abb32 | 271 | match ty.kind { |
29967ef6 | 272 | TyKind::MacCall(..) => self.visit_macro_invoc(ty.id), |
29967ef6 | 273 | _ => visit::walk_ty(self, ty), |
5bcae85e | 274 | } |
a7813a04 XL |
275 | } |
276 | ||
476ff2be | 277 | fn visit_stmt(&mut self, stmt: &'a Stmt) { |
e74abb32 | 278 | match stmt.kind { |
ba9703b0 | 279 | StmtKind::MacCall(..) => self.visit_macro_invoc(stmt.id), |
c30ab7b3 SL |
280 | _ => visit::walk_stmt(self, stmt), |
281 | } | |
282 | } | |
abe05a73 | 283 | |
e1599b0c | 284 | fn visit_arm(&mut self, arm: &'a Arm) { |
dfeec247 | 285 | if arm.is_placeholder { self.visit_macro_invoc(arm.id) } else { visit::walk_arm(self, arm) } |
e1599b0c XL |
286 | } |
287 | ||
6a06907d XL |
288 | fn visit_expr_field(&mut self, f: &'a ExprField) { |
289 | if f.is_placeholder { | |
290 | self.visit_macro_invoc(f.id) | |
291 | } else { | |
292 | visit::walk_expr_field(self, f) | |
293 | } | |
e1599b0c XL |
294 | } |
295 | ||
6a06907d | 296 | fn visit_pat_field(&mut self, fp: &'a PatField) { |
e1599b0c XL |
297 | if fp.is_placeholder { |
298 | self.visit_macro_invoc(fp.id) | |
299 | } else { | |
6a06907d | 300 | visit::walk_pat_field(self, fp) |
e1599b0c XL |
301 | } |
302 | } | |
303 | ||
304 | fn visit_param(&mut self, p: &'a Param) { | |
6a06907d XL |
305 | if p.is_placeholder { |
306 | self.visit_macro_invoc(p.id) | |
307 | } else { | |
308 | self.with_impl_trait(ImplTraitContext::Universal(self.parent_def), |this| { | |
309 | visit::walk_param(this, p) | |
310 | }) | |
311 | } | |
e1599b0c XL |
312 | } |
313 | ||
314 | // This method is called only when we are visiting an individual field | |
315 | // after expanding an attribute on it. | |
6a06907d | 316 | fn visit_field_def(&mut self, field: &'a FieldDef) { |
e1599b0c XL |
317 | self.collect_field(field, None); |
318 | } | |
a2a8927a XL |
319 | |
320 | fn visit_crate(&mut self, krate: &'a Crate) { | |
321 | if krate.is_placeholder { | |
322 | self.visit_macro_invoc(krate.id) | |
323 | } else { | |
324 | visit::walk_crate(self, krate) | |
325 | } | |
326 | } | |
a7813a04 | 327 | } |