Skip to content

Commit a8926a5

Browse files
Use panic::set_hook to print the ICE message
1 parent 19a38de commit a8926a5

File tree

5 files changed

+68
-47
lines changed

5 files changed

+68
-47
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3204,6 +3204,7 @@ version = "0.0.0"
32043204
dependencies = [
32053205
"env_logger 0.5.13",
32063206
"graphviz",
3207+
"lazy_static 1.3.0",
32073208
"log",
32083209
"rustc",
32093210
"rustc_ast_borrowck",

src/librustc_driver/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ crate-type = ["dylib"]
1111

1212
[dependencies]
1313
graphviz = { path = "../libgraphviz" }
14+
lazy_static = "1.0"
1415
log = "0.4"
1516
env_logger = { version = "0.5", default-features = false }
1617
rustc = { path = "../librustc" }

src/librustc_driver/lib.rs

Lines changed: 64 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ pub extern crate getopts;
2121
extern crate libc;
2222
#[macro_use]
2323
extern crate log;
24+
#[macro_use]
25+
extern crate lazy_static;
2426

2527
pub extern crate rustc_plugin_impl as plugin;
2628

@@ -1143,61 +1145,77 @@ fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
11431145
}
11441146
}
11451147

1146-
/// Runs a procedure which will detect panics in the compiler and print nicer
1147-
/// error messages rather than just failing the test.
1148+
/// Runs a closure and catches unwinds triggered by fatal errors.
11481149
///
1149-
/// The diagnostic emitter yielded to the procedure should be used for reporting
1150-
/// errors of the compiler.
1151-
pub fn report_ices_to_stderr_if_any<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorReported> {
1150+
/// The compiler currently panics with a special sentinel value to abort
1151+
/// compilation on fatal errors. This function catches that sentinel and turns
1152+
/// the panic into a `Result` instead.
1153+
pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorReported> {
11521154
catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
11531155
if value.is::<errors::FatalErrorMarker>() {
11541156
ErrorReported
11551157
} else {
1156-
// Thread panicked without emitting a fatal diagnostic
1157-
eprintln!("");
1158-
1159-
let emitter = Box::new(errors::emitter::EmitterWriter::stderr(
1160-
errors::ColorConfig::Auto,
1161-
None,
1162-
false,
1163-
false,
1164-
None,
1165-
));
1166-
let handler = errors::Handler::with_emitter(true, None, emitter);
1167-
1168-
// a .span_bug or .bug call has already printed what
1169-
// it wants to print.
1170-
if !value.is::<errors::ExplicitBug>() {
1171-
handler.emit(&MultiSpan::new(),
1172-
"unexpected panic",
1173-
errors::Level::Bug);
1174-
}
1158+
panic::resume_unwind(value);
1159+
}
1160+
})
1161+
}
11751162

1176-
let mut xs: Vec<Cow<'static, str>> = vec![
1177-
"the compiler unexpectedly panicked. this is a bug.".into(),
1178-
format!("we would appreciate a bug report: {}", BUG_REPORT_URL).into(),
1179-
format!("rustc {} running on {}",
1180-
option_env!("CFG_VERSION").unwrap_or("unknown_version"),
1181-
config::host_triple()).into(),
1182-
];
1163+
lazy_static! {
1164+
static ref DEFAULT_HOOK: Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static> = {
1165+
let hook = panic::take_hook();
1166+
panic::set_hook(Box::new(report_ice));
1167+
hook
1168+
};
1169+
}
11831170

1184-
if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
1185-
xs.push(format!("compiler flags: {}", flags.join(" ")).into());
1171+
pub fn report_ice(info: &panic::PanicInfo<'_>) {
1172+
(*DEFAULT_HOOK)(info);
1173+
1174+
// Thread panicked without emitting a fatal diagnostic
1175+
eprintln!();
1176+
1177+
let emitter = Box::new(errors::emitter::EmitterWriter::stderr(
1178+
errors::ColorConfig::Auto,
1179+
None,
1180+
false,
1181+
false,
1182+
None,
1183+
));
1184+
let handler = errors::Handler::with_emitter(true, None, emitter);
1185+
1186+
// a .span_bug or .bug call has already printed what
1187+
// it wants to print.
1188+
if !info.payload().is::<errors::ExplicitBug>() {
1189+
handler.emit(&MultiSpan::new(),
1190+
"unexpected panic",
1191+
errors::Level::Bug);
1192+
}
11861193

1187-
if excluded_cargo_defaults {
1188-
xs.push("some of the compiler flags provided by cargo are hidden".into());
1189-
}
1190-
}
1194+
let mut xs: Vec<Cow<'static, str>> = vec![
1195+
"the compiler unexpectedly panicked. this is a bug.".into(),
1196+
format!("we would appreciate a bug report: {}", BUG_REPORT_URL).into(),
1197+
format!("rustc {} running on {}",
1198+
option_env!("CFG_VERSION").unwrap_or("unknown_version"),
1199+
config::host_triple()).into(),
1200+
];
11911201

1192-
for note in &xs {
1193-
handler.emit(&MultiSpan::new(),
1194-
note,
1195-
errors::Level::Note);
1196-
}
1202+
if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
1203+
xs.push(format!("compiler flags: {}", flags.join(" ")).into());
11971204

1198-
panic::resume_unwind(Box::new(errors::FatalErrorMarker));
1205+
if excluded_cargo_defaults {
1206+
xs.push("some of the compiler flags provided by cargo are hidden".into());
11991207
}
1200-
})
1208+
}
1209+
1210+
for note in &xs {
1211+
handler.emit(&MultiSpan::new(),
1212+
note,
1213+
errors::Level::Note);
1214+
}
1215+
}
1216+
1217+
pub fn install_ice_hook() {
1218+
lazy_static::initialize(&DEFAULT_HOOK);
12011219
}
12021220

12031221
/// This allows tools to enable rust logging without having to magically match rustc's
@@ -1210,7 +1228,8 @@ pub fn main() {
12101228
let start = Instant::now();
12111229
init_rustc_env_logger();
12121230
let mut callbacks = TimePassesCallbacks::default();
1213-
let result = report_ices_to_stderr_if_any(|| {
1231+
install_ice_hook();
1232+
let result = catch_fatal_errors(|| {
12141233
let args = env::args_os().enumerate()
12151234
.map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| {
12161235
early_error(ErrorOutputType::default(),

src/librustdoc/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ where R: 'static + Send,
453453
// First, parse the crate and extract all relevant information.
454454
info!("starting to run rustc");
455455

456-
let result = rustc_driver::report_ices_to_stderr_if_any(move || {
456+
let result = rustc_driver::catch_fatal_errors(move || {
457457
let crate_name = options.crate_name.clone();
458458
let crate_version = options.crate_version.clone();
459459
let (mut krate, renderinfo, renderopts) = core::run_core(options);

src/test/ui-fulldeps/compiler-calls.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ impl rustc_driver::Callbacks for TestCalls<'_> {
2424
fn main() {
2525
let mut count = 1;
2626
let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()];
27-
rustc_driver::report_ices_to_stderr_if_any(|| {
27+
rustc_driver::catch_fatal_errors(|| {
2828
rustc_driver::run_compiler(&args, &mut TestCalls { count: &mut count }, None, None).ok();
2929
}).ok();
3030
assert_eq!(count, 2);

0 commit comments

Comments
 (0)