Use `panic::set_hook` to print the ICE message
This commit is contained in:
parent
19a38de68a
commit
a8926a5e9c
|
@ -3204,6 +3204,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"env_logger 0.5.13",
|
||||
"graphviz",
|
||||
"lazy_static 1.3.0",
|
||||
"log",
|
||||
"rustc",
|
||||
"rustc_ast_borrowck",
|
||||
|
|
|
@ -11,6 +11,7 @@ crate-type = ["dylib"]
|
|||
|
||||
[dependencies]
|
||||
graphviz = { path = "../libgraphviz" }
|
||||
lazy_static = "1.0"
|
||||
log = "0.4"
|
||||
env_logger = { version = "0.5", default-features = false }
|
||||
rustc = { path = "../librustc" }
|
||||
|
|
|
@ -21,6 +21,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;
|
||||
|
||||
|
@ -1143,63 +1145,79 @@ 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 panics 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);
|
||||
}
|
||||
|
||||
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(),
|
||||
];
|
||||
|
||||
if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
|
||||
xs.push(format!("compiler flags: {}", flags.join(" ")).into());
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
panic::resume_unwind(Box::new(errors::FatalErrorMarker));
|
||||
panic::resume_unwind(value);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref DEFAULT_HOOK: Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static> = {
|
||||
let hook = panic::take_hook();
|
||||
panic::set_hook(Box::new(report_ice));
|
||||
hook
|
||||
};
|
||||
}
|
||||
|
||||
pub fn report_ice(info: &panic::PanicInfo<'_>) {
|
||||
(*DEFAULT_HOOK)(info);
|
||||
|
||||
// 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 !info.payload().is::<errors::ExplicitBug>() {
|
||||
handler.emit(&MultiSpan::new(),
|
||||
"unexpected panic",
|
||||
errors::Level::Bug);
|
||||
}
|
||||
|
||||
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(),
|
||||
];
|
||||
|
||||
if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
|
||||
xs.push(format!("compiler flags: {}", flags.join(" ")).into());
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn install_ice_hook() {
|
||||
lazy_static::initialize(&DEFAULT_HOOK);
|
||||
}
|
||||
|
||||
/// This allows tools to enable rust logging without having to magically match rustc's
|
||||
/// log crate version
|
||||
pub fn init_rustc_env_logger() {
|
||||
|
@ -1210,7 +1228,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(),
|
||||
|
|
|
@ -453,7 +453,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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue