@@ -21,6 +21,8 @@ pub extern crate getopts;
2121extern crate libc;
2222#[ macro_use]
2323extern crate log;
24+ #[ macro_use]
25+ extern crate lazy_static;
2426
2527pub 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 ( ) ,
0 commit comments