rustc_errors: Add the ability to delay as bugs

This adds a function to `DiagnosticBuilder` to delay the entire diagnostic as a
bug to be emitted at a later time. This'll end up getting used in the compiler
in the subsequent commits...
This commit is contained in:
Alex Crichton 2017-08-23 12:52:22 -07:00
parent 2aeb5930f3
commit 64b0b2bfeb
2 changed files with 26 additions and 12 deletions

View file

@ -110,6 +110,22 @@ impl<'a> DiagnosticBuilder<'a> {
// }
}
/// Delay emission of this diagnostic as a bug.
///
/// This can be useful in contexts where an error indicates a bug but
/// typically this only happens when other compilation errors have already
/// happened. In those cases this can be used to defer emission of this
/// diagnostic as a bug in the compiler only if no other errors have been
/// emitted.
///
/// In the meantime, though, callsites are required to deal with the "bug"
/// locally in whichever way makes the most sense.
pub fn delay_as_bug(&mut self) {
self.level = Level::Bug;
*self.handler.delayed_span_bug.borrow_mut() = Some(self.diagnostic.clone());
self.cancel();
}
/// Add a span/label to be included in the resulting snippet.
/// This is pushed onto the `MultiSpan` that was created when the
/// diagnostic was first built. If you don't call this function at
@ -182,8 +198,10 @@ impl<'a> DiagnosticBuilder<'a> {
DiagnosticBuilder::new_diagnostic(handler, diagnostic)
}
/// Creates a new `DiagnosticBuilder` with an already constructed diagnostic.
pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> DiagnosticBuilder<'a> {
/// Creates a new `DiagnosticBuilder` with an already constructed
/// diagnostic.
pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic)
-> DiagnosticBuilder<'a> {
DiagnosticBuilder { handler, diagnostic }
}
}

View file

@ -275,7 +275,7 @@ pub struct Handler {
pub can_emit_warnings: bool,
treat_err_as_bug: bool,
continue_after_error: Cell<bool>,
delayed_span_bug: RefCell<Option<(MultiSpan, String)>>,
delayed_span_bug: RefCell<Option<Diagnostic>>,
tracked_diagnostics: RefCell<Option<Vec<Diagnostic>>>,
}
@ -442,8 +442,9 @@ impl Handler {
if self.treat_err_as_bug {
self.span_bug(sp, msg);
}
let mut delayed = self.delayed_span_bug.borrow_mut();
*delayed = Some((sp.into(), msg.to_string()));
let mut diagnostic = Diagnostic::new(Level::Bug, msg);
diagnostic.set_span(sp.into());
*self.delayed_span_bug.borrow_mut() = Some(diagnostic);
}
pub fn span_bug_no_panic<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.emit(&sp.into(), msg, Bug);
@ -510,14 +511,9 @@ impl Handler {
let s;
match self.err_count.get() {
0 => {
let delayed_bug = self.delayed_span_bug.borrow();
match *delayed_bug {
Some((ref span, ref errmsg)) => {
self.span_bug(span.clone(), errmsg);
}
_ => {}
if let Some(bug) = self.delayed_span_bug.borrow_mut().take() {
DiagnosticBuilder::new_diagnostic(self, bug).emit();
}
return;
}
1 => s = "aborting due to previous error".to_string(),