diff --git a/Cargo.lock b/Cargo.lock
index ee60ba5ca2d..5feb21a65b7 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"
@@ -6030,6 +6062,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 62d0fcc1a60..4539c9b3285 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 bfe6c959e7c..8c50bcd5b61 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -705,6 +705,8 @@ pub fn expected_output_path(
pub const UI_EXTENSIONS: &[&str] = &[
UI_STDERR,
+ UI_SVG,
+ UI_WINDOWS_SVG,
UI_STDOUT,
UI_FIXED,
UI_RUN_STDERR,
@@ -716,6 +718,8 @@ pub fn expected_output_path(
UI_COVERAGE_MAP,
];
pub const UI_STDERR: &str = "stderr";
+pub const UI_SVG: &str = "svg";
+pub const UI_WINDOWS_SVG: &str = "windows.svg";
pub const UI_STDOUT: &str = "stdout";
pub const UI_FIXED: &str = "fixed";
pub const UI_RUN_STDERR: &str = "run.stderr";
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index a942aa9dc90..ae0db88d873 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1,6 +1,8 @@
// 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, UI_WINDOWS_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 +4016,22 @@ fn load_compare_outputs(
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=always"));
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.
+ UI_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 +4066,9 @@ fn load_compare_outputs(
_ => {}
};
- 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 8899a55b2df..e35f3f05d66 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -23,6 +23,7 @@
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.rs b/tests/ui/diagnostic-flags/colored-session-opt-error.rs
index c8568eff325..932c2bf2473 100644
--- a/tests/ui/diagnostic-flags/colored-session-opt-error.rs
+++ b/tests/ui/diagnostic-flags/colored-session-opt-error.rs
@@ -1,4 +1,6 @@
//@ check-pass
//@ ignore-windows
-//@ compile-flags: -Cremark=foo --error-format=human --color always
+//@ compile-flags: -Cremark=foo --error-format=human --color=always
+// Temporary until next release:
+//@ ignore-stage2
fn main() {}
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 ef79d5b0f2f..00000000000
--- 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 00000000000..e8835534e04
--- /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 922bb19a248..00000000000
--- 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.rs b/tests/ui/error-emitter/highlighting.rs
index 34da2fe6b81..16794a80914 100644
--- a/tests/ui/error-emitter/highlighting.rs
+++ b/tests/ui/error-emitter/highlighting.rs
@@ -3,10 +3,8 @@
//@ compile-flags: --error-format=human --color=always
//@ error-pattern:[35mfor<'a> [0m
//@ edition:2018
-
-//@ revisions: windows not-windows
-//@ [windows]only-windows
-//@ [not-windows]ignore-windows
+// Temporary until next release:
+//@ ignore-stage2
use core::pin::Pin;
use core::future::Future;
diff --git a/tests/ui/error-emitter/highlighting.svg b/tests/ui/error-emitter/highlighting.svg
new file mode 100644
index 00000000000..b5791858ab6
--- /dev/null
+++ b/tests/ui/error-emitter/highlighting.svg
@@ -0,0 +1,72 @@
+
diff --git a/tests/ui/error-emitter/highlighting.windows.stderr b/tests/ui/error-emitter/highlighting.windows.stderr
deleted file mode 100644
index 11d4125db4b..00000000000
--- a/tests/ui/error-emitter/highlighting.windows.stderr
+++ /dev/null
@@ -1,22 +0,0 @@
-[0m[1m[38;5;9merror[E0308][0m[0m[1m[38;5;15m: mismatched types[0m
-[0m [0m[0m[1m[38;5;14m--> [0m[0m$DIR/highlighting.rs:26:11[0m
-[0m [0m[0m[1m[38;5;14m|[0m
-[0m[1m[38;5;14mLL[0m[0m [0m[0m[1m[38;5;14m|[0m[0m [0m[0m query(wrapped_fn);[0m
-[0m [0m[0m[1m[38;5;14m| [0m[0m [0m[0m[1m[38;5;14m-----[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;14m| [0m[0m [0m[0m[1m[38;5;14m|[0m
-[0m [0m[0m[1m[38;5;14m| [0m[0m [0m[0m[1m[38;5;14marguments to this function are incorrect[0m
-[0m [0m[0m[1m[38;5;14m|[0m
-[0m [0m[0m[1m[38;5;14m= [0m[0m[1m[38;5;15mnote[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;14m--> [0m[0m$DIR/highlighting.rs:15:4[0m
-[0m [0m[0m[1m[38;5;14m|[0m
-[0m[1m[38;5;14mLL[0m[0m [0m[0m[1m[38;5;14m|[0m[0m [0m[0mfn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin, String>> + Send + 'static[0m
-[0m[1m[38;5;14mLL[0m[0m [0m[0m[1m[38;5;14m|[0m[0m [0m[0m[1m[38;5;14m|[0m[0m [0m[0m)>>) {}[0m
-[0m [0m[0m[1m[38;5;14m| [0m[0m[1m[38;5;14m|___-[0m
-
-[0m[1m[38;5;9merror[0m[0m[1m[38;5;15m: aborting due to 1 previous error[0m
-
-[0m[1m[38;5;15mFor more information about this error, try `rustc --explain E0308`.[0m
diff --git a/tests/ui/error-emitter/highlighting.windows.svg b/tests/ui/error-emitter/highlighting.windows.svg
new file mode 100644
index 00000000000..6b714d64ade
--- /dev/null
+++ b/tests/ui/error-emitter/highlighting.windows.svg
@@ -0,0 +1,73 @@
+
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 49c0354a2a7..00000000000
--- 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.rs b/tests/ui/error-emitter/multiline-multipart-suggestion.rs
index fac8f34f59f..12c9324edb7 100644
--- a/tests/ui/error-emitter/multiline-multipart-suggestion.rs
+++ b/tests/ui/error-emitter/multiline-multipart-suggestion.rs
@@ -1,9 +1,7 @@
//@ compile-flags: --error-format=human --color=always
//@ error-pattern: missing lifetime specifier
-
-//@ revisions: windows not-windows
-//@ [windows]only-windows
-//@ [not-windows]ignore-windows
+// Temporary until next release:
+//@ ignore-stage2
fn short(foo_bar: &Vec<&i32>) -> &i32 {
&12
diff --git a/tests/ui/error-emitter/multiline-multipart-suggestion.svg b/tests/ui/error-emitter/multiline-multipart-suggestion.svg
new file mode 100644
index 00000000000..3aa607ea693
--- /dev/null
+++ b/tests/ui/error-emitter/multiline-multipart-suggestion.svg
@@ -0,0 +1,120 @@
+
diff --git a/tests/ui/error-emitter/multiline-multipart-suggestion.windows.stderr b/tests/ui/error-emitter/multiline-multipart-suggestion.windows.stderr
deleted file mode 100644
index bf32c228de3..00000000000
--- a/tests/ui/error-emitter/multiline-multipart-suggestion.windows.stderr
+++ /dev/null
@@ -1,46 +0,0 @@
-[0m[1m[38;5;9merror[E0106][0m[0m[1m[38;5;15m: missing lifetime specifier[0m
-[0m [0m[0m[1m[38;5;14m--> [0m[0m$DIR/multiline-multipart-suggestion.rs:8:34[0m
-[0m [0m[0m[1m[38;5;14m|[0m
-[0m[1m[38;5;14mLL[0m[0m [0m[0m[1m[38;5;14m|[0m[0m [0m[0mfn short(foo_bar: &Vec<&i32>) -> &i32 {[0m
-[0m [0m[0m[1m[38;5;14m| [0m[0m [0m[0m[1m[38;5;14m----------[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;14m|[0m
-[0m [0m[0m[1m[38;5;14m= [0m[0m[1m[38;5;15mhelp[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;14m|[0m
-[0m[1m[38;5;14mLL[0m[0m [0m[0m[1m[38;5;14m| [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;14m|[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[38;5;15m: missing lifetime specifier[0m
-[0m [0m[0m[1m[38;5;14m--> [0m[0m$DIR/multiline-multipart-suggestion.rs:15:6[0m
-[0m [0m[0m[1m[38;5;14m|[0m
-[0m[1m[38;5;14mLL[0m[0m [0m[0m[1m[38;5;14m|[0m[0m [0m[0m foo_bar: &Vec<&i32>,[0m
-[0m [0m[0m[1m[38;5;14m| [0m[0m [0m[0m[1m[38;5;14m----------[0m
-[0m[1m[38;5;14mLL[0m[0m [0m[0m[1m[38;5;14m|[0m[0m [0m[0m something_very_long_so_that_the_line_will_wrap_around__________: i32,[0m
-[0m[1m[38;5;14mLL[0m[0m [0m[0m[1m[38;5;14m|[0m[0m [0m[0m) -> &i32 {[0m
-[0m [0m[0m[1m[38;5;14m| [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;14m|[0m
-[0m [0m[0m[1m[38;5;14m= [0m[0m[1m[38;5;15mhelp[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;14m|[0m
-[0m[1m[38;5;14mLL[0m[0m [0m[0m[38;5;10m~ [0m[0mfn long[0m[0m[38;5;10m<'a>[0m[0m([0m
-[0m[1m[38;5;14mLL[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;14mLL[0m[0m [0m[0m[1m[38;5;14m| [0m[0m something_very_long_so_that_the_line_will_wrap_around__________: i32,[0m
-[0m[1m[38;5;14mLL[0m[0m [0m[0m[38;5;10m~ [0m[0m) -> &[0m[0m[38;5;10m'a [0m[0mi32 {[0m
-[0m [0m[0m[1m[38;5;14m|[0m
-
-[0m[1m[38;5;9merror[E0106][0m[0m[1m[38;5;15m: missing lifetime specifier[0m
-[0m [0m[0m[1m[38;5;14m--> [0m[0m$DIR/multiline-multipart-suggestion.rs:20:29[0m
-[0m [0m[0m[1m[38;5;14m|[0m
-[0m[1m[38;5;14mLL[0m[0m [0m[0m[1m[38;5;14m|[0m[0m [0m[0m foo_bar: &Vec<&i32>) -> &i32 {[0m
-[0m [0m[0m[1m[38;5;14m| [0m[0m [0m[0m[1m[38;5;14m----------[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;14m|[0m
-[0m [0m[0m[1m[38;5;14m= [0m[0m[1m[38;5;15mhelp[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;14m|[0m
-[0m[1m[38;5;14mLL[0m[0m [0m[0m[38;5;10m~ [0m[0mfn long2[0m[0m[38;5;10m<'a>[0m[0m([0m
-[0m[1m[38;5;14mLL[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;14m|[0m
-
-[0m[1m[38;5;9merror[0m[0m[1m[38;5;15m: aborting due to 3 previous errors[0m
-
-[0m[1m[38;5;15mFor more information about this error, try `rustc --explain E0106`.[0m
diff --git a/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg b/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg
new file mode 100644
index 00000000000..330eb96e4ae
--- /dev/null
+++ b/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg
@@ -0,0 +1,120 @@
+