Good path bugs are just a flavor of delayed bug

This commit is contained in:
Michael Goulet 2024-01-12 03:15:14 +00:00
parent 3330940f7f
commit eb79bc0470
3 changed files with 44 additions and 29 deletions

View File

@ -85,7 +85,7 @@ fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
/// Maps `Diagnostic::Level` to `snippet::AnnotationType` /// Maps `Diagnostic::Level` to `snippet::AnnotationType`
fn annotation_type_for_level(level: Level) -> AnnotationType { fn annotation_type_for_level(level: Level) -> AnnotationType {
match level { match level {
Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error => AnnotationType::Error, Level::Bug | Level::DelayedBug(_) | Level::Fatal | Level::Error => AnnotationType::Error,
Level::ForceWarning(_) | Level::Warning => AnnotationType::Warning, Level::ForceWarning(_) | Level::Warning => AnnotationType::Warning,
Level::Note | Level::OnceNote => AnnotationType::Note, Level::Note | Level::OnceNote => AnnotationType::Note,
Level::Help | Level::OnceHelp => AnnotationType::Help, Level::Help | Level::OnceHelp => AnnotationType::Help,

View File

@ -1,7 +1,7 @@
use crate::snippet::Style; use crate::snippet::Style;
use crate::{ use crate::{
CodeSuggestion, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level, MultiSpan, CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level,
SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle, MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
}; };
use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_error_messages::fluent_value_from_str_list_sep_by_and; use rustc_error_messages::fluent_value_from_str_list_sep_by_and;
@ -243,12 +243,15 @@ impl Diagnostic {
pub fn is_error(&self) -> bool { pub fn is_error(&self) -> bool {
match self.level { match self.level {
Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error | Level::FailureNote => { Level::Bug
true | Level::DelayedBug(DelayedBugKind::Normal)
} | Level::Fatal
| Level::Error
| Level::FailureNote => true,
Level::ForceWarning(_) Level::ForceWarning(_)
| Level::Warning | Level::Warning
| Level::DelayedBug(DelayedBugKind::GoodPath)
| Level::Note | Level::Note
| Level::OnceNote | Level::OnceNote
| Level::Help | Level::Help
@ -318,7 +321,7 @@ impl Diagnostic {
"downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error", "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error",
self.level self.level
); );
self.level = Level::DelayedBug; self.level = Level::DelayedBug(DelayedBugKind::Normal);
} }
/// Appends a labeled span to the diagnostic. /// Appends a labeled span to the diagnostic.

View File

@ -519,7 +519,8 @@ fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) {
pub static TRACK_DIAGNOSTIC: AtomicRef<fn(Diagnostic, &mut dyn FnMut(Diagnostic))> = pub static TRACK_DIAGNOSTIC: AtomicRef<fn(Diagnostic, &mut dyn FnMut(Diagnostic))> =
AtomicRef::new(&(default_track_diagnostic as _)); AtomicRef::new(&(default_track_diagnostic as _));
enum DelayedBugKind { #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)]
pub enum DelayedBugKind {
Normal, Normal,
GoodPath, GoodPath,
} }
@ -865,7 +866,8 @@ impl DiagCtxt {
if treat_next_err_as_bug { if treat_next_err_as_bug {
self.bug(msg); self.bug(msg);
} }
DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug, msg).emit() DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg)
.emit()
} }
/// Like `delayed_bug`, but takes an additional span. /// Like `delayed_bug`, but takes an additional span.
@ -882,16 +884,15 @@ impl DiagCtxt {
if treat_next_err_as_bug { if treat_next_err_as_bug {
self.span_bug(sp, msg); self.span_bug(sp, msg);
} }
DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug, msg).with_span(sp).emit() DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg)
.with_span(sp)
.emit()
} }
// FIXME(eddyb) note the comment inside `impl Drop for DiagCtxtInner`, that's // FIXME(eddyb) note the comment inside `impl Drop for DiagCtxtInner`, that's
// where the explanation of what "good path" is (also, it should be renamed). // where the explanation of what "good path" is (also, it should be renamed).
pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) { pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) {
let mut inner = self.inner.borrow_mut(); DiagnosticBuilder::<()>::new(self, DelayedBug(DelayedBugKind::GoodPath), msg).emit()
let diagnostic = Diagnostic::new(DelayedBug, msg);
let backtrace = std::backtrace::Backtrace::capture();
inner.good_path_delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
} }
#[track_caller] #[track_caller]
@ -1268,17 +1269,27 @@ impl DiagCtxtInner {
return None; return None;
} }
if diagnostic.level == DelayedBug { // FIXME(eddyb) this should check for `has_errors` and stop pushing
// FIXME(eddyb) this should check for `has_errors` and stop pushing // once *any* errors were emitted (and truncate `span_delayed_bugs`
// once *any* errors were emitted (and truncate `span_delayed_bugs` // when an error is first emitted, also), but maybe there's a case
// when an error is first emitted, also), but maybe there's a case // in which that's not sound? otherwise this is really inefficient.
// in which that's not sound? otherwise this is really inefficient. match diagnostic.level {
let backtrace = std::backtrace::Backtrace::capture(); DelayedBug(DelayedBugKind::Normal) => {
self.span_delayed_bugs let backtrace = std::backtrace::Backtrace::capture();
.push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace)); self.span_delayed_bugs
.push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
#[allow(deprecated)] #[allow(deprecated)]
return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
}
DelayedBug(DelayedBugKind::GoodPath) => {
let backtrace = std::backtrace::Backtrace::capture();
self.good_path_delayed_bugs
.push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
return None;
}
_ => {}
} }
if diagnostic.has_future_breakage() { if diagnostic.has_future_breakage() {
@ -1438,7 +1449,7 @@ impl DiagCtxtInner {
if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner }; if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
// "Undelay" the `DelayedBug`s (into plain `Bug`s). // "Undelay" the `DelayedBug`s (into plain `Bug`s).
if bug.level != DelayedBug { if !matches!(bug.level, DelayedBug(_)) {
// NOTE(eddyb) not panicking here because we're already producing // NOTE(eddyb) not panicking here because we're already producing
// an ICE, and the more information the merrier. // an ICE, and the more information the merrier.
bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel { bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel {
@ -1526,8 +1537,9 @@ pub enum Level {
/// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths /// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths
/// that should only be reached when compiling erroneous code. /// that should only be reached when compiling erroneous code.
/// ///
/// Its `EmissionGuarantee` is `ErrorGuaranteed`. /// Its `EmissionGuarantee` is `ErrorGuaranteed` for `Normal` delayed bugs, and `()` for
DelayedBug, /// `GoodPath` delayed bugs.
DelayedBug(DelayedBugKind),
/// An error that causes an immediate abort. Used for things like configuration errors, /// An error that causes an immediate abort. Used for things like configuration errors,
/// internal overflows, some file operation errors. /// internal overflows, some file operation errors.
@ -1602,7 +1614,7 @@ impl Level {
fn color(self) -> ColorSpec { fn color(self) -> ColorSpec {
let mut spec = ColorSpec::new(); let mut spec = ColorSpec::new();
match self { match self {
Bug | DelayedBug | Fatal | Error => { Bug | DelayedBug(_) | Fatal | Error => {
spec.set_fg(Some(Color::Red)).set_intense(true); spec.set_fg(Some(Color::Red)).set_intense(true);
} }
ForceWarning(_) | Warning => { ForceWarning(_) | Warning => {
@ -1622,7 +1634,7 @@ impl Level {
pub fn to_str(self) -> &'static str { pub fn to_str(self) -> &'static str {
match self { match self {
Bug | DelayedBug => "error: internal compiler error", Bug | DelayedBug(_) => "error: internal compiler error",
Fatal | Error => "error", Fatal | Error => "error",
ForceWarning(_) | Warning => "warning", ForceWarning(_) | Warning => "warning",
Note | OnceNote => "note", Note | OnceNote => "note",