about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2016-11-02 18:25:31 -0400
committerNiko Matsakis <niko@alum.mit.edu>2016-11-16 13:51:36 -0500
commitb889259e2b42479584343eb3674b7a3de1870e5b (patch)
treef85a495d294b6030fc84257cbbfbe376638fffca
parent36fbf8c53cd37498e5eaadf02740e2aac87f6118 (diff)
downloadrust-b889259e2b42479584343eb3674b7a3de1870e5b.tar.gz
rust-b889259e2b42479584343eb3674b7a3de1870e5b.zip
separate impl-items from the impl in the HIR
This commit does not change how the incremental accounting is done, so
changes (or accessses) to an impl-item are still tagged to the enclosing
impl.

This commits adds the "main guts" of this change. It does not build on
its own.
-rw-r--r--src/librustc/dep_graph/visit.rs12
-rw-r--r--src/librustc/hir/intravisit.rs18
-rw-r--r--src/librustc/hir/itemlikevisit.rs2
-rw-r--r--src/librustc/hir/lowering.rs22
-rw-r--r--src/librustc/hir/map/mod.rs9
-rw-r--r--src/librustc/hir/mod.rs20
-rw-r--r--src/librustc/hir/print.rs14
7 files changed, 86 insertions, 11 deletions
diff --git a/src/librustc/dep_graph/visit.rs b/src/librustc/dep_graph/visit.rs
index 30de5e5288a..6d89bbba54e 100644
--- a/src/librustc/dep_graph/visit.rs
+++ b/src/librustc/dep_graph/visit.rs
@@ -45,6 +45,18 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>
             self.visitor.visit_item(i);
             debug!("Ended task {:?}", task_id);
         }
+
+        fn visit_impl_item(&mut self, i: &'tcx hir::ImplItem) {
+            // TODO -- use the def-id of the impl for now
+            let impl_def_id = self.tcx.map.get_parent_did(i.id);
+            let task_id = (self.dep_node_fn)(impl_def_id);
+            let _task = self.tcx.dep_graph.in_task(task_id.clone());
+            debug!("Started task {:?}", task_id);
+            assert!(!self.tcx.map.is_inlined_def_id(impl_def_id));
+            self.tcx.dep_graph.read(DepNode::Hir(impl_def_id));
+            self.visitor.visit_impl_item(i);
+            debug!("Ended task {:?}", task_id);
+        }
     }
 
     let krate = tcx.dep_graph.with_ignore(|| tcx.map.krate());
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 2fc27e0cea0..5a193a0ac94 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -94,7 +94,17 @@ pub trait Visitor<'v> : Sized {
     fn visit_nested_item(&mut self, id: ItemId) {
     }
 
-    /// Visit the top-level item and (optionally) nested items. See
+    /// Invoked when a nested impl item is encountered. By default, does
+    /// nothing. If you want a deep walk, you need to override to
+    /// fetch the item contents. But most of the time, it is easier
+    /// (and better) to invoke `Crate::visit_all_item_likes`, which visits
+    /// all items in the crate in some order (but doesn't respect
+    /// nesting).
+    #[allow(unused_variables)]
+    fn visit_nested_impl_item(&mut self, id: ImplItemId) {
+    }
+
+    /// Visit the top-level item and (optionally) nested items / impl items. See
     /// `visit_nested_item` for details.
     fn visit_item(&mut self, i: &'v Item) {
         walk_item(self, i)
@@ -359,12 +369,14 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_id(item.id);
             visitor.visit_trait_ref(trait_ref)
         }
