]> git.lizzy.rs Git - rust.git/commitdiff
Give function bodies their own dep graph node
authorFlorian Diebold <flodiebold@gmail.com>
Sat, 5 Nov 2016 19:12:59 +0000 (20:12 +0100)
committerFlorian Diebold <florian.diebold@freiheit.com>
Tue, 29 Nov 2016 12:04:27 +0000 (13:04 +0100)
15 files changed:
src/librustc/dep_graph/dep_node.rs
src/librustc/hir/map/mod.rs
src/librustc_const_eval/eval.rs
src/librustc_incremental/calculate_svh/mod.rs
src/librustc_incremental/calculate_svh/svh_visitor.rs
src/librustc_incremental/persist/dirty_clean.rs
src/librustc_incremental/persist/hash.rs
src/librustc_incremental/persist/save.rs
src/test/incremental/hello_world.rs
src/test/incremental/ich_method_call_trait_scope.rs
src/test/incremental/ich_nested_items.rs
src/test/incremental/ich_resolve_results.rs
src/test/incremental/source_loc_macros.rs
src/test/incremental/spans_insignificant_w_o_debuginfo.rs
src/test/incremental/spans_significant_w_debuginfo.rs

index 397d61d5372e025a80bafdde754dff7f1e36a5b1..0fc8bf9e17de2e06dca4e9f260917e4fd1a17b05 100644 (file)
@@ -42,6 +42,9 @@ pub enum DepNode<D: Clone + Debug> {
     // Represents the HIR node with the given node-id
     Hir(D),
 
+    // Represents the body of a function or method
+    HirBody(D),
+
     // Represents the metadata for a given HIR node, typically found
     // in an extern crate.
     MetaData(D),
@@ -150,6 +153,7 @@ macro_rules! check {
             CollectItem,
             BorrowCheck,
             Hir,
+            HirBody,
             TransCrateItem,
             TypeckItemType,
             TypeckItemBody,
@@ -199,6 +203,7 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
             WorkProduct(ref id) => Some(WorkProduct(id.clone())),
 
             Hir(ref d) => op(d).map(Hir),
+            HirBody(ref d) => op(d).map(HirBody),
             MetaData(ref d) => op(d).map(MetaData),
             CollectItem(ref d) => op(d).map(CollectItem),
             CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl),
index 33cdb428220871142b5fed9aa49f7650cc1302a7..a78f4de475a447b9b401a21dc2607e78f78a7ca9 100644 (file)
@@ -256,18 +256,39 @@ fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
         let map = self.map.borrow();
         let mut id = id0;
         if !self.is_inlined_node_id(id) {
+            let mut last_expr = None;
             loop {
                 match map[id.as_usize()] {
                     EntryItem(_, item) => {
                         assert_eq!(id, item.id);
                         let def_id = self.local_def_id(id);
                         assert!(!self.is_inlined_def_id(def_id));
+
+                        if let Some(last_id) = last_expr {
+                            // The body of the item may have a separate dep node
+                            // (Note that impl/trait items don't currently have
+                            // their own dep node, so there's also just one
+                            // HirBody node for all the items)
+                            if self.is_body(last_id, item) {
+                                return DepNode::HirBody(def_id);
+                            }
+                        }
                         return DepNode::Hir(def_id);
                     }
 
-                    EntryImplItem(..) => {
+                    EntryImplItem(_, item) => {
                         let def_id = self.local_def_id(id);
                         assert!(!self.is_inlined_def_id(def_id));
+
+                        if let Some(last_id) = last_expr {
+                            // The body of the item may have a separate dep node
+                            // (Note that impl/trait items don't currently have
+                            // their own dep node, so there's also just one
+                            // HirBody node for all the items)
+                            if self.is_impl_item_body(last_id, item) {
+                                return DepNode::HirBody(def_id);
+                            }
+                        }
                         return DepNode::Hir(def_id);
                     }
 
@@ -275,7 +296,6 @@ fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
                     EntryTraitItem(p, _) |
                     EntryVariant(p, _) |
                     EntryField(p, _) |
-                    EntryExpr(p, _) |
                     EntryStmt(p, _) |
                     EntryTy(p, _) |
                     EntryTraitRef(p, _) |
@@ -288,6 +308,11 @@ fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
                     EntryVisibility(p, _) =>
                         id = p,
 
+                    EntryExpr(p, _) => {
+                        last_expr = Some(id);
+                        id = p;
+                    }
+
                     RootCrate =>
                         return DepNode::Krate,
 
@@ -345,6 +370,29 @@ fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
         }
     }
 
+    fn is_body(&self, node_id: NodeId, item: &Item) -> bool {
+        match item.node {
+            ItemFn(_, _, _, _, _, body) => body.node_id() == node_id,
+            // Since trait/impl items currently don't get their own dep nodes,
+            // we check here whether node_id is the body of any of the items.
+            // Once they get their own dep nodes, this can go away
+            ItemTrait(_, _, _, ref trait_items) => {
+                trait_items.iter().any(|trait_item| { match trait_item.node {
+                    MethodTraitItem(_, Some(body)) => body.node_id() == node_id,
+                    _ => false
+                }})
+            }
+            _ => false
+        }
+    }
+
+    fn is_impl_item_body(&self, node_id: NodeId, item: &ImplItem) -> bool {
+        match item.node {
+            ImplItemKind::Method(_, body) => body.node_id() == node_id,
+            _ => false
+        }
+    }
+
     pub fn num_local_def_ids(&self) -> usize {
         self.definitions.borrow().len()
     }
index fb5cff5695072a8558e21208cd450ea9494f4a9b..7972b9dc0987329a68205e02f3626a599f520dd0 100644 (file)
@@ -33,7 +33,6 @@
 use syntax::ast;
 use rustc::hir::{Expr, PatKind};
 use rustc::hir;
-use rustc::hir::intravisit::FnKind;
 use syntax::ptr::P;
 use syntax::codemap;
 use syntax::attr::IntType;
index 250ef061e5109305f9ff50ed1dde0db074685a43..578732edd83dd76f5fc80911b02cca71553cf864 100644 (file)
@@ -149,19 +149,27 @@ fn calculate_def_id<W>(&mut self, def_id: DefId, mut walk_op: W)
     {
         assert!(def_id.is_local());
         debug!("HashItemsVisitor::calculate(def_id={:?})", def_id);
+        self.calculate_def_hash(DepNode::Hir(def_id), false, &mut walk_op);
+        self.calculate_def_hash(DepNode::HirBody(def_id), true, &mut walk_op);
+    }
+
+    fn calculate_def_hash<W>(&mut self, dep_node: DepNode<DefId>, hash_bodies: bool, walk_op: &mut W)
+        where W: for<'v> FnMut(&mut StrictVersionHashVisitor<'v, 'a, 'tcx>)
+    {
         let mut state = IchHasher::new();
         walk_op(&mut StrictVersionHashVisitor::new(&mut state,
                                                    self.tcx,
                                                    &mut self.def_path_hashes,
                                                    &mut self.codemap,
-                                                   self.hash_spans));
+                                                   self.hash_spans,
+                                                   hash_bodies));
         let bytes_hashed = state.bytes_hashed();
         let item_hash = state.finish();
-        self.hashes.insert(DepNode::Hir(def_id), item_hash);
-        debug!("calculate_item_hash: def_id={:?} hash={:?}", def_id, item_hash);
+        debug!("calculate_def_hash: dep_node={:?} hash={:?}", dep_node, item_hash);
+        self.hashes.insert(dep_node, item_hash);
 
         let bytes_hashed = self.tcx.sess.perf_stats.incr_comp_bytes_hashed.get() +
-                           bytes_hashed;
+            bytes_hashed;
         self.tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed);
     }
 
