about summary refs log tree commit diff
path: root/compiler/rustc_errors/src
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-02-29 17:08:38 +0100
committerGitHub <noreply@github.com>2024-02-29 17:08:38 +0100
commit0e9f02d6fa769f1e96fc5e54af7b77b101bcc603 (patch)
tree3bd55c979127cf371e5059d7debb7e9e8677c160 /compiler/rustc_errors/src
parenta5945b5d8d0b5b19aa01926ce3cd8c33de6fde8e (diff)
parent607bf653c2bed1ec3f7979d9511f3c9cef604bc3 (diff)
downloadrust-0e9f02d6fa769f1e96fc5e54af7b77b101bcc603.tar.gz
rust-0e9f02d6fa769f1e96fc5e54af7b77b101bcc603.zip
Rollup merge of #121783 - nnethercote:emitter-cleanups, r=oli-obk
Emitter cleanups

Some cleanups I made when reading emitter code. In particular, `HumanEmitter` and `JsonEmitter` have gone from three constructors to one.

r? `@oli-obk`
Diffstat (limited to 'compiler/rustc_errors/src')
-rw-r--r--compiler/rustc_errors/src/emitter.rs61
-rw-r--r--compiler/rustc_errors/src/error.rs3
-rw-r--r--compiler/rustc_errors/src/json.rs131
-rw-r--r--compiler/rustc_errors/src/json/tests.rs12
-rw-r--r--compiler/rustc_errors/src/lib.rs25
5 files changed, 69 insertions, 163 deletions
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 304922018eb..5637c05d04c 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -21,12 +21,11 @@ use crate::{
     FluentBundle, LazyFallbackBundle, Level, MultiSpan, Subdiag, SubstitutionHighlight,
     SuggestionStyle, TerminalUrl,
 };
-use rustc_lint_defs::pluralize;
-
 use derive_setters::Setters;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
 use rustc_data_structures::sync::{DynSend, IntoDynSyncSend, Lrc};
 use rustc_error_messages::{FluentArgs, SpanLabel};
+use rustc_lint_defs::pluralize;
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use std::borrow::Cow;
 use std::cmp::{max, min, Reverse};
@@ -35,7 +34,7 @@ use std::io::prelude::*;
 use std::io::{self, IsTerminal};
 use std::iter;
 use std::path::Path;
-use termcolor::{Ansi, Buffer, BufferWriter, ColorChoice, ColorSpec, StandardStream};
+use termcolor::{Buffer, BufferWriter, ColorChoice, ColorSpec, StandardStream};
 use termcolor::{Color, WriteColor};
 
 /// Default column width, used in tests and when terminal dimensions cannot be determined.
@@ -58,18 +57,6 @@ impl HumanReadableErrorType {
             HumanReadableErrorType::AnnotateSnippet(cc) => (false, cc),
         }
     }
-    pub fn new_emitter(
-        self,
-        mut dst: Box<dyn WriteColor + Send>,
-        fallback_bundle: LazyFallbackBundle,
-    ) -> HumanEmitter {
-        let (short, color_config) = self.unzip();
-        let color = color_config.suggests_using_colors();
-        if !dst.supports_color() && color {
-            dst = Box::new(Ansi::new(dst));
-        }
-        HumanEmitter::new(dst, fallback_bundle).short_message(short)
-    }
 }
 
 #[derive(Clone, Copy, Debug)]
