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.rs50
1 files changed, 32 insertions, 18 deletions
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 0a533833e64..6b1ccbc5f7c 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -712,6 +712,7 @@ impl DiagCtxt {
     /// Stashes a diagnostic for possible later improvement in a different,
     /// later stage of the compiler. Possible actions depend on the diagnostic
     /// level:
+    /// - Level::Bug, Level:Fatal: not allowed, will trigger a panic.
     /// - Level::Error: immediately counted as an error that has occurred, because it
     ///   is guaranteed to be emitted eventually. Can be later accessed with the
     ///   provided `span` and `key` through
@@ -719,26 +720,39 @@ impl DiagCtxt {
     ///   [`DiagCtxt::try_steal_replace_and_emit_err`]. These do not allow
     ///   cancellation or downgrading of the error. Returns
     ///   `Some(ErrorGuaranteed)`.
+    /// - Level::DelayedBug: this does happen occasionally with errors that are
+    ///   downgraded to delayed bugs. It is not stashed, but immediately
+    ///   emitted as a delayed bug. This is because stashing it would cause it
+    ///   to be counted by `err_count` which we don't want. It doesn't matter
+    ///   that we cannot steal and improve it later, because it's not a
+    ///   user-facing error. Returns `Some(ErrorGuaranteed)` as is normal for
+    ///   delayed bugs.
     /// - Level::Warning and lower (i.e. !is_error()): can be accessed with the
     ///   provided `span` and `key` through [`DiagCtxt::steal_non_err()`]. This
     ///   allows cancelling and downgrading of the diagnostic. Returns `None`.
-    /// - Others: not allowed, will trigger a panic.
     pub fn stash_diagnostic(
         &self,
         span: Span,
         key: StashKey,
         diag: DiagInner,
     ) -> Option<ErrorGuaranteed> {
-        let guar = if diag.level() == Level::Error {
-            // This `unchecked_error_guaranteed` is valid. It is where the
-            // `ErrorGuaranteed` for stashed errors originates. See
-            // `DiagCtxtInner::drop`.
-            #[allow(deprecated)]
-            Some(ErrorGuaranteed::unchecked_error_guaranteed())
-        } else if !diag.is_error() {
-            None
-        } else {
-            self.span_bug(span, format!("invalid level in `stash_diagnostic`: {}", diag.level));
+        let guar = match diag.level {
+            Bug | Fatal => {
+                self.span_bug(
+                    span,
+                    format!("invalid level in `stash_diagnostic`: {:?}", diag.level),
+                );
+            }
+            Error => {
+                // This `unchecked_error_guaranteed` is valid. It is where the
+                // `ErrorGuaranteed` for stashed errors originates. See
+                // `DiagCtxtInner::drop`.
+                #[allow(deprecated)]
+                Some(ErrorGuaranteed::unchecked_error_guaranteed())
+            }
+            DelayedBug => return self.inner.borrow_mut().emit_diagnostic(diag),
+            ForceWarning(_) | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow
+            | Expect(_) => None,
         };
 
         // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic
@@ -780,11 +794,11 @@ impl DiagCtxt {
         let err = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key);
         err.map(|(err, guar)| {
             // The use of `::<ErrorGuaranteed>` is safe because level is `Level::Error`.
-            assert_eq!(err.level, Level::Error);
+            assert_eq!(err.level, Error);
             assert!(guar.is_some());
             let mut err = Diag::<ErrorGuaranteed>::new_diagnostic(self, err);
             modify_err(&mut err);
-            assert_eq!(err.level, Level::Error);
+            assert_eq!(err.level, Error);
             err.emit()
         })
     }
@@ -803,7 +817,7 @@ impl DiagCtxt {
         let old_err = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key);
         match old_err {
             Some((old_err, guar)) => {
-                assert_eq!(old_err.level, Level::Error);
+                assert_eq!(old_err.level, Error);
                 assert!(guar.is_some());
                 // Because `old_err` has already been counted, it can only be
                 // safely cancelled because the `new_err` supplants it.
@@ -1367,7 +1381,7 @@ impl DiagCtxtInner {
         }
 
         if diagnostic.has_future_breakage() {
-            // Future breakages aren't emitted if they're Level::Allow,
+            // Future breakages aren't emitted if they're `Level::Allow`,
             // but they still need to be constructed and stashed below,
             // so they'll trigger the must_produce_diag check.
             self.suppressed_expected_diag = true;
@@ -1453,7 +1467,7 @@ impl DiagCtxtInner {
                 diagnostic.children.extract_if(already_emitted_sub).for_each(|_| {});
                 if already_emitted {
                     let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`";
-                    diagnostic.sub(Level::Note, msg, MultiSpan::new());
+                    diagnostic.sub(Note, msg, MultiSpan::new());
                 }
 
                 if is_error {
@@ -1623,7 +1637,7 @@ impl DiagCtxtInner {
                 bug.arg("level", bug.level);
                 let msg = crate::fluent_generated::errors_invalid_flushed_delayed_diagnostic_level;
                 let msg = self.eagerly_translate_for_subdiag(&bug, msg); // after the `arg` call
-                bug.sub(Level::Note, msg, bug.span.primary_span().unwrap().into());
+                bug.sub(Note, msg, bug.span.primary_span().unwrap().into());
             }
             bug.level = Bug;
 
@@ -1671,7 +1685,7 @@ impl DelayedDiagInner {
         diag.arg("emitted_at", diag.emitted_at.clone());
         diag.arg("note", self.note);
         let msg = dcx.eagerly_translate_for_subdiag(&diag, msg); // after the `arg` calls
-        diag.sub(Level::Note, msg, diag.span.primary_span().unwrap_or(DUMMY_SP).into());
+        diag.sub(Note, msg, diag.span.primary_span().unwrap_or(DUMMY_SP).into());
         diag
     }
 }