incr.comp.: Already hash HIR bodies during metadata export so they don't have to be hashed in downstream crates.
This commit is contained in:
parent
e3f913167c
commit
b9816c5fab
11 changed files with 163 additions and 55 deletions
|
@ -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>,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue