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`
fn annotation_type_for_level(level: Level) -> AnnotationType {
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::Note | Level::OnceNote => AnnotationType::Note,
Level::Help | Level::OnceHelp => AnnotationType::Help,

View File

@ -1,7 +1,7 @@
use crate::snippet::Style;
use crate::{
CodeSuggestion, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level, MultiSpan,
SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level,
MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_error_messages::fluent_value_from_str_list_sep_by_and;
@ -243,12 +243,15 @@ impl Diagnostic {
pub fn is_error(&self) -> bool {
match self.level {
Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error | Level::FailureNote => {
true
}
Level::Bug
| Level::DelayedBug(DelayedBugKind::Normal)
| Level::Fatal
| Level::Error
| Level::FailureNote => true,
Level::ForceWarning(_)
| Level::Warning
| Level::DelayedBug(DelayedBugKind::GoodPath)
| Level::Note
| Level::OnceNote
| Level::Help
@ -318,7 +321,7 @@ impl Diagnostic {
"downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error",
self.level
);
self.level = Level::DelayedBug;
self.level = Level::DelayedBug(DelayedBugKind::Normal);
}
/// 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))> =
AtomicRef::new(&(default_track_diagnostic as _));
enum DelayedBugKind {
#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)]
pub enum DelayedBugKind {
Normal,
GoodPath,
}
@ -865,7 +866,8 @@ impl DiagCtxt {
if treat_next_err_as_bug {
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.
@ -882,16 +884,15 @@ impl DiagCtxt {
if treat_next_err_as_bug {
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
// where the explanation of what "good path" is (also, it should be renamed).
pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) {
let mut inner = self.inner.borrow_mut();
let diagnostic = Diagnostic::new(DelayedBug, msg);
let backtrace = std::backtrace::Backtrace::capture();
inner.good_path_delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
DiagnosticBuilder::<()>::new(self, DelayedBug(DelayedBugKind::GoodPath), msg).emit()
}
#[track_caller]
@ -1268,17 +1269,27 @@ impl DiagCtxtInner {
return None;
}
if diagnostic.level == DelayedBug {
// FIXME(eddyb) this should check for `has_errors` and stop pushing
// once *any* errors were emitted (and truncate `span_delayed_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.
let backtrace = std::backtrace::Backtrace::capture();
self.span_delayed_bugs
.push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
// FIXME(eddyb) this should check for `has_errors` and stop pushing
// once *any* errors were emitted (and truncate `span_delayed_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.
match diagnostic.level {
DelayedBug(DelayedBugKind::Normal) => {
let backtrace = std::backtrace::Backtrace::capture();
self.span_delayed_bugs
.push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
#[allow(deprecated)]
return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
#[allow(deprecated)]
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() {
@ -1438,7 +1449,7 @@ impl DiagCtxtInner {
if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
// "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
// an ICE, and the more information the merrier.
bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel {
@ -1526,8 +1537,9 @@ pub enum Level {
/// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths
/// that should only be reached when compiling erroneous code.
///
/// Its `EmissionGuarantee` is `ErrorGuaranteed`.
DelayedBug,
/// Its `EmissionGuarantee` is `ErrorGuaranteed` for `Normal` delayed bugs, and `()` for
/// `GoodPath` delayed bugs.
DelayedBug(DelayedBugKind),
/// An error that causes an immediate abort. Used for things like configuration errors,
/// internal overflows, some file operation errors.
@ -1602,7 +1614,7 @@ impl Level {
fn color(self) -> ColorSpec {
let mut spec = ColorSpec::new();
match self {
Bug | DelayedBug | Fatal | Error => {
Bug | DelayedBug(_) | Fatal | Error => {
spec.set_fg(Some(Color::Red)).set_intense(true);
}
ForceWarning(_) | Warning => {
@ -1622,7 +1634,7 @@ impl Level {
pub fn to_str(self) -> &'static str {
match self {
Bug | DelayedBug => "error: internal compiler error",
Bug | DelayedBug(_) => "error: internal compiler error",
Fatal | Error => "error",
ForceWarning(_) | Warning => "warning",
Note | OnceNote => "note",