about summary refs log tree commit diff
path: root/compiler/rustc_errors/src
diff options
context:
space:
mode:
authorThe Miri Conjob Bot <miri@cron.bot>2024-01-13 05:03:10 +0000
committerThe Miri Conjob Bot <miri@cron.bot>2024-01-13 05:03:10 +0000
commit9b46f3bb6499c263c9c81e7cea4815396bbbce14 (patch)
treeab6ca2c31a68888b7c34f3b091e899054f3a56aa /compiler/rustc_errors/src
parent86190488cd05ffd48394d9d1c464d7f50ee19614 (diff)
parentf1f8687b06a5908dd096f51da32347b3313279db (diff)
downloadrust-9b46f3bb6499c263c9c81e7cea4815396bbbce14.tar.gz
rust-9b46f3bb6499c263c9c81e7cea4815396bbbce14.zip
Merge from rustc
Diffstat (limited to 'compiler/rustc_errors/src')
-rw-r--r--compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs13
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs15
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs30
-rw-r--r--compiler/rustc_errors/src/lib.rs122
-rw-r--r--compiler/rustc_errors/src/markdown/tests/term.rs5
5 files changed, 89 insertions, 96 deletions
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
index 97f2efa7874..648c9118400 100644
--- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
+++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
@@ -12,8 +12,7 @@ use crate::{
     CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle,
     LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic,
 };
-use annotate_snippets::display_list::{DisplayList, FormatOptions};
-use annotate_snippets::snippet::*;
+use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
 use rustc_data_structures::sync::Lrc;
 use rustc_error_messages::FluentArgs;
 use rustc_span::source_map::SourceMap;