@@ -200,7 +208,8 @@ fn compute_crate_hash(&mut self) {
                                                             self.tcx,
                                                             &mut self.def_path_hashes,
                                                             &mut self.codemap,
-                                                            self.hash_spans);
+                                                            self.hash_spans,
+                                                            false);
             visitor.hash_attributes(&krate.attrs);
         }
 
index e2b141f2ea62d5f35afb774f9b47823d3cfc34ff..6a045216ce9cb24f2d40edf4db3b99845595bbb1 100644 (file)
@@ -52,6 +52,7 @@ pub struct StrictVersionHashVisitor<'a, 'hash: 'a, 'tcx: 'hash> {
     hash_spans: bool,
     codemap: &'a mut CachingCodemapView<'tcx>,
     overflow_checks_enabled: bool,
+    hash_bodies: bool,
 }
 
 impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
@@ -59,7 +60,8 @@ pub fn new(st: &'a mut IchHasher,
                tcx: TyCtxt<'hash, 'tcx, 'tcx>,
                def_path_hashes: &'a mut DefPathHashes<'hash, 'tcx>,
                codemap: &'a mut CachingCodemapView<'tcx>,
-               hash_spans: bool)
+               hash_spans: bool,
+               hash_bodies: bool)
                -> Self {
         let check_overflow = tcx.sess.opts.debugging_opts.force_overflow_checks
             .unwrap_or(tcx.sess.opts.debug_assertions);
@@ -71,6 +73,7 @@ pub fn new(st: &'a mut IchHasher,
             hash_spans: hash_spans,
             codemap: codemap,
             overflow_checks_enabled: check_overflow,
+            hash_bodies: hash_bodies,
         }
     }
 
