about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2020-01-29 09:34:43 +0900
committerGitHub <noreply@github.com>2020-01-29 09:34:43 +0900
commitcb3884adaa538a9d380ac64dd3c9bb6ce6738da6 (patch)
treefa27a4039a8a185b3ce23bcd596a2660481707e5 /src
parent3761dcd3467441f78939ccb3b341b03b6a7558d7 (diff)
parent6f4b904aa999aded3b1ee317146387a8686715e3 (diff)
Rollup merge of #68289 - pnkfelix:issue-62649-dont-ice-on-path-collision-in-dep-graph, r=michaelwoerister
Don't ICE on path-collision in dep-graph

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.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/dep_graph/graph.rs39
-rw-r--r--src/test/incremental/issue-62649-path-collisions-happen.rs13
2 files changed, 43 insertions, 9 deletions
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 8d1efc7bc04..258723bb39d 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 00000000000..ee81be76baf
--- /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() {}