@@ -86,7 +85,7 @@ fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
 /// Maps `Diagnostic::Level` to `snippet::AnnotationType`
 fn annotation_type_for_level(level: Level) -> AnnotationType {
     match level {
-        Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error => AnnotationType::Error,
+        Level::Bug | Level::DelayedBug(_) | Level::Fatal | Level::Error => AnnotationType::Error,
         Level::ForceWarning(_) | Level::Warning => AnnotationType::Warning,
         Level::Note | Level::OnceNote => AnnotationType::Note,
         Level::Help | Level::OnceHelp => AnnotationType::Help,
@@ -190,11 +189,6 @@ impl AnnotateSnippetEmitter {
                     annotation_type: annotation_type_for_level(*level),
                 }),
                 footer: vec![],
-                opt: FormatOptions {
-                    color: true,
-                    anonymized_line_numbers: self.ui_testing,
-                    margin: None,
-                },
                 slices: annotated_files
                     .iter()
                     .map(|(file_name, source, line_index, annotations)| {
@@ -222,7 +216,8 @@ impl AnnotateSnippetEmitter {
             // FIXME(#59346): Figure out if we can _always_ print to stderr or not.
             // `emitter.rs` has the `Destination` enum that lists various possible output
             // destinations.
-            eprintln!("{}", DisplayList::from(snippet))
+            let renderer = Renderer::plain().anonymized_line_numbers(self.ui_testing);
+            eprintln!("{}", renderer.render(snippet))
         }
         // FIXME(#59346): Is it ok to return None if there's no source_map?
     }
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index d8d6922a1bc..786aced5b4f 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -1,7 +1,7 @@
 use crate::snippet::Style;
 use crate::{
-    CodeSuggestion, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level, MultiSpan,
-    SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
+    CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level,
+    MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
 };
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_error_messages::fluent_value_from_str_list_sep_by_and;
@@ -243,12 +243,15 @@ impl Diagnostic {
 
     pub fn is_error(&self) -> bool {
         match self.level {
-            Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error | Level::FailureNote => {
-                true
-            }
+            Level::Bug
+            | Level::DelayedBug(DelayedBugKind::Normal)
+            | Level::Fatal
+            | Level::Error
+            | Level::FailureNote => true,
 
             Level::ForceWarning(_)
             | Level::Warning
+            | Level::DelayedBug(DelayedBugKind::GoodPath)
             | Level::Note
             | Level::OnceNote
             | Level::Help
@@ -318,7 +321,7 @@ impl Diagnostic {
             "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error",
             self.level
         );
-        self.level = Level::DelayedBug;
+        self.level = Level::DelayedBug(DelayedBugKind::Normal);
     }
 
     /// Appends a labeled span to the diagnostic.
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index a02909f29c4..bd7c58d904e 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -255,35 +255,13 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
     /// Stashes diagnostic for possible later improvement in a different,
     /// later stage of the compiler. The diagnostic can be accessed with
     /// the provided `span` and `key` through [`DiagCtxt::steal_diagnostic()`].
-    ///
-    /// As with `buffer`, this is unless the dcx has disabled such buffering.
     pub fn stash(self, span: Span, key: StashKey) {
-        if let Some((diag, dcx)) = self.into_diagnostic() {
-            dcx.stash_diagnostic(span, key, diag);
-        }
-    }
-
-    /// Converts the builder to a `Diagnostic` for later emission,
-    /// unless dcx has disabled such buffering.
-    fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a DiagCtxt)> {
-        if self.dcx.inner.lock().flags.treat_err_as_bug.is_some() {
-            self.emit();
-            return None;
-        }
-
-        let diag = self.take_diag();
-
-        // Logging here is useful to help track down where in logs an error was
-        // actually emitted.
-        debug!("buffer: diag={:?}", diag);
-
-        Some((diag, self.dcx))
+        self.dcx.stash_diagnostic(span, key, self.into_diagnostic());
     }
 
-    /// Buffers the diagnostic for later emission,
-    /// unless dcx has disabled such buffering.
-    pub fn buffer(self, buffered_diagnostics: &mut Vec<Diagnostic>) {
-        buffered_diagnostics.extend(self.into_diagnostic().map(|(diag, _)| diag));
+    /// Converts the builder to a `Diagnostic` for later emission.
+    pub fn into_diagnostic(mut self) -> Diagnostic {
+        self.take_diag()
     }
 
     /// Delay emission of this diagnostic as a bug.
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 8fb539fc358..8c2752af659 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -519,6 +519,12 @@ fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) {
 pub static TRACK_DIAGNOSTIC: AtomicRef<fn(Diagnostic, &mut dyn FnMut(Diagnostic))> =
     AtomicRef::new(&(default_track_diagnostic as _));
 
+#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)]
+pub enum DelayedBugKind {
+    Normal,
+    GoodPath,
+}
+
 #[derive(Copy, Clone, Default)]
 pub struct DiagCtxtFlags {
     /// If false, warning-level lints are suppressed.
@@ -527,6 +533,9 @@ pub struct DiagCtxtFlags {
     /// If Some, the Nth error-level diagnostic is upgraded to bug-level.
     /// (rustc: see `-Z treat-err-as-bug`)
     pub treat_err_as_bug: Option<NonZeroUsize>,
+    /// Eagerly emit delayed bugs as errors, so that the compiler debugger may
+    /// see all of the errors being emitted at once.
+    pub eagerly_emit_delayed_bugs: bool,
     /// Show macro backtraces.
     /// (rustc: see `-Z macro-backtrace`)
     pub macro_backtrace: bool,
@@ -541,8 +550,7 @@ impl Drop for DiagCtxtInner {
         self.emit_stashed_diagnostics();
 
         if !self.has_errors() {
-            let bugs = std::mem::replace(&mut self.span_delayed_bugs, Vec::new());
-            self.flush_delayed(bugs, "no errors encountered even though `span_delayed_bug` issued");
+            self.flush_delayed(DelayedBugKind::Normal)
         }
 
         // FIXME(eddyb) this explains what `good_path_delayed_bugs` are!
@@ -551,11 +559,7 @@ impl Drop for DiagCtxtInner {
         // lints can be `#[allow]`'d, potentially leading to this triggering.
         // Also, "good path" should be replaced with a better naming.
         if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
-            let bugs = std::mem::replace(&mut self.good_path_delayed_bugs, Vec::new());
-            self.flush_delayed(
-                bugs,
-                "no warnings or errors encountered even though `good_path_delayed_bugs` issued",
-            );
+            self.flush_delayed(DelayedBugKind::GoodPath);
         }
 
         if self.check_unstable_expect_diagnostics {
@@ -865,7 +869,8 @@ impl DiagCtxt {
         if treat_next_err_as_bug {
             self.bug(msg);
         }
-        DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug, msg).emit()
+        DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg)
+            .emit()
     }
 
     /// Like `delayed_bug`, but takes an additional span.
@@ -882,16 +887,15 @@ impl DiagCtxt {
         if treat_next_err_as_bug {
             self.span_bug(sp, msg);
         }
-        DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug, msg).with_span(sp).emit()
+        DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg)
+            .with_span(sp)
+            .emit()
     }
 
     // FIXME(eddyb) note the comment inside `impl Drop for DiagCtxtInner`, that's
     // where the explanation of what "good path" is (also, it should be renamed).
     pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) {
-        let mut inner = self.inner.borrow_mut();
-        let diagnostic = Diagnostic::new(DelayedBug, msg);
-        let backtrace = std::backtrace::Backtrace::capture();
-        inner.good_path_delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
+        DiagnosticBuilder::<()>::new(self, DelayedBug(DelayedBugKind::GoodPath), msg).emit()
     }
 
     #[track_caller]
@@ -981,6 +985,10 @@ impl DiagCtxt {
 
         inner.emit_stashed_diagnostics();
 
+        if inner.treat_err_as_bug() {
+            return;
+        }
+
         let warnings = match inner.deduplicated_warn_count {
             0 => Cow::from(""),
             1 => Cow::from("1 warning emitted"),
@@ -991,9 +999,6 @@ impl DiagCtxt {
             1 => Cow::from("aborting due to 1 previous error"),
             count => Cow::from(format!("aborting due to {count} previous errors")),
         };
-        if inner.treat_err_as_bug() {
-            return;
-        }
 
         match (errors.len(), warnings.len()) {
             (0, 0) => return,
@@ -1168,7 +1173,8 @@ impl DiagCtxt {
         let mut inner = self.inner.borrow_mut();
 
         if loud && lint_level.is_error() {
-            inner.bump_err_count();
+            inner.err_count += 1;
+            inner.panic_if_treat_err_as_bug();
         }
 
         inner.emitter.emit_unused_externs(lint_level, unused_externs)
@@ -1216,9 +1222,7 @@ impl DiagCtxt {
     }
 
     pub fn flush_delayed(&self) {
-        let mut inner = self.inner.borrow_mut();
-        let bugs = std::mem::replace(&mut inner.span_delayed_bugs, Vec::new());
-        inner.flush_delayed(bugs, "no errors encountered even though `span_delayed_bug` issued");
+        self.inner.borrow_mut().flush_delayed(DelayedBugKind::Normal);
     }
 }
 
@@ -1255,7 +1259,7 @@ impl DiagCtxtInner {
     }
 
     fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option<ErrorGuaranteed> {
-        if matches!(diagnostic.level, Error | Fatal) && self.treat_err_as_bug() {
+        if matches!(diagnostic.level, Error | Fatal) && self.treat_next_err_as_bug() {
             diagnostic.level = Bug;
         }
 
@@ -1268,17 +1272,30 @@ impl DiagCtxtInner {
             return None;
         }
 
-        if diagnostic.level == DelayedBug {
-            // FIXME(eddyb) this should check for `has_errors` and stop pushing
-            // once *any* errors were emitted (and truncate `span_delayed_bugs`
-            // when an error is first emitted, also), but maybe there's a case
-            // in which that's not sound? otherwise this is really inefficient.
-            let backtrace = std::backtrace::Backtrace::capture();
-            self.span_delayed_bugs
-                .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
+        // FIXME(eddyb) this should check for `has_errors` and stop pushing
+        // once *any* errors were emitted (and truncate `span_delayed_bugs`
+        // when an error is first emitted, also), but maybe there's a case
+        // in which that's not sound? otherwise this is really inefficient.
+        match diagnostic.level {
+            DelayedBug(_) if self.flags.eagerly_emit_delayed_bugs => {
+                diagnostic.level = Error;
+            }
+            DelayedBug(DelayedBugKind::Normal) => {
+                let backtrace = std::backtrace::Backtrace::capture();
+                self.span_delayed_bugs
+                    .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
 
-            #[allow(deprecated)]
-            return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
+                #[allow(deprecated)]
+                return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
+            }
+            DelayedBug(DelayedBugKind::GoodPath) => {
+                let backtrace = std::backtrace::Backtrace::capture();
+                self.good_path_delayed_bugs
+                    .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
+
+                return None;
+            }
+            _ => {}
         }
 
         if diagnostic.has_future_breakage() {
@@ -1353,10 +1370,11 @@ impl DiagCtxtInner {
             }
             if diagnostic.is_error() {
                 if diagnostic.is_lint {
-                    self.bump_lint_err_count();
+                    self.lint_err_count += 1;
                 } else {
-                    self.bump_err_count();
+                    self.err_count += 1;
                 }
+                self.panic_if_treat_err_as_bug();
 
                 #[allow(deprecated)]
                 {
@@ -1393,11 +1411,18 @@ impl DiagCtxtInner {
         self.emit_diagnostic(Diagnostic::new(FailureNote, msg));
     }
 
-    fn flush_delayed(
-        &mut self,
-        bugs: Vec<DelayedDiagnostic>,
-        explanation: impl Into<DiagnosticMessage> + Copy,
-    ) {
+    fn flush_delayed(&mut self, kind: DelayedBugKind) {
+        let (bugs, explanation) = match kind {
+            DelayedBugKind::Normal => (
+                std::mem::take(&mut self.span_delayed_bugs),
+                "no errors encountered even though `span_delayed_bug` issued",
+            ),
+            DelayedBugKind::GoodPath => (
+                std::mem::take(&mut self.good_path_delayed_bugs),
+                "no warnings or errors encountered even though `good_path_delayed_bugs` issued",
+            ),
+        };
+
         if bugs.is_empty() {
             return;
         }
@@ -1430,7 +1455,7 @@ impl DiagCtxtInner {
                 if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
 
             // "Undelay" the `DelayedBug`s (into plain `Bug`s).
-            if bug.level != DelayedBug {
+            if !matches!(bug.level, DelayedBug(_)) {
                 // NOTE(eddyb) not panicking here because we're already producing
                 // an ICE, and the more information the merrier.
                 bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel {
@@ -1447,16 +1472,6 @@ impl DiagCtxtInner {
         panic::panic_any(DelayedBugPanic);
     }
 
-    fn bump_lint_err_count(&mut self) {
-        self.lint_err_count += 1;
-        self.panic_if_treat_err_as_bug();
-    }
-
-    fn bump_err_count(&mut self) {
-        self.err_count += 1;
-        self.panic_if_treat_err_as_bug();
-    }
-
     fn panic_if_treat_err_as_bug(&self) {
         if self.treat_err_as_bug() {
             match (
@@ -1528,8 +1543,9 @@ pub enum Level {
     /// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths
     /// that should only be reached when compiling erroneous code.
     ///
-    /// Its `EmissionGuarantee` is `ErrorGuaranteed`.
-    DelayedBug,
+    /// Its `EmissionGuarantee` is `ErrorGuaranteed` for `Normal` delayed bugs, and `()` for
+    /// `GoodPath` delayed bugs.
+    DelayedBug(DelayedBugKind),
 
     /// An error that causes an immediate abort. Used for things like configuration errors,
     /// internal overflows, some file operation errors.
@@ -1604,7 +1620,7 @@ impl Level {
     fn color(self) -> ColorSpec {
         let mut spec = ColorSpec::new();
         match self {
-            Bug | DelayedBug | Fatal | Error => {
+            Bug | DelayedBug(_) | Fatal | Error => {
                 spec.set_fg(Some(Color::Red)).set_intense(true);
             }
             ForceWarning(_) | Warning => {
@@ -1624,7 +1640,7 @@ impl Level {
 
     pub fn to_str(self) -> &'static str {
         match self {
-            Bug | DelayedBug => "error: internal compiler error",
+            Bug | DelayedBug(_) => "error: internal compiler error",
             Fatal | Error => "error",
             ForceWarning(_) | Warning => "warning",
             Note | OnceNote => "note",
diff --git a/compiler/rustc_errors/src/markdown/tests/term.rs b/compiler/rustc_errors/src/markdown/tests/term.rs
index a0d956bf0cd..bab47dcc175 100644
--- a/compiler/rustc_errors/src/markdown/tests/term.rs
+++ b/compiler/rustc_errors/src/markdown/tests/term.rs
@@ -5,7 +5,8 @@ use termcolor::{BufferWriter, ColorChoice};
 use super::*;
 
 const INPUT: &str = include_str!("input.md");
-const OUTPUT_PATH: &[&str] = &[env!("CARGO_MANIFEST_DIR"), "src","markdown","tests","output.stdout"];
+const OUTPUT_PATH: &[&str] =
+    &[env!("CARGO_MANIFEST_DIR"), "src", "markdown", "tests", "output.stdout"];
 
 const TEST_WIDTH: usize = 80;
 
@@ -34,7 +35,7 @@ quis dolor non venenatis. Aliquam ut. ";
 fn test_wrapping_write() {
     WIDTH.with(|w| w.set(TEST_WIDTH));
     let mut buf = BufWriter::new(Vec::new());
-    let txt = TXT.replace("-\n","-").replace("_\n","_").replace('\n', " ").replace("    ", "");
+    let txt = TXT.replace("-\n", "-").replace("_\n", "_").replace('\n', " ").replace("    ", "");
     write_wrapping(&mut buf, &txt, 0, None).unwrap();
     write_wrapping(&mut buf, &txt, 4, None).unwrap();
     write_wrapping(