about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo>2017-09-13 14:59:10 +0200
committerMichael Woerister <michaelwoerister@posteo>2017-09-18 11:26:11 +0200
commitb9816c5fab6bfde01f83d83a0b53e78bb00d3900 (patch)
tree508e8aaba83b6537fc14d3d1f86dc278c2cfcbdc /src
parente3f913167c0f232478b945aa236aab8340be62a9 (diff)
downloadrust-b9816c5fab6bfde01f83d83a0b53e78bb00d3900.tar.gz
rust-b9816c5fab6bfde01f83d83a0b53e78bb00d3900.zip
incr.comp.: Already hash HIR bodies during metadata export so they don't have to be hashed in downstream crates.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/ich/hcx.rs34
-rw-r--r--src/librustc/ich/impls_cstore.rs28
-rw-r--r--src/librustc/ich/impls_hir.rs50
-rw-r--r--src/librustc/middle/cstore.rs22
-rw-r--r--src/librustc/ty/maps.rs11
-rw-r--r--src/librustc_const_eval/eval.rs5
-rw-r--r--src/librustc_const_eval/pattern.rs2
-rw-r--r--src/librustc_metadata/astencode.rs25
-rw-r--r--src/librustc_metadata/cstore_impl.rs2
-rw-r--r--src/librustc_metadata/decoder.rs35
-rw-r--r--src/librustdoc/clean/inline.rs4
11 files changed, 163 insertions, 55 deletions
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index daf1ff8ad2b..bd3a3583676 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -202,6 +202,40 @@ impl<'a, 'gcx, 'lcx> StableHashingContextProvider for ty::TyCtxt<'a, 'gcx, 'lcx>
     }
 }
 
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::HirId {
+    #[inline]
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        match hcx.node_id_hashing_mode {
+            NodeIdHashingMode::Ignore => {
+                // Don't do anything.
+            }
+            NodeIdHashingMode::HashDefPath => {
+                let hir::HirId {
+                    owner,
+                    local_id,
+                } = *self;
+
+                hcx.tcx.hir.definitions().def_path_hash(owner).hash_stable(hcx, hasher);
+                local_id.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
+
+impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for hir::HirId {
+    type KeyType = (DefPathHash, hir::ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self,
+                          hcx: &StableHashingContext<'a, 'gcx, 'tcx>)
+                          -> (DefPathHash, hir::ItemLocalId) {
+        let def_path_hash = hcx.tcx().hir.definitions().def_path_hash(self.owner);
+        (def_path_hash, self.local_id)
+    }
+}
+
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::NodeId {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
diff --git a/src/librustc/ich/impls_cstore.rs b/src/librustc/ich/impls_cstore.rs
index 057a83ebbe3..18a02ff5c58 100644
--- a/src/librustc/ich/impls_cstore.rs
+++ b/src/librustc/ich/impls_cstore.rs
@@ -11,6 +11,8 @@
 //! This module contains `HashStable` implementations for various data types
 //! from rustc::middle::cstore in no particular order.
 
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
+
 use middle;
 
 impl_stable_hash_for!(enum middle::cstore::DepKind {
@@ -51,3 +53,29 @@ impl_stable_hash_for!(struct middle::cstore::CrateSource {
     rlib,
     rmeta
 });
+
+impl<HCX> HashStable<HCX> for middle::cstore::ExternBodyNestedBodies {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut HCX,
+                                          hasher: &mut StableHasher<W>) {
+        let middle::cstore::ExternBodyNestedBodies {
+            nested_bodies: _,
+            fingerprint,
+        } = *self;
+
+        fingerprint.hash_stable(hcx, hasher);
+    }
+}
+
+impl<'a, HCX> HashStable<HCX> for middle::cstore::ExternConstBody<'a> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut HCX,
+                                          hasher: &mut StableHasher<W>) {
+        let middle::cstore::ExternConstBody {
+            body: _,
+            fingerprint,
+        } = *self;
+
+        fingerprint.hash_stable(hcx, hasher);
+    }
+}
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 9da147472ce..3c89e10a0d2 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -38,33 +38,6 @@ impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for D
     }
 }
 
-impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::HirId {
-    #[inline]
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
-                                          hasher: &mut StableHasher<W>) {
-        let hir::HirId {
-            owner,
-            local_id,
-        } = *self;
-
-        hcx.tcx().hir.definitions().def_path_hash(owner).hash_stable(hcx, hasher);
-        local_id.hash_stable(hcx, hasher);
-    }
-}
-
-impl<'a, 'gcx, 'tcx> ToStableHashKey<StableHashingContext<'a, 'gcx, 'tcx>> for hir::HirId {
-    type KeyType = (DefPathHash, hir::ItemLocalId);
-
-    #[inline]
-    fn to_stable_hash_key(&self,
-                          hcx: &StableHashingContext<'a, 'gcx, 'tcx>)
-                          -> (DefPathHash, hir::ItemLocalId) {
-        let def_path_hash = hcx.tcx().hir.definitions().def_path_hash(self.owner);
-        (def_path_hash, self.local_id)
-    }
-}
-
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for CrateNum {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
@@ -415,6 +388,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::P
             ref span
         } = *self;
 
+
         node.hash_stable(hcx, hasher);
         span.hash_stable(hcx, hasher);
     }
@@ -1003,11 +977,23 @@ impl_stable_hash_for!(struct hir::Arg {
     hir_id
 });
 
-impl_stable_hash_for!(struct hir::Body {
-    arguments,
-    value,
-    is_generator
-});
+impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::Body {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
+                                          hasher: &mut StableHasher<W>) {
+        let hir::Body {
+            ref arguments,
+            ref value,
+            is_generator,
+        } = *self;
+
+        hcx.with_node_id_hashing_mode(NodeIdHashingMode::Ignore, |hcx| {
+            arguments.hash_stable(hcx, hasher);
+            value.hash_stable(hcx, hasher);
+            is_generator.hash_stable(hcx, hasher);
+        });
+    }
+}
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::BodyId {
     fn hash_stable<W: StableHasherResult>(&self,
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 7c60c6d6430..de647913f0f 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -22,6 +22,7 @@
 //! are *mostly* used as a part of that interface, but these should
 //! probably get a better home if someone can find one.
 
+use hir;
 use hir::def;
 use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
 use hir::map as hir_map;
@@ -34,6 +35,7 @@ use session::search_paths::PathKind;
 use util::nodemap::NodeSet;
 
 use std::any::Any;
+use std::collections::BTreeMap;
 use std::path::{Path, PathBuf};
 use std::rc::Rc;
 use owning_ref::ErasedBoxRef;
@@ -218,6 +220,26 @@ pub trait MetadataLoader {
                           -> Result<ErasedBoxRef<[u8]>, String>;
 }
 
+#[derive(Clone)]
+pub struct ExternConstBody<'tcx> {
+    pub body: &'tcx hir::Body,
+
+    // It would require a lot of infrastructure to enable stable-hashing Bodies
+    // from other crates, so we hash on export and just store the fingerprint
+    // with them.
+    pub fingerprint: ich::Fingerprint,
+}
+
+#[derive(Clone)]
+pub struct ExternBodyNestedBodies {
+    pub nested_bodies: Rc<BTreeMap<hir::BodyId, hir::Body>>,
+
+    // It would require a lot of infrastructure to enable stable-hashing Bodies
+    // from other crates, so we hash on export and just store the fingerprint
+    // with them.
+    pub fingerprint: ich::Fingerprint,
+}
+
 /// A store of Rust crates, through with their metadata
 /// can be accessed.
 ///
diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs
index fc803d1c849..5207aaa0c5b 100644
--- a/src/librustc/ty/maps.rs
+++ b/src/librustc/ty/maps.rs
@@ -16,8 +16,9 @@ use hir::{self, TraitCandidate, ItemLocalId};
 use hir::svh::Svh;
 use lint;
 use middle::const_val;
-use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary};
-use middle::cstore::{NativeLibraryKind, DepKind, CrateSource};
+use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary,
+                     ExternBodyNestedBodies};
+use middle::cstore::{NativeLibraryKind, DepKind, CrateSource, ExternConstBody};
 use middle::privacy::AccessLevels;
 use middle::reachable::ReachableSet;
 use middle::region;