@@ -459,15 +462,16 @@ fn saw_ty(node: &Ty_) -> SawTyComponent {
 #[derive(Hash)]
 enum SawTraitOrImplItemComponent {
     SawTraitOrImplItemConst,
-    SawTraitOrImplItemMethod(Unsafety, Constness, Abi),
+    // The boolean signifies whether a body is present
+    SawTraitOrImplItemMethod(Unsafety, Constness, Abi, bool),
     SawTraitOrImplItemType
 }
 
 fn saw_trait_item(ti: &TraitItem_) -> SawTraitOrImplItemComponent {
     match *ti {
         ConstTraitItem(..) => SawTraitOrImplItemConst,
-        MethodTraitItem(ref sig, _) =>
-            SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi),
+        MethodTraitItem(ref sig, ref body) =>
+            SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, body.is_some()),
         TypeTraitItem(..) => SawTraitOrImplItemType
     }
 }
@@ -476,7 +480,7 @@ fn saw_impl_item(ii: &ImplItemKind) -> SawTraitOrImplItemComponent {
     match *ii {
         ImplItemKind::Const(..) => SawTraitOrImplItemConst,
         ImplItemKind::Method(ref sig, _) =>
-            SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi),
+            SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, true),
         ImplItemKind::Type(..) => SawTraitOrImplItemType
     }
 }
