From 6f4b904aa999aded3b1ee317146387a8686715e3 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 16 Jan 2020 20:33:18 +0100 Subject: [PATCH] Collisions in the dep-graph due to path-reuse are rare but can occur. So, instead of ICE'ing, just fail to mark green in such cases (for `DepKind::{Hir, HirBody, CrateMetadata}`). Fix #62649. --- src/librustc/dep_graph/graph.rs | 39 ++++++++++++++----- .../issue-62649-path-collisions-happen.rs | 13 +++++++ 2 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 src/test/incremental/issue-62649-path-collisions-happen.rs diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 8d1efc7bc048d..258723bb39d83 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -6,6 +6,7 @@ use rustc_data_structures::sharded::{self, Sharded}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering}; use rustc_errors::Diagnostic; +use rustc_hir::def_id::DefId; use rustc_index::vec::{Idx, IndexVec}; use smallvec::SmallVec; use std::collections::hash_map::Entry; @@ -677,18 +678,33 @@ impl DepGraph { } else { match dep_dep_node.kind { DepKind::Hir | DepKind::HirBody | DepKind::CrateMetadata => { - if dep_dep_node.extract_def_id(tcx).is_none() { + if let Some(def_id) = dep_dep_node.extract_def_id(tcx) { + if def_id_corresponds_to_hir_dep_node(tcx, def_id) { + // The `DefPath` has corresponding node, + // and that node should have been marked + // either red or green in `data.colors`. + bug!( + "DepNode {:?} should have been \ + pre-marked as red or green but wasn't.", + dep_dep_node + ); + } else { + // This `DefPath` does not have a + // corresponding `DepNode` (e.g. a + // struct field), and the ` DefPath` + // collided with the `DefPath` of a + // proper item that existed in the + // previous compilation session. + // + // Since the given `DefPath` does not + // denote the item that previously + // existed, we just fail to mark green. + return None; + } + } else { // If the node does not exist anymore, we // just fail to mark green. return None; - } else { - // If the node does exist, it should have - // been pre-allocated. - bug!( - "DepNode {:?} should have been \ - pre-allocated but wasn't.", - dep_dep_node - ) } } _ => { @@ -899,6 +915,11 @@ impl DepGraph { } } +fn def_id_corresponds_to_hir_dep_node(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); + def_id.index == hir_id.owner +} + /// A "work product" is an intermediate result that we save into the /// incremental directory for later re-use. The primary example are /// the object files that we save for each partition at code diff --git a/src/test/incremental/issue-62649-path-collisions-happen.rs b/src/test/incremental/issue-62649-path-collisions-happen.rs new file mode 100644 index 0000000000000..ee81be76bafe3 --- /dev/null +++ b/src/test/incremental/issue-62649-path-collisions-happen.rs @@ -0,0 +1,13 @@ +// revisions: rpass1 rpass2 + +#[cfg(rpass1)] +pub trait Something { + fn foo(); +} + +#[cfg(rpass2)] +pub struct Something { + pub foo: u8, +} + +fn main() {}