@@ -5,9 +5,9 @@ use std::sync::Arc;
55use rustc_ast:: { LitKind , MetaItemKind , token} ;
66use rustc_codegen_ssa:: traits:: CodegenBackend ;
77use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
8+ use rustc_data_structures:: jobserver;
89use rustc_data_structures:: stable_hasher:: StableHasher ;
910use rustc_data_structures:: sync:: Lrc ;
10- use rustc_data_structures:: { defer, jobserver} ;
1111use rustc_errors:: registry:: Registry ;
1212use rustc_errors:: { DiagCtxtHandle , ErrorGuaranteed } ;
1313use rustc_lint:: LintStore ;
@@ -492,21 +492,13 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
492492
493493 // There are two paths out of `f`.
494494 // - Normal exit.
495- // - Panic, e.g. triggered by `abort_if_errors`.
495+ // - Panic, e.g. triggered by `abort_if_errors` or a fatal error .
496496 //
497497 // We must run `finish_diagnostics` in both cases.
498498 let res = {
499- // If `f` panics, `finish_diagnostics` will run during
500- // unwinding because of the `defer`.
501- let sess_abort_guard = defer ( || {
502- compiler. sess . finish_diagnostics ( ) ;
503- } ) ;
499+ let res = std:: panic:: catch_unwind ( std:: panic:: AssertUnwindSafe ( || f ( & compiler) ) ) ;
504500
505- let res = f ( & compiler) ;
506-
507- // If `f` doesn't panic, `finish_diagnostics` will run
508- // normally when `sess_abort_guard` is dropped.
509- drop ( sess_abort_guard) ;
501+ compiler. sess . finish_diagnostics ( ) ;
510502
511503 // If error diagnostics have been emitted, we can't return an
512504 // error directly, because the return type of this function
@@ -515,9 +507,20 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
515507 // mistakenly think that no errors occurred and return a zero
516508 // exit code. So we abort (panic) instead, similar to if `f`
517509 // had panicked.
518- compiler. sess . dcx ( ) . abort_if_errors ( ) ;
510+ if res. is_ok ( ) {
511+ compiler. sess . dcx ( ) . abort_if_errors ( ) ;
512+ }
519513
520- res
514+ // Also make sure to flush delayed bugs as if we panicked, the
515+ // bugs would be flushed by the Drop impl of DiagCtxt while
516+ // unwinding, which would result in an abort with
517+ // "panic in a destructor during cleanup".
518+ compiler. sess . dcx ( ) . flush_delayed ( ) ;
519+
520+ match res {
521+ Ok ( res) => res,
522+ Err ( err) => std:: panic:: resume_unwind ( err) ,
523+ }
521524 } ;
522525
523526 let prof = compiler. sess . prof . clone ( ) ;
0 commit comments