@@ -130,8 +117,8 @@ impl Margin {
     fn was_cut_right(&self, line_len: usize) -> bool {
         let right =
             if self.computed_right == self.span_right || self.computed_right == self.label_right {
-                // Account for the "..." padding given above. Otherwise we end up with code lines that
-                // do fit but end in "..." as if they were trimmed.
+                // Account for the "..." padding given above. Otherwise we end up with code lines
+                // that do fit but end in "..." as if they were trimmed.
                 self.computed_right - 6
             } else {
                 self.computed_right
@@ -628,12 +615,6 @@ impl ColorConfig {
             ColorConfig::Auto => ColorChoice::Never,
         }
     }
-    fn suggests_using_colors(self) -> bool {
-        match self {
-            ColorConfig::Always | ColorConfig::Auto => true,
-            ColorConfig::Never => false,
-        }
-    }
 }
 
 /// Handles the writing of `HumanReadableErrorType::Default` and `HumanReadableErrorType::Short`
@@ -657,19 +638,14 @@ pub struct HumanEmitter {
 }
 
 #[derive(Debug)]
-pub struct FileWithAnnotatedLines {
-    pub file: Lrc<SourceFile>,
-    pub lines: Vec<Line>,
+pub(crate) struct FileWithAnnotatedLines {
+    pub(crate) file: Lrc<SourceFile>,
+    pub(crate) lines: Vec<Line>,
     multiline_depth: usize,
 }
 
 impl HumanEmitter {
-    pub fn stderr(color_config: ColorConfig, fallback_bundle: LazyFallbackBundle) -> HumanEmitter {
-        let dst = from_stderr(color_config);
-        Self::create(dst, fallback_bundle)
-    }
-
-    fn create(dst: Destination, fallback_bundle: LazyFallbackBundle) -> HumanEmitter {
+    pub fn new(dst: Destination, fallback_bundle: LazyFallbackBundle) -> HumanEmitter {
         HumanEmitter {
             dst: IntoDynSyncSend(dst),
             sm: None,
@@ -686,13 +662,6 @@ impl HumanEmitter {
         }
     }
 
-    pub fn new(
-        dst: Box<dyn WriteColor + Send>,
-        fallback_bundle: LazyFallbackBundle,
-    ) -> HumanEmitter {
-        Self::create(dst, fallback_bundle)
-    }
-
     fn maybe_anonymized(&self, line_num: usize) -> Cow<'static, str> {
         if self.ui_testing {
             Cow::Borrowed(ANONYMIZED_LINE_NUM)
@@ -724,8 +693,9 @@ impl HumanEmitter {
             .skip(left)
             .take_while(|ch| {
                 // Make sure that the trimming on the right will fall within the terminal width.
-                // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is.
-                // For now, just accept that sometimes the code line will be longer than desired.
+                // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char`
+                // is. For now, just accept that sometimes the code line will be longer than
+                // desired.
                 let next = unicode_width::UnicodeWidthChar::width(*ch).unwrap_or(1);
                 if taken + next > right - left {
                     return false;
@@ -2228,8 +2198,8 @@ impl HumanEmitter {
                 buffer.puts(*row_num - 1, max_line_num_len + 3, &line, Style::NoStyle);
                 *row_num += 1;
             }
-            // If the last line is exactly equal to the line we need to add, we can skip both of them.
-            // This allows us to avoid output like the following:
+            // If the last line is exactly equal to the line we need to add, we can skip both of
+            // them. This allows us to avoid output like the following:
             // 2 - &
             // 2 + if true { true } else { false }
             // 3 - if true { true } else { false }
@@ -2586,6 +2556,7 @@ fn num_overlap(
     let extra = if inclusive { 1 } else { 0 };
     (b_start..b_end + extra).contains(&a_start) || (a_start..a_end + extra).contains(&b_start)
 }
+
 fn overlaps(a1: &Annotation, a2: &Annotation, padding: usize) -> bool {
     num_overlap(
         a1.start_col.display,
@@ -2632,7 +2603,7 @@ fn emit_to_destination(
     Ok(())
 }
 
-pub type Destination = Box<(dyn WriteColor + Send)>;
+pub type Destination = Box<dyn WriteColor + Send>;
 
 struct Buffy {
     buffer_writer: BufferWriter,
@@ -2674,7 +2645,7 @@ impl WriteColor for Buffy {
     }
 }
 
-fn from_stderr(color: ColorConfig) -> Destination {
+pub fn stderr_destination(color: ColorConfig) -> Destination {
     let choice = color.to_color_choice();
     // On Windows we'll be performing global synchronization on the entire
     // system for emitting rustc errors, so there's no need to buffer
diff --git a/compiler/rustc_errors/src/error.rs b/compiler/rustc_errors/src/error.rs
index ec0a2fe8cd8..ca818a4d832 100644
--- a/compiler/rustc_errors/src/error.rs
+++ b/compiler/rustc_errors/src/error.rs
@@ -23,9 +23,11 @@ impl<'args> TranslateError<'args> {
     pub fn message(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self {
         Self::One { id, args, kind: TranslateErrorKind::MessageMissing }
     }
+
     pub fn primary(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self {
         Self::One { id, args, kind: TranslateErrorKind::PrimaryBundleMissing }
     }
+
     pub fn attribute(
         id: &'args Cow<'args, str>,
         args: &'args FluentArgs<'args>,
@@ -33,6 +35,7 @@ impl<'args> TranslateError<'args> {
     ) -> Self {
         Self::One { id, args, kind: TranslateErrorKind::AttributeMissing { attr } }
     }
+
     pub fn value(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self {
         Self::One { id, args, kind: TranslateErrorKind::ValueMissing }
     }
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs
index 88a83c8bf78..bc1822f83fc 100644
--- a/compiler/rustc_errors/src/json.rs
+++ b/compiler/rustc_errors/src/json.rs
@@ -9,42 +9,49 @@
 
 // FIXME: spec the JSON output properly.
 
-use rustc_span::source_map::{FilePathMapping, SourceMap};
-use termcolor::{ColorSpec, WriteColor};
-
-use crate::emitter::{should_show_source_code, Emitter, HumanReadableErrorType};
+use crate::emitter::{
+    should_show_source_code, ColorConfig, Destination, Emitter, HumanEmitter,
+    HumanReadableErrorType,
+};
 use crate::registry::Registry;
 use crate::translation::{to_fluent_args, Translate};
 use crate::{
     diagnostic::IsLint, CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel,
     Subdiag, TerminalUrl,
 };
-use rustc_lint_defs::Applicability;
-
+use derive_setters::Setters;
 use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
 use rustc_error_messages::FluentArgs;
+use rustc_lint_defs::Applicability;
 use rustc_span::hygiene::ExpnData;
+use rustc_span::source_map::SourceMap;
 use rustc_span::Span;
+use serde::Serialize;
 use std::error::Report;
 use std::io::{self, Write};
 use std::path::Path;
 use std::sync::{Arc, Mutex};
 use std::vec;
-
-use serde::Serialize;
+use termcolor::{ColorSpec, WriteColor};
 
 #[cfg(test)]
 mod tests;
 
+#[derive(Setters)]
 pub struct JsonEmitter {
+    #[setters(skip)]
     dst: IntoDynSyncSend<Box<dyn Write + Send>>,
     registry: Option<Registry>,
+    #[setters(skip)]
     sm: Lrc<SourceMap>,
     fluent_bundle: Option<Lrc<FluentBundle>>,
+    #[setters(skip)]
     fallback_bundle: LazyFallbackBundle,
+    #[setters(skip)]
     pretty: bool,
     ui_testing: bool,
     ignored_directories_in_source_blocks: Vec<String>,
+    #[setters(skip)]
     json_rendered: HumanReadableErrorType,
     diagnostic_width: Option<usize>,
     macro_backtrace: bool,
@@ -53,98 +60,30 @@ pub struct JsonEmitter {
 }
 
 impl JsonEmitter {
-    pub fn stderr(
-        registry: Option<Registry>,
-        source_map: Lrc<SourceMap>,
-        fluent_bundle: Option<Lrc<FluentBundle>>,
-        fallback_bundle: LazyFallbackBundle,
-        pretty: bool,
-        json_rendered: HumanReadableErrorType,
-        diagnostic_width: Option<usize>,
-        macro_backtrace: bool,
-        track_diagnostics: bool,
-        terminal_url: TerminalUrl,
-    ) -> JsonEmitter {
-        JsonEmitter {
-            dst: IntoDynSyncSend(Box::new(io::BufWriter::new(io::stderr()))),
-            registry,
-            sm: source_map,
-            fluent_bundle,
-            fallback_bundle,
-            pretty,
-            ui_testing: false,
-            ignored_directories_in_source_blocks: Vec::new(),
-            json_rendered,
-            diagnostic_width,
-            macro_backtrace,
-            track_diagnostics,
-            terminal_url,
-        }
-    }
-
-    pub fn basic(
-        pretty: bool,
-        json_rendered: HumanReadableErrorType,
-        fluent_bundle: Option<Lrc<FluentBundle>>,
-        fallback_bundle: LazyFallbackBundle,
-        diagnostic_width: Option<usize>,
-        macro_backtrace: bool,
-        track_diagnostics: bool,
-        terminal_url: TerminalUrl,
-    ) -> JsonEmitter {
-        let file_path_mapping = FilePathMapping::empty();
-        JsonEmitter::stderr(
-            None,
-            Lrc::new(SourceMap::new(file_path_mapping)),
-            fluent_bundle,
-            fallback_bundle,
-            pretty,
-            json_rendered,
-            diagnostic_width,
-            macro_backtrace,
-            track_diagnostics,
-            terminal_url,
-        )
-    }
-
     pub fn new(
         dst: Box<dyn Write + Send>,
-        registry: Option<Registry>,
-        source_map: Lrc<SourceMap>,
-        fluent_bundle: Option<Lrc<FluentBundle>>,
+        sm: Lrc<SourceMap>,
         fallback_bundle: LazyFallbackBundle,
         pretty: bool,
         json_rendered: HumanReadableErrorType,
-        diagnostic_width: Option<usize>,
-        macro_backtrace: bool,
-        track_diagnostics: bool,
-        terminal_url: TerminalUrl,
     ) -> JsonEmitter {
         JsonEmitter {
             dst: IntoDynSyncSend(dst),
-            registry,
-            sm: source_map,
-            fluent_bundle,
+            registry: None,
+            sm,
+            fluent_bundle: None,
             fallback_bundle,
             pretty,
             ui_testing: false,
             ignored_directories_in_source_blocks: Vec::new(),
             json_rendered,
-            diagnostic_width,
-            macro_backtrace,
-            track_diagnostics,
-            terminal_url,
+            diagnostic_width: None,
+            macro_backtrace: false,
+            track_diagnostics: false,
+            terminal_url: TerminalUrl::No,
         }
     }
 
-    pub fn ui_testing(self, ui_testing: bool) -> Self {
-        Self { ui_testing, ..self }
-    }
-
-    pub fn ignored_directories_in_source_blocks(self, value: Vec<String>) -> Self {
-        Self { ignored_directories_in_source_blocks: value, ..self }
-    }
-
     fn emit(&mut self, val: EmitTyped<'_>) -> io::Result<()> {
         if self.pretty {
             serde_json::to_writer_pretty(&mut *self.dst, &val)?
@@ -162,7 +101,7 @@ enum EmitTyped<'a> {
     Diagnostic(Diagnostic),
     Artifact(ArtifactNotification<'a>),
     FutureIncompat(FutureIncompatReport<'a>),
-    UnusedExtern(UnusedExterns<'a, 'a, 'a>),
+    UnusedExtern(UnusedExterns<'a>),
 }
 
 impl Translate for JsonEmitter {
@@ -332,14 +271,15 @@ struct FutureIncompatReport<'a> {
 // We could unify this struct the one in rustdoc but they have different
 // ownership semantics, so doing so would create wasteful allocations.
 #[derive(Serialize)]
-struct UnusedExterns<'a, 'b, 'c> {
+struct UnusedExterns<'a> {
     /// The severity level of the unused dependencies lint
     lint_level: &'a str,
     /// List of unused externs by their names.
-    unused_extern_names: &'b [&'c str],
+    unused_extern_names: &'a [&'a str],
 }
 
 impl Diagnostic {
+    /// Converts from `rustc_errors::DiagInner` to `Diagnostic`.
     fn from_errors_diagnostic(diag: crate::DiagInner, je: &JsonEmitter) -> Diagnostic {
         let args = to_fluent_args(diag.args.iter());
         let sugg = diag.suggestions.iter().flatten().map(|sugg| {
@@ -405,9 +345,14 @@ impl Diagnostic {
             .collect();
 
         let buf = BufWriter::default();
-        let output = buf.clone();
-        je.json_rendered
-            .new_emitter(Box::new(buf), je.fallback_bundle.clone())
+        let mut dst: Destination = Box::new(buf.clone());
+        let (short, color_config) = je.json_rendered.unzip();
+        match color_config {
+            ColorConfig::Always | ColorConfig::Auto => dst = Box::new(termcolor::Ansi::new(dst)),
+            ColorConfig::Never => {}
+        }
+        HumanEmitter::new(dst, je.fallback_bundle.clone())
+            .short_message(short)
             .sm(Some(je.sm.clone()))
             .fluent_bundle(je.fluent_bundle.clone())
             .diagnostic_width(je.diagnostic_width)
@@ -417,8 +362,8 @@ impl Diagnostic {
             .ui_testing(je.ui_testing)
             .ignored_directories_in_source_blocks(je.ignored_directories_in_source_blocks.clone())
             .emit_diagnostic(diag);
-        let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap();
-        let output = String::from_utf8(output).unwrap();
+        let buf = Arc::try_unwrap(buf.0).unwrap().into_inner().unwrap();
+        let buf = String::from_utf8(buf).unwrap();
 
         Diagnostic {
             message: translated_message.to_string(),
@@ -426,7 +371,7 @@ impl Diagnostic {
             level,
             spans,
             children,
-            rendered: Some(output),
+            rendered: Some(buf),
         }
     }
 
diff --git a/compiler/rustc_errors/src/json/tests.rs b/compiler/rustc_errors/src/json/tests.rs
index 303de0a93f6..80b4d2bf75c 100644
--- a/compiler/rustc_errors/src/json/tests.rs
+++ b/compiler/rustc_errors/src/json/tests.rs
@@ -1,7 +1,7 @@
 use super::*;
 
-use crate::emitter::ColorConfig;
 use crate::DiagCtxt;
+use rustc_span::source_map::FilePathMapping;
 use rustc_span::BytePos;
 
 use std::str;
@@ -48,20 +48,14 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
         let output = Arc::new(Mutex::new(Vec::new()));
         let je = JsonEmitter::new(
             Box::new(Shared { data: output.clone() }),
-            None,
             sm,
-            None,
             fallback_bundle,
-            true,
+            true, // pretty
             HumanReadableErrorType::Short(ColorConfig::Never),
-            None,
-            false,
-            false,
-            TerminalUrl::No,
         );
 
         let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1));
-        let dcx = DiagCtxt::with_emitter(Box::new(je));
+        let dcx = DiagCtxt::new(Box::new(je));
         dcx.span_err(span, "foo");
 
         let bytes = output.lock().unwrap();
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 87c4d66e163..0a533833e64 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -59,11 +59,11 @@ pub use snippet::Style;
 // See https://github.com/rust-lang/rust/pull/115393.
 pub use termcolor::{Color, ColorSpec, WriteColor};
 
-use emitter::{is_case_difference, DynEmitter, Emitter, HumanEmitter};
+use emitter::{is_case_difference, DynEmitter, Emitter};
 use registry::Registry;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
-use rustc_data_structures::sync::{Lock, Lrc};
+use rustc_data_structures::sync::Lock;
 use rustc_data_structures::AtomicRef;
 use rustc_lint_defs::LintExpectationId;
 use rustc_span::source_map::SourceMap;
@@ -217,10 +217,10 @@ impl CodeSuggestion {
 
         use rustc_span::{CharPos, Pos};
 
-        /// Extracts a substring from the provided `line_opt` based on the specified low and high indices,
-        /// appends it to the given buffer `buf`, and returns the count of newline characters in the substring
-        /// for accurate highlighting.
-        /// If `line_opt` is `None`, a newline character is appended to the buffer, and 0 is returned.
+        /// Extracts a substring from the provided `line_opt` based on the specified low and high
+        /// indices, appends it to the given buffer `buf`, and returns the count of newline
+        /// characters in the substring for accurate highlighting. If `line_opt` is `None`, a
+        /// newline character is appended to the buffer, and 0 is returned.
         ///
         /// ## Returns
         ///
@@ -482,8 +482,8 @@ struct DiagCtxtInner {
     /// have been converted.
     check_unstable_expect_diagnostics: bool,
 
-    /// Expected [`DiagInner`][struct@diagnostic::DiagInner]s store a [`LintExpectationId`] as part of
-    /// the lint level. [`LintExpectationId`]s created early during the compilation
+    /// Expected [`DiagInner`][struct@diagnostic::DiagInner]s store a [`LintExpectationId`] as part
+    /// of the lint level. [`LintExpectationId`]s created early during the compilation
     /// (before `HirId`s have been defined) are not stable and can therefore not be
     /// stored on disk. This buffer stores these diagnostics until the ID has been
     /// replaced by a stable [`LintExpectationId`]. The [`DiagInner`][struct@diagnostic::DiagInner]s
@@ -590,13 +590,6 @@ impl Drop for DiagCtxtInner {
 }
 
 impl DiagCtxt {
-    pub fn with_tty_emitter(
-        sm: Option<Lrc<SourceMap>>,
-        fallback_bundle: LazyFallbackBundle,
-    ) -> Self {
-        let emitter = Box::new(HumanEmitter::stderr(ColorConfig::Auto, fallback_bundle).sm(sm));
-        Self::with_emitter(emitter)
-    }
     pub fn disable_warnings(mut self) -> Self {
         self.inner.get_mut().flags.can_emit_warnings = false;
         self
@@ -612,7 +605,7 @@ impl DiagCtxt {
         self
     }
 
-    pub fn with_emitter(emitter: Box<DynEmitter>) -> Self {
+    pub fn new(emitter: Box<DynEmitter>) -> Self {
         Self {
             inner: Lock::new(DiagCtxtInner {
                 flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },