Good path bugs are just a flavor of delayed bug
This commit is contained in:
parent
3330940f7f
commit
eb79bc0470
3 changed files with 44 additions and 29 deletions
|
@ -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",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue