diff options
| author | bors <bors@rust-lang.org> | 2019-09-15 00:10:08 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-09-15 00:10:08 +0000 |
| commit | 572d3d9634b253bdd85af32380b10d1f7d189cdb (patch) | |
| tree | 210899281b5d8ed3f9d8b5ada124f523de652441 | |
| parent | b35ebac96102cd12406d9d87827b0838d129c278 (diff) | |
| parent | dab68131d314e6608c547311dfca1655ac8da886 (diff) | |
| download | rust-572d3d9634b253bdd85af32380b10d1f7d189cdb.tar.gz rust-572d3d9634b253bdd85af32380b10d1f7d189cdb.zip | |
Auto merge of #60584 - jonas-schievink:ice-panic-hook, r=oli-obk
Use `panic::set_hook` to print the ICE message This allows custom frontends and backends to override the hook with their own, for example to point people to a different issue tracker. ICE messages are printed in a slightly different order now. Nightly prints: ``` thread 'rustc' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:347:21 note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace. error: aborting due to 2 previous errors Some errors have detailed explanations: E0277, E0658. For more information about an error, try `rustc --explain E0277`. 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.36.0-nightly (08bfe1612 2019-05-02) running on x86_64-unknown-linux-gnu ``` After this PR, rustc prints: ``` thread 'rustc' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:347:21 note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace. 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.36.0-dev running on x86_64-unknown-linux-gnu error: aborting due to 2 previous errors Some errors have detailed explanations: E0277, E0658. For more information about an error, try `rustc --explain E0277`. ```
| -rw-r--r-- | Cargo.lock | 2 | ||||
| -rw-r--r-- | src/librustc/Cargo.toml | 1 | ||||
| -rw-r--r-- | src/librustc/lib.rs | 1 | ||||
| -rw-r--r-- | src/librustc/util/common.rs | 37 | ||||
| -rw-r--r-- | src/librustc_driver/Cargo.toml | 1 | ||||
| -rw-r--r-- | src/librustc_driver/lib.rs | 143 | ||||
| -rw-r--r-- | src/librustdoc/lib.rs | 2 | ||||
| -rw-r--r-- | src/test/ui-fulldeps/compiler-calls.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/proc-macro/invalid-punct-ident-1.rs | 5 | ||||
| -rw-r--r-- | src/test/ui/proc-macro/invalid-punct-ident-1.stderr | 2 | ||||
| -rw-r--r-- | src/test/ui/proc-macro/invalid-punct-ident-2.rs | 5 | ||||
| -rw-r--r-- | src/test/ui/proc-macro/invalid-punct-ident-2.stderr | 2 | ||||
| -rw-r--r-- | src/test/ui/proc-macro/invalid-punct-ident-3.rs | 5 | ||||
| -rw-r--r-- | src/test/ui/proc-macro/invalid-punct-ident-3.stderr | 2 |
14 files changed, 116 insertions, 94 deletions
diff --git a/Cargo.lock b/Cargo.lock index 57e4a227427..679a02441c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3014,7 +3014,6 @@ dependencies = [ "fmt_macros", "graphviz", "jobserver", - "lazy_static 1.3.0", "log", "measureme", "num_cpus", @@ -3370,6 +3369,7 @@ version = "0.0.0" dependencies = [ "env_logger", "graphviz", + "lazy_static 1.3.0", "log", "rustc", "rustc_ast_borrowck", diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index a479fabafc0..66071d6b6ce 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -15,7 +15,6 @@ bitflags = "1.0" fmt_macros = { path = "../libfmt_macros" } graphviz = { path = "../libgraphviz" } jobserver = "0.1" -lazy_static = "1.0.0" num_cpus = "1.0" scoped-tls = "1.0" log = { version = "0.4", features = ["release_max_level_info", "std"] } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 63ef82a7401..7a01ae6b6d9 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -67,7 +67,6 @@ #[macro_use] extern crate bitflags; extern crate getopts; -#[macro_use] extern crate lazy_static; #[macro_use] extern crate scoped_tls; #[cfg(windows)] extern crate libc; diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 7118d05204c..2475b93d95f 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -5,17 +5,13 @@ use rustc_data_structures::{fx::FxHashMap, sync::Lock}; use std::cell::{RefCell, Cell}; use std::fmt::Debug; use std::hash::Hash; -use std::panic; -use std::env; use std::time::{Duration, Instant}; use std::sync::mpsc::{Sender}; use syntax_pos::{SpanData}; use syntax::symbol::{Symbol, sym}; use rustc_macros::HashStable; -use crate::ty::TyCtxt; use crate::dep_graph::{DepNode}; -use lazy_static; use crate::session::Session; #[cfg(test)] @@ -31,39 +27,6 @@ pub struct ErrorReported; thread_local!(static TIME_DEPTH: Cell<usize> = Cell::new(0)); -lazy_static! { - static ref DEFAULT_HOOK: Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static> = { - let hook = panic::take_hook(); - panic::set_hook(Box::new(panic_hook)); - hook - }; -} - -fn panic_hook(info: &panic::PanicInfo<'_>) { - (*DEFAULT_HOOK)(info); - - let backtrace = env::var_os("RUST_BACKTRACE").map(|x| &x != "0").unwrap_or(false); - - if backtrace { - TyCtxt::try_print_query_stack(); - } - - #[cfg(windows)] - unsafe { - if env::var("RUSTC_BREAK_ON_ICE").is_ok() { - extern "system" { - fn DebugBreak(); - } - // Trigger a debugger if we crashed during bootstrap. - DebugBreak(); - } - } -} - -pub fn install_panic_hook() { - lazy_static::initialize(&DEFAULT_HOOK); -} - /// Parameters to the `Dump` variant of type `ProfileQueriesMsg`. #[derive(Clone,Debug)] pub struct ProfQDumpParams { diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index a839ee56b2b..25f67b30468 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -11,6 +11,7 @@ crate-type = ["dylib"] [dependencies] graphviz = { path = "../libgraphviz" } +lazy_static = "1.0" log = "0.4" env_logger = { version = "0.6", default-features = false } rustc = { path = "../librustc" } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index a912ea3c358..005cdcfaf68 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -20,6 +20,8 @@ pub extern crate getopts; extern crate libc; #[macro_use] extern crate log; +#[macro_use] +extern crate lazy_static; pub extern crate rustc_plugin_impl as plugin; @@ -35,8 +37,8 @@ use rustc::session::{early_error, early_warn}; use rustc::lint::Lint; use rustc::lint; use rustc::hir::def_id::LOCAL_CRATE; -use rustc::util::common::{ErrorReported, install_panic_hook, print_time_passes_entry}; -use rustc::util::common::{set_time_depth, time}; +use rustc::ty::TyCtxt; +use rustc::util::common::{set_time_depth, time, print_time_passes_entry, ErrorReported}; use rustc_metadata::locator; use rustc_metadata::cstore::CStore; use rustc_codegen_utils::codegen_backend::CodegenBackend; @@ -161,8 +163,6 @@ pub fn run_compiler( None => return Ok(()), }; - install_panic_hook(); - let (sopts, cfg) = config::build_session_options_and_crate_config(&matches); let mut dummy_config = |sopts, cfg, diagnostic_output| { @@ -1151,61 +1151,105 @@ fn extra_compiler_flags() -> Option<(Vec<String>, bool)> { } } -/// Runs a procedure which will detect panics in the compiler and print nicer -/// error messages rather than just failing the test. +/// Runs a closure and catches unwinds triggered by fatal errors. /// -/// The diagnostic emitter yielded to the procedure should be used for reporting -/// errors of the compiler. -pub fn report_ices_to_stderr_if_any<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorReported> { +/// The compiler currently unwinds with a special sentinel value to abort +/// compilation on fatal errors. This function catches that sentinel and turns +/// the panic into a `Result` instead. +pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorReported> { catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| { if value.is::<errors::FatalErrorMarker>() { ErrorReported } else { - // Thread panicked without emitting a fatal diagnostic - eprintln!(""); - - let emitter = Box::new(errors::emitter::EmitterWriter::stderr( - errors::ColorConfig::Auto, - None, - false, - false, - None, - )); - let handler = errors::Handler::with_emitter(true, None, emitter); - - // a .span_bug or .bug call has already printed what - // it wants to print. - if !value.is::<errors::ExplicitBug>() { - handler.emit(&MultiSpan::new(), - "unexpected panic", - errors::Level::Bug); - } + panic::resume_unwind(value); + } + }) +} - let mut xs: Vec<Cow<'static, str>> = vec![ - "the compiler unexpectedly panicked. this is a bug.".into(), - format!("we would appreciate a bug report: {}", BUG_REPORT_URL).into(), - format!("rustc {} running on {}", - option_env!("CFG_VERSION").unwrap_or("unknown_version"), - config::host_triple()).into(), - ]; +lazy_static! { + static ref DEFAULT_HOOK: Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static> = { + let hook = panic::take_hook(); + panic::set_hook(Box::new(|info| report_ice(info, BUG_REPORT_URL))); + hook + }; +} - if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() { - xs.push(format!("compiler flags: {}", flags.join(" ")).into()); +/// Prints the ICE message, including backtrace and query stack. +/// +/// The message will point the user at `bug_report_url` to report the ICE. +/// +/// When `install_ice_hook` is called, this function will be called as the panic +/// hook. +pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { + // Invoke the default handler, which prints the actual panic message and optionally a backtrace + (*DEFAULT_HOOK)(info); + + // Separate the output with an empty line + eprintln!(); + + let emitter = Box::new(errors::emitter::EmitterWriter::stderr( + errors::ColorConfig::Auto, + None, + false, + false, + None, + )); + let handler = errors::Handler::with_emitter(true, None, emitter); + + // a .span_bug or .bug call has already printed what + // it wants to print. + if !info.payload().is::<errors::ExplicitBug>() { + handler.emit(&MultiSpan::new(), + "unexpected panic", + errors::Level::Bug); + } - if excluded_cargo_defaults { - xs.push("some of the compiler flags provided by cargo are hidden".into()); - } - } + let mut xs: Vec<Cow<'static, str>> = vec![ + "the compiler unexpectedly panicked. this is a bug.".into(), + format!("we would appreciate a bug report: {}", bug_report_url).into(), + format!("rustc {} running on {}", + option_env!("CFG_VERSION").unwrap_or("unknown_version"), + config::host_triple()).into(), + ]; - for note in &xs { - handler.emit(&MultiSpan::new(), - note, - errors::Level::Note); - } + if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() { + xs.push(format!("compiler flags: {}", flags.join(" ")).into()); - panic::resume_unwind(Box::new(errors::FatalErrorMarker)); + if excluded_cargo_defaults { + xs.push("some of the compiler flags provided by cargo are hidden".into()); } - }) + } + + for note in &xs { + handler.emit(&MultiSpan::new(), + note, + errors::Level::Note); + } + + // If backtraces are enabled, also print the query stack + let backtrace = env::var_os("RUST_BACKTRACE").map(|x| &x != "0").unwrap_or(false); + + if backtrace { + TyCtxt::try_print_query_stack(); + } + + #[cfg(windows)] + unsafe { + if env::var("RUSTC_BREAK_ON_ICE").is_ok() { + extern "system" { + fn DebugBreak(); + } + // Trigger a debugger if we crashed during bootstrap + DebugBreak(); + } + } +} + +/// Installs a panic hook that will print the ICE message on unexpected panics. +/// +/// A custom rustc driver can skip calling this to set up a custom ICE hook. +pub fn install_ice_hook() { + lazy_static::initialize(&DEFAULT_HOOK); } /// This allows tools to enable rust logging without having to magically match rustc's @@ -1218,7 +1262,8 @@ pub fn main() { let start = Instant::now(); init_rustc_env_logger(); let mut callbacks = TimePassesCallbacks::default(); - let result = report_ices_to_stderr_if_any(|| { + install_ice_hook(); + let result = catch_fatal_errors(|| { let args = env::args_os().enumerate() .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| { early_error(ErrorOutputType::default(), diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index d77e790d4a4..0b9e717221f 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -473,7 +473,7 @@ where R: 'static + Send, // First, parse the crate and extract all relevant information. info!("starting to run rustc"); - let result = rustc_driver::report_ices_to_stderr_if_any(move || { + let result = rustc_driver::catch_fatal_errors(move || { let crate_name = options.crate_name.clone(); let crate_version = options.crate_version.clone(); let (mut krate, renderinfo, renderopts) = core::run_core(options); diff --git a/src/test/ui-fulldeps/compiler-calls.rs b/src/test/ui-fulldeps/compiler-calls.rs index ea24f5809d5..bd9113c7079 100644 --- a/src/test/ui-fulldeps/compiler-calls.rs +++ b/src/test/ui-fulldeps/compiler-calls.rs @@ -24,7 +24,7 @@ impl rustc_driver::Callbacks for TestCalls<'_> { fn main() { let mut count = 1; let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()]; - rustc_driver::report_ices_to_stderr_if_any(|| { + rustc_driver::catch_fatal_errors(|| { rustc_driver::run_compiler(&args, &mut TestCalls { count: &mut count }, None, None).ok(); }).ok(); assert_eq!(count, 2); diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.rs b/src/test/ui/proc-macro/invalid-punct-ident-1.rs index c9881ad2c38..94a4b403d5a 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-1.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-1.rs @@ -3,6 +3,11 @@ // FIXME https://github.com/rust-lang/rust/issues/59998 // normalize-stderr-test "thread.*panicked.*proc_macro_server.rs.*\n" -> "" // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" +// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> "" +// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" +// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> "" +// normalize-stderr-test "note: compiler flags.*\n\n" -> "" +// normalize-stderr-test "note: rustc.*running on.*\n\n" -> "" #[macro_use] extern crate invalid_punct_ident; diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr index 40333a3f4c2..107f5fb515b 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr @@ -1,5 +1,5 @@ error: proc macro panicked - --> $DIR/invalid-punct-ident-1.rs:10:1 + --> $DIR/invalid-punct-ident-1.rs:15:1 | LL | invalid_punct!(); | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.rs b/src/test/ui/proc-macro/invalid-punct-ident-2.rs index 15e2286a650..778b7eeecd7 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-2.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-2.rs @@ -3,6 +3,11 @@ // FIXME https://github.com/rust-lang/rust/issues/59998 // normalize-stderr-test "thread.*panicked.*proc_macro_server.rs.*\n" -> "" // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" +// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> "" +// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" +// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> "" +// normalize-stderr-test "note: compiler flags.*\n\n" -> "" +// normalize-stderr-test "note: rustc.*running on.*\n\n" -> "" #[macro_use] extern crate invalid_punct_ident; diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr index ec97e265c3f..f1b9ecc6cbf 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr @@ -1,5 +1,5 @@ error: proc macro panicked - --> $DIR/invalid-punct-ident-2.rs:10:1 + --> $DIR/invalid-punct-ident-2.rs:15:1 | LL | invalid_ident!(); | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.rs b/src/test/ui/proc-macro/invalid-punct-ident-3.rs index 629bbaa9e38..f68ee3de7f4 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-3.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-3.rs @@ -3,6 +3,11 @@ // FIXME https://github.com/rust-lang/rust/issues/59998 // normalize-stderr-test "thread.*panicked.*proc_macro_server.rs.*\n" -> "" // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" +// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> "" +// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" +// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> "" +// normalize-stderr-test "note: compiler flags.*\n\n" -> "" +// normalize-stderr-test "note: rustc.*running on.*\n\n" -> "" #[macro_use] extern crate invalid_punct_ident; diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr index a5e5ded6533..6044b988740 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr @@ -1,5 +1,5 @@ error: proc macro panicked - --> $DIR/invalid-punct-ident-3.rs:10:1 + --> $DIR/invalid-punct-ident-3.rs:15:1 | LL | invalid_raw_ident!(); | ^^^^^^^^^^^^^^^^^^^^^ |
