about summary refs log tree commit diff
path: root/compiler/rustc_errors/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_errors/src/lib.rs')
-rw-r--r--compiler/rustc_errors/src/lib.rs74
1 files changed, 62 insertions, 12 deletions
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 395bf5aad01..fe2afdf5a20 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -625,19 +625,13 @@ impl Handler {
     /// Stash a given diagnostic with the given `Span` and `StashKey` as the key for later stealing.
     pub fn stash_diagnostic(&self, span: Span, key: StashKey, diag: Diagnostic) {
         let mut inner = self.inner.borrow_mut();
-        // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic
-        // if/when we have a more robust macro-friendly replacement for `(span, key)` as a key.
-        // See the PR for a discussion.
-        inner.stashed_diagnostics.insert((span, key), diag);
+        inner.stash((span, key), diag);
     }
 
     /// Steal a previously stashed diagnostic with the given `Span` and `StashKey` as the key.
     pub fn steal_diagnostic(&self, span: Span, key: StashKey) -> Option<DiagnosticBuilder<'_, ()>> {
-        self.inner
-            .borrow_mut()
-            .stashed_diagnostics
-            .remove(&(span, key))
-            .map(|diag| DiagnosticBuilder::new_diagnostic(self, diag))
+        let mut inner = self.inner.borrow_mut();
+        inner.steal((span, key)).map(|diag| DiagnosticBuilder::new_diagnostic(self, diag))
     }
 
     /// Emit all stashed diagnostics.
@@ -1105,13 +1099,31 @@ impl HandlerInner {
 
     /// Emit all stashed diagnostics.
     fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
+        let has_errors = self.has_errors();
         let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::<Vec<_>>();
         let mut reported = None;
         for mut diag in diags {
+            // Decrement the count tracking the stash; emitting will increment it.
             if diag.is_error() {
-                reported = Some(ErrorGuaranteed(()));
+                if matches!(diag.level, Level::Error { lint: true }) {
+                    self.lint_err_count -= 1;
+                } else {
+                    self.err_count -= 1;
+                }
+            } else {
+                if diag.is_force_warn() {
+                    self.warn_count -= 1;
+                } else {
+                    // Unless they're forced, don't flush stashed warnings when
+                    // there are errors, to avoid causing warning overload. The
+                    // stash would've been stolen already if it were important.
+                    if has_errors {
+                        continue;
+                    }
+                }
             }
-            self.emit_diagnostic(&mut diag);
+            let reported_this = self.emit_diagnostic(&mut diag);
+            reported = reported.or(reported_this);
         }
         reported
     }
@@ -1301,9 +1313,47 @@ impl HandlerInner {
         }
     }
 
+    fn stash(&mut self, key: (Span, StashKey), diagnostic: Diagnostic) {
+        // Track the diagnostic for counts, but don't panic-if-treat-err-as-bug
+        // yet; that happens when we actually emit the diagnostic.
+        if diagnostic.is_error() {
+            if matches!(diagnostic.level, Level::Error { lint: true }) {
+                self.lint_err_count += 1;
+            } else {
+                self.err_count += 1;
+            }
+        } else {
+            // Warnings are only automatically flushed if they're forced.
+            if diagnostic.is_force_warn() {
+                self.warn_count += 1;
+            }
+        }
+
+        // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic
+        // if/when we have a more robust macro-friendly replacement for `(span, key)` as a key.
+        // See the PR for a discussion.
+        self.stashed_diagnostics.insert(key, diagnostic);
+    }
+
+    fn steal(&mut self, key: (Span, StashKey)) -> Option<Diagnostic> {
+        let diagnostic = self.stashed_diagnostics.remove(&key)?;
+        if diagnostic.is_error() {
+            if matches!(diagnostic.level, Level::Error { lint: true }) {
+                self.lint_err_count -= 1;
+            } else {
+                self.err_count -= 1;
+            }
+        } else {
+            if diagnostic.is_force_warn() {
+                self.warn_count -= 1;
+            }
+        }
+        Some(diagnostic)
+    }
+
     #[inline]
     fn err_count(&self) -> usize {
-        self.err_count + self.stashed_diagnostics.len()
+        self.err_count
     }
 
     fn has_errors(&self) -> bool {