about summary refs log tree commit diff
path: root/compiler/rustc_errors/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_errors/src')
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs6
-rw-r--r--compiler/rustc_errors/src/lib.rs95
2 files changed, 64 insertions, 37 deletions
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index 98b8b2a569e..72471638a96 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -128,7 +128,7 @@ impl EmissionGuarantee for ErrorGuaranteed {
             DiagnosticBuilderState::Emittable(handler) => {
                 db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
 
-                handler.emit_diagnostic(&db.inner.diagnostic);
+                let guar = handler.emit_diagnostic(&db.inner.diagnostic);
 
                 // Only allow a guarantee if the `level` wasn't switched to a
                 // non-error - the field isn't `pub`, but the whole `Diagnostic`
@@ -139,7 +139,7 @@ impl EmissionGuarantee for ErrorGuaranteed {
                      from `DiagnosticBuilder<ErrorGuaranteed>`",
                     db.inner.diagnostic.level,
                 );
-                ErrorGuaranteed
+                guar.unwrap()
             }
             // `.emit()` was previously called, disallowed from repeating it,
             // but can take advantage of the previous `.emit()`'s guarantee
@@ -154,7 +154,7 @@ impl EmissionGuarantee for ErrorGuaranteed {
                      became non-error ({:?}), after original `.emit()`",
                     db.inner.diagnostic.level,
                 );
-                ErrorGuaranteed
+                ErrorGuaranteed::unchecked_claim_error_was_emitted()
             }
         }
     }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 345247b0700..c719e4910ce 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -399,7 +399,7 @@ impl fmt::Display for ExplicitBug {
 impl error::Error for ExplicitBug {}
 
 pub use diagnostic::{Diagnostic, DiagnosticId, DiagnosticStyledString, SubDiagnostic};
-pub use diagnostic_builder::DiagnosticBuilder;
+pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee};
 use std::backtrace::Backtrace;
 
 /// A handler deals with errors and other compiler output.
@@ -644,8 +644,8 @@ impl Handler {
     }
 
     /// Emit all stashed diagnostics.
