diff options
| author | bjorn3 <17426603+bjorn3@users.noreply.github.com> | 2024-11-28 14:47:21 +0000 |
|---|---|---|
| committer | bjorn3 <17426603+bjorn3@users.noreply.github.com> | 2024-12-06 18:42:31 +0000 |
| commit | 618d4c3eeb9a9f410f35b666e8b929056f820987 (patch) | |
| tree | 1692bcdb0f7315280949aa7745ad3eb9adb5f5b5 /compiler/rustc_interface/src/interface.rs | |
| parent | 401dd840ff301f13c4006132cc4e4eb80e9702eb (diff) | |
| download | rust-618d4c3eeb9a9f410f35b666e8b929056f820987.tar.gz rust-618d4c3eeb9a9f410f35b666e8b929056f820987.zip | |
Handle unwinding out of the closure argument of run_compiler with pending delayed bugs
Diffstat (limited to 'compiler/rustc_interface/src/interface.rs')
| -rw-r--r-- | compiler/rustc_interface/src/interface.rs | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 71095ca8899..a631e9cd93c 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -5,9 +5,9 @@ use std::sync::Arc; use rustc_ast::{LitKind, MetaItemKind, token}; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::jobserver; use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::Lrc; -use rustc_data_structures::{defer, jobserver}; use rustc_errors::registry::Registry; use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed}; use rustc_lint::LintStore; @@ -492,21 +492,13 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se // There are two paths out of `f`. // - Normal exit. - // - Panic, e.g. triggered by `abort_if_errors`. + // - Panic, e.g. triggered by `abort_if_errors` or a fatal error. // // We must run `finish_diagnostics` in both cases. let res = { - // If `f` panics, `finish_diagnostics` will run during - // unwinding because of the `defer`. - let sess_abort_guard = defer(|| { - compiler.sess.finish_diagnostics(); - }); + let res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(&compiler))); - let res = f(&compiler); - - // If `f` doesn't panic, `finish_diagnostics` will run - // normally when `sess_abort_guard` is dropped. - drop(sess_abort_guard); + compiler.sess.finish_diagnostics(); // If error diagnostics have been emitted, we can't return an // 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 // mistakenly think that no errors occurred and return a zero // exit code. So we abort (panic) instead, similar to if `f` // had panicked. - compiler.sess.dcx().abort_if_errors(); + if res.is_ok() { + compiler.sess.dcx().abort_if_errors(); + } - res + // Also make sure to flush delayed bugs as if we panicked, the + // bugs would be flushed by the Drop impl of DiagCtxt while + // unwinding, which would result in an abort with + // "panic in a destructor during cleanup". + compiler.sess.dcx().flush_delayed(); + + match res { + Ok(res) => res, + Err(err) => std::panic::resume_unwind(err), + } }; let prof = compiler.sess.prof.clone(); |