@@ -50,7 +51,6 @@ use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
 use std::mem;
-use std::collections::BTreeMap;
 use std::ops::Deref;
 use std::rc::Rc;
 use std::sync::Arc;
@@ -1321,8 +1321,7 @@ define_maps! { <'tcx>
     [] fn impl_parent: ImplParent(DefId) -> Option<DefId>,
     [] fn trait_of_item: TraitOfItem(DefId) -> Option<DefId>,
     [] fn is_exported_symbol: IsExportedSymbol(DefId) -> bool,
-    [] fn item_body_nested_bodies: ItemBodyNestedBodies(DefId)
-        -> Rc<BTreeMap<hir::BodyId, hir::Body>>,
+    [] fn item_body_nested_bodies: ItemBodyNestedBodies(DefId) -> ExternBodyNestedBodies,
     [] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool,
     [] fn is_mir_available: IsMirAvailable(DefId) -> bool,
 
@@ -1402,7 +1401,7 @@ define_maps! { <'tcx>
     [] fn get_lang_items: get_lang_items_node(CrateNum) -> Rc<LanguageItems>,
     [] fn defined_lang_items: DefinedLangItems(CrateNum) -> Rc<Vec<(DefId, usize)>>,
     [] fn missing_lang_items: MissingLangItems(CrateNum) -> Rc<Vec<LangItem>>,
-    [] fn extern_const_body: ExternConstBody(DefId) -> &'tcx hir::Body,
+    [] fn extern_const_body: ExternConstBody(DefId) -> ExternConstBody<'tcx>,
     [] fn visible_parent_map: visible_parent_map_node(CrateNum)
         -> Rc<DefIdMap<DefId>>,
     [] fn missing_extern_crate_item: MissingExternCrateItem(CrateNum) -> bool,
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 61eb5dfd18b..7520c6ac652 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -34,7 +34,6 @@ use syntax_pos::Span;
 use std::cmp::Ordering;
 
 use rustc_const_math::*;
-
 macro_rules! signal {
     ($e:expr, $exn:expr) => {
         return Err(ConstEvalErr { span: $e.span, kind: $exn })
@@ -366,7 +365,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
             }
           } else {
             if tcx.is_const_fn(def_id) {
-                tcx.extern_const_body(def_id)
+                tcx.extern_const_body(def_id).body
             } else {
                 signal!(e, TypeckError)
             }
@@ -790,7 +789,7 @@ fn const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         tcx.mir_const_qualif(def_id);
         tcx.hir.body(tcx.hir.body_owned_by(id))
     } else {
-        tcx.extern_const_body(def_id)
+        tcx.extern_const_body(def_id).body
     };
     ConstContext::new(tcx, key.param_env.and(substs), tables).eval(&body.value)
 }
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index a87fa0c2746..7586ad5a75f 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -607,7 +607,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                         let body = if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
                             self.tcx.hir.body(self.tcx.hir.body_owned_by(id))
                         } else {
-                            self.tcx.extern_const_body(def_id)
+                            self.tcx.extern_const_body(def_id).body
                         };
                         let pat = self.lower_const_expr(&body.value, pat_id, span);
                         self.tables = old_tables;
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
index ade2612855e..3bc281e5486 100644
--- a/src/librustc_metadata/astencode.rs
+++ b/src/librustc_metadata/astencode.rs
@@ -16,26 +16,46 @@ use schema::*;
 use rustc::hir;
 use rustc::ty::{self, TyCtxt};
 