-        ItemImpl(.., ref type_parameters, ref opt_trait_reference, ref typ, ref impl_items) => {
+        ItemImpl(.., ref type_parameters, ref opt_trait_reference, ref typ, ref impl_item_ids) => {
             visitor.visit_id(item.id);
             visitor.visit_generics(type_parameters);
             walk_list!(visitor, visit_trait_ref, opt_trait_reference);
             visitor.visit_ty(typ);
-            walk_list!(visitor, visit_impl_item, impl_items);
+            for &impl_item_id in impl_item_ids {
+                visitor.visit_nested_impl_item(impl_item_id);
+            }
         }
         ItemStruct(ref struct_definition, ref generics) |
         ItemUnion(ref struct_definition, ref generics) => {
diff --git a/src/librustc/hir/itemlikevisit.rs b/src/librustc/hir/itemlikevisit.rs
index 6da47015d7d..22b56604428 100644
--- a/src/librustc/hir/itemlikevisit.rs
+++ b/src/librustc/hir/itemlikevisit.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::Item;
+use super::{Item, ImplItem};
 use super::intravisit::Visitor;
 
 /// The "item-like visitor" visitor defines only the top-level methods
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index b985298e47c..0731c35ff16 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -105,6 +105,7 @@ impl<'a> LoweringContext<'a> {
     fn lower_crate(&mut self, c: &Crate) -> hir::Crate {
         struct ItemLowerer<'lcx, 'interner: 'lcx> {
             items: BTreeMap<NodeId, hir::Item>,
+            impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
             lctx: &'lcx mut LoweringContext<'interner>,
         }
 
@@ -113,12 +114,20 @@ impl<'a> LoweringContext<'a> {
                 self.items.insert(item.id, self.lctx.lower_item(item));
                 visit::walk_item(self, item);
             }
+
+            fn visit_impl_item(&mut self, item: &ImplItem) {
+                let id = self.lctx.lower_impl_item_id(item);
+                self.impl_items.insert(id, self.lctx.lower_impl_item(item));
+                visit::walk_impl_item(self, item);
+            }
         }
 
-        let items = {
-            let mut item_lowerer = ItemLowerer { items: BTreeMap::new(), lctx: self };
+        let (items, impl_items) = {
+            let mut item_lowerer = ItemLowerer { items: BTreeMap::new(),
+                                                 impl_items: BTreeMap::new(),
+                                                 lctx: self };
             visit::walk_crate(&mut item_lowerer, c);
-            item_lowerer.items
+            (item_lowerer.items, item_lowerer.impl_items)
         };
 
         hir::Crate {
@@ -127,6 +136,7 @@ impl<'a> LoweringContext<'a> {
             span: c.span,
             exported_macros: c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect(),
             items: items,
+            impl_items: impl_items,
         }
     }
 
@@ -631,7 +641,7 @@ impl<'a> LoweringContext<'a> {
             }
             ItemKind::Impl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => {
                 let new_impl_items = impl_items.iter()
-                                               .map(|item| self.lower_impl_item(item))
+                                               .map(|item| self.lower_impl_item_id(item))
                                                .collect();
                 let ifce = ifce.as_ref().map(|trait_ref| self.lower_trait_ref(trait_ref));
                 hir::ItemImpl(self.lower_unsafety(unsafety),
@@ -707,6 +717,10 @@ impl<'a> LoweringContext<'a> {
         })
     }
 
+    fn lower_impl_item_id(&mut self, i: &ImplItem) -> hir::ImplItemId {
+        hir::ImplItemId { id: i.id }
+    }
+
     fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
         hir::Mod {
             inner: m.inner,
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 39114ec4238..c629ec66ca4 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -378,6 +378,15 @@ impl<'ast> Map<'ast> {
         self.forest.krate()
     }
 
+    pub fn impl_item(&self, id: ImplItemId) -> &'ast ImplItem {
+        // TODO right now this triggers a read of the whole impl
+        self.read(id.id);
+
+        // NB: intentionally bypass `self.forest.krate()` so that we
+        // do not trigger a read of the whole krate here
+        self.forest.krate.impl_item(id)
+    }
+
     /// Get the attributes on the krate. This is preferable to
     /// invoking `krate.attrs` because it registers a tighter
     /// dep-graph access.
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 4716a09ad35..c9892135b1d 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -424,6 +424,8 @@ pub struct Crate {
     // detected, which in turn can make compile-fail tests yield
     // slightly different results.
     pub items: BTreeMap<NodeId, Item>,
+
+    pub impl_items: BTreeMap<ImplItemId, ImplItem>,
 }
 
 impl Crate {
@@ -431,6 +433,10 @@ impl Crate {
         &self.items[&id]
     }
 
+    pub fn impl_item(&self, id: ImplItemId) -> &ImplItem {
+        &self.impl_items[&id]
+    }
+
     /// Visits all items in the crate in some determinstic (but
     /// unspecified) order. If you just need to process every item,
     /// but don't care about nesting, this method is the best choice.
@@ -445,6 +451,10 @@ impl Crate {
         for (_, item) in &self.items {
             visitor.visit_item(item);
         }
+
+        for (_, impl_item) in &self.impl_items {
+            visitor.visit_impl_item(impl_item);
+        }
     }
 }
 
@@ -1042,6 +1052,14 @@ pub enum TraitItem_ {
     TypeTraitItem(TyParamBounds, Option<P<Ty>>),
 }
 
+// The bodies for items are stored "out of line", in a separate
+// hashmap in the `Crate`. Here we just record the node-id of the item
+// so it can fetched later.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct ImplItemId {
+    pub id: NodeId,
+}
+
 /// Represents anything within an `impl` block
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct ImplItem {
@@ -1528,7 +1546,7 @@ pub enum Item_ {
              Generics,
              Option<TraitRef>, // (optional) trait this impl implements
              P<Ty>, // self
-             HirVec<ImplItem>),
+             HirVec<ImplItemId>),
 }
 
 impl Item_ {
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 2c4ffb853c1..ed274b5a23e 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -808,8 +808,8 @@ impl<'a> State<'a> {
                 space(&mut self.s)?;
                 self.bopen()?;
                 self.print_inner_attributes(&item.attrs)?;
-                for impl_item in impl_items {
-                    self.print_impl_item(impl_item)?;
+                for &impl_item in impl_items {
+                    self.print_impl_item_id(impl_item)?;
                 }
                 self.bclose(item.span)?;
             }
@@ -1020,6 +1020,16 @@ impl<'a> State<'a> {
         self.ann.post(self, NodeSubItem(ti.id))
     }
 
+    pub fn print_impl_item_id(&mut self, item_id: hir::ImplItemId) -> io::Result<()> {
+        if let Some(krate) = self.krate {
+            // skip nested items if krate context was not provided
+            let item = &krate.impl_item(item_id);
+            self.print_impl_item(item)
+        } else {
+            Ok(())
+        }
+    }
+
     pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> {
         self.ann.pre(self, NodeSubItem(ii.id))?;
         self.hardbreak_if_not_bol()?;