1 use crate::hir
::map
::definitions
::*;
2 use crate::hir
::def_id
::{CRATE_DEF_INDEX, DefIndex, DefIndexAddressSpace}
;
3 use crate::session
::CrateDisambiguator
;
6 use syntax
::ext
::hygiene
::Mark
;
8 use syntax
::symbol
::keywords
;
9 use syntax
::symbol
::Symbol
;
10 use syntax
::parse
::token
::{self, Token}
;
13 use crate::hir
::map
::{ITEM_LIKE_SPACE, REGULAR_SPACE}
;
15 /// Creates `DefId`s for nodes in the AST.
16 pub struct DefCollector
<'a
> {
17 definitions
: &'a
mut Definitions
,
18 parent_def
: Option
<DefIndex
>,
20 pub visit_macro_invoc
: Option
<&'a
mut dyn FnMut(MacroInvocationData
)>,
23 pub struct MacroInvocationData
{
25 pub def_index
: DefIndex
,
28 impl<'a
> DefCollector
<'a
> {
29 pub fn new(definitions
: &'a
mut Definitions
, expansion
: Mark
) -> Self {
34 visit_macro_invoc
: None
,
38 pub fn collect_root(&mut self,
40 crate_disambiguator
: CrateDisambiguator
) {
41 let root
= self.definitions
.create_root_def(crate_name
,
43 assert_eq
!(root
, CRATE_DEF_INDEX
);
44 self.parent_def
= Some(root
);
47 fn create_def(&mut self,
50 address_space
: DefIndexAddressSpace
,
53 let parent_def
= self.parent_def
.unwrap();
54 debug
!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id
, data
, parent_def
);
56 .create_def_with_parent(parent_def
, node_id
, data
, address_space
, self.expansion
, span
)
59 pub fn with_parent
<F
: FnOnce(&mut Self)>(&mut self, parent_def
: DefIndex
, f
: F
) {
60 let parent
= self.parent_def
;
61 self.parent_def
= Some(parent_def
);
63 self.parent_def
= parent
;
72 generics
: &'a Generics
,
76 let (closure_id
, return_impl_trait_id
) = match header
.asyncness
{
80 } => (closure_id
, return_impl_trait_id
),
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
);
91 visit
::walk_generics(this
, generics
);
92 visit
::walk_fn_decl(this
, decl
);
94 let closure_def
= this
.create_def(closure_id
,
95 DefPathData
::ClosureExpr
,
98 this
.with_parent(closure_def
, |this
| {
99 visit
::walk_block(this
, body
);
104 fn visit_macro_invoc(&mut self, id
: NodeId
) {
105 if let Some(ref mut visit
) = self.visit_macro_invoc
{
106 visit(MacroInvocationData
{
107 mark
: id
.placeholder_to_mark(),
108 def_index
: self.parent_def
.unwrap(),
114 impl<'a
> visit
::Visitor
<'a
> for DefCollector
<'a
> {
115 fn visit_item(&mut self, i
: &'a Item
) {
116 debug
!("visit_item: {:?}", i
);
118 // Pick the def data. This need not be unique, but the more
119 // information we encapsulate into, the better
120 let def_data
= match i
.node
{
121 ItemKind
::Impl(..) => DefPathData
::Impl
,
122 ItemKind
::Trait(..) => DefPathData
::Trait(i
.ident
.as_interned_str()),
123 ItemKind
::TraitAlias(..) => DefPathData
::TraitAlias(i
.ident
.as_interned_str()),
124 ItemKind
::Enum(..) | ItemKind
::Struct(..) | ItemKind
::Union(..) |
125 ItemKind
::Existential(..) | ItemKind
::ExternCrate(..) | ItemKind
::ForeignMod(..) |
126 ItemKind
::Ty(..) => DefPathData
::TypeNs(i
.ident
.as_interned_str()),
127 ItemKind
::Mod(..) if i
.ident
== keywords
::Invalid
.ident() => {
128 return visit
::walk_item(self, i
);
132 ref header @ FnHeader { asyncness: IsAsync::Async { .. }
, .. },
136 return self.visit_async_fn(
146 ItemKind
::Mod(..) => DefPathData
::Module(i
.ident
.as_interned_str()),
147 ItemKind
::Static(..) | ItemKind
::Const(..) | ItemKind
::Fn(..) =>
148 DefPathData
::ValueNs(i
.ident
.as_interned_str()),
149 ItemKind
::MacroDef(..) => DefPathData
::MacroDef(i
.ident
.as_interned_str()),
150 ItemKind
::Mac(..) => return self.visit_macro_invoc(i
.id
),
151 ItemKind
::GlobalAsm(..) => DefPathData
::Misc
,
152 ItemKind
::Use(..) => {
153 return visit
::walk_item(self, i
);
156 let def
= self.create_def(i
.id
, def_data
, ITEM_LIKE_SPACE
, i
.span
);
158 self.with_parent(def
, |this
| {
160 ItemKind
::Struct(ref struct_def
, _
) | ItemKind
::Union(ref struct_def
, _
) => {
161 // If this is a tuple-like struct, register the constructor.
162 if !struct_def
.is_struct() {
163 this
.create_def(struct_def
.id(),
164 DefPathData
::StructCtor
,
171 visit
::walk_item(this
, i
);
175 fn visit_use_tree(&mut self, use_tree
: &'a UseTree
, id
: NodeId
, _nested
: bool
) {
176 self.create_def(id
, DefPathData
::Misc
, ITEM_LIKE_SPACE
, use_tree
.span
);
177 visit
::walk_use_tree(self, use_tree
, id
);
180 fn visit_foreign_item(&mut self, foreign_item
: &'a ForeignItem
) {
181 if let ForeignItemKind
::Macro(_
) = foreign_item
.node
{
182 return self.visit_macro_invoc(foreign_item
.id
);
185 let def
= self.create_def(foreign_item
.id
,
186 DefPathData
::ValueNs(foreign_item
.ident
.as_interned_str()),
190 self.with_parent(def
, |this
| {
191 visit
::walk_foreign_item(this
, foreign_item
);
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(),
197 DefPathData
::EnumVariant(v
.node
.ident
.as_interned_str()),
200 self.with_parent(def
, |this
| visit
::walk_variant(this
, v
, g
, item_id
));
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()),
212 self.with_parent(def
, |this
| this
.visit_struct_field(field
));
216 fn visit_generic_param(&mut self, param
: &'a GenericParam
) {
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
),
221 GenericParamKind
::Const { .. }
=> DefPathData
::ConstParam(name
),
223 self.create_def(param
.id
, def_path_data
, REGULAR_SPACE
, param
.ident
.span
);
225 visit
::walk_generic_param(self, param
);
228 fn visit_trait_item(&mut self, ti
: &'a TraitItem
) {
229 let def_data
= match ti
.node
{
230 TraitItemKind
::Method(..) | TraitItemKind
::Const(..) =>
231 DefPathData
::ValueNs(ti
.ident
.as_interned_str()),
232 TraitItemKind
::Type(..) => {
233 DefPathData
::AssocTypeInTrait(ti
.ident
.as_interned_str())
235 TraitItemKind
::Macro(..) => return self.visit_macro_invoc(ti
.id
),
238 let def
= self.create_def(ti
.id
, def_data
, ITEM_LIKE_SPACE
, ti
.span
);
239 self.with_parent(def
, |this
| visit
::walk_trait_item(this
, ti
));
242 fn visit_impl_item(&mut self, ii
: &'a ImplItem
) {
243 let def_data
= match ii
.node
{
244 ImplItemKind
::Method(MethodSig
{
245 header
: ref header @ FnHeader { asyncness: IsAsync::Async { .. }
, .. },
248 return self.visit_async_fn(
258 ImplItemKind
::Method(..) | ImplItemKind
::Const(..) =>
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())
264 ImplItemKind
::Macro(..) => return self.visit_macro_invoc(ii
.id
),
267 let def
= self.create_def(ii
.id
, def_data
, ITEM_LIKE_SPACE
, ii
.span
);
268 self.with_parent(def
, |this
| visit
::walk_impl_item(this
, ii
));
271 fn visit_pat(&mut self, pat
: &'a Pat
) {
273 PatKind
::Mac(..) => return self.visit_macro_invoc(pat
.id
),
274 _
=> visit
::walk_pat(self, pat
),
278 fn visit_anon_const(&mut self, constant
: &'a AnonConst
) {
279 let def
= self.create_def(constant
.id
,
280 DefPathData
::AnonConst
,
282 constant
.value
.span
);
283 self.with_parent(def
, |this
| visit
::walk_anon_const(this
, constant
));
286 fn visit_expr(&mut self, expr
: &'a Expr
) {
287 let parent_def
= self.parent_def
;
290 ExprKind
::Mac(..) => return self.visit_macro_invoc(expr
.id
),
291 ExprKind
::Closure(_
, asyncness
, ..) => {
292 let closure_def
= self.create_def(expr
.id
,
293 DefPathData
::ClosureExpr
,
296 self.parent_def
= Some(closure_def
);
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
,
305 self.parent_def
= Some(async_def
);
308 ExprKind
::Async(_
, async_id
, _
) => {
309 let async_def
= self.create_def(async_id
,
310 DefPathData
::ClosureExpr
,
313 self.parent_def
= Some(async_def
);
318 visit
::walk_expr(self, expr
);
319 self.parent_def
= parent_def
;
322 fn visit_ty(&mut self, ty
: &'a Ty
) {
324 TyKind
::Mac(..) => return self.visit_macro_invoc(ty
.id
),
325 TyKind
::ImplTrait(node_id
, _
) => {
326 self.create_def(node_id
, DefPathData
::ImplTrait
, REGULAR_SPACE
, ty
.span
);
330 visit
::walk_ty(self, ty
);
333 fn visit_stmt(&mut self, stmt
: &'a Stmt
) {
335 StmtKind
::Mac(..) => self.visit_macro_invoc(stmt
.id
),
336 _
=> visit
::walk_stmt(self, stmt
),
340 fn visit_token(&mut self, t
: Token
) {
341 if let Token
::Interpolated(nt
) = t
{
342 if let token
::NtExpr(ref expr
) = *nt
{
343 if let ExprKind
::Mac(..) = expr
.node
{
344 self.visit_macro_invoc(expr
.id
);