]> git.lizzy.rs Git - rust.git/commitdiff
HIR visitor for DefCollector
authorNick Cameron <ncameron@mozilla.com>
Thu, 14 Apr 2016 06:04:55 +0000 (18:04 +1200)
committerNick Cameron <ncameron@mozilla.com>
Tue, 19 Apr 2016 22:13:35 +0000 (10:13 +1200)
So that we can work with inlined HIR from metadata.

src/librustc/hir/map/def_collector.rs
src/librustc/hir/map/mod.rs

index 9d6027932f6dea9938ca8134001845813cf57658..f8d0243548fd13afcb031a57281975812cf484ed 100644 (file)
 
 use super::*;
 
+use hir;
+use hir::intravisit;
 use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
 
+use middle::cstore::InlinedItem;
+
 use syntax::ast::*;
 use syntax::visit;
 
 /// Creates def ids for nodes in the HIR.
-pub struct DefCollector {
+pub struct DefCollector<'ast> {
+    // If we are walking HIR (c.f., AST), we need to keep a reference to the
+    // crate.
+    hir_crate: Option<&'ast hir::Crate>,
     pub definitions: Definitions,
-    pub parent_def: Option<DefIndex>,
+    parent_def: Option<DefIndex>,
 }
 
-impl DefCollector {
-    pub fn root() -> DefCollector {
+impl<'ast> DefCollector<'ast> {
+    pub fn root() -> DefCollector<'ast> {
         let mut collector = DefCollector {
+            hir_crate: None,
             definitions: Definitions::new(),
             parent_def: None,
         };
@@ -39,8 +47,9 @@ pub fn extend(parent_node: NodeId,
                   parent_def_path: DefPath,
                   parent_def_id: DefId,
                   definitions: Definitions)
-                  -> DefCollector {
+                  -> DefCollector<'ast> {
         let mut collector = DefCollector {
+            hir_crate: None,
             parent_def: None,
             definitions: definitions,
         };
@@ -57,6 +66,11 @@ pub fn extend(parent_node: NodeId,
         collector
     }
 
+    pub fn walk_item(&mut self, ii: &'ast InlinedItem, krate: &'ast hir::Crate) {
+        self.hir_crate = Some(krate);
+        ii.visit(self);
+    }
+
     fn parent_def(&self) -> Option<DefIndex> {
         self.parent_def
     }
@@ -83,7 +97,7 @@ fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
     }
 }
 
-impl<'ast> visit::Visitor<'ast> for DefCollector {
+impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
     fn visit_item(&mut self, i: &'ast Item) {
         debug!("visit_item: {:?}", i);
 
@@ -226,3 +240,151 @@ fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
         self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.ident.name));
     }
 }
