@@ -21,6 +21,8 @@ pub extern crate getopts;
21
21
extern crate libc;
22
22
#[ macro_use]
23
23
extern crate log;
24
+ #[ macro_use]
25
+ extern crate lazy_static;
24
26
25
27
pub extern crate rustc_plugin_impl as plugin;
26
28
@@ -1143,61 +1145,77 @@ fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
1143
1145
}
1144
1146
}
1145
1147
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.
1148
1149
///
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 > {
1152
1154
catch_unwind ( panic:: AssertUnwindSafe ( f) ) . map_err ( |value| {
1153
1155
if value. is :: < errors:: FatalErrorMarker > ( ) {
1154
1156
ErrorReported
1155
1157
} 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
+ }
1175
1162
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
+ }
1183
1170
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
+ }
1186
1193
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
+ ] ;
1191
1201
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 ( ) ) ;
1197
1204
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 ( ) ) ;
1199
1207
}
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 ) ;
1201
1219
}
1202
1220
1203
1221
/// This allows tools to enable rust logging without having to magically match rustc's
@@ -1210,7 +1228,8 @@ pub fn main() {
1210
1228
let start = Instant :: now ( ) ;
1211
1229
init_rustc_env_logger ( ) ;
1212
1230
let mut callbacks = TimePassesCallbacks :: default ( ) ;
1213
- let result = report_ices_to_stderr_if_any ( || {
1231
+ install_ice_hook ( ) ;
1232
+ let result = catch_fatal_errors ( || {
1214
1233
let args = env:: args_os ( ) . enumerate ( )
1215
1234
. map ( |( i, arg) | arg. into_string ( ) . unwrap_or_else ( |arg| {
1216
1235
early_error ( ErrorOutputType :: default ( ) ,
0 commit comments