From c94d1358e903fc25aa8015ff4c1f20f61db8d161 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Tue, 28 Oct 2025 12:40:48 -0600 Subject: [PATCH] feat: Add unstable rustc-unicode flag --- src/cargo/core/compiler/mod.rs | 13 ++++--- src/cargo/core/features.rs | 2 + src/cargo/core/shell.rs | 34 ++++++++++++++++- src/cargo/util/context/mod.rs | 3 ++ src/doc/src/reference/unstable.md | 7 ++++ tests/testsuite/cargo/z_help/stdout.term.svg | 36 +++++++++--------- tests/testsuite/lints/mod.rs | 39 ++++++++++++++++++++ tests/testsuite/message_format.rs | 36 ++++++++++++++++++ 8 files changed, 147 insertions(+), 23 deletions(-) diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 3385d7fbdf4..02349a20849 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -1095,11 +1095,14 @@ fn add_error_format_and_color(build_runner: &BuildRunner<'_, '_>, cmd: &mut Proc cmd.arg("--error-format=json"); let mut json = String::from("--json=diagnostic-rendered-ansi,artifacts,future-incompat"); - match build_runner.bcx.build_config.message_format { - MessageFormat::Short | MessageFormat::Json { short: true, .. } => { - json.push_str(",diagnostic-short"); - } - _ => {} + if let MessageFormat::Short | MessageFormat::Json { short: true, .. } = + build_runner.bcx.build_config.message_format + { + json.push_str(",diagnostic-short"); + } else if build_runner.bcx.gctx.shell().err_unicode() + && build_runner.bcx.gctx.cli_unstable().rustc_unicode + { + json.push_str(",diagnostic-unicode"); } if enable_timings { diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index 0abd8bd2068..f9f13dc2951 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -881,6 +881,7 @@ unstable_cli_options!( public_dependency: bool = ("Respect a dependency's `public` field in Cargo.toml to control public/private dependencies"), publish_timeout: bool = ("Enable the `publish.timeout` key in .cargo/config.toml file"), root_dir: Option = ("Set the root directory relative to which paths are printed (defaults to workspace root)"), + rustc_unicode: bool = ("Enable `rustc`'s unicode error format in Cargo's error messages"), rustdoc_depinfo: bool = ("Use dep-info files in rustdoc rebuild detection"), rustdoc_map: bool = ("Allow passing external documentation mappings to rustdoc"), rustdoc_scrape_examples: bool = ("Allows Rustdoc to scrape code examples from reverse-dependencies"), @@ -1411,6 +1412,7 @@ impl CliUnstable { "trim-paths" => self.trim_paths = parse_empty(k, v)?, "publish-timeout" => self.publish_timeout = parse_empty(k, v)?, "root-dir" => self.root_dir = v.map(|v| v.into()), + "rustc-unicode" => self.rustc_unicode = parse_empty(k, v)?, "rustdoc-depinfo" => self.rustdoc_depinfo = parse_empty(k, v)?, "rustdoc-map" => self.rustdoc_map = parse_empty(k, v)?, "rustdoc-scrape-examples" => self.rustdoc_scrape_examples = parse_empty(k, v)?, diff --git a/src/cargo/core/shell.rs b/src/cargo/core/shell.rs index 6a5077dd1b5..be622ef1e7c 100644 --- a/src/cargo/core/shell.rs +++ b/src/cargo/core/shell.rs @@ -2,6 +2,7 @@ use std::fmt; use std::io::IsTerminal; use std::io::prelude::*; +use annotate_snippets::renderer::DecorStyle; use annotate_snippets::{Renderer, Report}; use anstream::AutoStream; use anstyle::Style; @@ -57,6 +58,7 @@ impl Shell { stdout_unicode: supports_unicode(&std::io::stdout()), stderr_unicode: supports_unicode(&std::io::stderr()), stderr_term_integration: supports_term_integration(&std::io::stderr()), + unstable_flags_rustc_unicode: false, }, verbosity: Verbosity::Verbose, needs_clear: false, @@ -380,6 +382,27 @@ impl Shell { Some(url) } + fn unstable_flags_rustc_unicode(&self) -> bool { + match &self.output { + ShellOut::Write(_) => false, + ShellOut::Stream { + unstable_flags_rustc_unicode, + .. + } => *unstable_flags_rustc_unicode, + } + } + + pub(crate) fn set_unstable_flags_rustc_unicode(&mut self, yes: bool) -> CargoResult<()> { + if let ShellOut::Stream { + unstable_flags_rustc_unicode, + .. + } = &mut self.output + { + *unstable_flags_rustc_unicode = yes; + } + Ok(()) + } + /// Prints a message to stderr and translates ANSI escape code into console colors. pub fn print_ansi_stderr(&mut self, message: &[u8]) -> CargoResult<()> { if self.needs_clear { @@ -419,7 +442,15 @@ impl Shell { .err_width() .diagnostic_terminal_width() .unwrap_or(annotate_snippets::renderer::DEFAULT_TERM_WIDTH); - let rendered = Renderer::styled().term_width(term_width).render(report); + let decor_style = if self.err_unicode() && self.unstable_flags_rustc_unicode() { + DecorStyle::Unicode + } else { + DecorStyle::Ascii + }; + let rendered = Renderer::styled() + .term_width(term_width) + .decor_style(decor_style) + .render(report); self.err().write_all(rendered.as_bytes())?; self.err().write_all(b"\n")?; Ok(()) @@ -446,6 +477,7 @@ enum ShellOut { stdout_unicode: bool, stderr_unicode: bool, stderr_term_integration: bool, + unstable_flags_rustc_unicode: bool, }, } diff --git a/src/cargo/util/context/mod.rs b/src/cargo/util/context/mod.rs index 41caafc0c1c..dfe60d5e73e 100644 --- a/src/cargo/util/context/mod.rs +++ b/src/cargo/util/context/mod.rs @@ -1174,6 +1174,9 @@ impl GlobalContext { let cli_target_dir = target_dir.as_ref().map(|dir| Filesystem::new(dir.clone())); self.target_dir = cli_target_dir; + self.shell() + .set_unstable_flags_rustc_unicode(self.unstable_flags.rustc_unicode)?; + Ok(()) } diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index 3571f60c1be..63a811ca1dd 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -116,6 +116,7 @@ Each new feature described below should explain how to use it. * [unit-graph](#unit-graph) --- Emits JSON for Cargo's internal graph structure. * [`cargo rustc --print`](#rustc---print) --- Calls rustc with `--print` to display information from rustc. * [Build analysis](#build-analysis) --- Record and persist detailed build metrics across runs, with new commands to query past builds. + * [`rustc-unicode`](#rustc-unicode) --- Enables `rustc`'s unicode error format in Cargo's error messages * Configuration * [config-include](#config-include) --- Adds the ability for config files to include other files. * [`cargo config`](#cargo-config) --- Adds a new subcommand for viewing config files. @@ -2028,6 +2029,12 @@ cargo +nightly build --compile-time-deps -Z unstable-options cargo +nightly check --compile-time-deps --all-targets -Z unstable-options ``` +# `rustc-unicode` +* Tracking Issue: [rust#148607](https://github.com/rust-lang/rust/issues/148607) + +Enable `rustc`'s unicode error format in Cargo's error messages + + # Stabilized and removed features ## Compile progress diff --git a/tests/testsuite/cargo/z_help/stdout.term.svg b/tests/testsuite/cargo/z_help/stdout.term.svg index 86cebba751f..f3354ac179b 100644 --- a/tests/testsuite/cargo/z_help/stdout.term.svg +++ b/tests/testsuite/cargo/z_help/stdout.term.svg @@ -1,7 +1,7 @@ - +