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;