about summary refs log tree commit diff
path: root/compiler/rustc_interface/src
diff options
context:
space:
mode:
authorbjorn3 <17426603+bjorn3@users.noreply.github.com>2024-11-28 14:47:21 +0000
committerbjorn3 <17426603+bjorn3@users.noreply.github.com>2024-12-06 18:42:31 +0000
commit618d4c3eeb9a9f410f35b666e8b929056f820987 (patch)
tree1692bcdb0f7315280949aa7745ad3eb9adb5f5b5 /compiler/rustc_interface/src
parent401dd840ff301f13c4006132cc4e4eb80e9702eb (diff)
downloadrust-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')
-rw-r--r--compiler/rustc_interface/src/interface.rs31
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();