Auto merge of #46004 - michaelwoerister:cached-mir-wip-3, r=nikomatsakis
incr.comp.: Implement query result cache and use it to cache type checking tables. This is a spike implementation of caching more than LLVM IR and object files when doing incremental compilation. At the moment, only the `typeck_tables_of` query is cached but MIR and borrow-check will follow shortly. The feature is activated by running with `-Zincremental-queries` in addition to `-Zincremental`, it is not yet active by default. r? @nikomatsakis
This commit is contained in:
commit
02eed2e9a5
29 changed files with 1168 additions and 377 deletions
|
@ -618,7 +618,7 @@ define_dep_nodes!( <'tcx>
|
|||
|
||||
[input] Freevars(DefId),
|
||||
[input] MaybeUnusedTraitImport(DefId),
|
||||
[] MaybeUnusedExternCrates,
|
||||
[input] MaybeUnusedExternCrates,
|
||||
[] StabilityIndex,
|
||||
[input] AllCrateNums,
|
||||
[] ExportedSymbols(CrateNum),
|
||||
|
|
|
@ -327,6 +327,7 @@ impl DepGraph {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint {
|
||||
match self.fingerprints.borrow().get(dep_node) {
|
||||
Some(&fingerprint) => fingerprint,
|
||||
|
@ -340,6 +341,11 @@ impl DepGraph {
|
|||
self.data.as_ref().unwrap().previous.fingerprint_of(dep_node)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn prev_dep_node_index_of(&self, dep_node: &DepNode) -> SerializedDepNodeIndex {
|
||||
self.data.as_ref().unwrap().previous.node_to_index(dep_node)
|
||||
}
|
||||
|
||||
/// Indicates that a previous work product exists for `v`. This is
|
||||
/// invoked during initial start-up based on what nodes are clean
|
||||
/// (and what files exist in the incr. directory).
|
||||
|
|
|
@ -44,6 +44,11 @@ impl PreviousDepGraph {
|
|||
self.data.nodes[dep_node_index].0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn node_to_index(&self, dep_node: &DepNode) -> SerializedDepNodeIndex {
|
||||
self.index[dep_node]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> {
|
||||
self.index
|
||||
|
|
|
@ -11,8 +11,7 @@
|
|||
use ty;
|
||||
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use serialize::{self, Encoder, Decoder};
|
||||
|
||||
use serialize;
|
||||
use std::fmt;
|
||||
use std::u32;
|
||||
|
||||
|
@ -32,6 +31,10 @@ newtype_index!(CrateNum
|
|||
|
||||
/// A CrateNum value that indicates that something is wrong.
|
||||
const INVALID_CRATE = u32::MAX - 1,
|
||||
|
||||
/// A special CrateNum that we use for the tcx.rcache when decoding from
|
||||
/// the incr. comp. cache.
|
||||
const RESERVED_FOR_INCR_COMP_CACHE = u32::MAX - 2,
|
||||
});
|
||||
|
||||
impl CrateNum {
|
||||
|
@ -61,17 +64,8 @@ impl fmt::Display for CrateNum {
|
|||
}
|
||||
}
|
||||
|
||||
impl serialize::UseSpecializedEncodable for CrateNum {
|
||||
fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
||||
s.emit_u32(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl serialize::UseSpecializedDecodable for CrateNum {
|
||||
fn default_decode<D: Decoder>(d: &mut D) -> Result<CrateNum, D::Error> {
|
||||
d.read_u32().map(CrateNum)
|
||||
}
|
||||
}
|
||||
impl serialize::UseSpecializedEncodable for CrateNum {}
|
||||
impl serialize::UseSpecializedDecodable for CrateNum {}
|
||||
|
||||
/// A DefIndex is an index into the hir-map for a crate, identifying a
|
||||
/// particular definition. It should really be considered an interned
|
||||
|
@ -88,6 +82,7 @@ impl serialize::UseSpecializedDecodable for CrateNum {
|
|||
/// don't have to care about these ranges.
|
||||
newtype_index!(DefIndex
|
||||
{
|
||||
ENCODABLE = custom
|
||||
DEBUG_FORMAT = custom,
|
||||
|
||||
/// The start of the "high" range of DefIndexes.
|
||||
|
@ -146,6 +141,9 @@ impl DefIndex {
|
|||
}
|
||||
}
|
||||
|
||||
impl serialize::UseSpecializedEncodable for DefIndex {}
|
||||
impl serialize::UseSpecializedDecodable for DefIndex {}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum DefIndexAddressSpace {
|
||||
Low = 0,
|
||||
|
@ -166,7 +164,7 @@ impl DefIndexAddressSpace {
|
|||
|
||||
/// A DefId identifies a particular *definition*, by combining a crate
|
||||
/// index and a def index.
|
||||
#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable, RustcDecodable, Hash, Copy)]
|
||||
#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, Hash, Copy)]
|
||||
pub struct DefId {
|
||||
pub krate: CrateNum,
|
||||
pub index: DefIndex,
|
||||
|
@ -188,14 +186,58 @@ impl fmt::Debug for DefId {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl DefId {
|
||||
/// Make a local `DefId` with the given index.
|
||||
#[inline]
|
||||
pub fn local(index: DefIndex) -> DefId {
|
||||
DefId { krate: LOCAL_CRATE, index: index }
|
||||
}
|
||||
|
||||
pub fn is_local(&self) -> bool {
|
||||
#[inline]
|
||||
pub fn is_local(self) -> bool {
|
||||
self.krate == LOCAL_CRATE
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_local(self) -> LocalDefId {
|
||||
LocalDefId::from_def_id(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl serialize::UseSpecializedEncodable for DefId {}
|
||||
impl serialize::UseSpecializedDecodable for DefId {}
|
||||
|
||||
/// A LocalDefId is equivalent to a DefId with `krate == LOCAL_CRATE`. Since
|
||||
/// we encode this information in the type, we can ensure at compile time that
|
||||
/// no DefIds from upstream crates get thrown into the mix. There are quite a
|
||||
/// few cases where we know that only DefIds from the local crate are expected
|
||||
/// and a DefId from a different crate would signify a bug somewhere. This
|
||||
/// is when LocalDefId comes in handy.
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct LocalDefId(DefIndex);
|
||||
|
||||
impl LocalDefId {
|
||||
|
||||
#[inline]
|
||||
pub fn from_def_id(def_id: DefId) -> LocalDefId {
|
||||
assert!(def_id.is_local());
|
||||
LocalDefId(def_id.index)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_def_id(self) -> DefId {
|
||||
DefId {
|
||||
krate: LOCAL_CRATE,
|
||||
index: self.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for LocalDefId {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.to_def_id().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl serialize::UseSpecializedEncodable for LocalDefId {}
|
||||
impl serialize::UseSpecializedDecodable for LocalDefId {}
|
||||
|
|
|
@ -17,7 +17,7 @@ pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
|
|||
|
||||
use dep_graph::{DepGraph, DepNode, DepKind, DepNodeIndex};
|
||||
|
||||
use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndexAddressSpace};
|
||||
use hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId, DefIndexAddressSpace};
|
||||
|
||||
use syntax::abi::Abi;
|
||||
use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID};
|
||||
|
@ -359,6 +359,16 @@ impl<'hir> Map<'hir> {
|
|||
self.definitions.as_local_node_id(DefId::local(def_index)).unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId {
|
||||
self.definitions.def_index_to_hir_id(def_id.to_def_id().index)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn local_def_id_to_node_id(&self, def_id: LocalDefId) -> NodeId {
|
||||
self.definitions.as_local_node_id(def_id.to_def_id()).unwrap()
|
||||
}
|
||||
|
||||
fn entry_count(&self) -> usize {
|
||||
self.map.len()
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ use ty::AdtKind;
|
|||
|
||||
use rustc_data_structures::indexed_vec;
|
||||
|
||||
use serialize::{self, Encoder, Encodable, Decoder, Decodable};
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
|
||||
|
@ -85,13 +86,37 @@ pub mod svh;
|
|||
/// the local_id part of the HirId changing, which is a very useful property in
|
||||
/// incremental compilation where we have to persist things through changes to
|
||||
/// the code base.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug,
|
||||
RustcEncodable, RustcDecodable)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||
pub struct HirId {
|
||||
pub owner: DefIndex,
|
||||
pub local_id: ItemLocalId,
|
||||
}
|
||||
|
||||
impl serialize::UseSpecializedEncodable for HirId {
|
||||
fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
||||
let HirId {
|
||||
owner,
|
||||
local_id,
|
||||
} = *self;
|
||||
|
||||
owner.encode(s)?;
|
||||
local_id.encode(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl serialize::UseSpecializedDecodable for HirId {
|
||||
fn default_decode<D: Decoder>(d: &mut D) -> Result<HirId, D::Error> {
|
||||
let owner = DefIndex::decode(d)?;
|
||||
let local_id = ItemLocalId::decode(d)?;
|
||||
|
||||
Ok(HirId {
|
||||
owner,
|
||||
local_id
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// An `ItemLocalId` uniquely identifies something within a given "item-like",
|
||||
/// that is within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no
|
||||
/// guarantee that the numerical value of a given `ItemLocalId` corresponds to
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
use hir;
|
||||
use hir::map::DefPathHash;
|
||||
use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
|
||||
use hir::def_id::{DefId, LocalDefId, CrateNum, CRATE_DEF_INDEX};
|
||||
use ich::{StableHashingContext, NodeIdHashingMode};
|
||||
use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
|
||||
StableHasher, StableHasherResult};
|
||||
|
@ -38,6 +38,24 @@ impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for DefId {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'gcx> HashStable<StableHashingContext<'gcx>> for LocalDefId {
|
||||
#[inline]
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
hcx: &mut StableHashingContext<'gcx>,
|
||||
hasher: &mut StableHasher<W>) {
|
||||
hcx.def_path_hash(self.to_def_id()).hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for LocalDefId {
|
||||
type KeyType = DefPathHash;
|
||||
|
||||
#[inline]
|
||||
fn to_stable_hash_key(&self, hcx: &StableHashingContext<'gcx>) -> DefPathHash {
|
||||
hcx.def_path_hash(self.to_def_id())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gcx> HashStable<StableHashingContext<'gcx>> for CrateNum {
|
||||
#[inline]
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
use hir;
|
||||
use hir::def;
|
||||
use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
|
||||
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
use hir::map as hir_map;
|
||||
use hir::map::definitions::{Definitions, DefKey, DefPathTable};
|
||||
use hir::svh::Svh;
|
||||
|
@ -180,7 +180,7 @@ impl EncodedMetadata {
|
|||
/// upstream crate.
|
||||
#[derive(Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
|
||||
pub struct EncodedMetadataHash {
|
||||
pub def_index: DefIndex,
|
||||
pub def_index: u32,
|
||||
pub hash: ich::Fingerprint,
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ use self::TrackMatchMode::*;
|
|||
use self::OverloadedCallType::*;
|
||||
|
||||
use hir::def::Def;
|
||||
use hir::def_id::{DefId};
|
||||
use hir::def_id::DefId;
|
||||
use infer::InferCtxt;
|
||||
use middle::mem_categorization as mc;
|
||||
use middle::region;
|
||||
|
@ -915,7 +915,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
|||
let closure_def_id = self.tcx().hir.local_def_id(closure_expr.id);
|
||||
let upvar_id = ty::UpvarId {
|
||||
var_id: var_hir_id,
|
||||
closure_expr_id: closure_def_id.index
|
||||
closure_expr_id: closure_def_id.to_local(),
|
||||
};
|
||||
let upvar_capture = self.mc.tables.upvar_capture(upvar_id);
|
||||
let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id,
|
||||
|
|
|
@ -70,7 +70,7 @@ pub use self::Note::*;
|
|||
use self::Aliasability::*;
|
||||
|
||||
use middle::region;
|
||||
use hir::def_id::{DefId, DefIndex};
|
||||
use hir::def_id::{DefId, LocalDefId};
|
||||
use hir::map as hir_map;
|
||||
use infer::InferCtxt;
|
||||
use hir::def::{Def, CtorKind};
|
||||
|
@ -191,7 +191,7 @@ pub type cmt<'tcx> = Rc<cmt_<'tcx>>;
|
|||
|
||||
pub enum ImmutabilityBlame<'tcx> {
|
||||
ImmLocal(ast::NodeId),
|
||||
ClosureEnv(DefIndex),
|
||||
ClosureEnv(LocalDefId),
|
||||
LocalDeref(ast::NodeId),
|
||||
AdtFieldDeref(&'tcx ty::AdtDef, &'tcx ty::FieldDef)
|
||||
}
|
||||
|
@ -759,11 +759,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
|||
ref t => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", t),
|
||||
};
|
||||
|
||||
let closure_expr_def_index = self.tcx.hir.local_def_id(fn_node_id).index;
|
||||
let closure_expr_def_id = self.tcx.hir.local_def_id(fn_node_id);
|
||||
let var_hir_id = self.tcx.hir.node_to_hir_id(var_id);
|
||||
let upvar_id = ty::UpvarId {
|
||||
var_id: var_hir_id,
|
||||
closure_expr_id: closure_expr_def_index
|
||||
closure_expr_id: closure_expr_def_id.to_local(),
|
||||
};
|
||||
|
||||
let var_ty = self.node_ty(var_hir_id)?;
|
||||
|
@ -838,7 +838,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
|||
// The environment of a closure is guaranteed to
|
||||
// outlive any bindings introduced in the body of the
|
||||
// closure itself.
|
||||
scope: DefId::local(upvar_id.closure_expr_id),
|
||||
scope: upvar_id.closure_expr_id.to_def_id(),
|
||||
bound_region: ty::BrEnv
|
||||
}));
|
||||
|
||||
|
|
|
@ -1042,6 +1042,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
"enable incremental compilation (experimental)"),
|
||||
incremental_cc: bool = (false, parse_bool, [UNTRACKED],
|
||||
"enable cross-crate incremental compilation (even more experimental)"),
|
||||
incremental_queries: bool = (true, parse_bool, [UNTRACKED],
|
||||
"enable incremental compilation support for queries (experimental)"),
|
||||
incremental_info: bool = (false, parse_bool, [UNTRACKED],
|
||||
"print high-level information about incremental reuse (or the lack thereof)"),
|
||||
incremental_dump_hash: bool = (false, parse_bool, [UNTRACKED],
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
use hir::def_id::{DefId, CrateNum};
|
||||
use middle::const_val::ByteArray;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_serialize::{Decodable, Decoder, Encoder, Encodable};
|
||||
use rustc_serialize::{Decodable, Decoder, Encoder, Encodable, opaque};
|
||||
use std::hash::Hash;
|
||||
use std::intrinsics;
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
|
@ -53,6 +53,13 @@ pub trait TyEncoder: Encoder {
|
|||
fn position(&self) -> usize;
|
||||
}
|
||||
|
||||
impl<'buf> TyEncoder for opaque::Encoder<'buf> {
|
||||
#[inline]
|
||||
fn position(&self) -> usize {
|
||||
self.position()
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode the given value or a previously cached shorthand.
|
||||
pub fn encode_with_shorthand<E, T, M>(encoder: &mut E,
|
||||
value: &T,
|
||||
|
@ -113,6 +120,8 @@ pub trait TyDecoder<'a, 'tcx: 'a>: Decoder {
|
|||
|
||||
fn peek_byte(&self) -> u8;
|
||||
|
||||
fn position(&self) -> usize;
|
||||
|
||||
fn cached_ty_for_shorthand<F>(&mut self,
|
||||
shorthand: usize,
|
||||
or_insert_with: F)
|
||||
|
@ -129,6 +138,7 @@ pub trait TyDecoder<'a, 'tcx: 'a>: Decoder {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decode_cnum<'a, 'tcx, D>(decoder: &mut D) -> Result<CrateNum, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
'tcx: 'a,
|
||||
|
@ -137,12 +147,12 @@ pub fn decode_cnum<'a, 'tcx, D>(decoder: &mut D) -> Result<CrateNum, D::Error>
|
|||
Ok(decoder.map_encoded_cnum_to_current(cnum))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decode_ty<'a, 'tcx, D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
'tcx: 'a,
|
||||
{
|
||||
// Handle shorthands first, if we have an usize > 0x80.
|
||||
// if self.opaque.data[self.opaque.position()] & 0x80 != 0 {
|
||||
if decoder.positioned_at_shorthand() {
|
||||
let pos = decoder.read_usize()?;
|
||||
assert!(pos >= SHORTHAND_OFFSET);
|
||||
|
@ -157,6 +167,7 @@ pub fn decode_ty<'a, 'tcx, D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decode_predicates<'a, 'tcx, D>(decoder: &mut D)
|
||||
-> Result<ty::GenericPredicates<'tcx>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
|
@ -180,6 +191,7 @@ pub fn decode_predicates<'a, 'tcx, D>(decoder: &mut D)
|
|||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decode_substs<'a, 'tcx, D>(decoder: &mut D) -> Result<&'tcx Substs<'tcx>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
'tcx: 'a,
|
||||
|
@ -189,6 +201,7 @@ pub fn decode_substs<'a, 'tcx, D>(decoder: &mut D) -> Result<&'tcx Substs<'tcx>,
|
|||
Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decode_region<'a, 'tcx, D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
'tcx: 'a,
|
||||
|
@ -196,6 +209,7 @@ pub fn decode_region<'a, 'tcx, D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D
|
|||
Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decode_ty_slice<'a, 'tcx, D>(decoder: &mut D)
|
||||
-> Result<&'tcx ty::Slice<Ty<'tcx>>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
|
@ -205,6 +219,7 @@ pub fn decode_ty_slice<'a, 'tcx, D>(decoder: &mut D)
|
|||
Ok(decoder.tcx().mk_type_list((0..len).map(|_| Decodable::decode(decoder)))?)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decode_adt_def<'a, 'tcx, D>(decoder: &mut D)
|
||||
-> Result<&'tcx ty::AdtDef, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
|
@ -214,6 +229,7 @@ pub fn decode_adt_def<'a, 'tcx, D>(decoder: &mut D)
|
|||
Ok(decoder.tcx().adt_def(def_id))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decode_existential_predicate_slice<'a, 'tcx, D>(decoder: &mut D)
|
||||
-> Result<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
|
@ -224,6 +240,7 @@ pub fn decode_existential_predicate_slice<'a, 'tcx, D>(decoder: &mut D)
|
|||
.mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decode_byte_array<'a, 'tcx, D>(decoder: &mut D)
|
||||
-> Result<ByteArray<'tcx>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
|
@ -234,6 +251,7 @@ pub fn decode_byte_array<'a, 'tcx, D>(decoder: &mut D)
|
|||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
|
||||
-> Result<&'tcx ty::Const<'tcx>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
|
@ -241,3 +259,138 @@ pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
|
|||
{
|
||||
Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! __impl_decoder_methods {
|
||||
($($name:ident -> $ty:ty;)*) => {
|
||||
$(fn $name(&mut self) -> Result<$ty, Self::Error> {
|
||||
self.opaque.$name()
|
||||
})*
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! implement_ty_decoder {
|
||||
($DecoderName:ident <$($typaram:tt),*>) => {
|
||||
mod __ty_decoder_impl {
|
||||
use super::$DecoderName;
|
||||
use $crate::ty;
|
||||
use $crate::ty::codec::*;
|
||||
use $crate::ty::subst::Substs;
|
||||
use $crate::hir::def_id::{CrateNum};
|
||||
use $crate::middle::const_val::ByteArray;
|
||||
use rustc_serialize::{Decoder, SpecializedDecoder};
|
||||
use std::borrow::Cow;
|
||||
|
||||
impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
|
||||
type Error = String;
|
||||
|
||||
__impl_decoder_methods! {
|
||||
read_nil -> ();
|
||||
|
||||
read_u128 -> u128;
|
||||
read_u64 -> u64;
|
||||
read_u32 -> u32;
|
||||
read_u16 -> u16;
|
||||
read_u8 -> u8;
|
||||
read_usize -> usize;
|
||||
|
||||
read_i128 -> i128;
|
||||
read_i64 -> i64;
|
||||
read_i32 -> i32;
|
||||
read_i16 -> i16;
|
||||
read_i8 -> i8;
|
||||
read_isize -> isize;
|
||||
|
||||
read_bool -> bool;
|
||||
read_f64 -> f64;
|
||||
read_f32 -> f32;
|
||||
read_char -> char;
|
||||
read_str -> Cow<str>;
|
||||
}
|
||||
|
||||
fn error(&mut self, err: &str) -> Self::Error {
|
||||
self.opaque.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(#36588) These impls are horribly unsound as they allow
|
||||
// the caller to pick any lifetime for 'tcx, including 'static,
|
||||
// by using the unspecialized proxies to them.
|
||||
|
||||
impl<$($typaram),*> SpecializedDecoder<CrateNum>
|
||||
for $DecoderName<$($typaram),*> {
|
||||
fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
|
||||
decode_cnum(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($typaram),*> SpecializedDecoder<ty::Ty<'tcx>>
|
||||
for $DecoderName<$($typaram),*> {
|
||||
fn specialized_decode(&mut self) -> Result<ty::Ty<'tcx>, Self::Error> {
|
||||
decode_ty(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($typaram),*> SpecializedDecoder<ty::GenericPredicates<'tcx>>
|
||||
for $DecoderName<$($typaram),*> {
|
||||
fn specialized_decode(&mut self)
|
||||
-> Result<ty::GenericPredicates<'tcx>, Self::Error> {
|
||||
decode_predicates(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($typaram),*> SpecializedDecoder<&'tcx Substs<'tcx>>
|
||||
for $DecoderName<$($typaram),*> {
|
||||
fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> {
|
||||
decode_substs(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($typaram),*> SpecializedDecoder<ty::Region<'tcx>>
|
||||
for $DecoderName<$($typaram),*> {
|
||||
fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
|
||||
decode_region(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($typaram),*> SpecializedDecoder<&'tcx ty::Slice<ty::Ty<'tcx>>>
|
||||
for $DecoderName<$($typaram),*> {
|
||||
fn specialized_decode(&mut self)
|
||||
-> Result<&'tcx ty::Slice<ty::Ty<'tcx>>, Self::Error> {
|
||||
decode_ty_slice(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($typaram),*> SpecializedDecoder<&'tcx ty::AdtDef>
|
||||
for $DecoderName<$($typaram),*> {
|
||||
fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
|
||||
decode_adt_def(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($typaram),*> SpecializedDecoder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>
|
||||
for $DecoderName<$($typaram),*> {
|
||||
fn specialized_decode(&mut self)
|
||||
-> Result<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, Self::Error> {
|
||||
decode_existential_predicate_slice(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($typaram),*> SpecializedDecoder<ByteArray<'tcx>>
|
||||
for $DecoderName<$($typaram),*> {
|
||||
fn specialized_decode(&mut self) -> Result<ByteArray<'tcx>, Self::Error> {
|
||||
decode_byte_array(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>>
|
||||
for $DecoderName<$($typaram),*> {
|
||||
fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
|
||||
decode_const(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -768,7 +768,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for TypeckTables<'gcx> {
|
|||
};
|
||||
let closure_def_id = DefId {
|
||||
krate: local_id_root.krate,
|
||||
index: closure_expr_id,
|
||||
index: closure_expr_id.to_def_id().index,
|
||||
};
|
||||
(hcx.def_path_hash(var_owner_def_id),
|
||||
var_id.local_id,
|
||||
|
@ -1306,9 +1306,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
pub fn serialize_query_result_cache<E>(self,
|
||||
encoder: &mut E)
|
||||
-> Result<(), E::Error>
|
||||
where E: ::rustc_serialize::Encoder
|
||||
where E: ty::codec::TyEncoder
|
||||
{
|
||||
self.on_disk_query_result_cache.serialize(encoder)
|
||||
self.on_disk_query_result_cache.serialize(self.global_tcx(), self.cstore, encoder)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use dep_graph::SerializedDepNodeIndex;
|
||||
use hir::def_id::{CrateNum, DefId, DefIndex};
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::maps::queries;
|
||||
|
@ -23,11 +24,21 @@ pub trait QueryConfig {
|
|||
type Value;
|
||||
}
|
||||
|
||||
pub(super) trait QueryDescription: QueryConfig {
|
||||
pub(super) trait QueryDescription<'tcx>: QueryConfig {
|
||||
fn describe(tcx: TyCtxt, key: Self::Key) -> String;
|
||||
|
||||
fn cache_on_disk(_: Self::Key) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn load_from_disk<'a>(_: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
_: SerializedDepNodeIndex)
|
||||
-> Self::Value {
|
||||
bug!("QueryDescription::load_from_disk() called for unsupport query.")
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: QueryConfig<Key=DefId>> QueryDescription for M {
|
||||
impl<'tcx, M: QueryConfig<Key=DefId>> QueryDescription<'tcx> for M {
|
||||
default fn describe(tcx: TyCtxt, def_id: DefId) -> String {
|
||||
if !tcx.sess.verbose() {
|
||||
format!("processing `{}`", tcx.item_path_str(def_id))
|
||||
|
@ -38,50 +49,50 @@ impl<M: QueryConfig<Key=DefId>> QueryDescription for M {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::is_copy_raw<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::is_copy_raw<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
|
||||
format!("computing whether `{}` is `Copy`", env.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::is_sized_raw<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::is_sized_raw<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
|
||||
format!("computing whether `{}` is `Sized`", env.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::is_freeze_raw<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::is_freeze_raw<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
|
||||
format!("computing whether `{}` is freeze", env.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::needs_drop_raw<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::needs_drop_raw<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
|
||||
format!("computing whether `{}` needs drop", env.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::layout_raw<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::layout_raw<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
|
||||
format!("computing layout of `{}`", env.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::super_predicates_of<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::super_predicates_of<'tcx> {
|
||||
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
|
||||
format!("computing the supertraits of `{}`",
|
||||
tcx.item_path_str(def_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::erase_regions_ty<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::erase_regions_ty<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, ty: Ty<'tcx>) -> String {
|
||||
format!("erasing regions from `{:?}`", ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::type_param_predicates<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::type_param_predicates<'tcx> {
|
||||
fn describe(tcx: TyCtxt, (_, def_id): (DefId, DefId)) -> String {
|
||||
let id = tcx.hir.as_local_node_id(def_id).unwrap();
|
||||
format!("computing the bounds for type parameter `{}`",
|
||||
|
@ -89,452 +100,468 @@ impl<'tcx> QueryDescription for queries::type_param_predicates<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::coherent_trait<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::coherent_trait<'tcx> {
|
||||
fn describe(tcx: TyCtxt, (_, def_id): (CrateNum, DefId)) -> String {
|
||||
format!("coherence checking all impls of trait `{}`",
|
||||
tcx.item_path_str(def_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::crate_inherent_impls<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::crate_inherent_impls<'tcx> {
|
||||
fn describe(_: TyCtxt, k: CrateNum) -> String {
|
||||
format!("all inherent impls defined in crate `{:?}`", k)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::crate_inherent_impls_overlap_check<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::crate_inherent_impls_overlap_check<'tcx> {
|
||||
fn describe(_: TyCtxt, _: CrateNum) -> String {
|
||||
format!("check for overlap between inherent impls defined in this crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::crate_variances<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::crate_variances<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("computing the variances for items in this crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::mir_shims<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::mir_shims<'tcx> {
|
||||
fn describe(tcx: TyCtxt, def: ty::InstanceDef<'tcx>) -> String {
|
||||
format!("generating MIR shim for `{}`",
|
||||
tcx.item_path_str(def.def_id()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::privacy_access_levels<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::privacy_access_levels<'tcx> {
|
||||
fn describe(_: TyCtxt, _: CrateNum) -> String {
|
||||
format!("privacy access levels")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::typeck_item_bodies<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::typeck_item_bodies<'tcx> {
|
||||
fn describe(_: TyCtxt, _: CrateNum) -> String {
|
||||
format!("type-checking all item bodies")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::reachable_set<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::reachable_set<'tcx> {
|
||||
fn describe(_: TyCtxt, _: CrateNum) -> String {
|
||||
format!("reachability")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::const_eval<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::const_eval<'tcx> {
|
||||
fn describe(tcx: TyCtxt, key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>) -> String {
|
||||
format!("const-evaluating `{}`", tcx.item_path_str(key.value.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::mir_keys<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::mir_keys<'tcx> {
|
||||
fn describe(_: TyCtxt, _: CrateNum) -> String {
|
||||
format!("getting a list of all mir_keys")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::symbol_name<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::symbol_name<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, instance: ty::Instance<'tcx>) -> String {
|
||||
format!("computing the symbol for `{}`", instance)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::describe_def<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::describe_def<'tcx> {
|
||||
fn describe(_: TyCtxt, _: DefId) -> String {
|
||||
bug!("describe_def")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::def_span<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::def_span<'tcx> {
|
||||
fn describe(_: TyCtxt, _: DefId) -> String {
|
||||
bug!("def_span")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'tcx> QueryDescription for queries::lookup_stability<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::lookup_stability<'tcx> {
|
||||
fn describe(_: TyCtxt, _: DefId) -> String {
|
||||
bug!("stability")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::lookup_deprecation_entry<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::lookup_deprecation_entry<'tcx> {
|
||||
fn describe(_: TyCtxt, _: DefId) -> String {
|
||||
bug!("deprecation")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::item_attrs<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::item_attrs<'tcx> {
|
||||
fn describe(_: TyCtxt, _: DefId) -> String {
|
||||
bug!("item_attrs")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::is_exported_symbol<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::is_exported_symbol<'tcx> {
|
||||
fn describe(_: TyCtxt, _: DefId) -> String {
|
||||
bug!("is_exported_symbol")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::fn_arg_names<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::fn_arg_names<'tcx> {
|
||||
fn describe(_: TyCtxt, _: DefId) -> String {
|
||||
bug!("fn_arg_names")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::impl_parent<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::impl_parent<'tcx> {
|
||||
fn describe(_: TyCtxt, _: DefId) -> String {
|
||||
bug!("impl_parent")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::trait_of_item<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::trait_of_item<'tcx> {
|
||||
fn describe(_: TyCtxt, _: DefId) -> String {
|
||||
bug!("trait_of_item")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::item_body_nested_bodies<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::item_body_nested_bodies<'tcx> {
|
||||
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
|
||||
format!("nested item bodies of `{}`", tcx.item_path_str(def_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::const_is_rvalue_promotable_to_static<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::const_is_rvalue_promotable_to_static<'tcx> {
|
||||
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
|
||||
format!("const checking if rvalue is promotable to static `{}`",
|
||||
tcx.item_path_str(def_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::rvalue_promotable_map<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::rvalue_promotable_map<'tcx> {
|
||||
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
|
||||
format!("checking which parts of `{}` are promotable to static",
|
||||
tcx.item_path_str(def_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::is_mir_available<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::is_mir_available<'tcx> {
|
||||
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
|
||||
format!("checking if item is mir available: `{}`",
|
||||
tcx.item_path_str(def_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::trans_fulfill_obligation<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::trans_fulfill_obligation<'tcx> {
|
||||
fn describe(tcx: TyCtxt, key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> String {
|
||||
format!("checking if `{}` fulfills its obligations", tcx.item_path_str(key.1.def_id()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::trait_impls_of<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::trait_impls_of<'tcx> {
|
||||
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
|
||||
format!("trait impls of `{}`", tcx.item_path_str(def_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::is_object_safe<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::is_object_safe<'tcx> {
|
||||
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
|
||||
format!("determine object safety of trait `{}`", tcx.item_path_str(def_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::is_const_fn<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::is_const_fn<'tcx> {
|
||||
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
|
||||
format!("checking if item is const fn: `{}`", tcx.item_path_str(def_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::dylib_dependency_formats<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::dylib_dependency_formats<'tcx> {
|
||||
fn describe(_: TyCtxt, _: CrateNum) -> String {
|
||||
"dylib dependency formats of crate".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::is_panic_runtime<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::is_panic_runtime<'tcx> {
|
||||
fn describe(_: TyCtxt, _: CrateNum) -> String {
|
||||
"checking if the crate is_panic_runtime".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::is_compiler_builtins<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::is_compiler_builtins<'tcx> {
|
||||
fn describe(_: TyCtxt, _: CrateNum) -> String {
|
||||
"checking if the crate is_compiler_builtins".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::has_global_allocator<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::has_global_allocator<'tcx> {
|
||||
fn describe(_: TyCtxt, _: CrateNum) -> String {
|
||||
"checking if the crate has_global_allocator".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::extern_crate<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::extern_crate<'tcx> {
|
||||
fn describe(_: TyCtxt, _: DefId) -> String {
|
||||
"getting crate's ExternCrateData".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::lint_levels<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::lint_levels<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("computing the lint levels for items in this crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::specializes<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::specializes<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: (DefId, DefId)) -> String {
|
||||
format!("computing whether impls specialize one another")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::in_scope_traits_map<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::in_scope_traits_map<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: DefIndex) -> String {
|
||||
format!("traits in scope at a block")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::is_no_builtins<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::is_no_builtins<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("test whether a crate has #![no_builtins]")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::panic_strategy<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::panic_strategy<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("query a crate's configured panic strategy")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::is_profiler_runtime<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::is_profiler_runtime<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("query a crate is #![profiler_runtime]")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::is_sanitizer_runtime<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::is_sanitizer_runtime<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("query a crate is #![sanitizer_runtime]")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::exported_symbol_ids<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::exported_symbol_ids<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("looking up the exported symbols of a crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::native_libraries<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::native_libraries<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("looking up the native libraries of a linked crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::plugin_registrar_fn<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::plugin_registrar_fn<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("looking up the plugin registrar for a crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::derive_registrar_fn<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::derive_registrar_fn<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("looking up the derive registrar for a crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::crate_disambiguator<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::crate_disambiguator<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("looking up the disambiguator a crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::crate_hash<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::crate_hash<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("looking up the hash a crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::original_crate_name<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::original_crate_name<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("looking up the original name a crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::implementations_of_trait<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::implementations_of_trait<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: (CrateNum, DefId)) -> String {
|
||||
format!("looking up implementations of a trait in a crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::all_trait_implementations<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::all_trait_implementations<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("looking up all (?) trait implementations")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::link_args<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::link_args<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("looking up link arguments for a crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::named_region_map<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::named_region_map<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: DefIndex) -> String {
|
||||
format!("looking up a named region")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::is_late_bound_map<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::is_late_bound_map<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: DefIndex) -> String {
|
||||
format!("testing if a region is late boudn")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::object_lifetime_defaults_map<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::object_lifetime_defaults_map<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: DefIndex) -> String {
|
||||
format!("looking up lifetime defaults for a region")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::dep_kind<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::dep_kind<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("fetching what a dependency looks like")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::crate_name<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::crate_name<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("fetching what a crate is named")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::get_lang_items<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::get_lang_items<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("calculating the lang items map")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::defined_lang_items<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::defined_lang_items<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("calculating the lang items defined in a crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::missing_lang_items<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::missing_lang_items<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("calculating the missing lang items in a crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::visible_parent_map<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::visible_parent_map<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("calculating the visible parent map")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::missing_extern_crate_item<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::missing_extern_crate_item<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("seeing if we're missing an `extern crate` item for this crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::used_crate_source<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::used_crate_source<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("looking at the source for a crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::postorder_cnums<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::postorder_cnums<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("generating a postorder list of CrateNums")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::maybe_unused_extern_crates<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::maybe_unused_extern_crates<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("looking up all possibly unused extern crates")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::stability_index<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::stability_index<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("calculating the stability index for the local crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::all_crate_nums<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::all_crate_nums<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("fetching all foreign CrateNum instances")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::exported_symbols<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::exported_symbols<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("exported_symbols")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::collect_and_partition_translation_items<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::collect_and_partition_translation_items<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("collect_and_partition_translation_items")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::codegen_unit<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::codegen_unit<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: InternedString) -> String {
|
||||
format!("codegen_unit")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::compile_codegen_unit<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::compile_codegen_unit<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: InternedString) -> String {
|
||||
format!("compile_codegen_unit")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::output_filenames<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::output_filenames<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("output_filenames")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::has_clone_closures<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::has_clone_closures<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("seeing if the crate has enabled `Clone` closures")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::vtable_methods<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::vtable_methods<'tcx> {
|
||||
fn describe(tcx: TyCtxt, key: ty::PolyTraitRef<'tcx> ) -> String {
|
||||
format!("finding all methods for trait {}", tcx.item_path_str(key.def_id()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::has_copy_closures<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::has_copy_closures<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("seeing if the crate has enabled `Copy` closures")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::fully_normalize_monormophic_ty<'tcx> {
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::fully_normalize_monormophic_ty<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: Ty) -> String {
|
||||
format!("normalizing types")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::typeck_tables_of<'tcx> {
|
||||
#[inline]
|
||||
fn cache_on_disk(def_id: Self::Key) -> bool {
|
||||
def_id.is_local()
|
||||
}
|
||||
|
||||
fn load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
id: SerializedDepNodeIndex)
|
||||
-> Self::Value {
|
||||
let typeck_tables: ty::TypeckTables<'tcx> = tcx.on_disk_query_result_cache
|
||||
.load_query_result(tcx, id);
|
||||
tcx.alloc_tables(typeck_tables)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,24 +9,42 @@
|
|||
// except according to those terms.
|
||||
|
||||
use dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use errors::Diagnostic;
|
||||
use hir;
|
||||
use hir::def_id::{CrateNum, DefIndex, DefId, LocalDefId,
|
||||
RESERVED_FOR_INCR_COMP_CACHE, LOCAL_CRATE};
|
||||
use hir::map::definitions::DefPathHash;
|
||||
use middle::cstore::CrateStore;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque,
|
||||
SpecializedDecoder};
|
||||
use session::Session;
|
||||
use std::borrow::Cow;
|
||||
SpecializedDecoder, SpecializedEncoder,
|
||||
UseSpecializedDecodable, UseSpecializedEncodable};
|
||||
use session::{CrateDisambiguator, Session};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::BTreeMap;
|
||||
use std::mem;
|
||||
use syntax::ast::NodeId;
|
||||
use syntax::codemap::{CodeMap, StableFilemapId};
|
||||
use syntax_pos::{BytePos, Span, NO_EXPANSION, DUMMY_SP};
|
||||
use ty;
|
||||
use ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
|
||||
use ty::context::TyCtxt;
|
||||
|
||||
// Some magic values used for verifying that encoding and decoding. These are
|
||||
// basically random numbers.
|
||||
const PREV_DIAGNOSTICS_TAG: u64 = 0x1234_5678_A1A1_A1A1;
|
||||
const QUERY_RESULT_INDEX_TAG: u64 = 0x1234_5678_C3C3_C3C3;
|
||||
|
||||
/// `OnDiskCache` provides an interface to incr. comp. data cached from the
|
||||
/// previous compilation session. This data will eventually include the results
|
||||
/// of a few selected queries (like `typeck_tables_of` and `mir_optimized`) and
|
||||
/// any diagnostics that have been emitted during a query.
|
||||
pub struct OnDiskCache<'sess> {
|
||||
|
||||
// The complete cache data in serialized form.
|
||||
serialized_data: Vec<u8>,
|
||||
|
||||
// The diagnostics emitted during the previous compilation session.
|
||||
prev_diagnostics: FxHashMap<SerializedDepNodeIndex, Vec<Diagnostic>>,
|
||||
|
||||
|
@ -34,68 +52,120 @@ pub struct OnDiskCache<'sess> {
|
|||
// compilation session.
|
||||
current_diagnostics: RefCell<FxHashMap<DepNodeIndex, Vec<Diagnostic>>>,
|
||||
|
||||
// This will eventually be needed for creating Decoders that can rebase
|
||||
// spans.
|
||||
_prev_filemap_starts: BTreeMap<BytePos, StableFilemapId>,
|
||||
prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
|
||||
cnum_map: RefCell<Option<IndexVec<CrateNum, Option<CrateNum>>>>,
|
||||
|
||||
prev_filemap_starts: BTreeMap<BytePos, StableFilemapId>,
|
||||
codemap: &'sess CodeMap,
|
||||
|
||||
// A map from dep-node to the position of the cached query result in
|
||||
// `serialized_data`.
|
||||
query_result_index: FxHashMap<SerializedDepNodeIndex, usize>,
|
||||
}
|
||||
|
||||
// This type is used only for (de-)serialization.
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
struct Header {
|
||||
prev_filemap_starts: BTreeMap<BytePos, StableFilemapId>,
|
||||
prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
|
||||
}
|
||||
|
||||
// This type is used only for (de-)serialization.
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
struct Body {
|
||||
diagnostics: Vec<(SerializedDepNodeIndex, Vec<Diagnostic>)>,
|
||||
}
|
||||
type EncodedPrevDiagnostics = Vec<(SerializedDepNodeIndex, Vec<Diagnostic>)>;
|
||||
type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, usize)>;
|
||||
|
||||
impl<'sess> OnDiskCache<'sess> {
|
||||
/// Create a new OnDiskCache instance from the serialized data in `data`.
|
||||
/// Note that the current implementation (which only deals with diagnostics
|
||||
/// so far) will eagerly deserialize the complete cache. Once we are
|
||||
/// dealing with larger amounts of data (i.e. cached query results),
|
||||
/// deserialization will need to happen lazily.
|
||||
pub fn new(sess: &'sess Session, data: &[u8]) -> OnDiskCache<'sess> {
|
||||
pub fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> OnDiskCache<'sess> {
|
||||
debug_assert!(sess.opts.incremental.is_some());
|
||||
|
||||
let mut decoder = opaque::Decoder::new(&data[..], 0);
|
||||
let header = Header::decode(&mut decoder).unwrap();
|
||||
// Decode the header
|
||||
let (header, post_header_pos) = {
|
||||
let mut decoder = opaque::Decoder::new(&data[..], start_pos);
|
||||
let header = Header::decode(&mut decoder)
|
||||
.expect("Error while trying to decode incr. comp. cache header.");
|
||||
(header, decoder.position())
|
||||
};
|
||||
|
||||
let prev_diagnostics: FxHashMap<_, _> = {
|
||||
let (prev_diagnostics, query_result_index) = {
|
||||
let mut decoder = CacheDecoder {
|
||||
opaque: decoder,
|
||||
tcx: None,
|
||||
opaque: opaque::Decoder::new(&data[..], post_header_pos),
|
||||
codemap: sess.codemap(),
|
||||
prev_filemap_starts: &header.prev_filemap_starts,
|
||||
cnum_map: &IndexVec::new(),
|
||||
};
|
||||
let body = Body::decode(&mut decoder).unwrap();
|
||||
body.diagnostics.into_iter().collect()
|
||||
|
||||
// Decode Diagnostics
|
||||
let prev_diagnostics: FxHashMap<_, _> = {
|
||||
let diagnostics: EncodedPrevDiagnostics =
|
||||
decode_tagged(&mut decoder, PREV_DIAGNOSTICS_TAG)
|
||||
.expect("Error while trying to decode previous session \
|
||||
diagnostics from incr. comp. cache.");
|
||||
diagnostics.into_iter().collect()
|
||||
};
|
||||
|
||||
// Decode the *position* of the query result index
|
||||
let query_result_index_pos = {
|
||||
let pos_pos = data.len() - IntEncodedWithFixedSize::ENCODED_SIZE;
|
||||
decoder.with_position(pos_pos, |decoder| {
|
||||
IntEncodedWithFixedSize::decode(decoder)
|
||||
}).expect("Error while trying to decode query result index position.")
|
||||
.0 as usize
|
||||
};
|
||||
|
||||
// Decode the query result index itself
|
||||
let query_result_index: EncodedQueryResultIndex =
|
||||
decoder.with_position(query_result_index_pos, |decoder| {
|
||||
decode_tagged(decoder, QUERY_RESULT_INDEX_TAG)
|
||||
}).expect("Error while trying to decode query result index.");
|
||||
|
||||
(prev_diagnostics, query_result_index)
|
||||
};
|
||||
|
||||
OnDiskCache {
|
||||
serialized_data: data,
|
||||
prev_diagnostics,
|
||||
_prev_filemap_starts: header.prev_filemap_starts,
|
||||
prev_filemap_starts: header.prev_filemap_starts,
|
||||
prev_cnums: header.prev_cnums,
|
||||
cnum_map: RefCell::new(None),
|
||||
codemap: sess.codemap(),
|
||||
current_diagnostics: RefCell::new(FxHashMap()),
|
||||
query_result_index: query_result_index.into_iter().collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_empty(codemap: &'sess CodeMap) -> OnDiskCache<'sess> {
|
||||
OnDiskCache {
|
||||
serialized_data: Vec::new(),
|
||||
prev_diagnostics: FxHashMap(),
|
||||
_prev_filemap_starts: BTreeMap::new(),
|
||||
prev_filemap_starts: BTreeMap::new(),
|
||||
prev_cnums: vec![],
|
||||
cnum_map: RefCell::new(None),
|
||||
codemap,
|
||||
current_diagnostics: RefCell::new(FxHashMap()),
|
||||
query_result_index: FxHashMap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn serialize<'a, 'tcx, E>(&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
cstore: &CrateStore,
|
||||
encoder: &mut E)
|
||||
-> Result<(), E::Error>
|
||||
where E: Encoder
|
||||
{
|
||||
where E: ty_codec::TyEncoder
|
||||
{
|
||||
// Serializing the DepGraph should not modify it:
|
||||
let _in_ignore = tcx.dep_graph.in_ignore();
|
||||
|
||||
let mut encoder = CacheEncoder {
|
||||
tcx,
|
||||
encoder,
|
||||
type_shorthands: FxHashMap(),
|
||||
predicate_shorthands: FxHashMap(),
|
||||
};
|
||||
|
||||
|
||||
// Encode the file header
|
||||
let prev_filemap_starts: BTreeMap<_, _> = self
|
||||
.codemap
|
||||
.files()
|
||||
|
@ -103,18 +173,61 @@ impl<'sess> OnDiskCache<'sess> {
|
|||
.map(|fm| (fm.start_pos, StableFilemapId::new(fm)))
|
||||
.collect();
|
||||
|
||||
Header { prev_filemap_starts }.encode(encoder)?;
|
||||
let sorted_cnums = sorted_cnums_including_local_crate(cstore);
|
||||
|
||||
let diagnostics: Vec<(SerializedDepNodeIndex, Vec<Diagnostic>)> =
|
||||
let prev_cnums: Vec<_> = sorted_cnums.iter().map(|&cnum| {
|
||||
let crate_name = tcx.original_crate_name(cnum).as_str().to_string();
|
||||
let crate_disambiguator = tcx.crate_disambiguator(cnum);
|
||||
(cnum.as_u32(), crate_name, crate_disambiguator)
|
||||
}).collect();
|
||||
|
||||
Header {
|
||||
prev_filemap_starts,
|
||||
prev_cnums,
|
||||
}.encode(&mut encoder)?;
|
||||
|
||||
|
||||
// Encode Diagnostics
|
||||
let diagnostics: EncodedPrevDiagnostics =
|
||||
self.current_diagnostics
|
||||
.borrow()
|
||||
.iter()
|
||||
.map(|(k, v)| (SerializedDepNodeIndex::new(k.index()), v.clone()))
|
||||
.collect();
|
||||
|
||||
Body { diagnostics }.encode(encoder)?;
|
||||
encoder.encode_tagged(PREV_DIAGNOSTICS_TAG, &diagnostics)?;
|
||||
|
||||
Ok(())
|
||||
|
||||
// Encode query results
|
||||
let mut query_result_index = EncodedQueryResultIndex::new();
|
||||
|
||||
{
|
||||
use ty::maps::queries::*;
|
||||
let enc = &mut encoder;
|
||||
let qri = &mut query_result_index;
|
||||
|
||||
// Encode TypeckTables
|
||||
encode_query_results::<typeck_tables_of, _>(tcx, enc, qri)?;
|
||||
}
|
||||
|
||||
// Encode query result index
|
||||
let query_result_index_pos = encoder.position() as u64;
|
||||
encoder.encode_tagged(QUERY_RESULT_INDEX_TAG, &query_result_index)?;
|
||||
|
||||
// Encode the position of the query result index as the last 8 bytes of
|
||||
// file so we know where to look for it.
|
||||
IntEncodedWithFixedSize(query_result_index_pos).encode(&mut encoder)?;
|
||||
|
||||
return Ok(());
|
||||
|
||||
fn sorted_cnums_including_local_crate(cstore: &CrateStore) -> Vec<CrateNum> {
|
||||
let mut cnums = vec![LOCAL_CRATE];
|
||||
cnums.extend_from_slice(&cstore.crates_untracked()[..]);
|
||||
cnums.sort_unstable();
|
||||
// Just to be sure...
|
||||
cnums.dedup();
|
||||
cnums
|
||||
}
|
||||
}
|
||||
|
||||
/// Load a diagnostic emitted during the previous compilation session.
|
||||
|
@ -135,6 +248,37 @@ impl<'sess> OnDiskCache<'sess> {
|
|||
debug_assert!(prev.is_none());
|
||||
}
|
||||
|
||||
pub fn load_query_result<'a, 'tcx, T>(&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
dep_node_index: SerializedDepNodeIndex)
|
||||
-> T
|
||||
where T: Decodable
|
||||
{
|
||||
let pos = self.query_result_index[&dep_node_index];
|
||||
|
||||
let mut cnum_map = self.cnum_map.borrow_mut();
|
||||
if cnum_map.is_none() {
|
||||
*cnum_map = Some(Self::compute_cnum_map(tcx, &self.prev_cnums[..]));
|
||||
}
|
||||
|
||||
let mut decoder = CacheDecoder {
|
||||
tcx: Some(tcx),
|
||||
opaque: opaque::Decoder::new(&self.serialized_data[..], pos),
|
||||
codemap: self.codemap,
|
||||
prev_filemap_starts: &self.prev_filemap_starts,
|
||||
cnum_map: cnum_map.as_ref().unwrap(),
|
||||
};
|
||||
|
||||
match decode_tagged(&mut decoder, dep_node_index) {
|
||||
Ok(value) => {
|
||||
value
|
||||
}
|
||||
Err(e) => {
|
||||
bug!("Could not decode cached query result: {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Store a diagnostic emitted during computation of an anonymous query.
|
||||
/// Since many anonymous queries can share the same `DepNode`, we aggregate
|
||||
/// them -- as opposed to regular queries where we assume that there is a
|
||||
|
@ -150,18 +294,57 @@ impl<'sess> OnDiskCache<'sess> {
|
|||
|
||||
x.extend(diagnostics.into_iter());
|
||||
}
|
||||
|
||||
// This function builds mapping from previous-session-CrateNum to
|
||||
// current-session-CrateNum. There might be CrateNums from the previous
|
||||
// Session that don't occur in the current one. For these, the mapping
|
||||
// maps to None.
|
||||
fn compute_cnum_map(tcx: TyCtxt,
|
||||
prev_cnums: &[(u32, String, CrateDisambiguator)])
|
||||
-> IndexVec<CrateNum, Option<CrateNum>>
|
||||
{
|
||||
let _in_ignore = tcx.dep_graph.in_ignore();
|
||||
|
||||
let current_cnums = tcx.all_crate_nums(LOCAL_CRATE).iter().map(|&cnum| {
|
||||
let crate_name = tcx.original_crate_name(cnum)
|
||||
.as_str()
|
||||
.to_string();
|
||||
let crate_disambiguator = tcx.crate_disambiguator(cnum);
|
||||
((crate_name, crate_disambiguator), cnum)
|
||||
}).collect::<FxHashMap<_,_>>();
|
||||
|
||||
let map_size = prev_cnums.iter()
|
||||
.map(|&(cnum, ..)| cnum)
|
||||
.max()
|
||||
.unwrap_or(0) + 1;
|
||||
let mut map = IndexVec::new();
|
||||
map.resize(map_size as usize, None);
|
||||
|
||||
for &(prev_cnum, ref crate_name, crate_disambiguator) in prev_cnums {
|
||||
let key = (crate_name.clone(), crate_disambiguator);
|
||||
map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&key).cloned();
|
||||
}
|
||||
|
||||
map[LOCAL_CRATE] = Some(LOCAL_CRATE);
|
||||
map
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//- DECODING -------------------------------------------------------------------
|
||||
|
||||
/// A decoder that can read the incr. comp. cache. It is similar to the one
|
||||
/// we use for crate metadata decoding in that it can rebase spans and
|
||||
/// eventually will also handle things that contain `Ty` instances.
|
||||
struct CacheDecoder<'a> {
|
||||
opaque: opaque::Decoder<'a>,
|
||||
codemap: &'a CodeMap,
|
||||
prev_filemap_starts: &'a BTreeMap<BytePos, StableFilemapId>,
|
||||
struct CacheDecoder<'a, 'tcx: 'a, 'x> {
|
||||
tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
|
||||
opaque: opaque::Decoder<'x>,
|
||||
codemap: &'x CodeMap,
|
||||
prev_filemap_starts: &'x BTreeMap<BytePos, StableFilemapId>,
|
||||
cnum_map: &'x IndexVec<CrateNum, Option<CrateNum>>,
|
||||
}
|
||||
|
||||
impl<'a> CacheDecoder<'a> {
|
||||
impl<'a, 'tcx, 'x> CacheDecoder<'a, 'tcx, 'x> {
|
||||
fn find_filemap_prev_bytepos(&self,
|
||||
prev_bytepos: BytePos)
|
||||
-> Option<(BytePos, StableFilemapId)> {
|
||||
|
@ -173,47 +356,91 @@ impl<'a> CacheDecoder<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! decoder_methods {
|
||||
($($name:ident -> $ty:ty;)*) => {
|
||||
$(fn $name(&mut self) -> Result<$ty, Self::Error> {
|
||||
self.opaque.$name()
|
||||
})*
|
||||
// Decode something that was encoded with encode_tagged() and verify that the
|
||||
// tag matches and the correct amount of bytes was read.
|
||||
fn decode_tagged<'a, 'tcx, D, T, V>(decoder: &mut D,
|
||||
expected_tag: T)
|
||||
-> Result<V, D::Error>
|
||||
where T: Decodable + Eq + ::std::fmt::Debug,
|
||||
V: Decodable,
|
||||
D: Decoder + ty_codec::TyDecoder<'a, 'tcx>,
|
||||
'tcx: 'a,
|
||||
{
|
||||
let start_pos = decoder.position();
|
||||
|
||||
let actual_tag = T::decode(decoder)?;
|
||||
assert_eq!(actual_tag, expected_tag);
|
||||
let value = V::decode(decoder)?;
|
||||
let end_pos = decoder.position();
|
||||
|
||||
let expected_len: u64 = Decodable::decode(decoder)?;
|
||||
assert_eq!((end_pos - start_pos) as u64, expected_len);
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
|
||||
impl<'a, 'tcx: 'a, 'x> ty_codec::TyDecoder<'a, 'tcx> for CacheDecoder<'a, 'tcx, 'x> {
|
||||
|
||||
#[inline]
|
||||
fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
self.tcx.expect("missing TyCtxt in CacheDecoder")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn position(&self) -> usize {
|
||||
self.opaque.position()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn peek_byte(&self) -> u8 {
|
||||
self.opaque.data[self.opaque.position()]
|
||||
}
|
||||
|
||||
fn cached_ty_for_shorthand<F>(&mut self,
|
||||
shorthand: usize,
|
||||
or_insert_with: F)
|
||||
-> Result<ty::Ty<'tcx>, Self::Error>
|
||||
where F: FnOnce(&mut Self) -> Result<ty::Ty<'tcx>, Self::Error>
|
||||
{
|
||||
let tcx = self.tcx();
|
||||
|
||||
let cache_key = ty::CReaderCacheKey {
|
||||
cnum: RESERVED_FOR_INCR_COMP_CACHE,
|
||||
pos: shorthand,
|
||||
};
|
||||
|
||||
if let Some(&ty) = tcx.rcache.borrow().get(&cache_key) {
|
||||
return Ok(ty);
|
||||
}
|
||||
|
||||
let ty = or_insert_with(self)?;
|
||||
tcx.rcache.borrow_mut().insert(cache_key, ty);
|
||||
Ok(ty)
|
||||
}
|
||||
|
||||
fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
|
||||
where F: FnOnce(&mut Self) -> R
|
||||
{
|
||||
debug_assert!(pos < self.opaque.data.len());
|
||||
|
||||
let new_opaque = opaque::Decoder::new(self.opaque.data, pos);
|
||||
let old_opaque = mem::replace(&mut self.opaque, new_opaque);
|
||||
let r = f(self);
|
||||
self.opaque = old_opaque;
|
||||
r
|
||||
}
|
||||
|
||||
fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
|
||||
self.cnum_map[cnum].unwrap_or_else(|| {
|
||||
bug!("Could not find new CrateNum for {:?}", cnum)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'sess> Decoder for CacheDecoder<'sess> {
|
||||
type Error = String;
|
||||
implement_ty_decoder!( CacheDecoder<'a, 'tcx, 'x> );
|
||||
|
||||
decoder_methods! {
|
||||
read_nil -> ();
|
||||
|
||||
read_u128 -> u128;
|
||||
read_u64 -> u64;
|
||||
read_u32 -> u32;
|
||||
read_u16 -> u16;
|
||||
read_u8 -> u8;
|
||||
read_usize -> usize;
|
||||
|
||||
read_i128 -> i128;
|
||||
read_i64 -> i64;
|
||||
read_i32 -> i32;
|
||||
read_i16 -> i16;
|
||||
read_i8 -> i8;
|
||||
read_isize -> isize;
|
||||
|
||||
read_bool -> bool;
|
||||
read_f64 -> f64;
|
||||
read_f32 -> f32;
|
||||
read_char -> char;
|
||||
read_str -> Cow<str>;
|
||||
}
|
||||
|
||||
fn error(&mut self, err: &str) -> Self::Error {
|
||||
self.opaque.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SpecializedDecoder<Span> for CacheDecoder<'a> {
|
||||
impl<'a, 'tcx, 'x> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx, 'x> {
|
||||
fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
|
||||
let lo = BytePos::decode(self)?;
|
||||
let hi = BytePos::decode(self)?;
|
||||
|
@ -229,3 +456,307 @@ impl<'a> SpecializedDecoder<Span> for CacheDecoder<'a> {
|
|||
Ok(DUMMY_SP)
|
||||
}
|
||||
}
|
||||
|
||||
// This impl makes sure that we get a runtime error when we try decode a
|
||||
// DefIndex that is not contained in a DefId. Such a case would be problematic
|
||||
// because we would not know how to transform the DefIndex to the current
|
||||
// context.
|
||||
impl<'a, 'tcx, 'x> SpecializedDecoder<DefIndex> for CacheDecoder<'a, 'tcx, 'x> {
|
||||
fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
|
||||
bug!("Trying to decode DefIndex outside the context of a DefId")
|
||||
}
|
||||
}
|
||||
|
||||
// Both the CrateNum and the DefIndex of a DefId can change in between two
|
||||
// compilation sessions. We use the DefPathHash, which is stable across
|
||||
// sessions, to map the old DefId to the new one.
|
||||
impl<'a, 'tcx, 'x> SpecializedDecoder<DefId> for CacheDecoder<'a, 'tcx, 'x> {
|
||||
fn specialized_decode(&mut self) -> Result<DefId, Self::Error> {
|
||||
// Load the DefPathHash which is was we encoded the DefId as.
|
||||
let def_path_hash = DefPathHash::decode(self)?;
|
||||
|
||||
// Using the DefPathHash, we can lookup the new DefId
|
||||
Ok(self.tcx().def_path_hash_to_def_id.as_ref().unwrap()[&def_path_hash])
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, 'x> SpecializedDecoder<LocalDefId> for CacheDecoder<'a, 'tcx, 'x> {
|
||||
fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
|
||||
Ok(LocalDefId::from_def_id(DefId::decode(self)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, 'x> SpecializedDecoder<hir::HirId> for CacheDecoder<'a, 'tcx, 'x> {
|
||||
fn specialized_decode(&mut self) -> Result<hir::HirId, Self::Error> {
|
||||
// Load the DefPathHash which is was we encoded the DefIndex as.
|
||||
let def_path_hash = DefPathHash::decode(self)?;
|
||||
|
||||
// Use the DefPathHash to map to the current DefId.
|
||||
let def_id = self.tcx()
|
||||
.def_path_hash_to_def_id
|
||||
.as_ref()
|
||||
.unwrap()[&def_path_hash];
|
||||
|
||||
debug_assert!(def_id.is_local());
|
||||
|
||||
// The ItemLocalId needs no remapping.
|
||||
let local_id = hir::ItemLocalId::decode(self)?;
|
||||
|
||||
// Reconstruct the HirId and look up the corresponding NodeId in the
|
||||
// context of the current session.
|
||||
Ok(hir::HirId {
|
||||
owner: def_id.index,
|
||||
local_id
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// NodeIds are not stable across compilation sessions, so we store them in their
|
||||
// HirId representation. This allows use to map them to the current NodeId.
|
||||
impl<'a, 'tcx, 'x> SpecializedDecoder<NodeId> for CacheDecoder<'a, 'tcx, 'x> {
|
||||
fn specialized_decode(&mut self) -> Result<NodeId, Self::Error> {
|
||||
let hir_id = hir::HirId::decode(self)?;
|
||||
Ok(self.tcx().hir.hir_to_node_id(hir_id))
|
||||
}
|
||||
}
|
||||
|
||||
//- ENCODING -------------------------------------------------------------------
|
||||
|
||||
struct CacheEncoder<'enc, 'a, 'tcx, E>
|
||||
where E: 'enc + ty_codec::TyEncoder,
|
||||
'tcx: 'a,
|
||||
{
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
encoder: &'enc mut E,
|
||||
type_shorthands: FxHashMap<ty::Ty<'tcx>, usize>,
|
||||
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
|
||||
}
|
||||
|
||||
impl<'enc, 'a, 'tcx, E> CacheEncoder<'enc, 'a, 'tcx, E>
|
||||
where E: 'enc + ty_codec::TyEncoder
|
||||
{
|
||||
/// Encode something with additional information that allows to do some
|
||||
/// sanity checks when decoding the data again. This method will first
|
||||
/// encode the specified tag, then the given value, then the number of
|
||||
/// bytes taken up by tag and value. On decoding, we can then verify that
|
||||
/// we get the expected tag and read the expected number of bytes.
|
||||
fn encode_tagged<T: Encodable, V: Encodable>(&mut self,
|
||||
tag: T,
|
||||
value: &V)
|
||||
-> Result<(), E::Error>
|
||||
{
|
||||
use ty::codec::TyEncoder;
|
||||
let start_pos = self.position();
|
||||
|
||||
tag.encode(self)?;
|
||||
value.encode(self)?;
|
||||
|
||||
let end_pos = self.position();
|
||||
((end_pos - start_pos) as u64).encode(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'enc, 'a, 'tcx, E> ty_codec::TyEncoder for CacheEncoder<'enc, 'a, 'tcx, E>
|
||||
where E: 'enc + ty_codec::TyEncoder
|
||||
{
|
||||
#[inline]
|
||||
fn position(&self) -> usize {
|
||||
self.encoder.position()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'enc, 'a, 'tcx, E> SpecializedEncoder<CrateNum> for CacheEncoder<'enc, 'a, 'tcx, E>
|
||||
where E: 'enc + ty_codec::TyEncoder
|
||||
{
|
||||
#[inline]
|
||||
fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> {
|
||||
self.emit_u32(cnum.as_u32())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'enc, 'a, 'tcx, E> SpecializedEncoder<ty::Ty<'tcx>> for CacheEncoder<'enc, 'a, 'tcx, E>
|
||||
where E: 'enc + ty_codec::TyEncoder
|
||||
{
|
||||
#[inline]
|
||||
fn specialized_encode(&mut self, ty: &ty::Ty<'tcx>) -> Result<(), Self::Error> {
|
||||
ty_codec::encode_with_shorthand(self, ty,
|
||||
|encoder| &mut encoder.type_shorthands)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'enc, 'a, 'tcx, E> SpecializedEncoder<ty::GenericPredicates<'tcx>>
|
||||
for CacheEncoder<'enc, 'a, 'tcx, E>
|
||||
where E: 'enc + ty_codec::TyEncoder
|
||||
{
|
||||
#[inline]
|
||||
fn specialized_encode(&mut self,
|
||||
predicates: &ty::GenericPredicates<'tcx>)
|
||||
-> Result<(), Self::Error> {
|
||||
ty_codec::encode_predicates(self, predicates,
|
||||
|encoder| &mut encoder.predicate_shorthands)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'enc, 'a, 'tcx, E> SpecializedEncoder<hir::HirId> for CacheEncoder<'enc, 'a, 'tcx, E>
|
||||
where E: 'enc + ty_codec::TyEncoder
|
||||
{
|
||||
#[inline]
|
||||
fn specialized_encode(&mut self, id: &hir::HirId) -> Result<(), Self::Error> {
|
||||
let hir::HirId {
|
||||
owner,
|
||||
local_id,
|
||||
} = *id;
|
||||
|
||||
let def_path_hash = self.tcx.hir.definitions().def_path_hash(owner);
|
||||
|
||||
def_path_hash.encode(self)?;
|
||||
local_id.encode(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'enc, 'a, 'tcx, E> SpecializedEncoder<DefId> for CacheEncoder<'enc, 'a, 'tcx, E>
|
||||
where E: 'enc + ty_codec::TyEncoder
|
||||
{
|
||||
#[inline]
|
||||
fn specialized_encode(&mut self, id: &DefId) -> Result<(), Self::Error> {
|
||||
let def_path_hash = self.tcx.def_path_hash(*id);
|
||||
def_path_hash.encode(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'enc, 'a, 'tcx, E> SpecializedEncoder<LocalDefId> for CacheEncoder<'enc, 'a, 'tcx, E>
|
||||
where E: 'enc + ty_codec::TyEncoder
|
||||
{
|
||||
#[inline]
|
||||
fn specialized_encode(&mut self, id: &LocalDefId) -> Result<(), Self::Error> {
|
||||
id.to_def_id().encode(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'enc, 'a, 'tcx, E> SpecializedEncoder<DefIndex> for CacheEncoder<'enc, 'a, 'tcx, E>
|
||||
where E: 'enc + ty_codec::TyEncoder
|
||||
{
|
||||
fn specialized_encode(&mut self, _: &DefIndex) -> Result<(), Self::Error> {
|
||||
bug!("Encoding DefIndex without context.")
|
||||
}
|
||||
}
|
||||
|
||||
// NodeIds are not stable across compilation sessions, so we store them in their
|
||||
// HirId representation. This allows use to map them to the current NodeId.
|
||||
impl<'enc, 'a, 'tcx, E> SpecializedEncoder<NodeId> for CacheEncoder<'enc, 'a, 'tcx, E>
|
||||
where E: 'enc + ty_codec::TyEncoder
|
||||
{
|
||||
#[inline]
|
||||
fn specialized_encode(&mut self, node_id: &NodeId) -> Result<(), Self::Error> {
|
||||
let hir_id = self.tcx.hir.node_to_hir_id(*node_id);
|
||||
hir_id.encode(self)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! encoder_methods {
|
||||
($($name:ident($ty:ty);)*) => {
|
||||
$(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
|
||||
self.encoder.$name(value)
|
||||
})*
|
||||
}
|
||||
}
|
||||
|
||||
impl<'enc, 'a, 'tcx, E> Encoder for CacheEncoder<'enc, 'a, 'tcx, E>
|
||||
where E: 'enc + ty_codec::TyEncoder
|
||||
{
|
||||
type Error = E::Error;
|
||||
|
||||
fn emit_nil(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
encoder_methods! {
|
||||
emit_usize(usize);
|
||||
emit_u128(u128);
|
||||
emit_u64(u64);
|
||||
emit_u32(u32);
|
||||
emit_u16(u16);
|
||||
emit_u8(u8);
|
||||
|
||||
emit_isize(isize);
|
||||
emit_i128(i128);
|
||||
emit_i64(i64);
|
||||
emit_i32(i32);
|
||||
emit_i16(i16);
|
||||
emit_i8(i8);
|
||||
|
||||
emit_bool(bool);
|
||||
emit_f64(f64);
|
||||
emit_f32(f32);
|
||||
emit_char(char);
|
||||
emit_str(&str);
|
||||
}
|
||||
}
|
||||
|
||||
// An integer that will always encode to 8 bytes.
|
||||
struct IntEncodedWithFixedSize(u64);
|
||||
|
||||
impl IntEncodedWithFixedSize {
|
||||
pub const ENCODED_SIZE: usize = 8;
|
||||
}
|
||||
|
||||
impl UseSpecializedEncodable for IntEncodedWithFixedSize {}
|
||||
impl UseSpecializedDecodable for IntEncodedWithFixedSize {}
|
||||
|
||||
impl<'enc, 'a, 'tcx, E> SpecializedEncoder<IntEncodedWithFixedSize>
|
||||
for CacheEncoder<'enc, 'a, 'tcx, E>
|
||||
where E: 'enc + ty_codec::TyEncoder
|
||||
{
|
||||
fn specialized_encode(&mut self, x: &IntEncodedWithFixedSize) -> Result<(), Self::Error> {
|
||||
let start_pos = self.position();
|
||||
for i in 0 .. IntEncodedWithFixedSize::ENCODED_SIZE {
|
||||
((x.0 >> i * 8) as u8).encode(self)?;
|
||||
}
|
||||
let end_pos = self.position();
|
||||
assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, 'x> SpecializedDecoder<IntEncodedWithFixedSize>
|
||||
for CacheDecoder<'a, 'tcx, 'x> {
|
||||
fn specialized_decode(&mut self) -> Result<IntEncodedWithFixedSize, Self::Error> {
|
||||
let mut value: u64 = 0;
|
||||
let start_pos = self.position();
|
||||
|
||||
for i in 0 .. IntEncodedWithFixedSize::ENCODED_SIZE {
|
||||
let byte: u8 = Decodable::decode(self)?;
|
||||
value |= (byte as u64) << (i * 8);
|
||||
}
|
||||
|
||||
let end_pos = self.position();
|
||||
assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
|
||||
|
||||
Ok(IntEncodedWithFixedSize(value))
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_query_results<'enc, 'a, 'tcx, Q, E>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
encoder: &mut CacheEncoder<'enc, 'a, 'tcx, E>,
|
||||
query_result_index: &mut EncodedQueryResultIndex)
|
||||
-> Result<(), E::Error>
|
||||
where Q: super::plumbing::GetCacheInternal<'tcx>,
|
||||
E: 'enc + TyEncoder,
|
||||
Q::Value: Encodable,
|
||||
{
|
||||
for (key, entry) in Q::get_cache_internal(tcx).map.iter() {
|
||||
if Q::cache_on_disk(key.clone()) {
|
||||
let dep_node = SerializedDepNodeIndex::new(entry.index.index());
|
||||
|
||||
// Record position of the cache entry
|
||||
query_result_index.push((dep_node, encoder.position()));
|
||||
|
||||
// Encode the type check tables with the SerializedDepNodeIndex
|
||||
// as tag.
|
||||
encoder.encode_tagged(dep_node, &entry.value)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -20,13 +20,13 @@ use ty::maps::config::QueryDescription;
|
|||
use ty::item_path;
|
||||
|
||||
use rustc_data_structures::fx::{FxHashMap};
|
||||
use std::cell::RefMut;
|
||||
use std::cell::{Ref, RefMut};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use syntax_pos::Span;
|
||||
|
||||
pub(super) struct QueryMap<D: QueryDescription> {
|
||||
phantom: PhantomData<D>,
|
||||
pub(super) struct QueryMap<'tcx, D: QueryDescription<'tcx>> {
|
||||
phantom: PhantomData<(D, &'tcx ())>,
|
||||
pub(super) map: FxHashMap<D::Key, QueryValue<D::Value>>,
|
||||
}
|
||||
|
||||
|
@ -46,8 +46,8 @@ impl<T> QueryValue<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<M: QueryDescription> QueryMap<M> {
|
||||
pub(super) fn new() -> QueryMap<M> {
|
||||
impl<'tcx, M: QueryDescription<'tcx>> QueryMap<'tcx, M> {
|
||||
pub(super) fn new() -> QueryMap<'tcx, M> {
|
||||
QueryMap {
|
||||
phantom: PhantomData,
|
||||
map: FxHashMap(),
|
||||
|
@ -55,6 +55,11 @@ impl<M: QueryDescription> QueryMap<M> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) trait GetCacheInternal<'tcx>: QueryDescription<'tcx> + Sized {
|
||||
fn get_cache_internal<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||
-> Ref<'a, QueryMap<'tcx, Self>>;
|
||||
}
|
||||
|
||||
pub(super) struct CycleError<'a, 'tcx: 'a> {
|
||||
span: Span,
|
||||
cycle: RefMut<'a, [(Span, Query<'tcx>)]>,
|
||||
|
@ -242,6 +247,13 @@ macro_rules! define_maps {
|
|||
type Value = $V;
|
||||
}
|
||||
|
||||
impl<$tcx> GetCacheInternal<$tcx> for queries::$name<$tcx> {
|
||||
fn get_cache_internal<'a>(tcx: TyCtxt<'a, $tcx, $tcx>)
|
||||
-> ::std::cell::Ref<'a, QueryMap<$tcx, Self>> {
|
||||
tcx.maps.$name.borrow()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $tcx, 'lcx> queries::$name<$tcx> {
|
||||
|
||||
#[allow(unused)]
|
||||
|
@ -379,18 +391,26 @@ macro_rules! define_maps {
|
|||
{
|
||||
debug_assert!(tcx.dep_graph.is_green(dep_node_index));
|
||||
|
||||
// We don't do any caching yet, so recompute.
|
||||
// The diagnostics for this query have already been promoted to
|
||||
// the current session during try_mark_green(), so we can ignore
|
||||
// them here.
|
||||
let (result, _) = tcx.cycle_check(span, Query::$name(key), || {
|
||||
tcx.sess.diagnostic().track_diagnostics(|| {
|
||||
// The dep-graph for this computation is already in place
|
||||
tcx.dep_graph.with_ignore(|| {
|
||||
Self::compute_result(tcx, key)
|
||||
let result = if tcx.sess.opts.debugging_opts.incremental_queries &&
|
||||
Self::cache_on_disk(key) {
|
||||
let prev_dep_node_index =
|
||||
tcx.dep_graph.prev_dep_node_index_of(dep_node);
|
||||
Self::load_from_disk(tcx.global_tcx(), prev_dep_node_index)
|
||||
} else {
|
||||
let (result, _ ) = tcx.cycle_check(span, Query::$name(key), || {
|
||||
// The diagnostics for this query have already been
|
||||
// promoted to the current session during
|
||||
// try_mark_green(), so we can ignore them here.
|
||||
tcx.sess.diagnostic().track_diagnostics(|| {
|
||||
// The dep-graph for this computation is already in
|
||||
// place
|
||||
tcx.dep_graph.with_ignore(|| {
|
||||
Self::compute_result(tcx, key)
|
||||
})
|
||||
})
|
||||
})
|
||||
})?;
|
||||
})?;
|
||||
result
|
||||
};
|
||||
|
||||
// If -Zincremental-verify-ich is specified, re-hash results from
|
||||
// the cache and make sure that they have the expected fingerprint.
|
||||
|
@ -547,7 +567,7 @@ macro_rules! define_map_struct {
|
|||
pub struct Maps<$tcx> {
|
||||
providers: IndexVec<CrateNum, Providers<$tcx>>,
|
||||
query_stack: RefCell<Vec<(Span, Query<$tcx>)>>,
|
||||
$($(#[$attr])* $name: RefCell<QueryMap<queries::$name<$tcx>>>,)*
|
||||
$($(#[$attr])* $name: RefCell<QueryMap<$tcx, queries::$name<$tcx>>>,)*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ pub use self::fold::TypeFoldable;
|
|||
|
||||
use hir::{map as hir_map, FreevarMap, TraitMap};
|
||||
use hir::def::{Def, CtorKind, ExportMap};
|
||||
use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use hir::map::DefPathData;
|
||||
use ich::StableHashingContext;
|
||||
use middle::const_val::ConstVal;
|
||||
|
@ -89,6 +89,7 @@ pub use self::maps::queries;
|
|||
pub mod adjustment;
|
||||
pub mod binding;
|
||||
pub mod cast;
|
||||
#[macro_use]
|
||||
pub mod codec;
|
||||
pub mod error;
|
||||
mod erase_regions;
|
||||
|
@ -582,7 +583,7 @@ impl<T> Slice<T> {
|
|||
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct UpvarId {
|
||||
pub var_id: hir::HirId,
|
||||
pub closure_expr_id: DefIndex,
|
||||
pub closure_expr_id: LocalDefId,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, Copy)]
|
||||
|
|
|
@ -29,7 +29,7 @@ use rustc::middle::dataflow::BitwiseOperator;
|
|||
use rustc::middle::dataflow::DataFlowOperator;
|
||||
use rustc::middle::dataflow::KillFrom;
|
||||
use rustc::middle::borrowck::BorrowCheckResult;
|
||||
use rustc::hir::def_id::{DefId, DefIndex};
|
||||
use rustc::hir::def_id::{DefId, LocalDefId};
|
||||
use rustc::middle::expr_use_visitor as euv;
|
||||
use rustc::middle::mem_categorization as mc;
|
||||
use rustc::middle::mem_categorization::Categorization;
|
||||
|
@ -376,9 +376,9 @@ pub enum LoanPathElem<'tcx> {
|
|||
LpInterior(Option<DefId>, InteriorKind),
|
||||
}
|
||||
|
||||
fn closure_to_block(closure_id: DefIndex,
|
||||
fn closure_to_block(closure_id: LocalDefId,
|
||||
tcx: TyCtxt) -> ast::NodeId {
|
||||
let closure_id = tcx.hir.def_index_to_node_id(closure_id);
|
||||
let closure_id = tcx.hir.local_def_id_to_node_id(closure_id);
|
||||
match tcx.hir.get(closure_id) {
|
||||
hir_map::NodeExpr(expr) => match expr.node {
|
||||
hir::ExprClosure(.., body_id, _, _) => {
|
||||
|
@ -1101,7 +1101,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
|||
} else {
|
||||
"consider changing this closure to take self by mutable reference"
|
||||
};
|
||||
let node_id = self.tcx.hir.def_index_to_node_id(id);
|
||||
let node_id = self.tcx.hir.local_def_id_to_node_id(id);
|
||||
let help_span = self.tcx.hir.span(node_id);
|
||||
self.cannot_act_on_capture_in_sharable_fn(span,
|
||||
prefix,
|
||||
|
@ -1297,7 +1297,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
|||
};
|
||||
if kind == ty::ClosureKind::Fn {
|
||||
let closure_node_id =
|
||||
self.tcx.hir.def_index_to_node_id(upvar_id.closure_expr_id);
|
||||
self.tcx.hir.local_def_id_to_node_id(upvar_id.closure_expr_id);
|
||||
db.span_help(self.tcx.hir.span(closure_node_id),
|
||||
"consider changing this closure to take \
|
||||
self by mutable reference");
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
//! The data that we will serialize and deserialize.
|
||||
|
||||
use rustc::dep_graph::{WorkProduct, WorkProductId};
|
||||
use rustc::hir::def_id::DefIndex;
|
||||
use rustc::hir::map::DefPathHash;
|
||||
use rustc::middle::cstore::EncodedMetadataHash;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
@ -58,5 +57,5 @@ pub struct SerializedMetadataHashes {
|
|||
/// is only populated if -Z query-dep-graph is specified. It will be
|
||||
/// empty otherwise. Importing crates are perfectly happy with just having
|
||||
/// the DefIndex.
|
||||
pub index_map: FxHashMap<DefIndex, DefPathHash>
|
||||
pub index_map: FxHashMap<u32, DefPathHash>
|
||||
}
|
||||
|
|
|
@ -53,19 +53,25 @@ pub fn write_file_header<W: io::Write>(stream: &mut W) -> io::Result<()> {
|
|||
|
||||
/// Reads the contents of a file with a file header as defined in this module.
|
||||
///
|
||||
/// - Returns `Ok(Some(data))` if the file existed and was generated by a
|
||||
/// - Returns `Ok(Some(data, pos))` if the file existed and was generated by a
|
||||
/// compatible compiler version. `data` is the entire contents of the file
|
||||
/// *after* the header.
|
||||
/// and `pos` points to the first byte after the header.
|
||||
/// - Returns `Ok(None)` if the file did not exist or was generated by an
|
||||
/// incompatible version of the compiler.
|
||||
/// - Returns `Err(..)` if some kind of IO error occurred while reading the
|
||||
/// file.
|
||||
pub fn read_file(sess: &Session, path: &Path) -> io::Result<Option<Vec<u8>>> {
|
||||
pub fn read_file(sess: &Session, path: &Path) -> io::Result<Option<(Vec<u8>, usize)>> {
|
||||
if !path.exists() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let mut file = File::open(path)?;
|
||||
let file_size = file.metadata()?.len() as usize;
|
||||
|
||||
let mut data = Vec::with_capacity(file_size);
|
||||
file.read_to_end(&mut data)?;
|
||||
|
||||
let mut file = io::Cursor::new(data);
|
||||
|
||||
// Check FILE_MAGIC
|
||||
{
|
||||
|
@ -107,10 +113,8 @@ pub fn read_file(sess: &Session, path: &Path) -> io::Result<Option<Vec<u8>>> {
|
|||
}
|
||||
}
|
||||
|
||||
let mut data = vec![];
|
||||
file.read_to_end(&mut data)?;
|
||||
|
||||
Ok(Some(data))
|
||||
let post_header_start_pos = file.position() as usize;
|
||||
Ok(Some((file.into_inner(), post_header_start_pos)))
|
||||
}
|
||||
|
||||
fn report_format_mismatch(sess: &Session, file: &Path, message: &str) {
|
||||
|
|
|
@ -42,9 +42,9 @@ pub fn dep_graph_tcx_init<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
|||
}
|
||||
|
||||
let work_products_path = work_products_path(tcx.sess);
|
||||
if let Some(work_products_data) = load_data(tcx.sess, &work_products_path) {
|
||||
if let Some((work_products_data, start_pos)) = load_data(tcx.sess, &work_products_path) {
|
||||
// Decode the list of work_products
|
||||
let mut work_product_decoder = Decoder::new(&work_products_data[..], 0);
|
||||
let mut work_product_decoder = Decoder::new(&work_products_data[..], start_pos);
|
||||
let work_products: Vec<SerializedWorkProduct> =
|
||||
RustcDecodable::decode(&mut work_product_decoder).unwrap_or_else(|e| {
|
||||
let msg = format!("Error decoding `work-products` from incremental \
|
||||
|
@ -77,9 +77,9 @@ pub fn dep_graph_tcx_init<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
|||
}
|
||||
}
|
||||
|
||||
fn load_data(sess: &Session, path: &Path) -> Option<Vec<u8>> {
|
||||
fn load_data(sess: &Session, path: &Path) -> Option<(Vec<u8>, usize)> {
|
||||
match file_format::read_file(sess, path) {
|
||||
Ok(Some(data)) => return Some(data),
|
||||
Ok(Some(data_and_pos)) => return Some(data_and_pos),
|
||||
Ok(None) => {
|
||||
// The file either didn't exist or was produced by an incompatible
|
||||
// compiler version. Neither is an error.
|
||||
|
@ -126,8 +126,8 @@ pub fn load_prev_metadata_hashes(tcx: TyCtxt) -> DefIdMap<Fingerprint> {
|
|||
|
||||
debug!("load_prev_metadata_hashes() - File: {}", file_path.display());
|
||||
|
||||
let data = match file_format::read_file(tcx.sess, &file_path) {
|
||||
Ok(Some(data)) => data,
|
||||
let (data, start_pos) = match file_format::read_file(tcx.sess, &file_path) {
|
||||
Ok(Some(data_and_pos)) => data_and_pos,
|
||||
Ok(None) => {
|
||||
debug!("load_prev_metadata_hashes() - File produced by incompatible \
|
||||
compiler version: {}", file_path.display());
|
||||
|
@ -141,7 +141,7 @@ pub fn load_prev_metadata_hashes(tcx: TyCtxt) -> DefIdMap<Fingerprint> {
|
|||
};
|
||||
|
||||
debug!("load_prev_metadata_hashes() - Decoding hashes");
|
||||
let mut decoder = Decoder::new(&data, 0);
|
||||
let mut decoder = Decoder::new(&data, start_pos);
|
||||
let _ = Svh::decode(&mut decoder).unwrap();
|
||||
let serialized_hashes = SerializedMetadataHashes::decode(&mut decoder).unwrap();
|
||||
|
||||
|
@ -171,8 +171,8 @@ pub fn load_dep_graph(sess: &Session) -> PreviousDepGraph {
|
|||
return empty
|
||||
}
|
||||
|
||||
if let Some(bytes) = load_data(sess, &dep_graph_path(sess)) {
|
||||
let mut decoder = Decoder::new(&bytes, 0);
|
||||
if let Some((bytes, start_pos)) = load_data(sess, &dep_graph_path(sess)) {
|
||||
let mut decoder = Decoder::new(&bytes, start_pos);
|
||||
let prev_commandline_args_hash = u64::decode(&mut decoder)
|
||||
.expect("Error reading commandline arg hash from cached dep-graph");
|
||||
|
||||
|
@ -184,6 +184,10 @@ pub fn load_dep_graph(sess: &Session) -> PreviousDepGraph {
|
|||
// We can't reuse the cache, purge it.
|
||||
debug!("load_dep_graph_new: differing commandline arg hashes");
|
||||
|
||||
delete_all_session_dir_contents(sess)
|
||||
.expect("Failed to delete invalidated incr. comp. session \
|
||||
directory contents.");
|
||||
|
||||
// No need to do any further work
|
||||
return empty
|
||||
}
|
||||
|
@ -198,12 +202,13 @@ pub fn load_dep_graph(sess: &Session) -> PreviousDepGraph {
|
|||
}
|
||||
|
||||
pub fn load_query_result_cache<'sess>(sess: &'sess Session) -> OnDiskCache<'sess> {
|
||||
if sess.opts.incremental.is_none() {
|
||||
if sess.opts.incremental.is_none() ||
|
||||
!sess.opts.debugging_opts.incremental_queries {
|
||||
return OnDiskCache::new_empty(sess.codemap());
|
||||
}
|
||||
|
||||
if let Some(bytes) = load_data(sess, &query_cache_path(sess)) {
|
||||
OnDiskCache::new(sess, &bytes[..])
|
||||
if let Some((bytes, start_pos)) = load_data(sess, &query_cache_path(sess)) {
|
||||
OnDiskCache::new(sess, bytes, start_pos)
|
||||
} else {
|
||||
OnDiskCache::new_empty(sess.codemap())
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
use rustc::dep_graph::{DepGraph, DepKind};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::def_id::{DefId, DefIndex};
|
||||
use rustc::hir::svh::Svh;
|
||||
use rustc::ich::Fingerprint;
|
||||
use rustc::middle::cstore::EncodedMetadataHashes;
|
||||
|
@ -69,11 +69,13 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|e| encode_query_cache(tcx, e));
|
||||
});
|
||||
|
||||
time(sess.time_passes(), "persist dep-graph", || {
|
||||
save_in(sess,
|
||||
dep_graph_path(sess),
|
||||
|e| encode_dep_graph(tcx, e));
|
||||
});
|
||||
if tcx.sess.opts.debugging_opts.incremental_queries {
|
||||
time(sess.time_passes(), "persist dep-graph", || {
|
||||
save_in(sess,
|
||||
dep_graph_path(sess),
|
||||
|e| encode_dep_graph(tcx, e));
|
||||
});
|
||||
}
|
||||
|
||||
dirty_clean::check_dirty_clean_annotations(tcx);
|
||||
dirty_clean::check_dirty_clean_metadata(tcx,
|
||||
|
@ -268,11 +270,11 @@ fn encode_metadata_hashes(tcx: TyCtxt,
|
|||
|
||||
if tcx.sess.opts.debugging_opts.query_dep_graph {
|
||||
for serialized_hash in &serialized_hashes.entry_hashes {
|
||||
let def_id = DefId::local(serialized_hash.def_index);
|
||||
let def_id = DefId::local(DefIndex::from_u32(serialized_hash.def_index));
|
||||
|
||||
// Store entry in the index_map
|
||||
let def_path_hash = tcx.def_path_hash(def_id);
|
||||
serialized_hashes.index_map.insert(def_id.index, def_path_hash);
|
||||
serialized_hashes.index_map.insert(def_id.index.as_u32(), def_path_hash);
|
||||
|
||||
// Record hash in current_metadata_hashes
|
||||
current_metadata_hashes.insert(def_id, serialized_hash.hash);
|
||||
|
|
|
@ -15,8 +15,6 @@ use schema::*;
|
|||
|
||||
use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
|
||||
use rustc::hir;
|
||||
|
||||
use rustc::middle::const_val::ByteArray;
|
||||
use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
|
||||
ExternBodyNestedBodies};
|
||||
use rustc::hir::def::{self, Def, CtorKind};
|
||||
|
@ -25,19 +23,15 @@ use rustc::ich::Fingerprint;
|
|||
use rustc::middle::lang_items;
|
||||
use rustc::session::Session;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::codec::{self as ty_codec, TyDecoder};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::codec::TyDecoder;
|
||||
use rustc::util::nodemap::DefIdSet;
|
||||
|
||||
use rustc::mir::Mir;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::cell::Ref;
|
||||
use std::collections::BTreeMap;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use std::str;
|
||||
use std::u32;
|
||||
|
||||
use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
|
||||
|
@ -174,57 +168,23 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! decoder_methods {
|
||||
($($name:ident -> $ty:ty;)*) => {
|
||||
$(fn $name(&mut self) -> Result<$ty, Self::Error> {
|
||||
self.opaque.$name()
|
||||
})*
|
||||
}
|
||||
}
|
||||
|
||||
impl<'doc, 'tcx> Decoder for DecodeContext<'doc, 'tcx> {
|
||||
type Error = <opaque::Decoder<'doc> as Decoder>::Error;
|
||||
|
||||
decoder_methods! {
|
||||
read_nil -> ();
|
||||
|
||||
read_u128 -> u128;
|
||||
read_u64 -> u64;
|
||||
read_u32 -> u32;
|
||||
read_u16 -> u16;
|
||||
read_u8 -> u8;
|
||||
read_usize -> usize;
|
||||
|
||||
read_i128 -> i128;
|
||||
read_i64 -> i64;
|
||||
read_i32 -> i32;
|
||||
read_i16 -> i16;
|
||||
read_i8 -> i8;
|
||||
read_isize -> isize;
|
||||
|
||||
read_bool -> bool;
|
||||
read_f64 -> f64;
|
||||
read_f32 -> f32;
|
||||
read_char -> char;
|
||||
read_str -> Cow<str>;
|
||||
}
|
||||
|
||||
fn error(&mut self, err: &str) -> Self::Error {
|
||||
self.opaque.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a, 'tcx: 'a> TyDecoder<'a, 'tcx> for DecodeContext<'a, 'tcx> {
|
||||
|
||||
#[inline]
|
||||
fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
self.tcx.expect("missing TyCtxt in DecodeContext")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn peek_byte(&self) -> u8 {
|
||||
self.opaque.data[self.opaque.position()]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn position(&self) -> usize {
|
||||
self.opaque.position()
|
||||
}
|
||||
|
||||
fn cached_ty_for_shorthand<F>(&mut self,
|
||||
shorthand: usize,
|
||||
or_insert_with: F)
|
||||
|
@ -286,14 +246,24 @@ impl<'a, 'tcx, T> SpecializedDecoder<LazySeq<T>> for DecodeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<CrateNum> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
|
||||
let cnum = CrateNum::from_u32(u32::decode(self)?);
|
||||
if cnum == LOCAL_CRATE {
|
||||
Ok(self.cdata().cnum)
|
||||
} else {
|
||||
Ok(self.cdata().cnum_map.borrow()[cnum])
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<DefId> for DecodeContext<'a, 'tcx> {
|
||||
#[inline]
|
||||
fn specialized_decode(&mut self) -> Result<DefId, Self::Error> {
|
||||
let krate = CrateNum::decode(self)?;
|
||||
let index = DefIndex::decode(self)?;
|
||||
|
||||
Ok(DefId {
|
||||
krate,
|
||||
index,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<DefIndex> for DecodeContext<'a, 'tcx> {
|
||||
#[inline]
|
||||
fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
|
||||
Ok(DefIndex::from_u32(self.read_u32()?))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,65 +327,7 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME(#36588) These impls are horribly unsound as they allow
|
||||
// the caller to pick any lifetime for 'tcx, including 'static,
|
||||
// by using the unspecialized proxies to them.
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<Ty<'tcx>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<Ty<'tcx>, Self::Error> {
|
||||
ty_codec::decode_ty(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<ty::GenericPredicates<'tcx>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<ty::GenericPredicates<'tcx>, Self::Error> {
|
||||
ty_codec::decode_predicates(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<&'tcx Substs<'tcx>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> {
|
||||
ty_codec::decode_substs(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<ty::Region<'tcx>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
|
||||
ty_codec::decode_region(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice<Ty<'tcx>>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<&'tcx ty::Slice<Ty<'tcx>>, Self::Error> {
|
||||
ty_codec::decode_ty_slice(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::AdtDef> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
|
||||
ty_codec::decode_adt_def(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>
|
||||
for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self)
|
||||
-> Result<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, Self::Error> {
|
||||
ty_codec::decode_existential_predicate_slice(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<ByteArray<'tcx>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<ByteArray<'tcx>, Self::Error> {
|
||||
ty_codec::decode_byte_array(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Const<'tcx>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
|
||||
ty_codec::decode_const(self)
|
||||
}
|
||||
}
|
||||
implement_ty_decoder!( DecodeContext<'a, 'tcx> );
|
||||
|
||||
impl<'a, 'tcx> MetadataBlob {
|
||||
pub fn is_compatible(&self) -> bool {
|
||||
|
|
|
@ -116,6 +116,33 @@ impl<'a, 'tcx, T> SpecializedEncoder<LazySeq<T>> for EncodeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedEncoder<CrateNum> for EncodeContext<'a, 'tcx> {
|
||||
#[inline]
|
||||
fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> {
|
||||
self.emit_u32(cnum.as_u32())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedEncoder<DefId> for EncodeContext<'a, 'tcx> {
|
||||
#[inline]
|
||||
fn specialized_encode(&mut self, def_id: &DefId) -> Result<(), Self::Error> {
|
||||
let DefId {
|
||||
krate,
|
||||
index,
|
||||
} = *def_id;
|
||||
|
||||
krate.encode(self)?;
|
||||
index.encode(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedEncoder<DefIndex> for EncodeContext<'a, 'tcx> {
|
||||
#[inline]
|
||||
fn specialized_encode(&mut self, def_index: &DefIndex) -> Result<(), Self::Error> {
|
||||
self.emit_u32(def_index.as_u32())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'a, 'tcx> {
|
||||
fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
|
||||
ty_codec::encode_with_shorthand(self, ty, |ecx| &mut ecx.type_shorthands)
|
||||
|
@ -213,7 +240,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
|
||||
if let Some(fingerprint) = fingerprint {
|
||||
this.metadata_hashes.hashes.push(EncodedMetadataHash {
|
||||
def_index,
|
||||
def_index: def_index.as_u32(),
|
||||
hash: fingerprint,
|
||||
})
|
||||
}
|
||||
|
@ -395,7 +422,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
let total_bytes = self.position();
|
||||
|
||||
self.metadata_hashes.hashes.push(EncodedMetadataHash {
|
||||
def_index: global_metadata_def_index(GlobalMetaDataKind::Krate),
|
||||
def_index: global_metadata_def_index(GlobalMetaDataKind::Krate).as_u32(),
|
||||
hash: Fingerprint::from_smaller_hash(link_meta.crate_hash.as_u64())
|
||||
});
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
|||
let (fingerprint, ecx) = entry_builder.finish();
|
||||
if let Some(hash) = fingerprint {
|
||||
ecx.metadata_hashes.hashes.push(EncodedMetadataHash {
|
||||
def_index: id.index,
|
||||
def_index: id.index.as_u32(),
|
||||
hash,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use build;
|
|||
use hair::cx::Cx;
|
||||
use hair::LintLevel;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::def_id::{DefId, LocalDefId};
|
||||
use rustc::middle::region;
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::visit::{MutVisitor, TyContext};
|
||||
|
@ -422,10 +422,10 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
|||
freevars.iter().map(|fv| {
|
||||
let var_id = fv.var_id();
|
||||
let var_hir_id = tcx.hir.node_to_hir_id(var_id);
|
||||
let closure_expr_id = tcx.hir.local_def_id(fn_id).index;
|
||||
let closure_expr_id = tcx.hir.local_def_id(fn_id);
|
||||
let capture = hir.tables().upvar_capture(ty::UpvarId {
|
||||
var_id: var_hir_id,
|
||||
closure_expr_id,
|
||||
closure_expr_id: LocalDefId::from_def_id(closure_expr_id),
|
||||
});
|
||||
let by_ref = match capture {
|
||||
ty::UpvarCapture::ByValue => false,
|
||||
|
|
|
@ -20,6 +20,7 @@ use rustc::ty::{self, AdtKind, VariantDef, Ty};
|
|||
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
|
||||
use rustc::ty::cast::CastKind as TyCastKind;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::LocalDefId;
|
||||
|
||||
impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
type Output = Expr<'tcx>;
|
||||
|
@ -783,7 +784,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
// point we need an implicit deref
|
||||
let upvar_id = ty::UpvarId {
|
||||
var_id: var_hir_id,
|
||||
closure_expr_id: closure_def_id.index,
|
||||
closure_expr_id: LocalDefId::from_def_id(closure_def_id),
|
||||
};
|
||||
match cx.tables().upvar_capture(upvar_id) {
|
||||
ty::UpvarCapture::ByValue => field_kind,
|
||||
|
@ -897,7 +898,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
let var_hir_id = cx.tcx.hir.node_to_hir_id(freevar.var_id());
|
||||
let upvar_id = ty::UpvarId {
|
||||
var_id: var_hir_id,
|
||||
closure_expr_id: cx.tcx.hir.local_def_id(closure_expr.id).index,
|
||||
closure_expr_id: cx.tcx.hir.local_def_id(closure_expr.id).to_local(),
|
||||
};
|
||||
let upvar_capture = cx.tables().upvar_capture(upvar_id);
|
||||
let temp_lifetime = cx.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id);
|
||||
|
|
|
@ -50,7 +50,7 @@ use rustc::infer::UpvarRegion;
|
|||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefIndex;
|
||||
use rustc::hir::def_id::LocalDefId;
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
|
||||
|
@ -128,7 +128,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
for freevar in freevars {
|
||||
let upvar_id = ty::UpvarId {
|
||||
var_id: self.tcx.hir.node_to_hir_id(freevar.var_id()),
|
||||
closure_expr_id: closure_def_id.index,
|
||||
closure_expr_id: LocalDefId::from_def_id(closure_def_id),
|
||||
};
|
||||
debug!("seed upvar_id {:?}", upvar_id);
|
||||
|
||||
|
@ -167,7 +167,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// Write the adjusted values back into the main tables.
|
||||
if infer_kind {
|
||||
if let Some(kind) = delegate.adjust_closure_kinds
|
||||
.remove(&closure_def_id.index) {
|
||||
.remove(&closure_def_id.to_local()) {
|
||||
self.tables
|
||||
.borrow_mut()
|
||||
.closure_kinds_mut()
|
||||
|
@ -231,7 +231,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// This may change if abstract return types of some sort are
|
||||
// implemented.
|
||||
let tcx = self.tcx;
|
||||
let closure_def_index = tcx.hir.local_def_id(closure_id).index;
|
||||
let closure_def_index = tcx.hir.local_def_id(closure_id);
|
||||
|
||||
tcx.with_freevars(closure_id, |freevars| {
|
||||
freevars.iter().map(|freevar| {
|
||||
|
@ -240,7 +240,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
let freevar_ty = self.node_ty(var_hir_id);
|
||||
let upvar_id = ty::UpvarId {
|
||||
var_id: var_hir_id,
|
||||
closure_expr_id: closure_def_index,
|
||||
closure_expr_id: LocalDefId::from_def_id(closure_def_index),
|
||||
};
|
||||
let capture = self.tables.borrow().upvar_capture(upvar_id);
|
||||
|
||||
|
@ -263,7 +263,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
struct InferBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
||||
adjust_closure_kinds: FxHashMap<DefIndex, (ty::ClosureKind, Option<(Span, ast::Name)>)>,
|
||||
adjust_closure_kinds: FxHashMap<LocalDefId, (ty::ClosureKind, Option<(Span, ast::Name)>)>,
|
||||
adjust_upvar_captures: ty::UpvarCaptureMap<'tcx>,
|
||||
}
|
||||
|
||||
|
@ -485,7 +485,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn adjust_closure_kind(&mut self,
|
||||
closure_id: DefIndex,
|
||||
closure_id: LocalDefId,
|
||||
new_kind: ty::ClosureKind,
|
||||
upvar_span: Span,
|
||||
var_name: ast::Name) {
|
||||
|
@ -494,7 +494,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
|
|||
|
||||
let closure_kind = self.adjust_closure_kinds.get(&closure_id).cloned()
|
||||
.or_else(|| {
|
||||
let closure_id = self.fcx.tcx.hir.def_index_to_hir_id(closure_id);
|
||||
let closure_id = self.fcx.tcx.hir.local_def_id_to_hir_id(closure_id);
|
||||
self.fcx.tables.borrow().closure_kinds().get(closure_id).cloned()
|
||||
});
|
||||
|
||||
|
|
|
@ -1388,6 +1388,7 @@ actual:\n\
|
|||
if let Some(ref incremental_dir) = self.props.incremental_dir {
|
||||
rustc.args(&["-Z", &format!("incremental={}", incremental_dir.display())]);
|
||||
rustc.args(&["-Z", "incremental-verify-ich"]);
|
||||
rustc.args(&["-Z", "incremental-queries"]);
|
||||
}
|
||||
|
||||
match self.config.mode {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue