1010
1111use super :: * ;
1212
13+ use hir;
14+ use hir:: intravisit;
1315use hir:: def_id:: { CRATE_DEF_INDEX , DefId , DefIndex } ;
1416
17+ use middle:: cstore:: InlinedItem ;
18+
1519use syntax:: ast:: * ;
1620use syntax:: visit;
1721
1822/// Creates def ids for nodes in the HIR.
19- pub struct DefCollector {
23+ pub struct DefCollector < ' ast > {
24+ // If we are walking HIR (c.f., AST), we need to keep a reference to the
25+ // crate.
26+ hir_crate : Option < & ' ast hir:: Crate > ,
2027 pub definitions : Definitions ,
21- pub parent_def : Option < DefIndex > ,
28+ parent_def : Option < DefIndex > ,
2229}
2330
24- impl DefCollector {
25- pub fn root ( ) -> DefCollector {
31+ impl < ' ast > DefCollector < ' ast > {
32+ pub fn root ( ) -> DefCollector < ' ast > {
2633 let mut collector = DefCollector {
34+ hir_crate : None ,
2735 definitions : Definitions :: new ( ) ,
2836 parent_def : None ,
2937 } ;
@@ -39,8 +47,9 @@ impl DefCollector {
3947 parent_def_path : DefPath ,
4048 parent_def_id : DefId ,
4149 definitions : Definitions )
42- -> DefCollector {
50+ -> DefCollector < ' ast > {
4351 let mut collector = DefCollector {
52+ hir_crate : None ,
4453 parent_def : None ,
4554 definitions : definitions,
4655 } ;
@@ -57,6 +66,11 @@ impl DefCollector {
5766 collector
5867 }
5968
69+ pub fn walk_item ( & mut self , ii : & ' ast InlinedItem , krate : & ' ast hir:: Crate ) {
70+ self . hir_crate = Some ( krate) ;
71+ ii. visit ( self ) ;
72+ }
73+
6074 fn parent_def ( & self ) -> Option < DefIndex > {
6175 self . parent_def
6276 }
@@ -83,7 +97,7 @@ impl DefCollector {
8397 }
8498}
8599
86- impl < ' ast > visit:: Visitor < ' ast > for DefCollector {
100+ impl < ' ast > visit:: Visitor < ' ast > for DefCollector < ' ast > {
87101 fn visit_item ( & mut self , i : & ' ast Item ) {
88102 debug ! ( "visit_item: {:?}" , i) ;
89103
@@ -226,3 +240,151 @@ impl<'ast> visit::Visitor<'ast> for DefCollector {
226240 self . create_def ( macro_def. id , DefPathData :: MacroDef ( macro_def. ident . name ) ) ;
227241 }
228242}
243+
244+ // We walk the HIR rather than the AST when reading items from metadata.
245+ impl < ' ast > intravisit:: Visitor < ' ast > for DefCollector < ' ast > {
246+ /// Because we want to track parent items and so forth, enable
247+ /// deep walking so that we walk nested items in the context of
248+ /// their outer items.
249+ fn visit_nested_item ( & mut self , item_id : hir:: ItemId ) {
250+ debug ! ( "visit_nested_item: {:?}" , item_id) ;
251+ let item = self . hir_crate . unwrap ( ) . item ( item_id. id ) ;
252+ self . visit_item ( item)
253+ }
254+
255+ fn visit_item ( & mut self , i : & ' ast hir:: Item ) {
256+ debug ! ( "visit_item: {:?}" , i) ;
257+
258+ // Pick the def data. This need not be unique, but the more
259+ // information we encapsulate into
260+ let def_data = match i. node {
261+ hir:: ItemDefaultImpl ( ..) | hir:: ItemImpl ( ..) =>
262+ DefPathData :: Impl ,
263+ hir:: ItemEnum ( ..) | hir:: ItemStruct ( ..) | hir:: ItemTrait ( ..) |
264+ hir:: ItemExternCrate ( ..) | hir:: ItemMod ( ..) | hir:: ItemForeignMod ( ..) |
265+ hir:: ItemTy ( ..) =>
266+ DefPathData :: TypeNs ( i. name ) ,
267+ hir:: ItemStatic ( ..) | hir:: ItemConst ( ..) | hir:: ItemFn ( ..) =>
268+ DefPathData :: ValueNs ( i. name ) ,
269+ hir:: ItemUse ( ..) => DefPathData :: Misc ,
270+ } ;
271+ let def = self . create_def ( i. id , def_data) ;
272+
273+ self . with_parent ( def, |this| {
274+ match i. node {
275+ hir:: ItemEnum ( ref enum_definition, _) => {
276+ for v in & enum_definition. variants {
277+ let variant_def_index =
278+ this. create_def ( v. node . data . id ( ) ,
279+ DefPathData :: EnumVariant ( v. node . name ) ) ;
280+
281+ for field in v. node . data . fields ( ) {
282+ this. create_def_with_parent ( Some ( variant_def_index) ,
283+ field. id ,
284+ DefPathData :: Field ( field. name ) ) ;
285+ }
286+ }
287+ }
288+ hir:: ItemStruct ( ref struct_def, _) => {
289+ // If this is a tuple-like struct, register the constructor.
290+ if !struct_def. is_struct ( ) {
291+ this. create_def ( struct_def. id ( ) ,
292+ DefPathData :: StructCtor ) ;
293+ }
294+
295+ for field in struct_def. fields ( ) {
296+ this. create_def ( field. id , DefPathData :: Field ( field. name ) ) ;
297+ }
298+ }
299+ _ => { }
300+ }
301+ intravisit:: walk_item ( this, i) ;
302+ } ) ;
303+ }
304+
305+ fn visit_foreign_item ( & mut self , foreign_item : & ' ast hir:: ForeignItem ) {
306+ let def = self . create_def ( foreign_item. id , DefPathData :: ValueNs ( foreign_item. name ) ) ;
307+
308+ self . with_parent ( def, |this| {
309+ intravisit:: walk_foreign_item ( this, foreign_item) ;
310+ } ) ;
311+ }
312+
313+ fn visit_generics ( & mut self , generics : & ' ast hir:: Generics ) {
314+ for ty_param in generics. ty_params . iter ( ) {
315+ self . create_def ( ty_param. id , DefPathData :: TypeParam ( ty_param. name ) ) ;
316+ }
317+
318+ intravisit:: walk_generics ( self , generics) ;
319+ }
320+
321+ fn visit_trait_item ( & mut self , ti : & ' ast hir:: TraitItem ) {
322+ let def_data = match ti. node {
323+ hir:: MethodTraitItem ( ..) | hir:: ConstTraitItem ( ..) =>
324+ DefPathData :: ValueNs ( ti. name ) ,
325+ hir:: TypeTraitItem ( ..) => DefPathData :: TypeNs ( ti. name ) ,
326+ } ;
327+
328+ let def = self . create_def ( ti. id , def_data) ;
329+ self . with_parent ( def, |this| {
330+ if let hir:: ConstTraitItem ( _, Some ( ref expr) ) = ti. node {
331+ this. create_def ( expr. id , DefPathData :: Initializer ) ;
332+ }
333+
334+ intravisit:: walk_trait_item ( this, ti) ;
335+ } ) ;
336+ }
337+
338+ fn visit_impl_item ( & mut self , ii : & ' ast hir:: ImplItem ) {
339+ let def_data = match ii. node {
340+ hir:: ImplItemKind :: Method ( ..) | hir:: ImplItemKind :: Const ( ..) =>
341+ DefPathData :: ValueNs ( ii. name ) ,
342+ hir:: ImplItemKind :: Type ( ..) => DefPathData :: TypeNs ( ii. name ) ,
343+ } ;
344+
345+ let def = self . create_def ( ii. id , def_data) ;
346+ self . with_parent ( def, |this| {
347+ if let hir:: ImplItemKind :: Const ( _, ref expr) = ii. node {
348+ this. create_def ( expr. id , DefPathData :: Initializer ) ;
349+ }
350+
351+ intravisit:: walk_impl_item ( this, ii) ;
352+ } ) ;
353+ }
354+
355+ fn visit_pat ( & mut self , pat : & ' ast hir:: Pat ) {
356+ let maybe_binding = match pat. node {
357+ hir:: PatKind :: Ident ( _, id, _) => Some ( id. node ) ,
358+ _ => None
359+ } ;
360+
361+ let parent_def = self . parent_def ;
362+ if let Some ( id) = maybe_binding {
363+ let def = self . create_def ( pat. id , DefPathData :: Binding ( id. name ) ) ;
364+ self . parent_def = Some ( def) ;
365+ }
366+
367+ intravisit:: walk_pat ( self , pat) ;
368+ self . parent_def = parent_def;
369+ }
370+
371+ fn visit_expr ( & mut self , expr : & ' ast hir:: Expr ) {
372+ let parent_def = self . parent_def ;
373+
374+ if let hir:: ExprClosure ( ..) = expr. node {
375+ let def = self . create_def ( expr. id , DefPathData :: ClosureExpr ) ;
376+ self . parent_def = Some ( def) ;
377+ }
378+
379+ intravisit:: walk_expr ( self , expr) ;
380+ self . parent_def = parent_def;
381+ }
382+
383+ fn visit_lifetime_def ( & mut self , def : & ' ast hir:: LifetimeDef ) {
384+ self . create_def ( def. lifetime . id , DefPathData :: LifetimeDef ( def. lifetime . name ) ) ;
385+ }
386+
387+ fn visit_macro_def ( & mut self , macro_def : & ' ast hir:: MacroDef ) {
388+ self . create_def ( macro_def. id , DefPathData :: MacroDef ( macro_def. name ) ) ;
389+ }
390+ }
0 commit comments