1
Fork 0

Auto merge of #49222 - Zoxc:print-query-stack, r=nikomatsakis

Print query stack on ICEs

ICE output is now:
```
thread 'rustc' panicked at 'no borrowck', librustc_borrowck\borrowck\mod.rs:95:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.
query stack during panic:
#0 [borrowck] processing `main`
  --> no-std.rs:10:1
   |
10 | fn main() {}
   | ^^^^^^^^^
end of query stack

error: internal compiler error: unexpected panic

note: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports

note: rustc 1.26.0-dev running on x86_64-pc-windows-msvc
```

Fixes #42529.

r? @eddyb
This commit is contained in:
bors 2018-04-07 02:51:17 +00:00
commit ee1014e505
3 changed files with 49 additions and 1 deletions

View file

@ -14,6 +14,8 @@
use dep_graph::{DepNodeIndex, DepNode, DepKind, DepNodeColor}; use dep_graph::{DepNodeIndex, DepNode, DepKind, DepNodeColor};
use errors::DiagnosticBuilder; use errors::DiagnosticBuilder;
use errors::Level;
use ty::tls;
use ty::{TyCtxt}; use ty::{TyCtxt};
use ty::maps::config::QueryDescription; use ty::maps::config::QueryDescription;
use ty::maps::job::{QueryResult, QueryInfo}; 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. /// 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 /// 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 /// 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> { impl<$tcx> Query<$tcx> {
pub fn name(&self) -> &'static str {
match *self {
$(Query::$name(_) => stringify!($name),)*
}
}
pub fn describe(&self, tcx: TyCtxt) -> String { pub fn describe(&self, tcx: TyCtxt) -> String {
let (r, name) = match *self { let (r, name) = match *self {
$(Query::$name(key) => { $(Query::$name(key) => {

View file

@ -17,12 +17,14 @@ use std::fmt::Debug;
use std::hash::{Hash, BuildHasher}; use std::hash::{Hash, BuildHasher};
use std::iter::repeat; use std::iter::repeat;
use std::panic; use std::panic;
use std::env;
use std::path::Path; use std::path::Path;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use std::sync::mpsc::{Sender}; use std::sync::mpsc::{Sender};
use syntax_pos::{SpanData}; use syntax_pos::{SpanData};
use ty::maps::{QueryMsg}; use ty::maps::{QueryMsg};
use ty::TyCtxt;
use dep_graph::{DepNode}; use dep_graph::{DepNode};
use proc_macro; use proc_macro;
use lazy_static; use lazy_static;
@ -48,7 +50,13 @@ lazy_static! {
fn panic_hook(info: &panic::PanicInfo) { fn panic_hook(info: &panic::PanicInfo) {
if !proc_macro::__internal::in_sess() { 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();
}
} }
} }

View file

@ -641,6 +641,11 @@ impl Handler {
self.tracked_diagnostic_codes.borrow().contains(code) 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) { fn emit_db(&self, db: &DiagnosticBuilder) {
let diagnostic = &**db; let diagnostic = &**db;