+
+// We walk the HIR rather than the AST when reading items from metadata.
+impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
+    /// Because we want to track parent items and so forth, enable
+    /// deep walking so that we walk nested items in the context of
+    /// their outer items.
+    fn visit_nested_item(&mut self, item_id: hir::ItemId) {
+        debug!("visit_nested_item: {:?}", item_id);
+        let item = self.hir_crate.unwrap().item(item_id.id);
+        self.visit_item(item)
+    }
+
+    fn visit_item(&mut self, i: &'ast hir::Item) {
+        debug!("visit_item: {:?}", i);
+
+        // Pick the def data. This need not be unique, but the more
+        // information we encapsulate into
+        let def_data = match i.node {
+            hir::ItemDefaultImpl(..) | hir::ItemImpl(..) =>
+                DefPathData::Impl,
+            hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemTrait(..) |
+            hir::ItemExternCrate(..) | hir::ItemMod(..) | hir::ItemForeignMod(..) |
+            hir::ItemTy(..) =>
+                DefPathData::TypeNs(i.name),
+            hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) =>
+                DefPathData::ValueNs(i.name),
+            hir::ItemUse(..) => DefPathData::Misc,
+        };
+        let def = self.create_def(i.id, def_data);
+
+        self.with_parent(def, |this| {
+            match i.node {
+                hir::ItemEnum(ref enum_definition, _) => {
+                    for v in &enum_definition.variants {
+                        let variant_def_index =
+                            this.create_def(v.node.data.id(),
+                                            DefPathData::EnumVariant(v.node.name));
+
+                        for field in v.node.data.fields() {
+                            this.create_def_with_parent(Some(variant_def_index),
+                                                        field.id,
+                                                        DefPathData::Field(field.name));
+                        }
+                    }
+                }
+                hir::ItemStruct(ref struct_def, _) => {
+                    // If this is a tuple-like struct, register the constructor.
+                    if !struct_def.is_struct() {
+                        this.create_def(struct_def.id(),
+                                        DefPathData::StructCtor);
+                    }
+
+                    for field in struct_def.fields() {
+                        this.create_def(field.id, DefPathData::Field(field.name));
+                    }
+                }
+                _ => {}
+            }
+            intravisit::walk_item(this, i);
+        });
+    }
+
+    fn visit_foreign_item(&mut self, foreign_item: &'ast hir::ForeignItem) {
+        let def = self.create_def(foreign_item.id, DefPathData::ValueNs(foreign_item.name));
+
+        self.with_parent(def, |this| {
+            intravisit::walk_foreign_item(this, foreign_item);
+        });
+    }
+
+    fn visit_generics(&mut self, generics: &'ast hir::Generics) {
+        for ty_param in generics.ty_params.iter() {
+            self.create_def(ty_param.id, DefPathData::TypeParam(ty_param.name));
+        }
+
+        intravisit::walk_generics(self, generics);
+    }
+
+    fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
+        let def_data = match ti.node {
+            hir::MethodTraitItem(..) | hir::ConstTraitItem(..) =>
+                DefPathData::ValueNs(ti.name),
+            hir::TypeTraitItem(..) => DefPathData::TypeNs(ti.name),
+        };
+
+        let def = self.create_def(ti.id, def_data);
+        self.with_parent(def, |this| {
+            if let hir::ConstTraitItem(_, Some(ref expr)) = ti.node {
+                this.create_def(expr.id, DefPathData::Initializer);
+            }
+
+            intravisit::walk_trait_item(this, ti);
+        });
+    }
+
+    fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
+        let def_data = match ii.node {
+            hir::ImplItemKind::Method(..) | hir::ImplItemKind::Const(..) =>
+                DefPathData::ValueNs(ii.name),
+            hir::ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name),
+        };
+
+        let def = self.create_def(ii.id, def_data);
+        self.with_parent(def, |this| {
+            if let hir::ImplItemKind::Const(_, ref expr) = ii.node {
+                this.create_def(expr.id, DefPathData::Initializer);
+            }
+
+            intravisit::walk_impl_item(this, ii);
+        });
+    }
+
+    fn visit_pat(&mut self, pat: &'ast hir::Pat) {
+        let maybe_binding = match pat.node {
+            hir::PatKind::Ident(_, id, _) => Some(id.node),
+            _ => None
+        };
+
+        let parent_def = self.parent_def;
+        if let Some(id) = maybe_binding {
+            let def = self.create_def(pat.id, DefPathData::Binding(id.name));
+            self.parent_def = Some(def);
+        }
+
+        intravisit::walk_pat(self, pat);
+        self.parent_def = parent_def;
+    }
+
+    fn visit_expr(&mut self, expr: &'ast hir::Expr) {
+        let parent_def = self.parent_def;
+
+        if let hir::ExprClosure(..) = expr.node {
+            let def = self.create_def(expr.id, DefPathData::ClosureExpr);
+            self.parent_def = Some(def);
+        }
+
+        intravisit::walk_expr(self, expr);
+        self.parent_def = parent_def;
+    }
+
+    fn visit_lifetime_def(&mut self, def: &'ast hir::LifetimeDef) {
+        self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
+    }
+
+    fn visit_macro_def(&mut self, macro_def: &'ast hir::MacroDef) {
+        self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
+    }
+}
\ No newline at end of file
index a505ad198896f585b85b11f9a22433575476c80c..1d0c40646b51a885589cf157d5dc4f32654b582c 100644 (file)
@@ -843,14 +843,13 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
     let ii = map.forest.inlined_items.alloc(ii);
     let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
 
-    // TODO need to save defs in metadata :-(
-    // let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new());
-    // let mut def_collector = DefCollector::extend(ii_parent_id,
-    //                                              parent_def_path.clone(),
-    //                                              parent_def_id,
-    //                                              defs);
-    // ii.visit(&mut def_collector);
-    // *map.definitions.borrow_mut() = def_collector.definitions;
+    let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new());
+    let mut def_collector = DefCollector::extend(ii_parent_id,
+                                                 parent_def_path.clone(),
+                                                 parent_def_id,
+                                                 defs);
+    def_collector.walk_item(ii, map.krate());
+    *map.definitions.borrow_mut() = def_collector.definitions;
 
     let mut collector = NodeCollector::extend(map.krate(),
                                               ii,