From 29de70da1be1c71b89b006f9955fedc70e084067 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 25 Jul 2023 13:09:53 +0000 Subject: [PATCH 01/11] Replace the many arguments of `EmitterWriter::stderr` with builder methods --- Cargo.lock | 54 +++++++++++++++++++++++++++ compiler/rustc_driver_impl/src/lib.rs | 12 +----- compiler/rustc_errors/Cargo.toml | 1 + compiler/rustc_errors/src/emitter.rs | 38 +++++++------------ compiler/rustc_errors/src/lib.rs | 13 +------ compiler/rustc_session/src/session.rs | 34 +++++------------ src/librustdoc/core.rs | 20 ++++------ src/librustdoc/doctest.rs | 16 ++------ src/tools/tidy/src/deps.rs | 7 ++++ 9 files changed, 97 insertions(+), 98 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 45959c039e7..dd8ce11ac12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -830,6 +830,41 @@ dependencies = [ "winapi", ] +[[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.27", +] + +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.27", +] + [[package]] name = "datafrog" version = "2.0.1" @@ -869,6 +904,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_setters" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e8ef033054e131169b8f0f9a7af8f5533a9436fadf3c500ed547f730f07090d" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.27", +] + [[package]] name = "diff" version = "0.1.13" @@ -1740,6 +1787,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.4.0" @@ -3523,6 +3576,7 @@ name = "rustc_errors" version = "0.0.0" dependencies = [ "annotate-snippets", + "derive_setters", "rustc_ast", "rustc_ast_pretty", "rustc_data_structures", diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 8f8b9eaa274..d4532873854 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -27,9 +27,7 @@ use rustc_data_structures::profiling::{ use rustc_data_structures::sync::SeqCst; use rustc_errors::registry::{InvalidErrorCode, Registry}; use rustc_errors::{markdown, ColorConfig}; -use rustc_errors::{ - DiagnosticMessage, ErrorGuaranteed, Handler, PResult, SubdiagnosticMessage, TerminalUrl, -}; +use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, PResult, SubdiagnosticMessage}; use rustc_feature::find_gated_cfg; use rustc_fluent_macro::fluent_messages; use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; @@ -1405,15 +1403,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info: rustc_errors::fallback_fluent_bundle(crate::DEFAULT_LOCALE_RESOURCES.to_vec(), false); let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr( rustc_errors::ColorConfig::Auto, - None, - None, fallback_bundle, - false, - false, - None, - false, - false, - TerminalUrl::No, )); let handler = rustc_errors::Handler::with_emitter(emitter); diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index e8bcd7c1184..faab9f09da8 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -25,6 +25,7 @@ annotate-snippets = "0.9" termize = "0.1.1" serde = { version = "1.0.125", features = [ "derive" ] } serde_json = "1.0.59" +derive_setters = "0.1.6" [target.'cfg(windows)'.dependencies.windows] version = "0.48.0" diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 44654571d43..70ca972ddb4 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -24,6 +24,7 @@ use crate::{ }; use rustc_lint_defs::pluralize; +use derive_setters::Setters; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_data_structures::sync::Lrc; use rustc_error_messages::{FluentArgs, SpanLabel}; @@ -639,10 +640,13 @@ impl ColorConfig { } /// Handles the writing of `HumanReadableErrorType::Default` and `HumanReadableErrorType::Short` +#[derive(Setters)] pub struct EmitterWriter { + #[setters(skip)] dst: Destination, sm: Option>, fluent_bundle: Option>, + #[setters(skip)] fallback_bundle: LazyFallbackBundle, short_message: bool, teach: bool, @@ -662,31 +666,20 @@ pub struct FileWithAnnotatedLines { } impl EmitterWriter { - pub fn stderr( - color_config: ColorConfig, - source_map: Option>, - fluent_bundle: Option>, - fallback_bundle: LazyFallbackBundle, - short_message: bool, - teach: bool, - diagnostic_width: Option, - macro_backtrace: bool, - track_diagnostics: bool, - terminal_url: TerminalUrl, - ) -> EmitterWriter { + pub fn stderr(color_config: ColorConfig, fallback_bundle: LazyFallbackBundle) -> EmitterWriter { let dst = Destination::from_stderr(color_config); EmitterWriter { dst, - sm: source_map, - fluent_bundle, + sm: None, + fluent_bundle: None, fallback_bundle, - short_message, - teach, + short_message: false, + teach: false, ui_testing: false, - diagnostic_width, - macro_backtrace, - track_diagnostics, - terminal_url, + diagnostic_width: None, + macro_backtrace: false, + track_diagnostics: false, + terminal_url: TerminalUrl::No, } } @@ -718,11 +711,6 @@ impl EmitterWriter { } } - pub fn ui_testing(mut self, ui_testing: bool) -> Self { - self.ui_testing = ui_testing; - self - } - fn maybe_anonymized(&self, line_num: usize) -> Cow<'static, str> { if self.ui_testing { Cow::Borrowed(ANONYMIZED_LINE_NUM) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 3d1639db4af..02b77cecbe2 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -556,18 +556,7 @@ impl Handler { sm: Option>, fallback_bundle: LazyFallbackBundle, ) -> Self { - let emitter = Box::new(EmitterWriter::stderr( - ColorConfig::Auto, - sm, - None, - fallback_bundle, - false, - false, - None, - false, - false, - TerminalUrl::No, - )); + let emitter = Box::new(EmitterWriter::stderr(ColorConfig::Auto, fallback_bundle).sm(sm)); Self::with_emitter(emitter) } pub fn disable_warnings(mut self) -> Self { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index ad22e7c703d..ac745d16161 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1350,18 +1350,15 @@ fn default_emitter( ); Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing)) } else { - let emitter = EmitterWriter::stderr( - color_config, - Some(source_map), - bundle, - fallback_bundle, - short, - sopts.unstable_opts.teach, - sopts.diagnostic_width, - macro_backtrace, - track_diagnostics, - terminal_url, - ); + let emitter = EmitterWriter::stderr(color_config, fallback_bundle) + .fluent_bundle(bundle) + .sm(Some(source_map)) + .short_message(short) + .teach(sopts.unstable_opts.teach) + .diagnostic_width(sopts.diagnostic_width) + .macro_backtrace(macro_backtrace) + .track_diagnostics(track_diagnostics) + .terminal_url(terminal_url); Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing)) } } @@ -1794,18 +1791,7 @@ fn mk_emitter(output: ErrorOutputType) -> Box = match output { config::ErrorOutputType::HumanReadable(kind) => { let (short, color_config) = kind.unzip(); - Box::new(EmitterWriter::stderr( - color_config, - None, - None, - fallback_bundle, - short, - false, - None, - false, - false, - TerminalUrl::No, - )) + Box::new(EmitterWriter::stderr(color_config, fallback_bundle).short_message(short)) } config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(JsonEmitter::basic( pretty, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 6f791aec3f2..12d620b5b18 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -136,19 +136,13 @@ pub(crate) fn new_handler( ErrorOutputType::HumanReadable(kind) => { let (short, color_config) = kind.unzip(); Box::new( - EmitterWriter::stderr( - color_config, - source_map.map(|sm| sm as _), - None, - fallback_bundle, - short, - unstable_opts.teach, - diagnostic_width, - false, - unstable_opts.track_diagnostics, - TerminalUrl::No, - ) - .ui_testing(unstable_opts.ui_testing), + EmitterWriter::stderr(color_config, fallback_bundle) + .sm(source_map.map(|sm| sm as _)) + .short_message(short) + .teach(unstable_opts.teach) + .diagnostic_width(diagnostic_width) + .track_diagnostics(unstable_opts.track_diagnostics) + .ui_testing(unstable_opts.ui_testing), ) } ErrorOutputType::Json { pretty, json_rendered } => { diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index a48273a5c73..8f25f765390 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -558,19 +558,9 @@ pub(crate) fn make_test( rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false, ); - supports_color = EmitterWriter::stderr( - ColorConfig::Auto, - None, - None, - fallback_bundle.clone(), - false, - false, - Some(80), - false, - false, - TerminalUrl::No, - ) - .supports_color(); + supports_color = EmitterWriter::stderr(ColorConfig::Auto, fallback_bundle.clone()) + .diagnostic_width(Some(80)) + .supports_color(); let emitter = EmitterWriter::new( Box::new(io::sink()), diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 57cbfe68be4..15151e645fa 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -138,8 +138,12 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "crossbeam-utils", "crypto-common", "cstr", + "darling", + "darling_core", + "darling_macro", "datafrog", "derive_more", + "derive_setters", "digest", "displaydoc", "dissimilar", @@ -158,6 +162,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "fluent-bundle", "fluent-langneg", "fluent-syntax", + "fnv", "fortanix-sgx-abi", "generic-array", "getopts", @@ -171,6 +176,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "icu_provider", "icu_provider_adapters", "icu_provider_macros", + "ident_case", "indexmap", "instant", "intl-memoizer", @@ -245,6 +251,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "stable_deref_trait", "stacker", "static_assertions", + "strsim", "syn", "synstructure", "tempfile", From 0e7ec9683dae0a0bc66797b1351059ed642f4e2d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 25 Jul 2023 13:25:38 +0000 Subject: [PATCH 02/11] Use builder pattern instead of lots of arguments for `EmitterWriter::new` --- compiler/rustc_errors/src/emitter.rs | 47 +++--------------------- compiler/rustc_errors/src/json.rs | 18 ++++----- compiler/rustc_expand/src/tests.rs | 19 +++------- src/librustdoc/doctest.rs | 30 ++------------- src/tools/clippy/clippy_lints/src/doc.rs | 10 +---- src/tools/rustfmt/src/parse/session.rs | 15 +------- 6 files changed, 24 insertions(+), 115 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 70ca972ddb4..41fb1cafe25 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -62,30 +62,11 @@ impl HumanReadableErrorType { pub fn new_emitter( self, dst: Box, - source_map: Option>, - bundle: Option>, fallback_bundle: LazyFallbackBundle, - teach: bool, - diagnostic_width: Option, - macro_backtrace: bool, - track_diagnostics: bool, - terminal_url: TerminalUrl, ) -> EmitterWriter { let (short, color_config) = self.unzip(); let color = color_config.suggests_using_colors(); - EmitterWriter::new( - dst, - source_map, - bundle, - fallback_bundle, - short, - teach, - color, - diagnostic_width, - macro_backtrace, - track_diagnostics, - terminal_url, - ) + EmitterWriter::new(dst, fallback_bundle, color).short_message(short) } } @@ -668,6 +649,10 @@ pub struct FileWithAnnotatedLines { impl EmitterWriter { pub fn stderr(color_config: ColorConfig, fallback_bundle: LazyFallbackBundle) -> EmitterWriter { let dst = Destination::from_stderr(color_config); + Self::create(dst, fallback_bundle) + } + + fn create(dst: Destination, fallback_bundle: LazyFallbackBundle) -> EmitterWriter { EmitterWriter { dst, sm: None, @@ -685,30 +670,10 @@ impl EmitterWriter { pub fn new( dst: Box, - source_map: Option>, - fluent_bundle: Option>, fallback_bundle: LazyFallbackBundle, - short_message: bool, - teach: bool, colored: bool, - diagnostic_width: Option, - macro_backtrace: bool, - track_diagnostics: bool, - terminal_url: TerminalUrl, ) -> EmitterWriter { - EmitterWriter { - dst: Raw(dst, colored), - sm: source_map, - fluent_bundle, - fallback_bundle, - short_message, - teach, - ui_testing: false, - diagnostic_width, - macro_backtrace, - track_diagnostics, - terminal_url, - } + Self::create(Raw(dst, colored), fallback_bundle) } fn maybe_anonymized(&self, line_num: usize) -> Cow<'static, str> { diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 55f7c485024..e199244b1e4 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -359,17 +359,13 @@ impl Diagnostic { let buf = BufWriter::default(); let output = buf.clone(); je.json_rendered - .new_emitter( - Box::new(buf), - Some(je.sm.clone()), - je.fluent_bundle.clone(), - je.fallback_bundle.clone(), - false, - je.diagnostic_width, - je.macro_backtrace, - je.track_diagnostics, - je.terminal_url, - ) + .new_emitter(Box::new(buf), je.fallback_bundle.clone()) + .sm(Some(je.sm.clone())) + .fluent_bundle(je.fluent_bundle.clone()) + .diagnostic_width(je.diagnostic_width) + .macro_backtrace(je.macro_backtrace) + .track_diagnostics(je.track_diagnostics) + .terminal_url(je.terminal_url) .ui_testing(je.ui_testing) .emit_diagnostic(diag); let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap(); diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs index 30fa5fea407..4d1d834ed2b 100644 --- a/compiler/rustc_expand/src/tests.rs +++ b/compiler/rustc_expand/src/tests.rs @@ -8,7 +8,7 @@ use rustc_span::{BytePos, Span}; use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::EmitterWriter; -use rustc_errors::{Handler, MultiSpan, PResult, TerminalUrl}; +use rustc_errors::{Handler, MultiSpan, PResult}; use std::io; use std::io::prelude::*; @@ -29,19 +29,10 @@ fn create_test_handler() -> (Handler, Lrc, Arc>>) { vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE], false, ); - let emitter = EmitterWriter::new( - Box::new(Shared { data: output.clone() }), - Some(source_map.clone()), - None, - fallback_bundle, - false, - false, - false, - Some(140), - false, - false, - TerminalUrl::No, - ); + let emitter = + EmitterWriter::new(Box::new(Shared { data: output.clone() }), fallback_bundle, false) + .sm(Some(source_map.clone())) + .diagnostic_width(Some(140)); let handler = Handler::with_emitter(Box::new(emitter)); (handler, source_map, output) } diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 8f25f765390..1afac214da3 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1,7 +1,7 @@ use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{ColorConfig, ErrorGuaranteed, FatalError, TerminalUrl}; +use rustc_errors::{ColorConfig, ErrorGuaranteed, FatalError}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::{self as hir, intravisit, CRATE_HIR_ID}; use rustc_interface::interface; @@ -562,19 +562,7 @@ pub(crate) fn make_test( .diagnostic_width(Some(80)) .supports_color(); - let emitter = EmitterWriter::new( - Box::new(io::sink()), - None, - None, - fallback_bundle, - false, - false, - false, - None, - false, - false, - TerminalUrl::No, - ); + let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle, false); // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser let handler = Handler::with_emitter(Box::new(emitter)).disable_warnings(); @@ -750,19 +738,7 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool { false, ); - let emitter = EmitterWriter::new( - Box::new(io::sink()), - None, - None, - fallback_bundle, - false, - false, - false, - None, - false, - false, - TerminalUrl::No, - ); + let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle, false); let handler = Handler::with_emitter(Box::new(emitter)).disable_warnings(); let sess = ParseSess::with_span_handler(handler, sm); diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs index 00f70e586f4..573838ce63e 100644 --- a/src/tools/clippy/clippy_lints/src/doc.rs +++ b/src/tools/clippy/clippy_lints/src/doc.rs @@ -16,7 +16,7 @@ use rustc_ast::token::CommentKind; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::EmitterWriter; -use rustc_errors::{Applicability, Handler, SuggestionStyle, TerminalUrl}; +use rustc_errors::{Applicability, Handler, SuggestionStyle}; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{AnonConst, Expr}; @@ -718,16 +718,8 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) { rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false); let emitter = EmitterWriter::new( Box::new(io::sink()), - None, - None, fallback_bundle, false, - false, - false, - None, - false, - false, - TerminalUrl::No, ); let handler = Handler::with_emitter(Box::new(emitter)).disable_warnings(); let sess = ParseSess::with_span_handler(handler, sm); diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index aa75b477473..945e3e42fdd 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -4,7 +4,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::{Lrc, Send}; use rustc_errors::emitter::{Emitter, EmitterWriter}; use rustc_errors::translation::Translate; -use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel, TerminalUrl}; +use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel}; use rustc_session::parse::ParseSess as RawParseSess; use rustc_span::{ source_map::{FilePathMapping, SourceMap}, @@ -139,18 +139,7 @@ fn default_handler( rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false, ); - Box::new(EmitterWriter::stderr( - emit_color, - Some(source_map.clone()), - None, - fallback_bundle, - false, - false, - None, - false, - false, - TerminalUrl::No, - )) + Box::new(EmitterWriter::stderr(emit_color, fallback_bundle).sm(Some(source_map.clone()))) }; Handler::with_emitter(Box::new(SilentOnIgnoredFilesEmitter { has_non_ignorable_parser_errors: false, From 51c22154f56d54d512b0b14aebf9eb18278963a1 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jul 2023 13:58:50 +0000 Subject: [PATCH 03/11] Remove a `bool` for color in favor of the `WriteColor` trait wrapping colored and uncolored printing --- Cargo.lock | 1 + compiler/rustc_errors/src/emitter.rs | 31 ++++++++++-------------- compiler/rustc_errors/src/json.rs | 14 +++++++++++ compiler/rustc_expand/Cargo.toml | 1 + compiler/rustc_expand/src/tests.rs | 22 ++++++++++++++--- src/librustdoc/doctest.rs | 4 +-- src/tools/clippy/clippy_lints/src/doc.rs | 1 - 7 files changed, 49 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dd8ce11ac12..7b7c0fd60d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3619,6 +3619,7 @@ dependencies = [ "rustc_session", "rustc_span", "smallvec", + "termcolor", "thin-vec", "tracing", ] diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 41fb1cafe25..87b3a25ed44 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -61,12 +61,15 @@ impl HumanReadableErrorType { } pub fn new_emitter( self, - dst: Box, + mut dst: Box, fallback_bundle: LazyFallbackBundle, ) -> EmitterWriter { let (short, color_config) = self.unzip(); let color = color_config.suggests_using_colors(); - EmitterWriter::new(dst, fallback_bundle, color).short_message(short) + if !dst.supports_color() && color { + dst = Box::new(Ansi::new(dst)); + } + EmitterWriter::new(dst, fallback_bundle).short_message(short) } } @@ -669,11 +672,10 @@ impl EmitterWriter { } pub fn new( - dst: Box, + dst: Box, fallback_bundle: LazyFallbackBundle, - colored: bool, ) -> EmitterWriter { - Self::create(Raw(dst, colored), fallback_bundle) + Self::create(Raw(dst), fallback_bundle) } fn maybe_anonymized(&self, line_num: usize) -> Cow<'static, str> { @@ -2603,15 +2605,13 @@ fn emit_to_destination( pub enum Destination { Terminal(StandardStream), Buffered(BufferWriter), - // The bool denotes whether we should be emitting ansi color codes or not - Raw(Box<(dyn Write + Send)>, bool), + Raw(Box<(dyn WriteColor + Send)>), } pub enum WritableDst<'a> { Terminal(&'a mut StandardStream), Buffered(&'a mut BufferWriter, Buffer), - Raw(&'a mut (dyn Write + Send)), - ColoredRaw(Ansi<&'a mut (dyn Write + Send)>), + Raw(&'a mut (dyn WriteColor + Send)), } impl Destination { @@ -2637,8 +2637,7 @@ impl Destination { let buf = t.buffer(); WritableDst::Buffered(t, buf) } - Destination::Raw(ref mut t, false) => WritableDst::Raw(t), - Destination::Raw(ref mut t, true) => WritableDst::ColoredRaw(Ansi::new(t)), + Destination::Raw(ref mut t) => WritableDst::Raw(t), } } @@ -2646,7 +2645,7 @@ impl Destination { match *self { Self::Terminal(ref stream) => stream.supports_color(), Self::Buffered(ref buffer) => buffer.buffer().supports_color(), - Self::Raw(_, supports_color) => supports_color, + Self::Raw(ref writer) => writer.supports_color(), } } } @@ -2706,8 +2705,7 @@ impl<'a> WritableDst<'a> { match *self { WritableDst::Terminal(ref mut t) => t.set_color(color), WritableDst::Buffered(_, ref mut t) => t.set_color(color), - WritableDst::ColoredRaw(ref mut t) => t.set_color(color), - WritableDst::Raw(_) => Ok(()), + WritableDst::Raw(ref mut t) => t.set_color(color), } } @@ -2715,8 +2713,7 @@ impl<'a> WritableDst<'a> { match *self { WritableDst::Terminal(ref mut t) => t.reset(), WritableDst::Buffered(_, ref mut t) => t.reset(), - WritableDst::ColoredRaw(ref mut t) => t.reset(), - WritableDst::Raw(_) => Ok(()), + WritableDst::Raw(ref mut t) => t.reset(), } } } @@ -2727,7 +2724,6 @@ impl<'a> Write for WritableDst<'a> { WritableDst::Terminal(ref mut t) => t.write(bytes), WritableDst::Buffered(_, ref mut buf) => buf.write(bytes), WritableDst::Raw(ref mut w) => w.write(bytes), - WritableDst::ColoredRaw(ref mut t) => t.write(bytes), } } @@ -2736,7 +2732,6 @@ impl<'a> Write for WritableDst<'a> { WritableDst::Terminal(ref mut t) => t.flush(), WritableDst::Buffered(_, ref mut buf) => buf.flush(), WritableDst::Raw(ref mut w) => w.flush(), - WritableDst::ColoredRaw(ref mut w) => w.flush(), } } } diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index e199244b1e4..b8f58e3057c 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -10,6 +10,7 @@ // FIXME: spec the JSON output properly. use rustc_span::source_map::{FilePathMapping, SourceMap}; +use termcolor::{ColorSpec, WriteColor}; use crate::emitter::{Emitter, HumanReadableErrorType}; use crate::registry::Registry; @@ -356,6 +357,19 @@ impl Diagnostic { self.0.lock().unwrap().flush() } } + impl WriteColor for BufWriter { + fn supports_color(&self) -> bool { + false + } + + fn set_color(&mut self, _spec: &ColorSpec) -> io::Result<()> { + Ok(()) + } + + fn reset(&mut self) -> io::Result<()> { + Ok(()) + } + } let buf = BufWriter::default(); let output = buf.clone(); je.json_rendered diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml index 2dae0e3f53c..02da5b5dc53 100644 --- a/compiler/rustc_expand/Cargo.toml +++ b/compiler/rustc_expand/Cargo.toml @@ -27,3 +27,4 @@ rustc_span = { path = "../rustc_span" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } thin-vec = "0.2.12" tracing = "0.1" +termcolor = "1.2" diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs index 4d1d834ed2b..8e3219c138c 100644 --- a/compiler/rustc_expand/src/tests.rs +++ b/compiler/rustc_expand/src/tests.rs @@ -9,6 +9,7 @@ use rustc_span::{BytePos, Span}; use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::EmitterWriter; use rustc_errors::{Handler, MultiSpan, PResult}; +use termcolor::WriteColor; use std::io; use std::io::prelude::*; @@ -29,10 +30,9 @@ fn create_test_handler() -> (Handler, Lrc, Arc>>) { vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE], false, ); - let emitter = - EmitterWriter::new(Box::new(Shared { data: output.clone() }), fallback_bundle, false) - .sm(Some(source_map.clone())) - .diagnostic_width(Some(140)); + let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }), fallback_bundle) + .sm(Some(source_map.clone())) + .diagnostic_width(Some(140)); let handler = Handler::with_emitter(Box::new(emitter)); (handler, source_map, output) } @@ -156,6 +156,20 @@ pub(crate) struct Shared { pub data: Arc>, } +impl WriteColor for Shared { + fn supports_color(&self) -> bool { + false + } + + fn set_color(&mut self, _spec: &termcolor::ColorSpec) -> io::Result<()> { + Ok(()) + } + + fn reset(&mut self) -> io::Result<()> { + Ok(()) + } +} + impl Write for Shared { fn write(&mut self, buf: &[u8]) -> io::Result { self.data.lock().unwrap().write(buf) diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 1afac214da3..3315ccad4d3 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -562,7 +562,7 @@ pub(crate) fn make_test( .diagnostic_width(Some(80)) .supports_color(); - let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle, false); + let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle); // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser let handler = Handler::with_emitter(Box::new(emitter)).disable_warnings(); @@ -738,7 +738,7 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool { false, ); - let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle, false); + let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle); let handler = Handler::with_emitter(Box::new(emitter)).disable_warnings(); let sess = ParseSess::with_span_handler(handler, sm); diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs index 573838ce63e..2c4d93e33ba 100644 --- a/src/tools/clippy/clippy_lints/src/doc.rs +++ b/src/tools/clippy/clippy_lints/src/doc.rs @@ -719,7 +719,6 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) { let emitter = EmitterWriter::new( Box::new(io::sink()), fallback_bundle, - false, ); let handler = Handler::with_emitter(Box::new(emitter)).disable_warnings(); let sess = ParseSess::with_span_handler(handler, sm); From 339890e18618ff6efbe999e079a242c083dd7060 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jul 2023 14:43:39 +0000 Subject: [PATCH 04/11] Remove an enum variant that can be covered by another --- compiler/rustc_errors/src/emitter.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 87b3a25ed44..a54bc1b3c49 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2609,7 +2609,6 @@ pub enum Destination { } pub enum WritableDst<'a> { - Terminal(&'a mut StandardStream), Buffered(&'a mut BufferWriter, Buffer), Raw(&'a mut (dyn WriteColor + Send)), } @@ -2632,7 +2631,7 @@ impl Destination { fn writable(&mut self) -> WritableDst<'_> { match *self { - Destination::Terminal(ref mut t) => WritableDst::Terminal(t), + Destination::Terminal(ref mut t) => WritableDst::Raw(t), Destination::Buffered(ref mut t) => { let buf = t.buffer(); WritableDst::Buffered(t, buf) @@ -2703,7 +2702,6 @@ impl<'a> WritableDst<'a> { fn set_color(&mut self, color: &ColorSpec) -> io::Result<()> { match *self { - WritableDst::Terminal(ref mut t) => t.set_color(color), WritableDst::Buffered(_, ref mut t) => t.set_color(color), WritableDst::Raw(ref mut t) => t.set_color(color), } @@ -2711,7 +2709,6 @@ impl<'a> WritableDst<'a> { fn reset(&mut self) -> io::Result<()> { match *self { - WritableDst::Terminal(ref mut t) => t.reset(), WritableDst::Buffered(_, ref mut t) => t.reset(), WritableDst::Raw(ref mut t) => t.reset(), } @@ -2721,7 +2718,6 @@ impl<'a> WritableDst<'a> { impl<'a> Write for WritableDst<'a> { fn write(&mut self, bytes: &[u8]) -> io::Result { match *self { - WritableDst::Terminal(ref mut t) => t.write(bytes), WritableDst::Buffered(_, ref mut buf) => buf.write(bytes), WritableDst::Raw(ref mut w) => w.write(bytes), } @@ -2729,7 +2725,6 @@ impl<'a> Write for WritableDst<'a> { fn flush(&mut self) -> io::Result<()> { match *self { - WritableDst::Terminal(ref mut t) => t.flush(), WritableDst::Buffered(_, ref mut buf) => buf.flush(), WritableDst::Raw(ref mut w) => w.flush(), } From 00074698a7addd9bc726e3742c6462d2ee9627bf Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jul 2023 14:56:34 +0000 Subject: [PATCH 05/11] Merge buffered destination into raw destination --- compiler/rustc_errors/src/emitter.rs | 54 +++++++++++++++++++--------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index a54bc1b3c49..d60d4c7c8fb 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -36,8 +36,8 @@ use std::io::prelude::*; use std::io::{self, IsTerminal}; use std::iter; use std::path::Path; -use termcolor::{Ansi, BufferWriter, ColorChoice, ColorSpec, StandardStream}; -use termcolor::{Buffer, Color, WriteColor}; +use termcolor::{Ansi, Buffer, BufferWriter, ColorChoice, ColorSpec, StandardStream}; +use termcolor::{Color, WriteColor}; /// Default column width, used in tests and when terminal dimensions cannot be determined. const DEFAULT_COLUMN_WIDTH: usize = 140; @@ -2604,15 +2604,44 @@ fn emit_to_destination( pub enum Destination { Terminal(StandardStream), - Buffered(BufferWriter), Raw(Box<(dyn WriteColor + Send)>), } pub enum WritableDst<'a> { - Buffered(&'a mut BufferWriter, Buffer), Raw(&'a mut (dyn WriteColor + Send)), } +struct Buffy { + buffer_writer: BufferWriter, + buffer: Buffer, +} + +impl Write for Buffy { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.buffer.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.buffer_writer.print(&self.buffer)?; + self.buffer.clear(); + Ok(()) + } +} + +impl WriteColor for Buffy { + fn supports_color(&self) -> bool { + self.buffer.supports_color() + } + + fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { + self.buffer.set_color(spec) + } + + fn reset(&mut self) -> io::Result<()> { + self.buffer.reset() + } +} + impl Destination { fn from_stderr(color: ColorConfig) -> Destination { let choice = color.to_color_choice(); @@ -2625,17 +2654,15 @@ impl Destination { if cfg!(windows) { Terminal(StandardStream::stderr(choice)) } else { - Buffered(BufferWriter::stderr(choice)) + let buffer_writer = BufferWriter::stderr(choice); + let buffer = buffer_writer.buffer(); + Raw(Box::new(Buffy { buffer_writer, buffer })) } } fn writable(&mut self) -> WritableDst<'_> { match *self { Destination::Terminal(ref mut t) => WritableDst::Raw(t), - Destination::Buffered(ref mut t) => { - let buf = t.buffer(); - WritableDst::Buffered(t, buf) - } Destination::Raw(ref mut t) => WritableDst::Raw(t), } } @@ -2643,7 +2670,6 @@ impl Destination { fn supports_color(&self) -> bool { match *self { Self::Terminal(ref stream) => stream.supports_color(), - Self::Buffered(ref buffer) => buffer.buffer().supports_color(), Self::Raw(ref writer) => writer.supports_color(), } } @@ -2702,14 +2728,12 @@ impl<'a> WritableDst<'a> { fn set_color(&mut self, color: &ColorSpec) -> io::Result<()> { match *self { - WritableDst::Buffered(_, ref mut t) => t.set_color(color), WritableDst::Raw(ref mut t) => t.set_color(color), } } fn reset(&mut self) -> io::Result<()> { match *self { - WritableDst::Buffered(_, ref mut t) => t.reset(), WritableDst::Raw(ref mut t) => t.reset(), } } @@ -2718,14 +2742,12 @@ impl<'a> WritableDst<'a> { impl<'a> Write for WritableDst<'a> { fn write(&mut self, bytes: &[u8]) -> io::Result { match *self { - WritableDst::Buffered(_, ref mut buf) => buf.write(bytes), WritableDst::Raw(ref mut w) => w.write(bytes), } } fn flush(&mut self) -> io::Result<()> { match *self { - WritableDst::Buffered(_, ref mut buf) => buf.flush(), WritableDst::Raw(ref mut w) => w.flush(), } } @@ -2733,9 +2755,7 @@ impl<'a> Write for WritableDst<'a> { impl<'a> Drop for WritableDst<'a> { fn drop(&mut self) { - if let WritableDst::Buffered(ref mut dst, ref mut buf) = self { - drop(dst.print(buf)); - } + self.flush().unwrap() } } From 1e2167f5b56b443c70546bcd332c87266c1def29 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jul 2023 14:58:04 +0000 Subject: [PATCH 06/11] Move `WritableDst` method onto `Style` directly --- compiler/rustc_errors/src/emitter.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index d60d4c7c8fb..13d405c41bc 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2590,7 +2590,8 @@ fn emit_to_destination( let _buffer_lock = lock::acquire_global_lock("rustc_errors"); for (pos, line) in rendered_buffer.iter().enumerate() { for part in line { - dst.apply_style(*lvl, part.style)?; + let style = part.style.color_spec(*lvl); + dst.set_color(&style)?; write!(dst, "{}", part.text)?; dst.reset()?; } @@ -2675,10 +2676,10 @@ impl Destination { } } -impl<'a> WritableDst<'a> { - fn apply_style(&mut self, lvl: Level, style: Style) -> io::Result<()> { +impl Style { + fn color_spec(&self, lvl: Level) -> ColorSpec { let mut spec = ColorSpec::new(); - match style { + match self { Style::Addition => { spec.set_fg(Some(Color::Green)).set_intense(true); } @@ -2723,9 +2724,11 @@ impl<'a> WritableDst<'a> { spec.set_bold(true); } } - self.set_color(&spec) + spec } +} +impl<'a> WritableDst<'a> { fn set_color(&mut self, color: &ColorSpec) -> io::Result<()> { match *self { WritableDst::Raw(ref mut t) => t.set_color(color), From 826a8ef52ed7809953e5a702d5ea88de2f1fd065 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jul 2023 18:24:14 +0000 Subject: [PATCH 07/11] Remove a now-redundant single-variant enum --- compiler/rustc_errors/src/emitter.rs | 48 +++------------------------- 1 file changed, 5 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 13d405c41bc..cf456ebc8d5 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2158,7 +2158,7 @@ impl EmitterWriter { Err(e) => panic!("failed to emit error: {e}"), } - let mut dst = self.dst.writable(); + let dst = self.dst.writable(); match writeln!(dst) { Err(e) => panic!("failed to emit error: {e}"), _ => { @@ -2573,7 +2573,7 @@ fn emit_to_destination( ) -> io::Result<()> { use crate::lock; - let mut dst = dst.writable(); + let dst = dst.writable(); // In order to prevent error message interleaving, where multiple error lines get intermixed // when multiple compiler processes error simultaneously, we emit errors with additional @@ -2608,10 +2608,6 @@ pub enum Destination { Raw(Box<(dyn WriteColor + Send)>), } -pub enum WritableDst<'a> { - Raw(&'a mut (dyn WriteColor + Send)), -} - struct Buffy { buffer_writer: BufferWriter, buffer: Buffer, @@ -2661,10 +2657,10 @@ impl Destination { } } - fn writable(&mut self) -> WritableDst<'_> { + fn writable(&mut self) -> &mut dyn WriteColor { match *self { - Destination::Terminal(ref mut t) => WritableDst::Raw(t), - Destination::Raw(ref mut t) => WritableDst::Raw(t), + Destination::Terminal(ref mut t) => t, + Destination::Raw(ref mut t) => t, } } @@ -2728,40 +2724,6 @@ impl Style { } } -impl<'a> WritableDst<'a> { - fn set_color(&mut self, color: &ColorSpec) -> io::Result<()> { - match *self { - WritableDst::Raw(ref mut t) => t.set_color(color), - } - } - - fn reset(&mut self) -> io::Result<()> { - match *self { - WritableDst::Raw(ref mut t) => t.reset(), - } - } -} - -impl<'a> Write for WritableDst<'a> { - fn write(&mut self, bytes: &[u8]) -> io::Result { - match *self { - WritableDst::Raw(ref mut w) => w.write(bytes), - } - } - - fn flush(&mut self) -> io::Result<()> { - match *self { - WritableDst::Raw(ref mut w) => w.flush(), - } - } -} - -impl<'a> Drop for WritableDst<'a> { - fn drop(&mut self) { - self.flush().unwrap() - } -} - /// Whether the original and suggested code are visually similar enough to warrant extra wording. pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool { // FIXME: this should probably be extended to also account for `FO0` → `FOO` and unicode. From 10da30f540f76c10c7f029da1eec27439496f703 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jul 2023 18:26:24 +0000 Subject: [PATCH 08/11] Merge all `Destination` variants --- compiler/rustc_errors/src/emitter.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index cf456ebc8d5..b51ec3a8fcd 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2604,7 +2604,6 @@ fn emit_to_destination( } pub enum Destination { - Terminal(StandardStream), Raw(Box<(dyn WriteColor + Send)>), } @@ -2649,7 +2648,7 @@ impl Destination { // On non-Windows we rely on the atomicity of `write` to ensure errors // don't get all jumbled up. if cfg!(windows) { - Terminal(StandardStream::stderr(choice)) + Raw(Box::new(StandardStream::stderr(choice))) } else { let buffer_writer = BufferWriter::stderr(choice); let buffer = buffer_writer.buffer(); @@ -2659,14 +2658,12 @@ impl Destination { fn writable(&mut self) -> &mut dyn WriteColor { match *self { - Destination::Terminal(ref mut t) => t, Destination::Raw(ref mut t) => t, } } fn supports_color(&self) -> bool { match *self { - Self::Terminal(ref stream) => stream.supports_color(), Self::Raw(ref writer) => writer.supports_color(), } } From 2131eee179019bb0572b17943e4913ff77108123 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jul 2023 18:39:10 +0000 Subject: [PATCH 09/11] Turn a single-variant enum into a struct --- compiler/rustc_errors/src/emitter.rs | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index b51ec3a8fcd..2d1b954690e 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -7,8 +7,6 @@ //! //! The output types are defined in `rustc_session::config::ErrorOutputType`. -use Destination::*; - use rustc_span::source_map::SourceMap; use rustc_span::{FileLines, SourceFile, Span}; @@ -675,7 +673,7 @@ impl EmitterWriter { dst: Box, fallback_bundle: LazyFallbackBundle, ) -> EmitterWriter { - Self::create(Raw(dst), fallback_bundle) + Self::create(Destination(dst), fallback_bundle) } fn maybe_anonymized(&self, line_num: usize) -> Cow<'static, str> { @@ -2603,9 +2601,7 @@ fn emit_to_destination( Ok(()) } -pub enum Destination { - Raw(Box<(dyn WriteColor + Send)>), -} +pub struct Destination(pub(crate) Box<(dyn WriteColor + Send)>); struct Buffy { buffer_writer: BufferWriter, @@ -2648,24 +2644,20 @@ impl Destination { // On non-Windows we rely on the atomicity of `write` to ensure errors // don't get all jumbled up. if cfg!(windows) { - Raw(Box::new(StandardStream::stderr(choice))) + Destination(Box::new(StandardStream::stderr(choice))) } else { let buffer_writer = BufferWriter::stderr(choice); let buffer = buffer_writer.buffer(); - Raw(Box::new(Buffy { buffer_writer, buffer })) + Destination(Box::new(Buffy { buffer_writer, buffer })) } } fn writable(&mut self) -> &mut dyn WriteColor { - match *self { - Destination::Raw(ref mut t) => t, - } + &mut self.0 } fn supports_color(&self) -> bool { - match *self { - Self::Raw(ref writer) => writer.supports_color(), - } + self.0.supports_color() } } From d9deaf4b8af7efc4b980e00e2f15622c20d9cdc3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jul 2023 18:47:38 +0000 Subject: [PATCH 10/11] Get rid of the thin wrapper type that is `Destination` and just write to the `Writer` trait object directly --- compiler/rustc_errors/src/emitter.rs | 51 +++++++++++----------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 2d1b954690e..0d73073395b 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -649,7 +649,7 @@ pub struct FileWithAnnotatedLines { impl EmitterWriter { pub fn stderr(color_config: ColorConfig, fallback_bundle: LazyFallbackBundle) -> EmitterWriter { - let dst = Destination::from_stderr(color_config); + let dst = from_stderr(color_config); Self::create(dst, fallback_bundle) } @@ -673,7 +673,7 @@ impl EmitterWriter { dst: Box, fallback_bundle: LazyFallbackBundle, ) -> EmitterWriter { - Self::create(Destination(dst), fallback_bundle) + Self::create(dst, fallback_bundle) } fn maybe_anonymized(&self, line_num: usize) -> Cow<'static, str> { @@ -2156,11 +2156,10 @@ impl EmitterWriter { Err(e) => panic!("failed to emit error: {e}"), } - let dst = self.dst.writable(); - match writeln!(dst) { + match writeln!(self.dst) { Err(e) => panic!("failed to emit error: {e}"), _ => { - if let Err(e) = dst.flush() { + if let Err(e) = self.dst.flush() { panic!("failed to emit error: {e}") } } @@ -2571,8 +2570,6 @@ fn emit_to_destination( ) -> io::Result<()> { use crate::lock; - let dst = dst.writable(); - // In order to prevent error message interleaving, where multiple error lines get intermixed // when multiple compiler processes error simultaneously, we emit errors with additional // steps. @@ -2601,7 +2598,7 @@ fn emit_to_destination( Ok(()) } -pub struct Destination(pub(crate) Box<(dyn WriteColor + Send)>); +pub type Destination = Box<(dyn WriteColor + Send)>; struct Buffy { buffer_writer: BufferWriter, @@ -2634,30 +2631,20 @@ impl WriteColor for Buffy { } } -impl Destination { - fn from_stderr(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 - // anything. - // - // On non-Windows we rely on the atomicity of `write` to ensure errors - // don't get all jumbled up. - if cfg!(windows) { - Destination(Box::new(StandardStream::stderr(choice))) - } else { - let buffer_writer = BufferWriter::stderr(choice); - let buffer = buffer_writer.buffer(); - Destination(Box::new(Buffy { buffer_writer, buffer })) - } - } - - fn writable(&mut self) -> &mut dyn WriteColor { - &mut self.0 - } - - fn supports_color(&self) -> bool { - self.0.supports_color() +fn from_stderr(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 + // anything. + // + // On non-Windows we rely on the atomicity of `write` to ensure errors + // don't get all jumbled up. + if cfg!(windows) { + Box::new(StandardStream::stderr(choice)) + } else { + let buffer_writer = BufferWriter::stderr(choice); + let buffer = buffer_writer.buffer(); + Box::new(Buffy { buffer_writer, buffer }) } } From 375d8f1b25b12d252e6aff030c0bcf64b77f886b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 26 Jul 2023 18:52:08 +0000 Subject: [PATCH 11/11] Sanity check that we actually flush all buffers --- compiler/rustc_errors/src/emitter.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 0d73073395b..0cae06881b1 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2617,6 +2617,15 @@ impl Write for Buffy { } } +impl Drop for Buffy { + fn drop(&mut self) { + if !self.buffer.is_empty() { + self.flush().unwrap(); + panic!("buffers need to be flushed in order to print their contents"); + } + } +} + impl WriteColor for Buffy { fn supports_color(&self) -> bool { self.buffer.supports_color()