Handle unwinding out of the closure argument of run_compiler with pending delayed bugs
This commit is contained in:
parent
401dd840ff
commit
618d4c3eeb
2 changed files with 24 additions and 17 deletions
|
@ -622,9 +622,7 @@ impl Drop for DiagCtxtInner {
|
|||
// Important: it is sound to produce an `ErrorGuaranteed` when emitting
|
||||
// delayed bugs because they are guaranteed to be emitted here if
|
||||
// necessary.
|
||||
if self.err_guars.is_empty() {
|
||||
self.flush_delayed()
|
||||
}
|
||||
self.flush_delayed();
|
||||
|
||||
// Sanity check: did we use some of the expensive `trimmed_def_paths` functions
|
||||
// unexpectedly, that is, without producing diagnostics? If so, for debugging purposes, we
|
||||
|
@ -1705,7 +1703,13 @@ impl DiagCtxtInner {
|
|||
// eventually happened.
|
||||
assert!(self.stashed_diagnostics.is_empty());
|
||||
|
||||
if !self.err_guars.is_empty() {
|
||||
// If an error happened already. We shouldn't expose delayed bugs.
|
||||
return;
|
||||
}
|
||||
|
||||
if self.delayed_bugs.is_empty() {
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue