1
Fork 0

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:
Michael Woerister 2017-09-13 14:59:10 +02:00
parent e3f913167c
commit b9816c5fab
11 changed files with 163 additions and 55 deletions

View file

@ -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>,

View file

@ -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);
}
}

View file

@ -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,

View file

@ -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.
///

View file

@ -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,

View file

@ -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)
}

View file

@ -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;

View file

@ -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,
})
}
}

View file

@ -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)
}

View file

@ -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 {

View file

@ -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))
}