-    pub fn emit_stashed_diagnostics(&self) {
-        self.inner.borrow_mut().emit_stashed_diagnostics();
+    pub fn emit_stashed_diagnostics(&self) -> Option<ErrorGuaranteed> {
+        self.inner.borrow_mut().emit_stashed_diagnostics()
     }
 
     /// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
@@ -805,8 +805,8 @@ impl Handler {
         FatalError.raise()
     }
 
-    pub fn span_err(&self, span: impl Into<MultiSpan>, msg: &str) {
-        self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span);
+    pub fn span_err(&self, span: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed {
+        self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span).unwrap()
     }
 
     pub fn span_err_with_code(&self, span: impl Into<MultiSpan>, msg: &str, code: DiagnosticId) {
@@ -829,7 +829,7 @@ impl Handler {
     }
 
     #[track_caller]
-    pub fn delay_span_bug(&self, span: impl Into<MultiSpan>, msg: &str) {
+    pub fn delay_span_bug(&self, span: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed {
         self.inner.borrow_mut().delay_span_bug(span, msg)
     }
 
@@ -858,8 +858,8 @@ impl Handler {
         self.inner.borrow_mut().fatal(msg)
     }
 
-    pub fn err(&self, msg: &str) {
-        self.inner.borrow_mut().err(msg);
+    pub fn err(&self, msg: &str) -> ErrorGuaranteed {
+        self.inner.borrow_mut().err(msg)
     }
 
     pub fn warn(&self, msg: &str) {
@@ -880,11 +880,15 @@ impl Handler {
         self.inner.borrow().err_count()
     }
 
-    pub fn has_errors(&self) -> bool {
-        self.inner.borrow().has_errors()
+    pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
+        if self.inner.borrow().has_errors() { Some(ErrorGuaranteed(())) } else { None }
     }
-    pub fn has_errors_or_lint_errors(&self) -> bool {
-        self.inner.borrow().has_errors_or_lint_errors()
+    pub fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
+        if self.inner.borrow().has_errors_or_lint_errors() {
+            Some(ErrorGuaranteed(()))
+        } else {
+            None
+        }
     }
     pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
         self.inner.borrow().has_errors_or_delayed_span_bugs()
@@ -915,13 +919,17 @@ impl Handler {
         self.inner.borrow_mut().force_print_diagnostic(db)
     }
 
-    pub fn emit_diagnostic(&self, diagnostic: &Diagnostic) {
+    pub fn emit_diagnostic(&self, diagnostic: &Diagnostic) -> Option<ErrorGuaranteed> {
         self.inner.borrow_mut().emit_diagnostic(diagnostic)
     }
 
-    fn emit_diag_at_span(&self, mut diag: Diagnostic, sp: impl Into<MultiSpan>) {
+    fn emit_diag_at_span(
+        &self,
+        mut diag: Diagnostic,
+        sp: impl Into<MultiSpan>,
+    ) -> Option<ErrorGuaranteed> {
         let mut inner = self.inner.borrow_mut();
-        inner.emit_diagnostic(diag.set_span(sp));
+        inner.emit_diagnostic(diag.set_span(sp))
     }
 
     pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
@@ -990,13 +998,20 @@ impl HandlerInner {
     }
 
     /// Emit all stashed diagnostics.
-    fn emit_stashed_diagnostics(&mut self) {
+    fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
         let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::<Vec<_>>();
-        diags.iter().for_each(|diag| self.emit_diagnostic(diag));
+        let mut reported = None;
+        diags.iter().for_each(|diag| {
+            if diag.is_error() {
+                reported = Some(ErrorGuaranteed(()));
+            }
+            self.emit_diagnostic(diag);
+        });
+        reported
     }
 
     // FIXME(eddyb) this should ideally take `diagnostic` by value.
-    fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
+    fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) -> Option<ErrorGuaranteed> {
         if diagnostic.level == Level::DelayedBug {
             // FIXME(eddyb) this should check for `has_errors` and stop pushing
             // once *any* errors were emitted (and truncate `delayed_span_bugs`
@@ -1005,7 +1020,7 @@ impl HandlerInner {
             self.delayed_span_bugs.push(diagnostic.clone());
 
             if !self.flags.report_delayed_bugs {
-                return;
+                return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
             }
         }
 
@@ -1020,7 +1035,7 @@ impl HandlerInner {
             if diagnostic.has_future_breakage() {
                 (*TRACK_DIAGNOSTICS)(diagnostic);
             }
-            return;
+            return None;
         }
 
         // The `LintExpectationId` can be stable or unstable depending on when it was created.
@@ -1029,16 +1044,16 @@ impl HandlerInner {
         // a stable one by the `LintLevelsBuilder`.
         if let Level::Expect(LintExpectationId::Unstable { .. }) = diagnostic.level {
             self.unstable_expect_diagnostics.push(diagnostic.clone());
-            return;
+            return None;
         }
 
         (*TRACK_DIAGNOSTICS)(diagnostic);
 
         if let Level::Expect(expectation_id) = diagnostic.level {
             self.fulfilled_expectations.insert(expectation_id);
-            return;
+            return None;
         } else if diagnostic.level == Allow {
-            return;
+            return None;
         }
 
         if let Some(ref code) = diagnostic.code {
@@ -1068,8 +1083,12 @@ impl HandlerInner {
             } else {
                 self.bump_err_count();
             }
+
+            Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
         } else {
             self.bump_warn_count();
+
+            None
         }
     }
 
@@ -1191,7 +1210,7 @@ impl HandlerInner {
     }
 
     #[track_caller]
-    fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) {
+    fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed {
         // This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before
         // incrementing `err_count` by one, so we need to +1 the comparing.
         // FIXME: Would be nice to increment err_count in a more coherent way.
@@ -1202,7 +1221,7 @@ impl HandlerInner {
         let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg);
         diagnostic.set_span(sp.into());
         diagnostic.note(&format!("delayed at {}", std::panic::Location::caller()));
-        self.emit_diagnostic(&diagnostic)
+        self.emit_diagnostic(&diagnostic).unwrap()
     }
 
     // FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's
@@ -1221,20 +1240,20 @@ impl HandlerInner {
     }
 
     fn fatal(&mut self, msg: &str) -> FatalError {
-        self.emit_error(Fatal, msg);
+        self.emit(Fatal, msg);
         FatalError
     }
 
-    fn err(&mut self, msg: &str) {
-        self.emit_error(Error { lint: false }, msg);
+    fn err(&mut self, msg: &str) -> ErrorGuaranteed {
+        self.emit(Error { lint: false }, msg)
     }
 
     /// Emit an error; level should be `Error` or `Fatal`.
-    fn emit_error(&mut self, level: Level, msg: &str) {
+    fn emit(&mut self, level: Level, msg: &str) -> ErrorGuaranteed {
         if self.treat_err_as_bug() {
             self.bug(msg);
         }
-        self.emit_diagnostic(&Diagnostic::new(level, msg));
+        self.emit_diagnostic(&Diagnostic::new(level, msg)).unwrap()
     }
 
     fn bug(&mut self, msg: &str) -> ! {
@@ -1433,9 +1452,17 @@ pub fn add_elided_lifetime_in_path_suggestion(
     );
 }
 
-// Useful type to use with `Result<>` indicate that an error has already
-// been reported to the user, so no need to continue checking.
-#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq)]
-pub struct ErrorGuaranteed;
+/// Useful type to use with `Result<>` indicate that an error has already
+/// been reported to the user, so no need to continue checking.
+#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)]
+pub struct ErrorGuaranteed(());
+
+impl ErrorGuaranteed {
+    /// To be used only if you really know what you are doing... ideally, we would find a way to
+    /// eliminate all calls to this method.
+    pub fn unchecked_claim_error_was_emitted() -> Self {
+        ErrorGuaranteed(())
+    }
+}
 
 rustc_data_structures::impl_stable_hash_via_hash!(ErrorGuaranteed);