From 05c1ac0215ef282c9ed6df6a5f758d824ee1ace9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 31 Dec 2022 01:56:59 +0000 Subject: [PATCH] Collect backtraces for delayed span-bugs too --- compiler/rustc_driver/src/lib.rs | 6 ++--- compiler/rustc_errors/src/lib.rs | 38 +++++++++++++------------------- 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 3cbe0052359b3..fcb73c64356fd 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1196,8 +1196,8 @@ static DEFAULT_HOOK: LazyLock) + 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::() { + // Don't do this for delayed bugs, which already emit their own more useful backtrace. + if !info.payload().is::() { (*DEFAULT_HOOK)(info); // Separate the output with an empty line @@ -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::() - && !info.payload().is::() + && !info.payload().is::() { let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic"); handler.emit_diagnostic(&mut d); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b4d23e96f8f45..66e5c41f56c28 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -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; @@ -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, @@ -399,7 +398,7 @@ struct HandlerInner { warn_count: usize, deduplicated_err_count: usize, emitter: Box, - delayed_span_bugs: Vec, + delayed_span_bugs: Vec, delayed_good_path_bugs: Vec, /// This flag indicates that an expected diagnostic was emitted and suppressed. /// This is used for the `delayed_good_path_bugs` check. @@ -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! @@ -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, ); } @@ -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"); } } @@ -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()); @@ -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() } @@ -1605,12 +1596,13 @@ impl HandlerInner { fn flush_delayed( &mut self, - bugs: impl IntoIterator, + bugs: impl IntoIterator, explanation: impl Into + 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). @@ -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); } }