+use rustc::ich::{StableHashingContext, Fingerprint};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct Ast<'tcx> {
     pub body: Lazy<hir::Body>,
     pub tables: Lazy<ty::TypeckTables<'tcx>>,
     pub nested_bodies: LazySeq<hir::Body>,
     pub rvalue_promotable_to_static: bool,
+    pub stable_bodies_hash: Fingerprint,
 }
 
 impl_stable_hash_for!(struct Ast<'tcx> {
     body,
     tables,
     nested_bodies,
-    rvalue_promotable_to_static
+    rvalue_promotable_to_static,
+    stable_bodies_hash
 });
 
 impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> {
     pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
         let body = self.tcx.hir.body(body_id);
-        let lazy_body = self.lazy(body);
 
+        // In order to avoid having to hash hir::Bodies from extern crates, we
+        // hash them here, during export, and store the hash with metadata.
+        let stable_bodies_hash = {
+            let mut hcx = StableHashingContext::new(self.tcx);
+            let mut hasher = StableHasher::new();
+
+            hcx.while_hashing_hir_bodies(true, |hcx| {
+                hcx.while_hashing_spans(false, |hcx| {
+                    body.hash_stable(hcx, &mut hasher);
+                });
+            });
+
+            hasher.finish()
+        };
+
+        let lazy_body = self.lazy(body);
         let tables = self.tcx.body_tables(body_id);
         let lazy_tables = self.lazy(tables);
 
@@ -54,6 +74,7 @@ impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> {
             tables: lazy_tables,
             nested_bodies: lazy_nested_bodies,
             rvalue_promotable_to_static,
+            stable_bodies_hash,
         })
     }
 }
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index e4de27ee15e..78c44c7e45c 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -159,7 +159,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     is_exported_symbol => {
         cdata.exported_symbols.contains(&def_id.index)
     }