@@ -509,6 +513,14 @@ macro_rules! hash_span {
 }
 
 impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'hash, 'tcx> {
+    fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, visit::NestedVisitMode)> {
+        if self.hash_bodies {
+            Some((&self.tcx.map, visit::NestedVisitMode::OnlyBodies))
+        } else {
+            None
+        }
+    }
+
     fn visit_variant_data(&mut self,
                           s: &'tcx VariantData,
                           name: Name,
@@ -609,7 +621,8 @@ fn visit_item(&mut self, i: &'tcx Item) {
 
     fn visit_mod(&mut self, m: &'tcx Mod, _s: Span, n: NodeId) {
         debug!("visit_mod: st={:?}", self.st);
-        SawMod.hash(self.st); visit::walk_mod(self, m, n)
+        SawMod.hash(self.st);
+        visit::walk_mod(self, m, n)
     }
 
     fn visit_ty(&mut self, t: &'tcx Ty) {
index 85c35bf79ce81347a4273e82b83200d94fc301b9..40873011a7b8d7fc73aaa76fa17fc9c75b91a8ac 100644 (file)
@@ -114,7 +114,8 @@ fn assert_dirty(&self, item: &hir::Item, dep_node: DepNode<DefId>) {
 
         match dep_node {
             DepNode::Krate |
-            DepNode::Hir(_) => {
+            DepNode::Hir(_) |
+            DepNode::HirBody(_) => {
                 // HIR nodes are inputs, so if we are asserting that the HIR node is
                 // dirty, we check the dirty input set.
                 if !self.dirty_inputs.contains(&dep_node) {
@@ -143,7 +144,8 @@ fn assert_clean(&self, item: &hir::Item, dep_node: DepNode<DefId>) {
 
         match dep_node {
             DepNode::Krate |
-            DepNode::Hir(_) => {
+            DepNode::Hir(_) |
+            DepNode::HirBody(_) => {
                 // For HIR nodes, check the inputs.
                 if self.dirty_inputs.contains(&dep_node) {
                     let dep_node_str = self.dep_node_str(&dep_node);
index 73311ee96c5308712fae79aa667076efcbb20d63..562efa4b0d2a8c2e720389fe1309475c0daf516b 100644 (file)
@@ -45,7 +45,9 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub fn is_hashable(dep_node: &DepNode<DefId>) -> bool {
         match *dep_node {
             DepNode::Krate |
-            DepNode::Hir(_) => true,
+            DepNode::Hir(_) |
+            DepNode::HirBody(_) =>
+                true,
             DepNode::MetaData(def_id) => !def_id.is_local(),
             _ => false,
         }
@@ -58,7 +60,7 @@ pub fn hash(&mut self, dep_node: &DepNode<DefId>) -> Option<Fingerprint> {
             }
 
             // HIR nodes (which always come from our crate) are an input:
-            DepNode::Hir(def_id) => {
+            DepNode::Hir(def_id) | DepNode::HirBody(def_id) => {
                 assert!(def_id.is_local(),
                         "cannot hash HIR for non-local def-id {:?} => {:?}",
                         def_id,
index 289eebb2162083a1ee44de841288d95e5b45b918..05e21aa19b1b8870c6841a3f5af68e4ffc879344 100644 (file)
@@ -145,8 +145,8 @@ pub fn encode_dep_graph(preds: &Predecessors,
     for (&target, sources) in &preds.inputs {
         match *target {
             DepNode::MetaData(ref def_id) => {
-                // Metadata *targets* are always local metadata nodes. We handle
-                // those in `encode_metadata_hashes`, which comes later.
+                // Metadata *targets* are always local metadata nodes. We have
+                // already handled those in `encode_metadata_hashes`.
                 assert!(def_id.is_local());
                 continue;
             }
index a06c25ac055c77b6ce313f8d345c5be8156af290..7138b4c7604e97ffa8f4329dec30ab7850372985 100644 (file)
@@ -31,7 +31,7 @@ pub fn x() -> i32 {
 mod y {
     use x;
 
-    #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")]
+    #[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
     pub fn y() {
         x::x();
     }
index f28ecf74dd47d38a53b60d8f5b43b13841ef44ec..0a36e3c693edbb22123c03131810e7652de29888 100644 (file)
@@ -46,12 +46,14 @@ fn baz() {
 mod mod3 {
     use Trait2;
 
-    #[rustc_dirty(label="Hir", cfg="rpass2")]
+    #[rustc_clean(label="Hir", cfg="rpass2")]
+    #[rustc_dirty(label="HirBody", cfg="rpass2")]
     fn bar() {
         ().method();
     }
 
     #[rustc_clean(label="Hir", cfg="rpass2")]
+    #[rustc_clean(label="HirBody", cfg="rpass2")]
     fn baz() {
         22; // no method call, traits in scope don't matter
     }
index 4466cfb1317d961d6b24919a9a21d1e02a92c37b..e8e40d57b1ee6b42e514900b0a45a435d95592f4 100644 (file)
@@ -23,11 +23,14 @@ fn baz() { }
 
 #[cfg(rpass2)]
 #[rustc_clean(label="Hir", cfg="rpass2")]
+#[rustc_clean(label="HirBody", cfg="rpass2")]
 fn foo() {
     #[rustc_clean(label="Hir", cfg="rpass2")]
+    #[rustc_clean(label="HirBody", cfg="rpass2")]
     fn baz() { } // order is different...
 
     #[rustc_clean(label="Hir", cfg="rpass2")]
+    #[rustc_clean(label="HirBody", cfg="rpass2")]
     fn bar() { } // but that doesn't matter.
 
     fn bap() { } // neither does adding a new item
index 680a91da09f92cdada3c8d74ddc1818157c3c28d..49a88c530ff64b1248ca46e678edcbfbd2be61d0 100644 (file)
@@ -45,11 +45,13 @@ mod mod3 {
     use test;
 
     #[rustc_clean(label="Hir", cfg="rpass2")]
+    #[rustc_clean(label="HirBody", cfg="rpass2")]
     fn in_expr() {
         Foo(0);
     }
 
     #[rustc_clean(label="Hir", cfg="rpass2")]
+    #[rustc_clean(label="HirBody", cfg="rpass2")]
     fn in_type() {
         test::<Foo>();
     }
@@ -60,12 +62,14 @@ mod mod3 {
     use test;
     use mod2::Foo; // <-- This changed!
 
-    #[rustc_dirty(label="Hir", cfg="rpass3")]
+    #[rustc_clean(label="Hir", cfg="rpass3")]
+    #[rustc_dirty(label="HirBody", cfg="rpass3")]
     fn in_expr() {
         Foo(0);
     }
 
-    #[rustc_dirty(label="Hir", cfg="rpass3")]
+    #[rustc_clean(label="Hir", cfg="rpass3")]
+    #[rustc_dirty(label="HirBody", cfg="rpass3")]
     fn in_type() {
         test::<Foo>();
     }
index f922ac0da41b193ca292c58d251a7c60a16a3358..e81f690f5cacba9b2a894ab1a851521561bcc0c0 100644 (file)
 
 #![feature(rustc_attrs)]
 
-#[rustc_clean(label="Hir", cfg="rpass2")]
+#[rustc_clean(label="HirBody", cfg="rpass2")]
 fn line_same() {
     let _ = line!();
 }
 
-#[rustc_clean(label="Hir", cfg="rpass2")]
+#[rustc_clean(label="HirBody", cfg="rpass2")]
 fn col_same() {
     let _ = column!();
 }
 
-#[rustc_clean(label="Hir", cfg="rpass2")]
+#[rustc_clean(label="HirBody", cfg="rpass2")]
 fn file_same() {
     let _ = file!();
 }
@@ -38,7 +38,7 @@ fn line_different() {
 }
 
 #[cfg(rpass2)]
-#[rustc_dirty(label="Hir", cfg="rpass2")]
+#[rustc_dirty(label="HirBody", cfg="rpass2")]
 fn line_different() {
     let _ = line!();
 }
@@ -49,7 +49,7 @@ fn col_different() {
 }
 
 #[cfg(rpass2)]
-#[rustc_dirty(label="Hir", cfg="rpass2")]
+#[rustc_dirty(label="HirBody", cfg="rpass2")]
 fn col_different() {
     let _ =        column!();
 }
index 9c8b8552498c492608470197262e63456cdd283a..90ec4a9d55831bb9b4ea4cd9dfa4ebc5392c6322 100644 (file)
@@ -22,4 +22,5 @@ pub fn main() {}
 
 #[cfg(rpass2)]
 #[rustc_clean(label="Hir", cfg="rpass2")]
+#[rustc_clean(label="HirBody", cfg="rpass2")]
 pub fn main() {}
index b0920aa1fa510dbda5706477214de25356b8d0e2..cdab8de9828ab1a22a6867b29bb5266349196d13 100644 (file)
@@ -22,4 +22,5 @@ pub fn main() {}
 
 #[cfg(rpass2)]
 #[rustc_dirty(label="Hir", cfg="rpass2")]
+#[rustc_dirty(label="HirBody", cfg="rpass2")]
 pub fn main() {}