summary refs log tree commit diff
path: root/src/librustc_errors
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-08-26 08:25:44 +0000
committerbors <bors@rust-lang.org>2017-08-26 08:25:44 +0000
commite7070dd019d70b089a9983571dc40b2f9ee16cf5 (patch)
treec7bd0ec6c84ed33a48d09047699659ba2425be6c /src/librustc_errors
parent398aaffc94367ed59420f5ac0b0238c04c9e4fa5 (diff)
parentc766aa4e3b90c17ed6ded91e964c3537ba5eb14b (diff)
downloadrust-e7070dd019d70b089a9983571dc40b2f9ee16cf5.tar.gz
rust-e7070dd019d70b089a9983571dc40b2f9ee16cf5.zip
Auto merge of #44071 - alexcrichton:no-cycles, r=nikomatsakis
rustc: Start moving toward "try_get is a bug" for incremental

This PR is an effort to burn down some of the work items on #42633. The basic change here was to leave the `try_get` function exposed but have it return a `DiagnosticBuilder` instead of a `CycleError`. This means that it should be a compiler bug to *not* handle the error as dropping a diagnostic should result in a complier panic.

After that change it was then necessary to update the compiler's callsites of `try_get` to handle the error coming out. These were handled as:

* The `sized_constraint` and `needs_drop_raw` checks take the diagnostic and defer it as a compiler bug. This was a new piece of functionality added to the error handling infrastructure, and the idea is that for both these checks a "real" compiler error should be emitted elsewhere, so it's only a bug if we don't actually emit the complier error elsewhere.
* MIR inlining was updated to just ignore the diagnostic. This is being tracked by https://github.com/rust-lang/rust/issues/43542 which sounded like it either already had some work underway or was planning to change regardless.
* The final case, `item_path`, is still sort of up for debate. At the time of this writing this PR simply removes the invocations of `try_get` there, assuming that the query will always succeed. This turns out to be true for the test suite anyway! It sounds like, though, that this logic was intended to assist in "weird" situations like `RUST_LOG` where debug implementations can trigger at any time. This PR would therefore, however, break those implementations.

I'm unfortunately sort of out of ideas on how to handle `item_path`, but other thoughts would be welcome!

Closes #42633
Diffstat (limited to 'src/librustc_errors')
-rw-r--r--src/librustc_errors/diagnostic_builder.rs22
-rw-r--r--src/librustc_errors/lib.rs16
2 files changed, 26 insertions, 12 deletions
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index 0a811989350..2c8d8b4691f 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 02cb1ede2b1..2f5aac65b92 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -272,7 +272,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>>>,
 }
 
@@ -439,8 +439,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);
@@ -507,14 +508,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(),