about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2018-03-20 23:41:25 +0100
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2018-04-06 16:23:31 +0200
commit4fd188e5f31f14625eb8b1feec38da5ad538e3c9 (patch)
treec626d62df27e4b9f516645978947f4ece44c1c1e
parenta143462783cec88b7b733e8aa09990bfeb59f754 (diff)
downloadrust-4fd188e5f31f14625eb8b1feec38da5ad538e3c9.tar.gz
rust-4fd188e5f31f14625eb8b1feec38da5ad538e3c9.zip
Print query stack on ICEs
-rw-r--r--src/librustc/ty/maps/plumbing.rs35
-rw-r--r--src/librustc/util/common.rs10
-rw-r--r--src/librustc_errors/lib.rs5
3 files changed, 49 insertions, 1 deletions
diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs
index bc5a14c96f0..1493c7e8310 100644
--- a/src/librustc/ty/maps/plumbing.rs
+++ b/src/librustc/ty/maps/plumbing.rs
@@ -14,6 +14,8 @@
 
 use dep_graph::{DepNodeIndex, DepNode, DepKind, DepNodeColor};
 use errors::DiagnosticBuilder;
+use errors::Level;
+use ty::tls;
 use ty::{TyCtxt};
 use ty::maps::config::QueryDescription;
 use ty::maps::job::{QueryResult, QueryInfo};
@@ -108,6 +110,33 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         })
     }
 
+    pub fn try_print_query_stack() {
+        eprintln!("query stack during panic:");
+
+        tls::with_context_opt(|icx| {
+            if let Some(icx) = icx {
+                let mut current_query = icx.query.clone();
+                let mut i = 0;
+
+                while let Some(query) = current_query {
+                    let mut db = DiagnosticBuilder::new(icx.tcx.sess.diagnostic(),
+                        Level::FailureNote,
+                        &format!("#{} [{}] {}",
+                                 i,
+                                 query.info.query.name(),
+                                 query.info.query.describe(icx.tcx)));
+                    db.set_span(icx.tcx.sess.codemap().def_span(query.info.span));
+                    icx.tcx.sess.diagnostic().force_print_db(db);
+
+                    current_query = query.parent.clone();
+                    i += 1;
+                }
+            }
+        });
+
+        eprintln!("end of query stack");
+    }
+
     /// Try to read a node index for the node dep_node.
     /// A node will have an index, when it's already been marked green, or when we can mark it
     /// green. This function will mark the current task as a reader of the specified node, when
@@ -219,6 +248,12 @@ macro_rules! define_maps {
         }
 
         impl<$tcx> Query<$tcx> {
+            pub fn name(&self) -> &'static str {
+                match *self {
+                    $(Query::$name(_) => stringify!($name),)*
+                }
+            }
+
             pub fn describe(&self, tcx: TyCtxt) -> String {
                 let (r, name) = match *self {
                     $(Query::$name(key) => {
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 6b896a889e3..32ec837f031 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -17,12 +17,14 @@ use std::fmt::Debug;
 use std::hash::{Hash, BuildHasher};
 use std::iter::repeat;
 use std::panic;
+use std::env;
 use std::path::Path;
 use std::time::{Duration, Instant};
 
 use std::sync::mpsc::{Sender};
 use syntax_pos::{SpanData};
 use ty::maps::{QueryMsg};
+use ty::TyCtxt;
 use dep_graph::{DepNode};
 use proc_macro;
 use lazy_static;
@@ -48,7 +50,13 @@ lazy_static! {
 
 fn panic_hook(info: &panic::PanicInfo) {
     if !proc_macro::__internal::in_sess() {
-        (*DEFAULT_HOOK)(info)
+        (*DEFAULT_HOOK)(info);
+
+        let backtrace = env::var_os("RUST_BACKTRACE").map(|x| &x != "0").unwrap_or(false);
+
+        if backtrace {
+            TyCtxt::try_print_query_stack();
+        }
     }
 }
 
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 990ae2fc544..43fe812a6ce 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -641,6 +641,11 @@ impl Handler {
         self.tracked_diagnostic_codes.borrow().contains(code)
     }
 
+    pub fn force_print_db(&self, mut db: DiagnosticBuilder) {
+        self.emitter.borrow_mut().emit(&db);
+        db.cancel();
+    }
+
     fn emit_db(&self, db: &DiagnosticBuilder) {
         let diagnostic = &**db;