From 64b0b2bfebf857f25f826ca9ebb07630287bc4d0 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 23 Aug 2017 12:52:22 -0700 Subject: [PATCH] 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... --- src/librustc_errors/diagnostic_builder.rs | 22 ++++++++++++++++++++-- src/librustc_errors/lib.rs | 16 ++++++---------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 0a8119893509..2c8d8b4691f0 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -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 } } } diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index a51e6022350c..60f9276c0ca8 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -275,7 +275,7 @@ pub struct Handler { pub can_emit_warnings: bool, treat_err_as_bug: bool, continue_after_error: Cell, - delayed_span_bug: RefCell>, + delayed_span_bug: RefCell>, tracked_diagnostics: RefCell>>, } @@ -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>(&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(),