diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 70cfe57d15023..89ce4bf928ad8 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -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, - - // Trait selection cache is a little funny. Given a trait - // reference like `Foo: SomeTrait`, 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: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }` - // - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }` - // - `Foo: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` - // - `Foo: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` - // - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` - // - `i32: Trait` -> `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. + [input] AllLocalTraitImpls, + [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 { diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 0fb4e354a52d4..a586424d196d3 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -506,60 +506,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 } } } @@ -772,7 +779,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::>()) + } + } + self.alloc_node(node, reads) } else { bug!("pop_task() - Expected regular task to be popped") @@ -793,6 +823,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(); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index a69d41d16033f..ba89961adc687 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -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 }); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 1236602aecf55..453d30dde7595 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -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 { 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) } diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index d24344e4e2166..f204d352842bf 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -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 | diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index f0fe6205fb6d0..6b78cd473be8f 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -356,33 +356,7 @@ impl<'gcx> HashStable> 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); diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index f4ba7890b170d..628538b41c5d8 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -273,7 +273,7 @@ pub trait CrateStore { fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec; fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro; fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option; - 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; @@ -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 diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 4c7ce4c09e25b..ffd06ee8a2e3a 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -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() }) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 8401d493b9dbf..51c53739e886e 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1017,6 +1017,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], diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index cc698cf03da98..24148bcc83f37 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -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) } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index cfc8d271327fb..155097cdbe26c 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -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 diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index c688b4c408a35..a86b55e269d41 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -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") } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 97c00aede90cf..8dcfb4c34b5b2 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -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); } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 603e79155fb72..e63037f4da1ef 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -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 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 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 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 { + fn get_attributes(&self, item: &Entry<'tcx>, sess: &Session) -> Vec { 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 { - self.root.native_libraries.decode(self).collect() + pub fn get_native_libraries(&self, sess: &Session) -> Vec { + self.root.native_libraries.decode((self, sess)).collect() } pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)> { diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index b9519bba2dd89..23890905718a8 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -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) }; } diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 6980ba8a52505..03c0f13e2f5f7 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -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 } diff --git a/src/test/incremental/hashes/panic_exprs.rs b/src/test/incremental/hashes/panic_exprs.rs index 5d4d434fd633f..4a3e4bc49ce6f 100644 --- a/src/test/incremental/hashes/panic_exprs.rs +++ b/src/test/incremental/hashes/panic_exprs.rs @@ -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 } diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs index e8e40d57b1ee6..2e0f0ba083783 100644 --- a/src/test/incremental/ich_nested_items.rs +++ b/src/test/incremental/ich_nested_items.rs @@ -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() { } diff --git a/src/test/incremental/remove_source_file/main.rs b/src/test/incremental/remove_source_file/main.rs index 4ba33f3bb3d62..3ae26c6aa4517 100644 --- a/src/test/incremental/remove_source_file/main.rs +++ b/src/test/incremental/remove_source_file/main.rs @@ -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"); } diff --git a/src/test/incremental/spans_in_type_debuginfo.rs b/src/test/incremental/spans_in_type_debuginfo.rs index 7d8e6c9d9d7ef..e1369d92c5ccb 100644 --- a/src/test/incremental/spans_in_type_debuginfo.rs +++ b/src/test/incremental/spans_in_type_debuginfo.rs @@ -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")] diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index de96aa9cdeb7f..8b423eaf7c8a7 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -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 {