diff --git a/Cargo.lock b/Cargo.lock
index a39e468e3d978..933c413bfee62 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -149,6 +149,15 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
+[[package]]
+name = "anstyle-lossy"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9a0444767dbd4aea9355cb47a370eb184dbfe918875e127eff52cb9d1638181"
+dependencies = [
+ "anstyle",
+]
+
[[package]]
name = "anstyle-parse"
version = "0.2.3"
@@ -167,6 +176,19 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "anstyle-svg"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b6ddad447b448d6d5db36b31cbd3ff27c7af071619501998eeceab01968287a"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "anstyle-lossy",
+ "html-escape",
+ "unicode-width",
+]
+
[[package]]
name = "anstyle-wincon"
version = "3.0.2"
@@ -724,6 +746,7 @@ dependencies = [
name = "compiletest"
version = "0.0.0"
dependencies = [
+ "anstyle-svg",
"anyhow",
"build_helper",
"colored",
@@ -1672,6 +1695,15 @@ dependencies = [
"walkdir",
]
+[[package]]
+name = "html-escape"
+version = "0.2.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476"
+dependencies = [
+ "utf8-width",
+]
+
[[package]]
name = "html5ever"
version = "0.26.0"
@@ -6019,6 +6051,12 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
+[[package]]
+name = "utf8-width"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
+
[[package]]
name = "utf8parse"
version = "0.2.1"
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index 62d0fcc1a6088..4539c9b3285ff 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
doctest = false
[dependencies]
+anstyle-svg = "0.1.3"
colored = "2"
diff = "0.1.10"
unified-diff = "0.2.1"
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 49f1226e2cc38..27eb8c83a9ab1 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -703,6 +703,7 @@ pub fn expected_output_path(
}
pub const UI_EXTENSIONS: &[&str] = &[
+ UI_SVG,
UI_STDERR,
UI_STDOUT,
UI_FIXED,
@@ -714,6 +715,7 @@ pub const UI_EXTENSIONS: &[&str] = &[
UI_COVERAGE,
UI_COVERAGE_MAP,
];
+pub const UI_SVG: &str = "svg";
pub const UI_STDERR: &str = "stderr";
pub const UI_STDOUT: &str = "stdout";
pub const UI_FIXED: &str = "fixed";
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index a942aa9dc90bd..b07acb506bfa4 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1,6 +1,6 @@
// ignore-tidy-filelength
-use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT};
+use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT, UI_SVG};
use crate::common::{incremental_dir, output_base_dir, output_base_name, output_testname_unique};
use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, RustdocJson, Ui};
use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc};
@@ -4014,9 +4014,22 @@ impl<'test> TestCx<'test> {
explicit_format: bool,
) -> usize {
let stderr_bits = format!("{}bit.stderr", self.config.get_pointer_width());
+ let force_color_svg = self.props.compile_flags.iter().any(|s| s.contains("--color"));
let (stderr_kind, stdout_kind) = match output_kind {
TestOutput::Compile => (
- { if self.props.stderr_per_bitwidth { &stderr_bits } else { UI_STDERR } },
+ if force_color_svg {
+ if self.config.target.contains("windows") {
+ // We single out Windows here because some of the CLI coloring is
+ // specifically changed for Windows.
+ "windows.svg"
+ } else {
+ UI_SVG
+ }
+ } else if self.props.stderr_per_bitwidth {
+ &stderr_bits
+ } else {
+ UI_STDERR
+ },
UI_STDOUT,
),
TestOutput::Run => (UI_RUN_STDERR, UI_RUN_STDOUT),
@@ -4051,7 +4064,9 @@ impl<'test> TestCx<'test> {
_ => {}
};
- let stderr = if explicit_format {
+ let stderr = if force_color_svg {
+ anstyle_svg::Term::new().render_svg(&proc_res.stderr)
+ } else if explicit_format {
proc_res.stderr.clone()
} else {
json::extract_rendered(&proc_res.stderr)
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 920fe16a9fcb4..51d52c8838fb2 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -23,6 +23,7 @@ const ROOT_ENTRY_LIMIT: usize = 872;
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
"rs", // test source files
"stderr", // expected stderr file, corresponds to a rs file
+ "svg", // expected svg file, corresponds to a rs file, equivalent to stderr
"stdout", // expected stdout file, corresponds to a rs file
"fixed", // expected source file after applying fixes
"md", // test directory descriptions
diff --git a/tests/ui/diagnostic-flags/colored-session-opt-error.stderr b/tests/ui/diagnostic-flags/colored-session-opt-error.stderr
deleted file mode 100644
index ef79d5b0f2f82..0000000000000
--- a/tests/ui/diagnostic-flags/colored-session-opt-error.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-[0m[1m[33mwarning[0m[0m[1m: -C remark requires "-C debuginfo=n" to show source locations[0m
-
diff --git a/tests/ui/diagnostic-flags/colored-session-opt-error.svg b/tests/ui/diagnostic-flags/colored-session-opt-error.svg
new file mode 100644
index 0000000000000..e8835534e04c3
--- /dev/null
+++ b/tests/ui/diagnostic-flags/colored-session-opt-error.svg
@@ -0,0 +1,29 @@
+
diff --git a/tests/ui/error-emitter/highlighting.not-windows.stderr b/tests/ui/error-emitter/highlighting.not-windows.stderr
deleted file mode 100644
index 922bb19a248ff..0000000000000
--- a/tests/ui/error-emitter/highlighting.not-windows.stderr
+++ /dev/null
@@ -1,22 +0,0 @@
-[0m[1m[38;5;9merror[E0308][0m[0m[1m: mismatched types[0m
-[0m [0m[0m[1m[38;5;12m--> [0m[0m$DIR/highlighting.rs:26:11[0m
-[0m [0m[0m[1m[38;5;12m|[0m
-[0m[1m[38;5;12mLL[0m[0m [0m[0m[1m[38;5;12m|[0m[0m [0m[0m query(wrapped_fn);[0m
-[0m [0m[0m[1m[38;5;12m| [0m[0m [0m[0m[1m[38;5;12m-----[0m[0m [0m[0m[1m[38;5;9m^^^^^^^^^^[0m[0m [0m[0m[1m[38;5;9mone type is more general than the other[0m
-[0m [0m[0m[1m[38;5;12m| [0m[0m [0m[0m[1m[38;5;12m|[0m
-[0m [0m[0m[1m[38;5;12m| [0m[0m [0m[0m[1m[38;5;12marguments to this function are incorrect[0m
-[0m [0m[0m[1m[38;5;12m|[0m
-[0m [0m[0m[1m[38;5;12m= [0m[0m[1mnote[0m[0m: expected fn pointer `[0m[0m[1m[35mfor<'a> [0m[0mfn(Box<[0m[0m[1m[35m(dyn Any + Send + 'a)[0m[0m>) -> Pin<_>`[0m
-[0m found fn item `fn(Box<[0m[0m[1m[35m(dyn Any + Send + 'static)[0m[0m>) -> Pin<_> {wrapped_fn}`[0m
-[0m[1m[38;5;10mnote[0m[0m: function defined here[0m
-[0m [0m[0m[1m[38;5;12m--> [0m[0m$DIR/highlighting.rs:15:4[0m
-[0m [0m[0m[1m[38;5;12m|[0m
-[0m[1m[38;5;12mLL[0m[0m [0m[0m[1m[38;5;12m|[0m[0m [0m[0mfn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin, String>> + Send + 'static[0m
-[0m[1m[38;5;12mLL[0m[0m [0m[0m[1m[38;5;12m|[0m[0m [0m[0m[1m[38;5;12m|[0m[0m [0m[0m)>>) {}[0m
-[0m [0m[0m[1m[38;5;12m| [0m[0m[1m[38;5;12m|___-[0m
-
-[0m[1m[38;5;9merror[0m[0m[1m: aborting due to 1 previous error[0m
-
-[0m[1mFor more information about this error, try `rustc --explain E0308`.[0m
diff --git a/tests/ui/error-emitter/highlighting.not-windows.svg b/tests/ui/error-emitter/highlighting.not-windows.svg
new file mode 100644
index 0000000000000..2d561ea8b169e
--- /dev/null
+++ b/tests/ui/error-emitter/highlighting.not-windows.svg
@@ -0,0 +1,72 @@
+
diff --git a/tests/ui/error-emitter/multiline-multipart-suggestion.not-windows.stderr b/tests/ui/error-emitter/multiline-multipart-suggestion.not-windows.stderr
deleted file mode 100644
index 49c0354a2a79c..0000000000000
--- a/tests/ui/error-emitter/multiline-multipart-suggestion.not-windows.stderr
+++ /dev/null
@@ -1,46 +0,0 @@
-[0m[1m[38;5;9merror[E0106][0m[0m[1m: missing lifetime specifier[0m
-[0m [0m[0m[1m[38;5;12m--> [0m[0m$DIR/multiline-multipart-suggestion.rs:8:34[0m
-[0m [0m[0m[1m[38;5;12m|[0m
-[0m[1m[38;5;12mLL[0m[0m [0m[0m[1m[38;5;12m|[0m[0m [0m[0mfn short(foo_bar: &Vec<&i32>) -> &i32 {[0m
-[0m [0m[0m[1m[38;5;12m| [0m[0m [0m[0m[1m[38;5;12m----------[0m[0m [0m[0m[1m[38;5;9m^[0m[0m [0m[0m[1m[38;5;9mexpected named lifetime parameter[0m
-[0m [0m[0m[1m[38;5;12m|[0m
-[0m [0m[0m[1m[38;5;12m= [0m[0m[1mhelp[0m[0m: this function's return type contains a borrowed value, but the signature does not say which one of `foo_bar`'s 2 lifetimes it is borrowed from[0m
-[0m[1m[38;5;14mhelp[0m[0m: consider introducing a named lifetime parameter[0m
-[0m [0m[0m[1m[38;5;12m|[0m
-[0m[1m[38;5;12mLL[0m[0m [0m[0m[1m[38;5;12m| [0m[0mfn short[0m[0m[38;5;10m<'a>[0m[0m(foo_bar: &[0m[0m[38;5;10m'a [0m[0mVec<&[0m[0m[38;5;10m'a [0m[0mi32>) -> &[0m[0m[38;5;10m'a [0m[0mi32 {[0m
-[0m [0m[0m[1m[38;5;12m|[0m[0m [0m[0m[38;5;10m++++[0m[0m [0m[0m[38;5;10m++[0m[0m [0m[0m[38;5;10m++[0m[0m [0m[0m[38;5;10m++[0m
-
-[0m[1m[38;5;9merror[E0106][0m[0m[1m: missing lifetime specifier[0m
-[0m [0m[0m[1m[38;5;12m--> [0m[0m$DIR/multiline-multipart-suggestion.rs:15:6[0m
-[0m [0m[0m[1m[38;5;12m|[0m
-[0m[1m[38;5;12mLL[0m[0m [0m[0m[1m[38;5;12m|[0m[0m [0m[0m foo_bar: &Vec<&i32>,[0m
-[0m [0m[0m[1m[38;5;12m| [0m[0m [0m[0m[1m[38;5;12m----------[0m
-[0m[1m[38;5;12mLL[0m[0m [0m[0m[1m[38;5;12m|[0m[0m [0m[0m something_very_long_so_that_the_line_will_wrap_around__________: i32,[0m
-[0m[1m[38;5;12mLL[0m[0m [0m[0m[1m[38;5;12m|[0m[0m [0m[0m) -> &i32 {[0m
-[0m [0m[0m[1m[38;5;12m| [0m[0m [0m[0m[1m[38;5;9m^[0m[0m [0m[0m[1m[38;5;9mexpected named lifetime parameter[0m
-[0m [0m[0m[1m[38;5;12m|[0m
-[0m [0m[0m[1m[38;5;12m= [0m[0m[1mhelp[0m[0m: this function's return type contains a borrowed value, but the signature does not say which one of `foo_bar`'s 2 lifetimes it is borrowed from[0m
-[0m[1m[38;5;14mhelp[0m[0m: consider introducing a named lifetime parameter[0m
-[0m [0m[0m[1m[38;5;12m|[0m
-[0m[1m[38;5;12mLL[0m[0m [0m[0m[38;5;10m~ [0m[0mfn long[0m[0m[38;5;10m<'a>[0m[0m([0m
-[0m[1m[38;5;12mLL[0m[0m [0m[0m[38;5;10m~ [0m[0m foo_bar: &[0m[0m[38;5;10m'a [0m[0mVec<&[0m[0m[38;5;10m'a [0m[0mi32>,[0m
-[0m[1m[38;5;12mLL[0m[0m [0m[0m[1m[38;5;12m| [0m[0m something_very_long_so_that_the_line_will_wrap_around__________: i32,[0m
-[0m[1m[38;5;12mLL[0m[0m [0m[0m[38;5;10m~ [0m[0m) -> &[0m[0m[38;5;10m'a [0m[0mi32 {[0m
-[0m [0m[0m[1m[38;5;12m|[0m
-
-[0m[1m[38;5;9merror[E0106][0m[0m[1m: missing lifetime specifier[0m
-[0m [0m[0m[1m[38;5;12m--> [0m[0m$DIR/multiline-multipart-suggestion.rs:20:29[0m
-[0m [0m[0m[1m[38;5;12m|[0m
-[0m[1m[38;5;12mLL[0m[0m [0m[0m[1m[38;5;12m|[0m[0m [0m[0m foo_bar: &Vec<&i32>) -> &i32 {[0m
-[0m [0m[0m[1m[38;5;12m| [0m[0m [0m[0m[1m[38;5;12m----------[0m[0m [0m[0m[1m[38;5;9m^[0m[0m [0m[0m[1m[38;5;9mexpected named lifetime parameter[0m
-[0m [0m[0m[1m[38;5;12m|[0m
-[0m [0m[0m[1m[38;5;12m= [0m[0m[1mhelp[0m[0m: this function's return type contains a borrowed value, but the signature does not say which one of `foo_bar`'s 2 lifetimes it is borrowed from[0m
-[0m[1m[38;5;14mhelp[0m[0m: consider introducing a named lifetime parameter[0m
-[0m [0m[0m[1m[38;5;12m|[0m
-[0m[1m[38;5;12mLL[0m[0m [0m[0m[38;5;10m~ [0m[0mfn long2[0m[0m[38;5;10m<'a>[0m[0m([0m
-[0m[1m[38;5;12mLL[0m[0m [0m[0m[38;5;10m~ [0m[0m foo_bar: &[0m[0m[38;5;10m'a [0m[0mVec<&[0m[0m[38;5;10m'a [0m[0mi32>) -> &[0m[0m[38;5;10m'a [0m[0mi32 {[0m
-[0m [0m[0m[1m[38;5;12m|[0m
-
-[0m[1m[38;5;9merror[0m[0m[1m: aborting due to 3 previous errors[0m
-
-[0m[1mFor more information about this error, try `rustc --explain E0106`.[0m
diff --git a/tests/ui/error-emitter/multiline-multipart-suggestion.not-windows.svg b/tests/ui/error-emitter/multiline-multipart-suggestion.not-windows.svg
new file mode 100644
index 0000000000000..f38d559d69c10
--- /dev/null
+++ b/tests/ui/error-emitter/multiline-multipart-suggestion.not-windows.svg
@@ -0,0 +1,120 @@
+
diff --git a/tests/ui/json/json-and-color.stderr b/tests/ui/json/json-and-color.stderr
deleted file mode 100644
index 1cda6af090dfa..0000000000000
--- a/tests/ui/json/json-and-color.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-error: cannot specify the `--color` option with `--json`
-
diff --git a/tests/ui/json/json-and-color.svg b/tests/ui/json/json-and-color.svg
new file mode 100644
index 0000000000000..f254b7f971c7e
--- /dev/null
+++ b/tests/ui/json/json-and-color.svg
@@ -0,0 +1,27 @@
+