-    item_body_nested_bodies => { Rc::new(cdata.item_body_nested_bodies(def_id.index)) }
+    item_body_nested_bodies => { cdata.item_body_nested_bodies(def_id.index) }
     const_is_rvalue_promotable_to_static => {
         cdata.const_is_rvalue_promotable_to_static(def_id.index)
     }
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 4696759817f..65cf15e5a0e 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -17,9 +17,11 @@ use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc::hir;
 
 use rustc::middle::const_val::ByteArray;
-use rustc::middle::cstore::LinkagePreference;
+use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
+                            ExternBodyNestedBodies};
 use rustc::hir::def::{self, Def, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc::ich::Fingerprint;
 use rustc::middle::lang_items;
 use rustc::session::Session;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -775,12 +777,16 @@ impl<'a, 'tcx> CrateMetadata {
     pub fn extern_const_body(&self,
                              tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              id: DefIndex)
-                             -> &'tcx hir::Body {
+                             -> ExternConstBody<'tcx> {
         assert!(!self.is_proc_macro(id));
         let ast = self.entry(id).ast.unwrap();
         let def_id = self.local_def_id(id);
-        let body = ast.decode((self, tcx)).body.decode((self, tcx));
-        tcx.hir.intern_inlined_body(def_id, body)
+        let ast = ast.decode((self, tcx));
+        let body = ast.body.decode((self, tcx));
+        ExternConstBody {
+            body: tcx.hir.intern_inlined_body(def_id, body),
+            fingerprint: ast.stable_bodies_hash,
+        }
     }
 
     pub fn item_body_tables(&self,
@@ -791,10 +797,23 @@ impl<'a, 'tcx> CrateMetadata {
         tcx.alloc_tables(ast.tables.decode((self, tcx)))
     }
 
-    pub fn item_body_nested_bodies(&self, id: DefIndex) -> BTreeMap<hir::BodyId, hir::Body> {
-        self.entry(id).ast.into_iter().flat_map(|ast| {
-            ast.decode(self).nested_bodies.decode(self).map(|body| (body.id(), body))
-        }).collect()
+    pub fn item_body_nested_bodies(&self, id: DefIndex) -> ExternBodyNestedBodies {
+        if let Some(ref ast) = self.entry(id).ast {
+            let ast = ast.decode(self);
+            let nested_bodies: BTreeMap<_, _> = ast.nested_bodies
+                                                   .decode(self)
+                                                   .map(|body| (body.id(), body))
+                                                   .collect();
+            ExternBodyNestedBodies {
+                nested_bodies: Rc::new(nested_bodies),
+                fingerprint: ast.stable_bodies_hash,
+            }
+        } else {
+            ExternBodyNestedBodies {
+                nested_bodies: Rc::new(BTreeMap::new()),
+                fingerprint: Fingerprint::zero(),
+            }
+        }
     }
 
     pub fn const_is_rvalue_promotable_to_static(&self, id: DefIndex) -> bool {
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 7f5d11ba5de..3a4dcc32173 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -474,9 +474,9 @@ impl hir::print::PpAnn for InlinedConst {
 }
 
 pub fn print_inlined_const(cx: &DocContext, did: DefId) -> String {
-    let body = cx.tcx.extern_const_body(did);
+    let body = cx.tcx.extern_const_body(did).body;
     let inlined = InlinedConst {
-        nested_bodies: cx.tcx.item_body_nested_bodies(did)
+        nested_bodies: cx.tcx.item_body_nested_bodies(did).nested_bodies
     };
     hir::print::to_string(&inlined, |s| s.print_expr(&body.value))
 }