Skip to content

Commit

Permalink
Collect backtraces for delayed span-bugs too
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Jan 9, 2023
1 parent 3020239 commit 05c1ac0
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 26 deletions.
6 changes: 3 additions & 3 deletions compiler/rustc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1196,8 1196,8 @@ static DEFAULT_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) Sync Send
};

// Invoke the default handler, which prints the actual panic message and optionally a backtrace
// Don't do this for `GoodPathBug`, which already emits its own more useful backtrace.
if !info.payload().is::<rustc_errors::GoodPathBug>() {
// Don't do this for delayed bugs, which already emit their own more useful backtrace.
if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
(*DEFAULT_HOOK)(info);

// Separate the output with an empty line
Expand Down Expand Up @@ -1235,7 1235,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
// a .span_bug or .bug call has already printed what
// it wants to print.
if !info.payload().is::<rustc_errors::ExplicitBug>()
&& !info.payload().is::<rustc_errors::GoodPathBug>()
&& !info.payload().is::<rustc_errors::DelayedBugPanic>()
{
let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
handler.emit_diagnostic(&mut d);
Expand Down
38 changes: 15 additions & 23 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 40,6 @@ use rustc_span::source_map::SourceMap;
use rustc_span::HashStableContext;
use rustc_span::{Loc, Span};

use std::any::Any;
use std::borrow::Cow;
use std::fmt;
use std::hash::Hash;
Expand Down Expand Up @@ -364,9 363,9 @@ pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker};
/// or `.span_bug` rather than a failed assertion, etc.
pub struct ExplicitBug;

/// Signifies that the compiler died with an explicit call to `.delay_good_path_bug`
/// Signifies that the compiler died with an explicit call to `.delay_*_bug`
/// rather than a failed assertion, etc.
pub struct GoodPathBug;
pub struct DelayedBugPanic;

pub use diagnostic::{
AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId,
Expand Down Expand Up @@ -399,7 398,7 @@ struct HandlerInner {
warn_count: usize,
deduplicated_err_count: usize,
emitter: Box<dyn Emitter sync::Send>,
delayed_span_bugs: Vec<Diagnostic>,
delayed_span_bugs: Vec<DelayedDiagnostic>,
delayed_good_path_bugs: Vec<DelayedDiagnostic>,
/// This flag indicates that an expected diagnostic was emitted and suppressed.
/// This is used for the `delayed_good_path_bugs` check.
Expand Down Expand Up @@ -505,11 504,7 @@ impl Drop for HandlerInner {

if !self.has_errors() {
let bugs = std::mem::replace(&mut self.delayed_span_bugs, Vec::new());
self.flush_delayed(
bugs,
"no errors encountered even though `delay_span_bug` issued",
ExplicitBug,
);
self.flush_delayed(bugs, "no errors encountered even though `delay_span_bug` issued");
}

// FIXME(eddyb) this explains what `delayed_good_path_bugs` are!
Expand All @@ -520,9 515,8 @@ impl Drop for HandlerInner {
if !self.has_any_message() && !self.suppressed_expected_diag {
let bugs = std::mem::replace(&mut self.delayed_good_path_bugs, Vec::new());
self.flush_delayed(
bugs.into_iter().map(DelayedDiagnostic::decorate),
bugs,
"no warnings or errors encountered even though `delayed_good_path_bugs` issued",
GoodPathBug,
);
}

Expand Down Expand Up @@ -1223,11 1217,7 @@ impl Handler {
pub fn flush_delayed(&self) {
let mut inner = self.inner.lock();
let bugs = std::mem::replace(&mut inner.delayed_span_bugs, Vec::new());
inner.flush_delayed(
bugs,
"no errors encountered even though `delay_span_bug` issued",
ExplicitBug,
);
inner.flush_delayed(bugs, "no errors encountered even though `delay_span_bug` issued");
}
}

Expand Down Expand Up @@ -1287,7 1277,9 @@ impl HandlerInner {
// once *any* errors were emitted (and truncate `delayed_span_bugs`
// when an error is first emitted, also), but maybe there's a case
// in which that's not sound? otherwise this is really inefficient.
self.delayed_span_bugs.push(diagnostic.clone());
let backtrace = std::backtrace::Backtrace::force_capture();
self.delayed_span_bugs
.push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));

if !self.flags.report_delayed_bugs {
return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
Expand Down Expand Up @@ -1562,7 1554,6 @@ impl HandlerInner {
}
let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg);
diagnostic.set_span(sp.into());
diagnostic.note(&format!("delayed at {}", std::panic::Location::caller()));
self.emit_diagnostic(&mut diagnostic).unwrap()
}

Expand Down Expand Up @@ -1605,12 1596,13 @@ impl HandlerInner {

fn flush_delayed(
&mut self,
bugs: impl IntoIterator<Item = Diagnostic>,
bugs: impl IntoIterator<Item = DelayedDiagnostic>,
explanation: impl Into<DiagnosticMessage> Copy,
panic_with: impl Any Send 'static,
) {
let mut no_bugs = true;
for mut bug in bugs {
for bug in bugs {
let mut bug = bug.decorate();

if no_bugs {
// Put the overall explanation before the `DelayedBug`s, to
// frame them better (e.g. separate warnings from them).
Expand All @@ -1633,9 1625,9 @@ impl HandlerInner {
self.emit_diagnostic(&mut bug);
}

// Panic with `ExplicitBug` to avoid "unexpected panic" messages.
// Panic with `DelayedBugPanic` to avoid "unexpected panic" messages.
if !no_bugs {
panic::panic_any(panic_with);
panic::panic_any(DelayedBugPanic);
}
}

Expand Down

0 comments on commit 05c1ac0

Please sign in to comment.