mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-27 22:34:14 +00:00
Auto merge of #45867 - michaelwoerister:check-ich-stability, r=nikomatsakis
incr.comp.: Verify stability of incr. comp. hashes and clean up various other things. The main contribution of this PR is that it adds the `-Z incremental-verify-ich` functionality. Normally, when the red-green tracking system determines that a certain query result has not changed, it does not re-compute the incr. comp. hash (ICH) for that query result because that hash is already known. `-Z incremental-verify-ich` tells the compiler to re-hash the query result and compare the new hash against the cached hash. This is a rather thorough way of - testing hashing implementation stability, - finding missing `[input]` annotations on `DepNodes`, and - finding missing read-edges, since both a missed read and a missing `[input]` annotation can lead to something being marked as green instead of red and thus will have a different hash than it should have. Case in point, implementing this verification logic and activating it for all `src/test/incremental` tests has revealed several such oversights, all of which are fixed in this PR. r? @nikomatsakis
This commit is contained in:
commit
da3fbe750f
@ -459,10 +459,6 @@ define_dep_nodes!( <'tcx>
|
||||
// Represents metadata from an extern crate.
|
||||
[input] CrateMetadata(CrateNum),
|
||||
|
||||
// Represents some artifact that we save to disk. Note that these
|
||||
// do not have a def-id as part of their identifier.
|
||||
[] WorkProduct(WorkProductId),
|
||||
|
||||
// Represents different phases in the compiler.
|
||||
[] RegionScopeTree(DefId),
|
||||
[eval_always] Coherence,
|
||||
@ -537,38 +533,19 @@ define_dep_nodes!( <'tcx>
|
||||
// The set of impls for a given trait.
|
||||
[] TraitImpls(DefId),
|
||||
|
||||
[] AllLocalTraitImpls,
|
||||
[input] AllLocalTraitImpls,
|
||||
|
||||
// Trait selection cache is a little funny. Given a trait
|
||||
// reference like `Foo: SomeTrait<Bar>`, there could be
|
||||
// arbitrarily many def-ids to map on in there (e.g., `Foo`,
|
||||
// `SomeTrait`, `Bar`). We could have a vector of them, but it
|
||||
// requires heap-allocation, and trait sel in general can be a
|
||||
// surprisingly hot path. So instead we pick two def-ids: the
|
||||
// trait def-id, and the first def-id in the input types. If there
|
||||
// is no def-id in the input types, then we use the trait def-id
|
||||
// again. So for example:
|
||||
//
|
||||
// - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
|
||||
// - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
|
||||
// - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
|
||||
// - `Vec<i32>: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }`
|
||||
// - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }`
|
||||
// - `Foo: Trait<Bar>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
|
||||
// - `Foo: Trait<i32>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
|
||||
// - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
|
||||
// - `i32: Trait<Foo>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
|
||||
//
|
||||
// You can see that we map many trait refs to the same
|
||||
// trait-select node. This is not a problem, it just means
|
||||
// imprecision in our dep-graph tracking. The important thing is
|
||||
// that for any given trait-ref, we always map to the **same**
|
||||
// trait-select node.
|
||||
[anon] TraitSelect,
|
||||
|
||||
[] ParamEnv(DefId),
|
||||
[] DescribeDef(DefId),
|
||||
[] DefSpan(DefId),
|
||||
|
||||
// FIXME(mw): DefSpans are not really inputs since they are derived from
|
||||
// HIR. But at the moment HIR hashing still contains some hacks that allow
|
||||
// to make type debuginfo to be source location independent. Declaring
|
||||
// DefSpan an input makes sure that changes to these are always detected
|
||||
// regardless of HIR hashing.
|
||||
[input] DefSpan(DefId),
|
||||
[] LookupStability(DefId),
|
||||
[] LookupDeprecationEntry(DefId),
|
||||
[] ItemBodyNestedBodies(DefId),
|
||||
@ -588,7 +565,7 @@ define_dep_nodes!( <'tcx>
|
||||
[eval_always] LintLevels,
|
||||
[] Specializes { impl1: DefId, impl2: DefId },
|
||||
[input] InScopeTraits(DefIndex),
|
||||
[] ModuleExports(DefId),
|
||||
[input] ModuleExports(DefId),
|
||||
[] IsSanitizerRuntime(CrateNum),
|
||||
[] IsProfilerRuntime(CrateNum),
|
||||
[] GetPanicStrategy(CrateNum),
|
||||
@ -598,9 +575,9 @@ define_dep_nodes!( <'tcx>
|
||||
[] NativeLibraries(CrateNum),
|
||||
[] PluginRegistrarFn(CrateNum),
|
||||
[] DeriveRegistrarFn(CrateNum),
|
||||
[] CrateDisambiguator(CrateNum),
|
||||
[] CrateHash(CrateNum),
|
||||
[] OriginalCrateName(CrateNum),
|
||||
[input] CrateDisambiguator(CrateNum),
|
||||
[input] CrateHash(CrateNum),
|
||||
[input] OriginalCrateName(CrateNum),
|
||||
|
||||
[] ImplementationsOfTrait { krate: CrateNum, trait_id: DefId },
|
||||
[] AllTraitImplementations(CrateNum),
|
||||
@ -608,27 +585,27 @@ define_dep_nodes!( <'tcx>
|
||||
[] IsDllimportForeignItem(DefId),
|
||||
[] IsStaticallyIncludedForeignItem(DefId),
|
||||
[] NativeLibraryKind(DefId),
|
||||
[] LinkArgs,
|
||||
[input] LinkArgs,
|
||||
|
||||
[] NamedRegion(DefIndex),
|
||||
[] IsLateBound(DefIndex),
|
||||
[] ObjectLifetimeDefaults(DefIndex),
|
||||
[input] NamedRegion(DefIndex),
|
||||
[input] IsLateBound(DefIndex),
|
||||
[input] ObjectLifetimeDefaults(DefIndex),
|
||||
|
||||
[] Visibility(DefId),
|
||||
[] DepKind(CrateNum),
|
||||
[] CrateName(CrateNum),
|
||||
[input] CrateName(CrateNum),
|
||||
[] ItemChildren(DefId),
|
||||
[] ExternModStmtCnum(DefId),
|
||||
[] GetLangItems,
|
||||
[input] GetLangItems,
|
||||
[] DefinedLangItems(CrateNum),
|
||||
[] MissingLangItems(CrateNum),
|
||||
[] ExternConstBody(DefId),
|
||||
[] VisibleParentMap,
|
||||
[] MissingExternCrateItem(CrateNum),
|
||||
[] UsedCrateSource(CrateNum),
|
||||
[] PostorderCnums,
|
||||
[] HasCloneClosures(CrateNum),
|
||||
[] HasCopyClosures(CrateNum),
|
||||
[input] PostorderCnums,
|
||||
[input] HasCloneClosures(CrateNum),
|
||||
[input] HasCopyClosures(CrateNum),
|
||||
|
||||
// This query is not expected to have inputs -- as a result, it's
|
||||
// not a good candidate for "replay" because it's essentially a
|
||||
@ -638,11 +615,11 @@ define_dep_nodes!( <'tcx>
|
||||
// may save a bit of time.
|
||||
[anon] EraseRegionsTy { ty: Ty<'tcx> },
|
||||
|
||||
[] Freevars(DefId),
|
||||
[] MaybeUnusedTraitImport(DefId),
|
||||
[input] Freevars(DefId),
|
||||
[input] MaybeUnusedTraitImport(DefId),
|
||||
[] MaybeUnusedExternCrates,
|
||||
[] StabilityIndex,
|
||||
[] AllCrateNums,
|
||||
[input] AllCrateNums,
|
||||
[] ExportedSymbols(CrateNum),
|
||||
[eval_always] CollectAndPartitionTranslationItems,
|
||||
[] ExportName(DefId),
|
||||
@ -650,7 +627,7 @@ define_dep_nodes!( <'tcx>
|
||||
[] IsTranslatedFunction(DefId),
|
||||
[] CodegenUnit(InternedString),
|
||||
[] CompileCodegenUnit(InternedString),
|
||||
[] OutputFilenames,
|
||||
[input] OutputFilenames,
|
||||
[anon] NormalizeTy,
|
||||
// We use this for most things when incr. comp. is turned off.
|
||||
[] Null,
|
||||
@ -800,13 +777,6 @@ impl WorkProductId {
|
||||
hash: fingerprint
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_dep_node(self) -> DepNode {
|
||||
DepNode {
|
||||
kind: DepKind::WorkProduct,
|
||||
hash: self.hash,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct ::dep_graph::WorkProductId {
|
||||
|
@ -511,60 +511,67 @@ impl DepGraph {
|
||||
return None
|
||||
}
|
||||
None => {
|
||||
if dep_dep_node.kind.is_input() {
|
||||
// This input does not exist anymore.
|
||||
debug_assert!(dep_dep_node.extract_def_id(tcx).is_none(),
|
||||
"Encountered input {:?} without color",
|
||||
dep_dep_node);
|
||||
debug!("try_mark_green({:?}) - END - dependency {:?} \
|
||||
was deleted input", dep_node, dep_dep_node);
|
||||
return None;
|
||||
// We don't know the state of this dependency. If it isn't
|
||||
// an input node, let's try to mark it green recursively.
|
||||
if !dep_dep_node.kind.is_input() {
|
||||
debug!("try_mark_green({:?}) --- state of dependency {:?} \
|
||||
is unknown, trying to mark it green", dep_node,
|
||||
dep_dep_node);
|
||||
|
||||
if let Some(node_index) = self.try_mark_green(tcx, dep_dep_node) {
|
||||
debug!("try_mark_green({:?}) --- managed to MARK \
|
||||
dependency {:?} as green", dep_node, dep_dep_node);
|
||||
current_deps.push(node_index);
|
||||
continue;
|
||||
}
|
||||
} else if cfg!(debug_assertions) {
|
||||
match dep_dep_node.kind {
|
||||
DepKind::Hir |
|
||||
DepKind::HirBody |
|
||||
DepKind::CrateMetadata => {
|
||||
assert!(dep_dep_node.extract_def_id(tcx).is_none(),
|
||||
"Input {:?} should have been pre-allocated but wasn't.",
|
||||
dep_dep_node);
|
||||
}
|
||||
_ => {
|
||||
// For other kinds of inputs it's OK to be
|
||||
// forced.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug!("try_mark_green({:?}) --- state of dependency {:?} \
|
||||
is unknown, trying to mark it green", dep_node,
|
||||
dep_dep_node);
|
||||
|
||||
// We don't know the state of this dependency. Let's try to
|
||||
// mark it green.
|
||||
if let Some(node_index) = self.try_mark_green(tcx, dep_dep_node) {
|
||||
debug!("try_mark_green({:?}) --- managed to MARK \
|
||||
dependency {:?} as green", dep_node, dep_dep_node);
|
||||
current_deps.push(node_index);
|
||||
} else {
|
||||
// We failed to mark it green, so we try to force the query.
|
||||
debug!("try_mark_green({:?}) --- trying to force \
|
||||
dependency {:?}", dep_node, dep_dep_node);
|
||||
if ::ty::maps::force_from_dep_node(tcx, dep_dep_node) {
|
||||
let dep_dep_node_color = data.colors
|
||||
.borrow()
|
||||
.get(dep_dep_node)
|
||||
.cloned();
|
||||
match dep_dep_node_color {
|
||||
Some(DepNodeColor::Green(node_index)) => {
|
||||
debug!("try_mark_green({:?}) --- managed to \
|
||||
FORCE dependency {:?} to green",
|
||||
dep_node, dep_dep_node);
|
||||
current_deps.push(node_index);
|
||||
}
|
||||
Some(DepNodeColor::Red) => {
|
||||
debug!("try_mark_green({:?}) - END - \
|
||||
dependency {:?} was red after forcing",
|
||||
dep_node,
|
||||
dep_dep_node);
|
||||
return None
|
||||
}
|
||||
None => {
|
||||
bug!("try_mark_green() - Forcing the DepNode \
|
||||
should have set its color")
|
||||
}
|
||||
// We failed to mark it green, so we try to force the query.
|
||||
debug!("try_mark_green({:?}) --- trying to force \
|
||||
dependency {:?}", dep_node, dep_dep_node);
|
||||
if ::ty::maps::force_from_dep_node(tcx, dep_dep_node) {
|
||||
let dep_dep_node_color = data.colors
|
||||
.borrow()
|
||||
.get(dep_dep_node)
|
||||
.cloned();
|
||||
match dep_dep_node_color {
|
||||
Some(DepNodeColor::Green(node_index)) => {
|
||||
debug!("try_mark_green({:?}) --- managed to \
|
||||
FORCE dependency {:?} to green",
|
||||
dep_node, dep_dep_node);
|
||||
current_deps.push(node_index);
|
||||
}
|
||||
Some(DepNodeColor::Red) => {
|
||||
debug!("try_mark_green({:?}) - END - \
|
||||
dependency {:?} was red after forcing",
|
||||
dep_node,
|
||||
dep_dep_node);
|
||||
return None
|
||||
}
|
||||
None => {
|
||||
bug!("try_mark_green() - Forcing the DepNode \
|
||||
should have set its color")
|
||||
}
|
||||
} else {
|
||||
// The DepNode could not be forced.
|
||||
debug!("try_mark_green({:?}) - END - dependency {:?} \
|
||||
could not be forced", dep_node, dep_dep_node);
|
||||
return None
|
||||
}
|
||||
} else {
|
||||
// The DepNode could not be forced.
|
||||
debug!("try_mark_green({:?}) - END - dependency {:?} \
|
||||
could not be forced", dep_node, dep_dep_node);
|
||||
return None
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -777,7 +784,30 @@ impl CurrentDepGraph {
|
||||
read_set: _,
|
||||
reads
|
||||
} = popped_node {
|
||||
debug_assert_eq!(node, key);
|
||||
assert_eq!(node, key);
|
||||
|
||||
// If this is an input node, we expect that it either has no
|
||||
// dependencies, or that it just depends on DepKind::CrateMetadata
|
||||
// or DepKind::Krate. This happens for some "thin wrapper queries"
|
||||
// like `crate_disambiguator` which sometimes have zero deps (for
|
||||
// when called for LOCAL_CRATE) or they depend on a CrateMetadata
|
||||
// node.
|
||||
if cfg!(debug_assertions) {
|
||||
if node.kind.is_input() && reads.len() > 0 &&
|
||||
// FIXME(mw): Special case for DefSpan until Spans are handled
|
||||
// better in general.
|
||||
node.kind != DepKind::DefSpan &&
|
||||
reads.iter().any(|&i| {
|
||||
!(self.nodes[i].kind == DepKind::CrateMetadata ||
|
||||
self.nodes[i].kind == DepKind::Krate)
|
||||
})
|
||||
{
|
||||
bug!("Input node {:?} with unexpected reads: {:?}",
|
||||
node,
|
||||
reads.iter().map(|&i| self.nodes[i]).collect::<Vec<_>>())
|
||||
}
|
||||
}
|
||||
|
||||
self.alloc_node(node, reads)
|
||||
} else {
|
||||
bug!("pop_task() - Expected regular task to be popped")
|
||||
@ -798,6 +828,8 @@ impl CurrentDepGraph {
|
||||
read_set: _,
|
||||
reads
|
||||
} = popped_node {
|
||||
debug_assert!(!kind.is_input());
|
||||
|
||||
let mut fingerprint = self.anon_id_seed;
|
||||
let mut hasher = StableHasher::new();
|
||||
|
||||
|
@ -838,7 +838,10 @@ impl<'a> LoweringContext<'a> {
|
||||
return n;
|
||||
}
|
||||
assert!(!def_id.is_local());
|
||||
let n = self.cstore.item_generics_cloned_untracked(def_id).regions.len();
|
||||
let n = self.cstore
|
||||
.item_generics_cloned_untracked(def_id, self.sess)
|
||||
.regions
|
||||
.len();
|
||||
self.type_def_lifetime_params.insert(def_id, n);
|
||||
n
|
||||
});
|
||||
|
@ -416,6 +416,12 @@ impl<'hir> Map<'hir> {
|
||||
/// if the node is a body owner, otherwise returns `None`.
|
||||
pub fn maybe_body_owned_by(&self, id: NodeId) -> Option<BodyId> {
|
||||
if let Some(entry) = self.find_entry(id) {
|
||||
if self.dep_graph.is_fully_enabled() {
|
||||
let hir_id_owner = self.node_to_hir_id(id).owner;
|
||||
let def_path_hash = self.definitions.def_path_hash(hir_id_owner);
|
||||
self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody));
|
||||
}
|
||||
|
||||
if let Some(body_id) = entry.associated_body() {
|
||||
// For item-like things and closures, the associated
|
||||
// body has its own distinct id, and that is returned
|
||||
@ -530,6 +536,12 @@ impl<'hir> Map<'hir> {
|
||||
/// from a node to the root of the ast (unless you get the same id back here
|
||||
/// that can happen if the id is not in the map itself or is just weird).
|
||||
pub fn get_parent_node(&self, id: NodeId) -> NodeId {
|
||||
if self.dep_graph.is_fully_enabled() {
|
||||
let hir_id_owner = self.node_to_hir_id(id).owner;
|
||||
let def_path_hash = self.definitions.def_path_hash(hir_id_owner);
|
||||
self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody));
|
||||
}
|
||||
|
||||
self.find_entry(id).and_then(|x| x.parent_node()).unwrap_or(id)
|
||||
}
|
||||
|
||||
|
@ -227,6 +227,8 @@ impl<'gcx> StableHashingContext<'gcx> {
|
||||
match binop {
|
||||
hir::BiAdd |
|
||||
hir::BiSub |
|
||||
hir::BiShl |
|
||||
hir::BiShr |
|
||||
hir::BiMul => self.overflow_checks_enabled,
|
||||
|
||||
hir::BiDiv |
|
||||
@ -237,8 +239,6 @@ impl<'gcx> StableHashingContext<'gcx> {
|
||||
hir::BiBitXor |
|
||||
hir::BiBitAnd |
|
||||
hir::BiBitOr |
|
||||
hir::BiShl |
|
||||
hir::BiShr |
|
||||
hir::BiEq |
|
||||
hir::BiLt |
|
||||
hir::BiLe |
|
||||
|
@ -356,33 +356,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Block {
|
||||
targeted_by_break,
|
||||
} = *self;
|
||||
|
||||
let non_item_stmts = || stmts.iter().filter(|stmt| {
|
||||
match stmt.node {
|
||||
hir::StmtDecl(ref decl, _) => {
|
||||
match decl.node {
|
||||
// If this is a declaration of a nested item, we don't
|
||||
// want to leave any trace of it in the hash value, not
|
||||
// even that it exists. Otherwise changing the position
|
||||
// of nested items would invalidate the containing item
|
||||
// even though that does not constitute a semantic
|
||||
// change.
|
||||
hir::DeclItem(_) => false,
|
||||
hir::DeclLocal(_) => true
|
||||
}
|
||||
}
|
||||
hir::StmtExpr(..) |
|
||||
hir::StmtSemi(..) => true
|
||||
}
|
||||
});
|
||||
|
||||
let count = non_item_stmts().count();
|
||||
|
||||
count.hash_stable(hcx, hasher);
|
||||
|
||||
for stmt in non_item_stmts() {
|
||||
stmt.hash_stable(hcx, hasher);
|
||||
}
|
||||
|
||||
stmts.hash_stable(hcx, hasher);
|
||||
expr.hash_stable(hcx, hasher);
|
||||
rules.hash_stable(hcx, hasher);
|
||||
span.hash_stable(hcx, hasher);
|
||||
|
@ -273,7 +273,7 @@ pub trait CrateStore {
|
||||
fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec<def::Export>;
|
||||
fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro;
|
||||
fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
|
||||
fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics;
|
||||
fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics;
|
||||
fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem;
|
||||
fn postorder_cnums_untracked(&self) -> Vec<CrateNum>;
|
||||
|
||||
@ -327,7 +327,7 @@ impl CrateStore for DummyCrateStore {
|
||||
{ bug!("crate_data_as_rc_any") }
|
||||
// item info
|
||||
fn visibility_untracked(&self, def: DefId) -> ty::Visibility { bug!("visibility") }
|
||||
fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics
|
||||
fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics
|
||||
{ bug!("item_generics_cloned") }
|
||||
|
||||
// trait/impl-item info
|
||||
|
@ -1001,8 +1001,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
&map.object_lifetime_defaults[&id]
|
||||
} else {
|
||||
let cstore = self.cstore;
|
||||
let sess = self.sess;
|
||||
self.xcrate_object_lifetime_defaults.entry(def_id).or_insert_with(|| {
|
||||
cstore.item_generics_cloned_untracked(def_id).types.into_iter().map(|def| {
|
||||
cstore.item_generics_cloned_untracked(def_id, sess)
|
||||
.types
|
||||
.into_iter()
|
||||
.map(|def| {
|
||||
def.object_lifetime_default
|
||||
}).collect()
|
||||
})
|
||||
|
@ -1046,6 +1046,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||
"print high-level information about incremental reuse (or the lack thereof)"),
|
||||
incremental_dump_hash: bool = (false, parse_bool, [UNTRACKED],
|
||||
"dump hash information in textual format to stdout"),
|
||||
incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED],
|
||||
"verify incr. comp. hashes of green query instances"),
|
||||
dump_dep_graph: bool = (false, parse_bool, [UNTRACKED],
|
||||
"dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
|
||||
query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
|
||||
|
@ -327,7 +327,8 @@ macro_rules! define_maps {
|
||||
return Self::load_from_disk_and_cache_in_memory(tcx,
|
||||
key,
|
||||
span,
|
||||
dep_node_index)
|
||||
dep_node_index,
|
||||
&dep_node)
|
||||
}
|
||||
}
|
||||
|
||||
@ -372,7 +373,8 @@ macro_rules! define_maps {
|
||||
fn load_from_disk_and_cache_in_memory(tcx: TyCtxt<'a, $tcx, 'lcx>,
|
||||
key: $K,
|
||||
span: Span,
|
||||
dep_node_index: DepNodeIndex)
|
||||
dep_node_index: DepNodeIndex,
|
||||
dep_node: &DepNode)
|
||||
-> Result<$V, CycleError<'a, $tcx>>
|
||||
{
|
||||
debug_assert!(tcx.dep_graph.is_green(dep_node_index));
|
||||
@ -390,6 +392,32 @@ macro_rules! define_maps {
|
||||
})
|
||||
})?;
|
||||
|
||||
// If -Zincremental-verify-ich is specified, re-hash results from
|
||||
// the cache and make sure that they have the expected fingerprint.
|
||||
if tcx.sess.opts.debugging_opts.incremental_verify_ich {
|
||||
use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
|
||||
use ich::Fingerprint;
|
||||
|
||||
assert!(Some(tcx.dep_graph.fingerprint_of(dep_node)) ==
|
||||
tcx.dep_graph.prev_fingerprint_of(dep_node),
|
||||
"Fingerprint for green query instance not loaded \
|
||||
from cache: {:?}", dep_node);
|
||||
|
||||
debug!("BEGIN verify_ich({:?})", dep_node);
|
||||
let mut hcx = tcx.create_stable_hashing_context();
|
||||
let mut hasher = StableHasher::new();
|
||||
|
||||
result.hash_stable(&mut hcx, &mut hasher);
|
||||
|
||||
let new_hash: Fingerprint = hasher.finish();
|
||||
debug!("END verify_ich({:?})", dep_node);
|
||||
|
||||
let old_hash = tcx.dep_graph.fingerprint_of(dep_node);
|
||||
|
||||
assert!(new_hash == old_hash, "Found unstable fingerprints \
|
||||
for {:?}", dep_node);
|
||||
}
|
||||
|
||||
if tcx.sess.opts.debugging_opts.query_dep_graph {
|
||||
tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true);
|
||||
}
|
||||
@ -693,9 +721,8 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
|
||||
DepKind::EraseRegionsTy |
|
||||
DepKind::NormalizeTy |
|
||||
|
||||
// These are just odd
|
||||
DepKind::Null |
|
||||
DepKind::WorkProduct => {
|
||||
// This one should never occur in this context
|
||||
DepKind::Null => {
|
||||
bug!("force_from_dep_node() - Encountered {:?}", dep_node.kind)
|
||||
}
|
||||
|
||||
|
@ -258,14 +258,15 @@ impl<'a> CrateLoader<'a> {
|
||||
let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind);
|
||||
|
||||
let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || {
|
||||
crate_root.def_path_table.decode(&metadata)
|
||||
crate_root.def_path_table.decode((&metadata, self.sess))
|
||||
});
|
||||
|
||||
let exported_symbols = crate_root.exported_symbols.decode(&metadata).collect();
|
||||
|
||||
let exported_symbols = crate_root.exported_symbols
|
||||
.decode((&metadata, self.sess))
|
||||
.collect();
|
||||
let trait_impls = crate_root
|
||||
.impls
|
||||
.decode(&metadata)
|
||||
.decode((&metadata, self.sess))
|
||||
.map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
|
||||
.collect();
|
||||
|
||||
@ -298,7 +299,7 @@ impl<'a> CrateLoader<'a> {
|
||||
let dllimports: FxHashSet<_> = cmeta
|
||||
.root
|
||||
.native_libraries
|
||||
.decode(&cmeta)
|
||||
.decode((&cmeta, self.sess))
|
||||
.filter(|lib| relevant_lib(self.sess, lib) &&
|
||||
lib.kind == cstore::NativeLibraryKind::NativeUnknown)
|
||||
.flat_map(|lib| {
|
||||
@ -685,14 +686,15 @@ impl<'a> CrateLoader<'a> {
|
||||
let mut needs_panic_runtime = attr::contains_name(&krate.attrs,
|
||||
"needs_panic_runtime");
|
||||
|
||||
let sess = self.sess;
|
||||
self.cstore.iter_crate_data(|cnum, data| {
|
||||
needs_panic_runtime = needs_panic_runtime ||
|
||||
data.needs_panic_runtime();
|
||||
if data.is_panic_runtime() {
|
||||
data.needs_panic_runtime(sess);
|
||||
if data.is_panic_runtime(sess) {
|
||||
// Inject a dependency from all #![needs_panic_runtime] to this
|
||||
// #![panic_runtime] crate.
|
||||
self.inject_dependency_if(cnum, "a panic runtime",
|
||||
&|data| data.needs_panic_runtime());
|
||||
&|data| data.needs_panic_runtime(sess));
|
||||
runtime_found = runtime_found || data.dep_kind.get() == DepKind::Explicit;
|
||||
}
|
||||
});
|
||||
@ -728,7 +730,7 @@ impl<'a> CrateLoader<'a> {
|
||||
|
||||
// Sanity check the loaded crate to ensure it is indeed a panic runtime
|
||||
// and the panic strategy is indeed what we thought it was.
|
||||
if !data.is_panic_runtime() {
|
||||
if !data.is_panic_runtime(self.sess) {
|
||||
self.sess.err(&format!("the crate `{}` is not a panic runtime",
|
||||
name));
|
||||
}
|
||||
@ -740,7 +742,7 @@ impl<'a> CrateLoader<'a> {
|
||||
|
||||
self.sess.injected_panic_runtime.set(Some(cnum));
|
||||
self.inject_dependency_if(cnum, "a panic runtime",
|
||||
&|data| data.needs_panic_runtime());
|
||||
&|data| data.needs_panic_runtime(self.sess));
|
||||
}
|
||||
|
||||
fn inject_sanitizer_runtime(&mut self) {
|
||||
@ -835,7 +837,7 @@ impl<'a> CrateLoader<'a> {
|
||||
PathKind::Crate, dep_kind);
|
||||
|
||||
// Sanity check the loaded crate to ensure it is indeed a sanitizer runtime
|
||||
if !data.is_sanitizer_runtime() {
|
||||
if !data.is_sanitizer_runtime(self.sess) {
|
||||
self.sess.err(&format!("the crate `{}` is not a sanitizer runtime",
|
||||
name));
|
||||
}
|
||||
@ -856,7 +858,7 @@ impl<'a> CrateLoader<'a> {
|
||||
PathKind::Crate, dep_kind);
|
||||
|
||||
// Sanity check the loaded crate to ensure it is indeed a profiler runtime
|
||||
if !data.is_profiler_runtime() {
|
||||
if !data.is_profiler_runtime(self.sess) {
|
||||
self.sess.err(&format!("the crate `profiler_builtins` is not \
|
||||
a profiler runtime"));
|
||||
}
|
||||
@ -875,7 +877,7 @@ impl<'a> CrateLoader<'a> {
|
||||
let mut needs_allocator = attr::contains_name(&krate.attrs,
|
||||
"needs_allocator");
|
||||
self.cstore.iter_crate_data(|_, data| {
|
||||
needs_allocator = needs_allocator || data.needs_allocator();
|
||||
needs_allocator = needs_allocator || data.needs_allocator(self.sess);
|
||||
});
|
||||
if !needs_allocator {
|
||||
return
|
||||
@ -997,7 +999,7 @@ impl<'a> CrateLoader<'a> {
|
||||
Some(data) => {
|
||||
// We have an allocator. We detect separately what kind it is, to allow for some
|
||||
// flexibility in misconfiguration.
|
||||
let attrs = data.get_item_attrs(CRATE_DEF_INDEX);
|
||||
let attrs = data.get_item_attrs(CRATE_DEF_INDEX, self.sess);
|
||||
let kind_interned = attr::first_attr_value_str_by_name(&attrs, "rustc_alloc_kind")
|
||||
.map(Symbol::as_str);
|
||||
let kind_str = kind_interned
|
||||
|
@ -17,7 +17,7 @@ use rustc::hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex};
|
||||
use rustc::hir::map::definitions::DefPathTable;
|
||||
use rustc::hir::svh::Svh;
|
||||
use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
|
||||
use rustc::session::CrateDisambiguator;
|
||||
use rustc::session::{Session, CrateDisambiguator};
|
||||
use rustc_back::PanicStrategy;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap};
|
||||
@ -176,8 +176,8 @@ impl CrateMetadata {
|
||||
self.root.disambiguator
|
||||
}
|
||||
|
||||
pub fn needs_allocator(&self) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
|
||||
pub fn needs_allocator(&self, sess: &Session) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
|
||||
attr::contains_name(&attrs, "needs_allocator")
|
||||
}
|
||||
|
||||
@ -189,43 +189,43 @@ impl CrateMetadata {
|
||||
self.root.has_default_lib_allocator.clone()
|
||||
}
|
||||
|
||||
pub fn is_panic_runtime(&self) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
|
||||
pub fn is_panic_runtime(&self, sess: &Session) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
|
||||
attr::contains_name(&attrs, "panic_runtime")
|
||||
}
|
||||
|
||||
pub fn needs_panic_runtime(&self) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
|
||||
pub fn needs_panic_runtime(&self, sess: &Session) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
|
||||
attr::contains_name(&attrs, "needs_panic_runtime")
|
||||
}
|
||||
|
||||
pub fn is_compiler_builtins(&self) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
|
||||
pub fn is_compiler_builtins(&self, sess: &Session) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
|
||||
attr::contains_name(&attrs, "compiler_builtins")
|
||||
}
|
||||
|
||||
pub fn is_sanitizer_runtime(&self) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
|
||||
pub fn is_sanitizer_runtime(&self, sess: &Session) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
|
||||
attr::contains_name(&attrs, "sanitizer_runtime")
|
||||
}
|
||||
|
||||
pub fn is_profiler_runtime(&self) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
|
||||
pub fn is_profiler_runtime(&self, sess: &Session) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
|
||||
attr::contains_name(&attrs, "profiler_runtime")
|
||||
}
|
||||
|
||||
pub fn is_no_builtins(&self) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
|
||||
pub fn is_no_builtins(&self, sess: &Session) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
|
||||
attr::contains_name(&attrs, "no_builtins")
|
||||
}
|
||||
|
||||
pub fn has_copy_closures(&self) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
|
||||
pub fn has_copy_closures(&self, sess: &Session) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
|
||||
attr::contains_feature_attr(&attrs, "copy_closures")
|
||||
}
|
||||
|
||||
pub fn has_clone_closures(&self) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
|
||||
pub fn has_clone_closures(&self, sess: &Session) -> bool {
|
||||
let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
|
||||
attr::contains_feature_attr(&attrs, "clone_closures")
|
||||
}
|
||||
|
||||
|
@ -99,11 +99,13 @@ impl IntoArgs for (CrateNum, DefId) {
|
||||
|
||||
provide! { <'tcx> tcx, def_id, other, cdata,
|
||||
type_of => { cdata.get_type(def_id.index, tcx) }
|
||||
generics_of => { tcx.alloc_generics(cdata.get_generics(def_id.index)) }
|
||||
generics_of => {
|
||||
tcx.alloc_generics(cdata.get_generics(def_id.index, tcx.sess))
|
||||
}
|
||||
predicates_of => { cdata.get_predicates(def_id.index, tcx) }
|
||||
super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) }
|
||||
trait_def => {
|
||||
tcx.alloc_trait_def(cdata.get_trait_def(def_id.index))
|
||||
tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx.sess))
|
||||
}
|
||||
adt_def => { cdata.get_adt_def(def_id.index, tcx) }
|
||||
adt_destructor => {
|
||||
@ -153,7 +155,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||
lookup_deprecation_entry => {
|
||||
cdata.get_deprecation(def_id.index).map(DeprecationEntry::external)
|
||||
}
|
||||
item_attrs => { cdata.get_item_attrs(def_id.index) }
|
||||
item_attrs => { cdata.get_item_attrs(def_id.index, tcx.sess) }
|
||||
// FIXME(#38501) We've skipped a `read` on the `HirBody` of
|
||||
// a `fn` when encoding, so the dep-tracking wouldn't work.
|
||||
// This is only used by rustdoc anyway, which shouldn't have
|
||||
@ -171,17 +173,17 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||
is_mir_available => { cdata.is_item_mir_available(def_id.index) }
|
||||
|
||||
dylib_dependency_formats => { Rc::new(cdata.get_dylib_dependency_formats()) }
|
||||
is_panic_runtime => { cdata.is_panic_runtime() }
|
||||
is_compiler_builtins => { cdata.is_compiler_builtins() }
|
||||
is_panic_runtime => { cdata.is_panic_runtime(tcx.sess) }
|
||||
is_compiler_builtins => { cdata.is_compiler_builtins(tcx.sess) }
|
||||
has_global_allocator => { cdata.has_global_allocator() }
|
||||
is_sanitizer_runtime => { cdata.is_sanitizer_runtime() }
|
||||
is_profiler_runtime => { cdata.is_profiler_runtime() }
|
||||
is_sanitizer_runtime => { cdata.is_sanitizer_runtime(tcx.sess) }
|
||||
is_profiler_runtime => { cdata.is_profiler_runtime(tcx.sess) }
|
||||
panic_strategy => { cdata.panic_strategy() }
|
||||
extern_crate => { Rc::new(cdata.extern_crate.get()) }
|
||||
is_no_builtins => { cdata.is_no_builtins() }
|
||||
is_no_builtins => { cdata.is_no_builtins(tcx.sess) }
|
||||
impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
|
||||
exported_symbol_ids => { Rc::new(cdata.get_exported_symbols()) }
|
||||
native_libraries => { Rc::new(cdata.get_native_libraries()) }
|
||||
native_libraries => { Rc::new(cdata.get_native_libraries(tcx.sess)) }
|
||||
plugin_registrar_fn => {
|
||||
cdata.root.plugin_registrar_fn.map(|index| {
|
||||
DefId { krate: def_id.krate, index }
|
||||
@ -237,8 +239,8 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||
|
||||
used_crate_source => { Rc::new(cdata.source.clone()) }
|
||||
|
||||
has_copy_closures => { cdata.has_copy_closures() }
|
||||
has_clone_closures => { cdata.has_clone_closures() }
|
||||
has_copy_closures => { cdata.has_copy_closures(tcx.sess) }
|
||||
has_clone_closures => { cdata.has_clone_closures(tcx.sess) }
|
||||
}
|
||||
|
||||
pub fn provide_local<'tcx>(providers: &mut Providers<'tcx>) {
|
||||
@ -358,8 +360,8 @@ impl CrateStore for cstore::CStore {
|
||||
self.get_crate_data(def.krate).get_visibility(def.index)
|
||||
}
|
||||
|
||||
fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics {
|
||||
self.get_crate_data(def.krate).get_generics(def.index)
|
||||
fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics {
|
||||
self.get_crate_data(def.krate).get_generics(def.index, sess)
|
||||
}
|
||||
|
||||
fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem
|
||||
@ -454,7 +456,7 @@ impl CrateStore for cstore::CStore {
|
||||
let body = filemap_to_stream(&sess.parse_sess, filemap, None);
|
||||
|
||||
// Mark the attrs as used
|
||||
let attrs = data.get_item_attrs(id.index);
|
||||
let attrs = data.get_item_attrs(id.index, sess);
|
||||
for attr in attrs.iter() {
|
||||
attr::mark_used(attr);
|
||||
}
|
||||
|
@ -87,6 +87,20 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'a Session) {
|
||||
fn raw_bytes(self) -> &'a [u8] {
|
||||
let (blob, _) = self;
|
||||
&blob.0
|
||||
}
|
||||
|
||||
fn sess(self) -> Option<&'a Session> {
|
||||
let (_, sess) = self;
|
||||
Some(sess)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadata {
|
||||
fn raw_bytes(self) -> &'a [u8] {
|
||||
self.blob.raw_bytes()
|
||||
@ -291,7 +305,7 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
|
||||
let sess = if let Some(sess) = self.sess {
|
||||
sess
|
||||
} else {
|
||||
return Ok(Span::new(lo, hi, NO_EXPANSION));
|
||||
bug!("Cannot decode Span without Session.")
|
||||
};
|
||||
|
||||
let (lo, hi) = if lo > hi {
|
||||
@ -313,7 +327,8 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
|
||||
// originate from the same filemap.
|
||||
let last_filemap = &imported_filemaps[self.last_filemap_index];
|
||||
|
||||
if lo >= last_filemap.original_start_pos && lo <= last_filemap.original_end_pos &&
|
||||
if lo >= last_filemap.original_start_pos &&
|
||||
lo <= last_filemap.original_end_pos &&
|
||||
hi >= last_filemap.original_start_pos &&
|
||||
hi <= last_filemap.original_end_pos {
|
||||
last_filemap
|
||||
@ -335,8 +350,8 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
let lo = (lo - filemap.original_start_pos) + filemap.translated_filemap.start_pos;
|
||||
let hi = (hi - filemap.original_start_pos) + filemap.translated_filemap.start_pos;
|
||||
let lo = (lo + filemap.translated_filemap.start_pos) - filemap.original_start_pos;
|
||||
let hi = (hi + filemap.translated_filemap.start_pos) - filemap.original_start_pos;
|
||||
|
||||
Ok(Span::new(lo, hi, NO_EXPANSION))
|
||||
}
|
||||
@ -521,9 +536,9 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_trait_def(&self, item_id: DefIndex) -> ty::TraitDef {
|
||||
pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
|
||||
let data = match self.entry(item_id).kind {
|
||||
EntryKind::Trait(data) => data.decode(self),
|
||||
EntryKind::Trait(data) => data.decode((self, sess)),
|
||||
_ => bug!(),
|
||||
};
|
||||
|
||||
@ -607,8 +622,11 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_generics(&self, item_id: DefIndex) -> ty::Generics {
|
||||
self.entry(item_id).generics.unwrap().decode(self)
|
||||
pub fn get_generics(&self,
|
||||
item_id: DefIndex,
|
||||
sess: &Session)
|
||||
-> ty::Generics {
|
||||
self.entry(item_id).generics.unwrap().decode((self, sess))
|
||||
}
|
||||
|
||||
pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
|
||||
@ -908,7 +926,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_item_attrs(&self, node_id: DefIndex) -> Rc<[ast::Attribute]> {
|
||||
pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Rc<[ast::Attribute]> {
|
||||
let (node_as, node_index) =
|
||||
(node_id.address_space().index(), node_id.as_array_index());
|
||||
if self.is_proc_macro(node_id) {
|
||||
@ -928,7 +946,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
if def_key.disambiguated_data.data == DefPathData::StructCtor {
|
||||
item = self.entry(def_key.parent.unwrap());
|
||||
}
|
||||
let result: Rc<[ast::Attribute]> = Rc::from(self.get_attributes(&item));
|
||||
let result: Rc<[ast::Attribute]> = Rc::from(self.get_attributes(&item, sess));
|
||||
let vec_ = &mut self.attribute_cache.borrow_mut()[node_as];
|
||||
if vec_.len() < node_index + 1 {
|
||||
vec_.resize(node_index + 1, None);
|
||||
@ -945,9 +963,9 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn get_attributes(&self, item: &Entry<'tcx>) -> Vec<ast::Attribute> {
|
||||
fn get_attributes(&self, item: &Entry<'tcx>, sess: &Session) -> Vec<ast::Attribute> {
|
||||
item.attributes
|
||||
.decode(self)
|
||||
.decode((self, sess))
|
||||
.map(|mut attr| {
|
||||
// Need new unique IDs: old thread-local IDs won't map to new threads.
|
||||
attr.id = attr::mk_attr_id();
|
||||
@ -1013,8 +1031,8 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
}
|
||||
|
||||
|
||||
pub fn get_native_libraries(&self) -> Vec<NativeLibrary> {
|
||||
self.root.native_libraries.decode(self).collect()
|
||||
pub fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLibrary> {
|
||||
self.root.native_libraries.decode((self, sess)).collect()
|
||||
}
|
||||
|
||||
pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)> {
|
||||
|
@ -125,6 +125,12 @@ pub fn provide_local(providers: &mut Providers) {
|
||||
None,
|
||||
SymbolExportLevel::Rust));
|
||||
}
|
||||
|
||||
// Sort so we get a stable incr. comp. hash.
|
||||
local_crate.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| {
|
||||
name1.cmp(name2)
|
||||
});
|
||||
|
||||
Arc::new(local_crate)
|
||||
};
|
||||
}
|
||||
@ -148,7 +154,7 @@ pub fn provide_extern(providers: &mut Providers) {
|
||||
let special_runtime_crate =
|
||||
tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum);
|
||||
|
||||
let crate_exports = tcx
|
||||
let mut crate_exports: Vec<_> = tcx
|
||||
.exported_symbol_ids(cnum)
|
||||
.iter()
|
||||
.map(|&def_id| {
|
||||
@ -176,6 +182,11 @@ pub fn provide_extern(providers: &mut Providers) {
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Sort so we get a stable incr. comp. hash.
|
||||
crate_exports.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| {
|
||||
name1.cmp(name2)
|
||||
});
|
||||
|
||||
Arc::new(crate_exports)
|
||||
};
|
||||
}
|
||||
|
@ -104,7 +104,7 @@
|
||||
|
||||
use collector::InliningMap;
|
||||
use common;
|
||||
use rustc::dep_graph::{DepNode, WorkProductId};
|
||||
use rustc::dep_graph::WorkProductId;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::map::DefPathData;
|
||||
use rustc::middle::trans::{Linkage, Visibility};
|
||||
@ -147,10 +147,6 @@ pub trait CodegenUnitExt<'tcx> {
|
||||
WorkProductId::from_cgu_name(self.name())
|
||||
}
|
||||
|
||||
fn work_product_dep_node(&self) -> DepNode {
|
||||
self.work_product_id().to_dep_node()
|
||||
}
|
||||
|
||||
fn items_in_deterministic_order<'a>(&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||
-> Vec<(TransItem<'tcx>,
|
||||
@ -253,14 +249,6 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
cgu1.name().cmp(cgu2.name())
|
||||
});
|
||||
|
||||
if tcx.sess.opts.enable_dep_node_debug_strs() {
|
||||
for cgu in &result {
|
||||
let dep_node = cgu.work_product_dep_node();
|
||||
tcx.dep_graph.register_dep_node_debug_str(dep_node,
|
||||
|| cgu.name().to_string());
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
|
@ -152,13 +152,48 @@ pub fn mod_by_zero(val: i32) -> i32 {
|
||||
}
|
||||
|
||||
|
||||
// shift left ------------------------------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
pub fn shift_left(val: i32, shift: usize) -> i32 {
|
||||
val << shift
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
pub fn shift_left(val: i32, shift: usize) -> i32 {
|
||||
val << shift
|
||||
}
|
||||
|
||||
|
||||
// shift right ------------------------------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
pub fn shift_right(val: i32, shift: usize) -> i32 {
|
||||
val >> shift
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="Hir", cfg="cfail3")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail3")]
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
pub fn shift_right(val: i32, shift: usize) -> i32 {
|
||||
val >> shift
|
||||
}
|
||||
|
||||
|
||||
// THE FOLLOWING ITEMS SHOULD NOT BE INFLUENCED BY THEIR SOURCE LOCATION
|
||||
|
||||
// bitwise ---------------------------------------------------------------------
|
||||
#[cfg(cfail1)]
|
||||
pub fn bitwise(val: i32) -> i32 {
|
||||
!val & 0x101010101 | 0x45689 ^ 0x2372382 << 1 >> 1
|
||||
!val & 0x101010101 | 0x45689 ^ 0x2372382
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
@ -169,7 +204,7 @@ pub fn bitwise(val: i32) -> i32 {
|
||||
#[rustc_metadata_clean(cfg="cfail2")]
|
||||
#[rustc_metadata_clean(cfg="cfail3")]
|
||||
pub fn bitwise(val: i32) -> i32 {
|
||||
!val & 0x101010101 | 0x45689 ^ 0x2372382 << 1 >> 1
|
||||
!val & 0x101010101 | 0x45689 ^ 0x2372382
|
||||
}
|
||||
|
||||
|
||||
|
@ -11,29 +11,29 @@
|
||||
// Check that the hash of `foo` doesn't change just because we ordered
|
||||
// the nested items (or even added new ones).
|
||||
|
||||
// revisions: rpass1 rpass2
|
||||
// revisions: cfail1 cfail2
|
||||
// must-compile-successfully
|
||||
|
||||
#![crate_type = "rlib"]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#[cfg(rpass1)]
|
||||
fn foo() {
|
||||
fn bar() { }
|
||||
fn baz() { }
|
||||
#[cfg(cfail1)]
|
||||
pub fn foo() {
|
||||
pub fn bar() { }
|
||||
pub fn baz() { }
|
||||
}
|
||||
|
||||
#[cfg(rpass2)]
|
||||
#[rustc_clean(label="Hir", cfg="rpass2")]
|
||||
#[rustc_clean(label="HirBody", cfg="rpass2")]
|
||||
fn foo() {
|
||||
#[rustc_clean(label="Hir", cfg="rpass2")]
|
||||
#[rustc_clean(label="HirBody", cfg="rpass2")]
|
||||
fn baz() { } // order is different...
|
||||
#[cfg(cfail2)]
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_dirty(label="HirBody", cfg="cfail2")]
|
||||
pub fn foo() {
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail2")]
|
||||
pub fn baz() { } // order is different...
|
||||
|
||||
#[rustc_clean(label="Hir", cfg="rpass2")]
|
||||
#[rustc_clean(label="HirBody", cfg="rpass2")]
|
||||
fn bar() { } // but that doesn't matter.
|
||||
#[rustc_clean(label="Hir", cfg="cfail2")]
|
||||
#[rustc_clean(label="HirBody", cfg="cfail2")]
|
||||
pub fn bar() { } // but that doesn't matter.
|
||||
|
||||
fn bap() { } // neither does adding a new item
|
||||
pub fn bap() { } // neither does adding a new item
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -11,21 +11,24 @@
|
||||
// This test case makes sure that the compiler doesn't crash due to a failing
|
||||
// table lookup when a source file is removed.
|
||||
|
||||
// revisions:rpass1 rpass2
|
||||
// revisions:cfail1 cfail2
|
||||
|
||||
// Note that we specify -g so that the FileMaps actually get referenced by the
|
||||
// incr. comp. cache:
|
||||
// compile-flags: -Z query-dep-graph -g
|
||||
// must-compile-successfully
|
||||
|
||||
#[cfg(rpass1)]
|
||||
#![crate_type= "rlib"]
|
||||
|
||||
#[cfg(cfail1)]
|
||||
mod auxiliary;
|
||||
|
||||
#[cfg(rpass1)]
|
||||
fn main() {
|
||||
#[cfg(cfail1)]
|
||||
pub fn foo() {
|
||||
auxiliary::print_hello();
|
||||
}
|
||||
|
||||
#[cfg(rpass2)]
|
||||
fn main() {
|
||||
#[cfg(cfail2)]
|
||||
pub fn foo() {
|
||||
println!("hello");
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
// revisions:rpass1 rpass2
|
||||
// compile-flags: -Z query-dep-graph -g
|
||||
|
||||
#![rustc_partition_reused(module="spans_in_type_debuginfo", cfg="rpass2")]
|
||||
#![rustc_partition_reused(module="spans_in_type_debuginfo-structs", cfg="rpass2")]
|
||||
#![rustc_partition_reused(module="spans_in_type_debuginfo-enums", cfg="rpass2")]
|
||||
|
||||
|
@ -1384,6 +1384,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"]);
|
||||
}
|
||||
|
||||
match self.config.mode {
|
||||
|
Loading…
Reference in New Issue
Block a user