From 2b9d480140c775a64d8e111041e5040a38d35717 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Fri, 30 May 2025 16:03:32 -0600 Subject: [PATCH 1/8] feat: Right align line numbers --- compiler/rustc_errors/src/emitter.rs | 8 +++- compiler/rustc_parse/src/parser/tests.rs | 48 +++++++++---------- .../foo.stderr | 12 ++--- .../doctest/standalone-warning-2024.stderr | 2 +- .../ui-testing-optout.stderr | 2 +- 5 files changed, 39 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 2f398cea926cd..f83951ed4bcd7 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -713,7 +713,13 @@ impl HumanEmitter { Style::LineNumber, ); } - buffer.puts(line_offset, 0, &self.maybe_anonymized(line_index), Style::LineNumber); + let line_num = self.maybe_anonymized(line_index); + buffer.puts( + line_offset, + (width_offset - 3).saturating_sub(str_width(&line_num)), + &line_num, + Style::LineNumber, + ); self.draw_col_separator_no_space(buffer, line_offset, width_offset - 2); left diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index 15679d23bc565..43a1d779a75d7 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -2114,15 +2114,15 @@ fn foo() { error: foo --> test.rs:3:6 | -3 | X0 Y0 Z0 + 3 | X0 Y0 Z0 | _______^ -4 | | X1 Y1 Z1 + 4 | | X1 Y1 Z1 | | ____^____- | ||____| | | `X` is a good letter -5 | | 1 -6 | | 2 -7 | | 3 + 5 | | 1 + 6 | | 2 + 7 | | 3 ... | 15 | | X2 Y2 Z2 16 | | X3 Y3 Z3 @@ -2133,15 +2133,15 @@ error: foo error: foo ╭▸ test.rs:3:6 │ -3 │ X0 Y0 Z0 + 3 │ X0 Y0 Z0 │ ┏━━━━━━━┛ -4 │ ┃ X1 Y1 Z1 + 4 │ ┃ X1 Y1 Z1 │ ┃┌────╿────┘ │ ┗│━━━━┥ │ │ `X` is a good letter -5 │ │ 1 -6 │ │ 2 -7 │ │ 3 + 5 │ │ 1 + 6 │ │ 2 + 7 │ │ 3 ‡ │ 15 │ │ X2 Y2 Z2 16 │ │ X3 Y3 Z3 @@ -2189,15 +2189,15 @@ fn foo() { error: foo --> test.rs:3:6 | -3 | X0 Y0 Z0 + 3 | X0 Y0 Z0 | _______^ -4 | | 1 -5 | | 2 -6 | | 3 -7 | | X1 Y1 Z1 + 4 | | 1 + 5 | | 2 + 6 | | 3 + 7 | | X1 Y1 Z1 | | _________- -8 | || 4 -9 | || 5 + 8 | || 4 + 9 | || 5 10 | || 6 11 | || X2 Y2 Z2 | ||__________- `Z` is a good letter too @@ -2211,15 +2211,15 @@ error: foo error: foo ╭▸ test.rs:3:6 │ -3 │ X0 Y0 Z0 + 3 │ X0 Y0 Z0 │ ┏━━━━━━━┛ -4 │ ┃ 1 -5 │ ┃ 2 -6 │ ┃ 3 -7 │ ┃ X1 Y1 Z1 + 4 │ ┃ 1 + 5 │ ┃ 2 + 6 │ ┃ 3 + 7 │ ┃ X1 Y1 Z1 │ ┃┌─────────┘ -8 │ ┃│ 4 -9 │ ┃│ 5 + 8 │ ┃│ 4 + 9 │ ┃│ 5 10 │ ┃│ 6 11 │ ┃│ X2 Y2 Z2 │ ┃└──────────┘ `Z` is a good letter too diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr b/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr index 7f131153540bb..9433a0ba00e80 100644 --- a/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr +++ b/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr @@ -7,19 +7,19 @@ error[E0277]: the trait bound `foo::Struct: Trait` is not satisfied note: there are multiple different versions of crate `foo` in the dependency graph --> foo-current.rs:7:1 | -4 | extern crate foo; + 4 | extern crate foo; | ----------------- one version of crate `foo` used here, as a direct dependency of the current crate -5 | -6 | pub struct Struct; + 5 | + 6 | pub struct Struct; | ----------------- this type implements the required trait -7 | pub trait Trait {} + 7 | pub trait Trait {} | ^^^^^^^^^^^^^^^ this is the required trait | ::: foo-prev.rs:X:Y | -4 | pub struct Struct; + 4 | pub struct Struct; | ----------------- this type doesn't implement the required trait -5 | pub trait Trait {} + 5 | pub trait Trait {} | --------------- this is the found trait = note: two types coming from two different versions of the same crate are different types even if they look the same = help: you can use `cargo tree` to explore your dependency tree diff --git a/tests/rustdoc-ui/doctest/standalone-warning-2024.stderr b/tests/rustdoc-ui/doctest/standalone-warning-2024.stderr index bfc1e91940453..ce65557c2c4a4 100644 --- a/tests/rustdoc-ui/doctest/standalone-warning-2024.stderr +++ b/tests/rustdoc-ui/doctest/standalone-warning-2024.stderr @@ -15,7 +15,7 @@ error: unknown attribute `standalone` note: the lint level is defined here --> $DIR/standalone-warning-2024.rs:9:9 | -9 | #![deny(warnings)] + 9 | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(warnings)]` diff --git a/tests/ui/compiletest-self-test/ui-testing-optout.stderr b/tests/ui/compiletest-self-test/ui-testing-optout.stderr index 652c472c0bcfe..f1d03eab14a9d 100644 --- a/tests/ui/compiletest-self-test/ui-testing-optout.stderr +++ b/tests/ui/compiletest-self-test/ui-testing-optout.stderr @@ -16,7 +16,7 @@ error[E0412]: cannot find type `D` in this scope error[E0412]: cannot find type `F` in this scope --> $DIR/ui-testing-optout.rs:92:10 | -4 | type A = B; + 4 | type A = B; | ----------- similarly named type alias `A` defined here ... 92 | type E = F; From 2602acdc0816dfce606d32e93eb6c4a469a9e8ed Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Fri, 30 May 2025 16:22:56 -0600 Subject: [PATCH 2/8] test: Subtract code_offset from width for ui_testing --- compiler/rustc_errors/src/emitter.rs | 4 +- .../ui/async-await/async-drop/ex-ice1.stderr | 8 ++-- .../ui/cast/func-pointer-issue-140491.stderr | 4 +- tests/ui/deprecation/deprecation-lint.stderr | 24 +++++------ ...width-unicode-multiline-label.ascii.stderr | 40 +++++++++---------- ...dth-unicode-multiline-label.unicode.stderr | 40 +++++++++---------- .../non-whitespace-trimming-2.ascii.stderr | 8 ++-- .../non-whitespace-trimming-2.unicode.stderr | 8 ++-- .../non-whitespace-trimming-unicode.stderr | 8 ++-- .../non-whitespace-trimming.stderr | 8 ++-- .../ui/diagnostic-width/tabs-trimming.stderr | 4 +- .../ui/lint/lint-stability-deprecated.stderr | 40 +++++++++---------- tests/ui/parser/raw/too-many-hash.stderr | 4 +- .../empty-match.exhaustive_patterns.stderr | 4 +- .../usefulness/empty-match.normal.stderr | 4 +- tests/ui/simd/not-out-of-bounds.stderr | 4 +- .../alignment/align-fail.stderr | 4 +- 17 files changed, 109 insertions(+), 107 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index f83951ed4bcd7..eee7732e88cb8 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1994,7 +1994,9 @@ impl HumanEmitter { fn column_width(&self, code_offset: usize) -> usize { if let Some(width) = self.diagnostic_width { width.saturating_sub(code_offset) - } else if self.ui_testing || cfg!(miri) { + } else if self.ui_testing { + DEFAULT_COLUMN_WIDTH.saturating_sub(code_offset) + } else if cfg!(miri) { DEFAULT_COLUMN_WIDTH } else { termize::dimensions() diff --git a/tests/ui/async-await/async-drop/ex-ice1.stderr b/tests/ui/async-await/async-drop/ex-ice1.stderr index 68533edeb086c..a1fa89f2c4001 100644 --- a/tests/ui/async-await/async-drop/ex-ice1.stderr +++ b/tests/ui/async-await/async-drop/ex-ice1.stderr @@ -1,14 +1,14 @@ error[E0423]: expected function, found module `core::future::async_drop` --> $DIR/ex-ice1.rs:9:35 | -LL | let async_drop_fut = pin!(core::future::async_drop(async {})); - | ^^^^^^^^^^^^^^^^^^^^^^^^ not a function +LL | ... let async_drop_fut = pin!(core::future::async_drop(async {})); + | ^^^^^^^^^^^^^^^^^^^^^^^^ not a function error[E0603]: module `async_drop` is private --> $DIR/ex-ice1.rs:9:49 | -LL | let async_drop_fut = pin!(core::future::async_drop(async {})); - | ^^^^^^^^^^ private module +LL | ... let async_drop_fut = pin!(core::future::async_drop(async {})); + | ^^^^^^^^^^ private module | note: the module `async_drop` is defined here --> $SRC_DIR/core/src/future/mod.rs:LL:COL diff --git a/tests/ui/cast/func-pointer-issue-140491.stderr b/tests/ui/cast/func-pointer-issue-140491.stderr index e1c07010e691c..0b777905da1f9 100644 --- a/tests/ui/cast/func-pointer-issue-140491.stderr +++ b/tests/ui/cast/func-pointer-issue-140491.stderr @@ -1,8 +1,8 @@ error[E0605]: non-primitive cast: `&for<'a, 'b> fn(&'a Event<'b>) {my_fn}` as `&for<'a, 'b> fn(&'a Event<'b>)` --> $DIR/func-pointer-issue-140491.rs:6:34 | -LL | ..._>) = &my_fn as _; - | ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object +LL | ... = &my_fn as _; + | ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object | = note: casting reference expression `&my_fn` because `&` binds tighter than `as` diff --git a/tests/ui/deprecation/deprecation-lint.stderr b/tests/ui/deprecation/deprecation-lint.stderr index 95ae1b04d8611..5a39b0cf31516 100644 --- a/tests/ui/deprecation/deprecation-lint.stderr +++ b/tests/ui/deprecation/deprecation-lint.stderr @@ -73,8 +73,8 @@ LL | let _ = nested::DeprecatedStruct { error: use of deprecated unit struct `deprecation_lint::nested::DeprecatedUnitStruct`: text --> $DIR/deprecation-lint.rs:48:25 | -LL | let _ = nested::DeprecatedUnitStruct; - | ^^^^^^^^^^^^^^^^^^^^ +LL | ... let _ = nested::DeprecatedUnitStruct; + | ^^^^^^^^^^^^^^^^^^^^ error: use of deprecated unit variant `deprecation_lint::nested::Enum::DeprecatedVariant`: text --> $DIR/deprecation-lint.rs:50:31 @@ -97,8 +97,8 @@ LL | macro_test_arg!(deprecated_text()); error: use of deprecated function `deprecation_lint::deprecated_text`: text --> $DIR/deprecation-lint.rs:60:41 | -LL | macro_test_arg!(macro_test_arg!(deprecated_text())); - | ^^^^^^^^^^^^^^^ +LL | ... macro_test_arg!(macro_test_arg!(deprecated_text())); + | ^^^^^^^^^^^^^^^ error: use of deprecated method `deprecation_lint::Trait::trait_deprecated`: text --> $DIR/deprecation-lint.rs:65:16 @@ -211,8 +211,8 @@ LL | Trait::trait_deprecated_text(&foo); error: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text --> $DIR/deprecation-lint.rs:261:25 | -LL | ::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated function `this_crate::deprecated_future`: text --> $DIR/deprecation-lint.rs:264:9 @@ -295,8 +295,8 @@ LL | Trait::trait_deprecated_text(&foo); error: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text --> $DIR/deprecation-lint.rs:299:25 | -LL | ::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated function `this_crate::test_fn_closure_body::{closure#0}::bar` --> $DIR/deprecation-lint.rs:317:13 @@ -391,8 +391,8 @@ LL | foo.method_deprecated_text(); error: use of deprecated method `deprecation_lint::MethodTester::method_deprecated_text`: text --> $DIR/deprecation-lint.rs:27:14 | -LL | Foo::method_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | ... Foo::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated method `deprecation_lint::MethodTester::method_deprecated_text`: text --> $DIR/deprecation-lint.rs:28:16 @@ -589,8 +589,8 @@ LL | Foo::method_deprecated_text(&foo); error: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text --> $DIR/deprecation-lint.rs:257:16 | -LL | ::method_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text --> $DIR/deprecation-lint.rs:258:13 diff --git a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.ascii.stderr b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.ascii.stderr index 60ce0d9a14839..9376a4cd5b24b 100644 --- a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.ascii.stderr +++ b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.ascii.stderr @@ -1,11 +1,11 @@ error[E0369]: cannot add `&str` to `&str` --> $DIR/non-1-width-unicode-multiline-label.rs:7:237 | -LL | ...👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦"; let _a = unicode_is_fun + " really fun!"; - | -------------- ^ -------------- &str - | | | - | | `+` cannot be used to concatenate two `&str` strings - | &str +LL | ...👧👦👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦"; let _a = unicode_is_fun + " really fun!"; + | -------------- ^ -------------- &str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &str | = note: string concatenation requires an owned `String` on the left help: create an owned `String` from a string reference @@ -16,11 +16,11 @@ LL | let _ = "👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧 error[E0369]: cannot add `&str` to `&str` --> $DIR/non-1-width-unicode-multiline-label.rs:9:384 | -LL | ...👧👦👨👩👧👦👨👩👧👦"; let _a = unicode_is_fun + " really fun!"; - | -------------- ^ -------------- &str - | | | - | | `+` cannot be used to concatenate two `&str` strings - | &str +LL | ...👦👨👩👧👦👨👩👧👦"; let _a = unicode_is_fun + " really fun!"; + | -------------- ^ -------------- &str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &str | = note: string concatenation requires an owned `String` on the left help: create an owned `String` from a string reference @@ -31,11 +31,11 @@ LL | let _ = "👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧 error[E0369]: cannot add `&str` to `&str` --> $DIR/non-1-width-unicode-multiline-label.rs:11:260 | -LL | ...࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; - | -------------- ^ -------------- &str - | | | - | | `+` cannot be used to concatenate two `&str` strings - | &str +LL | ...࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; + | -------------- ^ -------------- &str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &str | = note: string concatenation requires an owned `String` on the left help: create an owned `String` from a string reference @@ -46,11 +46,11 @@ LL | let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓ error[E0369]: cannot add `&str` to `&str` --> $DIR/non-1-width-unicode-multiline-label.rs:13:219 | -LL | ...xxxxxxxxxxxxxxxxxxxx"; let _a = unicode_is_fun + " really fun!"; - | -------------- ^ -------------- &str - | | | - | | `+` cannot be used to concatenate two `&str` strings - | &str +LL | ...xxxxxxxxxxxxxxxxxx"; let _a = unicode_is_fun + " really fun!"; + | -------------- ^ -------------- &str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &str | = note: string concatenation requires an owned `String` on the left help: create an owned `String` from a string reference diff --git a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.unicode.stderr b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.unicode.stderr index 15b5dd9d7e2d7..3cca6ffa2ce86 100644 --- a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.unicode.stderr +++ b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.unicode.stderr @@ -1,11 +1,11 @@ error[E0369]: cannot add `&str` to `&str` ╭▸ $DIR/non-1-width-unicode-multiline-label.rs:7:237 │ -LL │ …👧👦👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦"; let _a = unicode_is_fun + " really fun!"; - │ ┬───────────── ┯ ────────────── &str - │ │ │ - │ │ `+` cannot be used to concatenate two `&str` strings - │ &str +LL │ …👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧👦"; let _a = unicode_is_fun + " really fun!"; + │ ┬───────────── ┯ ────────────── &str + │ │ │ + │ │ `+` cannot be used to concatenate two `&str` strings + │ &str │ ╰ note: string concatenation requires an owned `String` on the left help: create an owned `String` from a string reference @@ -16,11 +16,11 @@ LL │ let _ = "👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧 error[E0369]: cannot add `&str` to `&str` ╭▸ $DIR/non-1-width-unicode-multiline-label.rs:9:384 │ -LL │ …👨👩👧👦👨👩👧👦👨👩👧👦"; let _a = unicode_is_fun + " really fun!"; - │ ┬───────────── ┯ ────────────── &str - │ │ │ - │ │ `+` cannot be used to concatenate two `&str` strings - │ &str +LL │ …👩👧👦👨👩👧👦👨👩👧👦"; let _a = unicode_is_fun + " really fun!"; + │ ┬───────────── ┯ ────────────── &str + │ │ │ + │ │ `+` cannot be used to concatenate two `&str` strings + │ &str │ ╰ note: string concatenation requires an owned `String` on the left help: create an owned `String` from a string reference @@ -31,11 +31,11 @@ LL │ let _ = "👨👩👧👦👨👩👧👦👨👩👧👦👨👩👧 error[E0369]: cannot add `&str` to `&str` ╭▸ $DIR/non-1-width-unicode-multiline-label.rs:11:260 │ -LL │ …࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; - │ ┬───────────── ┯ ────────────── &str - │ │ │ - │ │ `+` cannot be used to concatenate two `&str` strings - │ &str +LL │ …࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; + │ ┬───────────── ┯ ────────────── &str + │ │ │ + │ │ `+` cannot be used to concatenate two `&str` strings + │ &str │ ╰ note: string concatenation requires an owned `String` on the left help: create an owned `String` from a string reference @@ -46,11 +46,11 @@ LL │ let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓ error[E0369]: cannot add `&str` to `&str` ╭▸ $DIR/non-1-width-unicode-multiline-label.rs:13:219 │ -LL │ …xxxxxxxxxxxxxxxxxxxxxx"; let _a = unicode_is_fun + " really fun!"; - │ ┬───────────── ┯ ────────────── &str - │ │ │ - │ │ `+` cannot be used to concatenate two `&str` strings - │ &str +LL │ …xxxxxxxxxxxxxxxxxxxx"; let _a = unicode_is_fun + " really fun!"; + │ ┬───────────── ┯ ────────────── &str + │ │ │ + │ │ `+` cannot be used to concatenate two `&str` strings + │ &str │ ╰ note: string concatenation requires an owned `String` on the left help: create an owned `String` from a string reference diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-2.ascii.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming-2.ascii.stderr index 70bd149545cfe..a414acc398bb2 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming-2.ascii.stderr +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-2.ascii.stderr @@ -1,10 +1,10 @@ error[E0308]: mismatched types --> $DIR/non-whitespace-trimming-2.rs:6:311 | -LL | ...13; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let ... - | -- ^^ expected `()`, found integer - | | - | expected due to this +LL | ... let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; le... + | -- ^^ expected `()`, found integer + | | + | expected due to this error: aborting due to 1 previous error diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-2.unicode.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming-2.unicode.stderr index 600d196de1673..bbf2995a3440e 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming-2.unicode.stderr +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-2.unicode.stderr @@ -1,10 +1,10 @@ error[E0308]: mismatched types ╭▸ $DIR/non-whitespace-trimming-2.rs:6:311 │ -LL │ …= 13; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _:… - │ ┬─ ━━ expected `()`, found integer - │ │ - ╰╴ expected due to this +LL │ …3; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let … + │ ┬─ ━━ expected `()`, found integer + │ │ + ╰╴ expected due to this error: aborting due to 1 previous error diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr index 18d80810ab0c3..373e494036c87 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr @@ -1,10 +1,10 @@ error[E0308]: mismatched types --> $DIR/non-whitespace-trimming-unicode.rs:4:415 | -LL | ...♣♤♥♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻☼☽ ... - | -- ^^ expected `()`, found integer - | | - | expected due to this +LL | ...♦♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀⚁⚂⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓ ☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷☸☹☺☻ ... + | -- ^^ expected `()`, found integer + | | + | expected due to this error: aborting due to 1 previous error diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming.stderr index 872c5ae3b7642..ce8ff66d7b30f 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming.stderr +++ b/tests/ui/diagnostic-width/non-whitespace-trimming.stderr @@ -1,10 +1,10 @@ error[E0308]: mismatched types --> $DIR/non-whitespace-trimming.rs:4:241 | -LL | ... () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = ... - | -- ^^ expected `()`, found integer - | | - | expected due to this +LL | ... = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () ... + | -- ^^ expected `()`, found integer + | | + | expected due to this error: aborting due to 1 previous error diff --git a/tests/ui/diagnostic-width/tabs-trimming.stderr b/tests/ui/diagnostic-width/tabs-trimming.stderr index e0d1c2d95a965..080b1b856d931 100644 --- a/tests/ui/diagnostic-width/tabs-trimming.stderr +++ b/tests/ui/diagnostic-width/tabs-trimming.stderr @@ -1,7 +1,7 @@ error[E0408]: variable `v` is not bound in all patterns --> $DIR/tabs-trimming.rs:9:16 | -LL | ... v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Long text here: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT... +LL | ... v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Long text here: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT... | - ^ ^ pattern doesn't bind `v` | | | | | pattern doesn't bind `v` @@ -10,7 +10,7 @@ LL | ... v @ 1 | 2 | 3 => panic!("You gave me too little mon error[E0381]: used binding `v` is possibly-uninitialized --> $DIR/tabs-trimming.rs:9:67 | -LL | ... v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Long text here: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT... +LL | ... v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Long text here: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT... | - ^ `v` used here but it is possibly-uninitialized | | | binding initialized here in some conditions diff --git a/tests/ui/lint/lint-stability-deprecated.stderr b/tests/ui/lint/lint-stability-deprecated.stderr index 51205ff434062..ce0bc36f62922 100644 --- a/tests/ui/lint/lint-stability-deprecated.stderr +++ b/tests/ui/lint/lint-stability-deprecated.stderr @@ -37,8 +37,8 @@ LL | Trait::trait_deprecated_text(&foo); warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:40:25 | -LL | ::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_unstable`: text --> $DIR/lint-stability-deprecated.rs:42:9 @@ -109,8 +109,8 @@ LL | let _ = Enum::DeprecatedVariant; warning: use of deprecated unit variant `lint_stability::Enum::DeprecatedUnstableVariant`: text --> $DIR/lint-stability-deprecated.rs:121:23 | -LL | let _ = Enum::DeprecatedUnstableVariant; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... let _ = Enum::DeprecatedUnstableVariant; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated tuple struct `lint_stability::DeprecatedTupleStruct`: text --> $DIR/lint-stability-deprecated.rs:125:17 @@ -121,8 +121,8 @@ LL | let _ = DeprecatedTupleStruct (1); warning: use of deprecated tuple struct `lint_stability::DeprecatedUnstableTupleStruct`: text --> $DIR/lint-stability-deprecated.rs:126:17 | -LL | let _ = DeprecatedUnstableTupleStruct (1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... let _ = DeprecatedUnstableTupleStruct (1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:135:25 @@ -133,14 +133,14 @@ LL | macro_test_arg!(deprecated_text()); warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text --> $DIR/lint-stability-deprecated.rs:136:25 | -LL | macro_test_arg!(deprecated_unstable_text()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... macro_test_arg!(deprecated_unstable_text()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:137:41 | -LL | macro_test_arg!(macro_test_arg!(deprecated_text())); - | ^^^^^^^^^^^^^^^ +LL | ... macro_test_arg!(macro_test_arg!(deprecated_text())); + | ^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text --> $DIR/lint-stability-deprecated.rs:142:16 @@ -163,8 +163,8 @@ LL | Trait::trait_deprecated_text(&foo); warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:148:25 | -LL | ::trait_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text --> $DIR/lint-stability-deprecated.rs:150:16 @@ -205,8 +205,8 @@ LL | trait LocalTrait2 : DeprecatedTrait { } warning: use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text --> $DIR/lint-stability-deprecated.rs:205:23 | -LL | unstable_mod::deprecated(); - | ^^^^^^^^^^ +LL | ... unstable_mod::deprecated(); + | ^^^^^^^^^^ warning: use of deprecated function `this_crate::deprecated`: text --> $DIR/lint-stability-deprecated.rs:327:9 @@ -367,14 +367,14 @@ LL | foo.method_deprecated_text(); warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:35:14 | -LL | Foo::method_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | ... Foo::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:36:16 | -LL | ::method_deprecated_text(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | ... ::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text --> $DIR/lint-stability-deprecated.rs:37:13 @@ -397,8 +397,8 @@ LL | foo.method_deprecated_unstable(); warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_unstable`: text --> $DIR/lint-stability-deprecated.rs:44:14 | -LL | Foo::method_deprecated_unstable(&foo); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... Foo::method_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_unstable`: text --> $DIR/lint-stability-deprecated.rs:45:16 diff --git a/tests/ui/parser/raw/too-many-hash.stderr b/tests/ui/parser/raw/too-many-hash.stderr index 6b3854eb4a237..499b21d3982c8 100644 --- a/tests/ui/parser/raw/too-many-hash.stderr +++ b/tests/ui/parser/raw/too-many-hash.stderr @@ -1,8 +1,8 @@ error: too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found 256 --> $DIR/too-many-hash.rs:4:19 | -LL | ... = r####################################################...#######################################; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ... = r###################################################...######################################; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr index f2067f0341fcd..b649aa122b255 100644 --- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr @@ -346,8 +346,8 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered --> $DIR/empty-match.rs:71:24 | -LL | match_guarded_arm!(NonEmptyEnum5::V1); - | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered +LL | ...ded_arm!(NonEmptyEnum5::V1); + | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here --> $DIR/empty-match.rs:38:10 diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr index f2067f0341fcd..b649aa122b255 100644 --- a/tests/ui/pattern/usefulness/empty-match.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr @@ -346,8 +346,8 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered --> $DIR/empty-match.rs:71:24 | -LL | match_guarded_arm!(NonEmptyEnum5::V1); - | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered +LL | ...ded_arm!(NonEmptyEnum5::V1); + | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here --> $DIR/empty-match.rs:38:10 diff --git a/tests/ui/simd/not-out-of-bounds.stderr b/tests/ui/simd/not-out-of-bounds.stderr index 4b6bda93e4561..c6680d9e7a1ec 100644 --- a/tests/ui/simd/not-out-of-bounds.stderr +++ b/tests/ui/simd/not-out-of-bounds.stderr @@ -79,8 +79,8 @@ LL | simd_insert(v, 2, 0u8); error[E0511]: invalid monomorphization of `simd_extract` intrinsic: SIMD index #1 is out of bounds (limit 2) --> $DIR/not-out-of-bounds.rs:84:24 | -LL | let _val: u8 = simd_extract(v, 2); - | ^^^^^^^^^^^^^^^^^^ +LL | ... let _val: u8 = simd_extract(v, 2); + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/tests/ui/transmutability/alignment/align-fail.stderr b/tests/ui/transmutability/alignment/align-fail.stderr index 7b69820a3c6df..164c57a362442 100644 --- a/tests/ui/transmutability/alignment/align-fail.stderr +++ b/tests/ui/transmutability/alignment/align-fail.stderr @@ -1,8 +1,8 @@ error[E0277]: `&[u8; 0]` cannot be safely transmuted into `&[u16; 0]` --> $DIR/align-fail.rs:21:55 | -LL | ...tatic [u8; 0], &'static [u16; 0]>(); - | ^^^^^^^^^^^^^^^^^ the minimum alignment of `&[u8; 0]` (1) should be greater than that of `&[u16; 0]` (2) +LL | ...ic [u8; 0], &'static [u16; 0]>(); + | ^^^^^^^^^^^^^^^^^ the minimum alignment of `&[u8; 0]` (1) should be greater than that of `&[u16; 0]` (2) | note: required by a bound in `is_maybe_transmutable` --> $DIR/align-fail.rs:9:14 From caf600679c662f04f7aabe2e96a86aec9e1177fc Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Tue, 3 Jun 2025 19:27:03 -0600 Subject: [PATCH 3/8] refactor: Move to anstream + anstyle for styling --- Cargo.lock | 3 +- compiler/rustc_errors/Cargo.toml | 4 +- compiler/rustc_errors/src/emitter.rs | 147 +-- compiler/rustc_errors/src/json.rs | 37 +- compiler/rustc_errors/src/lib.rs | 26 +- compiler/rustc_errors/src/snippet.rs | 2 +- compiler/rustc_errors/src/styled_buffer.rs | 10 +- compiler/rustc_parse/Cargo.toml | 1 - compiler/rustc_parse/src/parser/tests.rs | 11 +- src/tools/compiletest/Cargo.toml | 2 +- src/tools/tidy/src/deps.rs | 8 + .../huge_multispan_highlight.ascii.svg | 78 +- .../huge_multispan_highlight.unicode.svg | 78 +- tests/ui/diagnostic-flags/terminal_urls.rs | 4 +- .../ui/diagnostic-flags/terminal_urls.stderr | 11 - tests/ui/diagnostic-flags/terminal_urls.svg | 48 + .../ui/error-emitter/E0308-clarification.svg | 66 +- tests/ui/error-emitter/highlighting.svg | 42 +- .../ui/error-emitter/highlighting.windows.svg | 46 +- .../multiline-multipart-suggestion.svg | 90 +- ...multiline-multipart-suggestion.windows.svg | 92 +- .../multiline-removal-suggestion.svg | 392 +++---- tests/ui/error-emitter/unicode-output.svg | 42 +- ...between-expected-trait-and-found-trait.svg | 40 +- tests/ui/lint/use_suggestion_json.stderr | 38 +- .../suggestions/incorrect-variant-literal.svg | 978 +++++++++--------- 26 files changed, 1170 insertions(+), 1126 deletions(-) delete mode 100644 tests/ui/diagnostic-flags/terminal_urls.stderr create mode 100644 tests/ui/diagnostic-flags/terminal_urls.svg diff --git a/Cargo.lock b/Cargo.lock index 6d823c5b5a596..4104d816b1fbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3751,6 +3751,8 @@ name = "rustc_errors" version = "0.0.0" dependencies = [ "annotate-snippets 0.11.5", + "anstream", + "anstyle", "derive_setters", "rustc_abi", "rustc_ast", @@ -4324,7 +4326,6 @@ dependencies = [ "rustc_macros", "rustc_session", "rustc_span", - "termcolor", "thin-vec", "tracing", "unicode-normalization", diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index c4181a62a35d0..cc4905367f187 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -6,6 +6,8 @@ edition = "2024" [dependencies] # tidy-alphabetical-start annotate-snippets = "0.11" +anstream = "0.6.19" +anstyle = "1.0.11" derive_setters = "0.1.6" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } @@ -25,7 +27,7 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_type_ir = { path = "../rustc_type_ir" } -serde = { version = "1.0.125", features = [ "derive" ] } +serde = { version = "1.0.125", features = ["derive"] } serde_json = "1.0.59" termcolor = "1.2.0" termize = "0.2" diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index eee7732e88cb8..8c0090dc07db9 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -16,6 +16,7 @@ use std::iter; use std::path::Path; use std::sync::Arc; +use anstream::stream::{AsLockedWrite, RawStream}; use derive_setters::Setters; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::sync::{DynSend, IntoDynSyncSend}; @@ -25,8 +26,7 @@ use rustc_lint_defs::pluralize; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::SourceMap; use rustc_span::{FileLines, FileName, SourceFile, Span, char_width, str_width}; -use termcolor::{Buffer, BufferWriter, Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; -use tracing::{debug, instrument, trace, warn}; +use tracing::{debug, info, instrument, trace, warn}; use crate::registry::Registry; use crate::snippet::{ @@ -598,18 +598,18 @@ pub enum ColorConfig { } impl ColorConfig { - pub fn to_color_choice(self) -> ColorChoice { + pub fn to_color_choice(self) -> anstream::ColorChoice { match self { ColorConfig::Always => { if io::stderr().is_terminal() { - ColorChoice::Always + anstream::ColorChoice::Always } else { - ColorChoice::AlwaysAnsi + anstream::ColorChoice::AlwaysAnsi } } - ColorConfig::Never => ColorChoice::Never, - ColorConfig::Auto if io::stderr().is_terminal() => ColorChoice::Auto, - ColorConfig::Auto => ColorChoice::Never, + ColorConfig::Never => anstream::ColorChoice::Never, + ColorConfig::Auto if io::stderr().is_terminal() => anstream::ColorChoice::Auto, + ColorConfig::Auto => anstream::ColorChoice::Never, } } } @@ -1589,13 +1589,18 @@ impl HumanEmitter { } } let mut annotated_files = FileWithAnnotatedLines::collect_annotations(self, args, msp); - trace!("{annotated_files:#?}"); + info!("{annotated_files:#?}"); // Make sure our primary file comes first let primary_span = msp.primary_span().unwrap_or_default(); let (Some(sm), false) = (self.sm.as_ref(), primary_span.is_dummy()) else { // If we don't have span information, emit and exit - return emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message); + return emit_to_destination( + &buffer.render(level), + level, + &mut self.dst, + self.short_message, + ); }; let primary_lo = sm.lookup_char_pos(primary_span.lo()); if let Ok(pos) = @@ -1677,7 +1682,6 @@ impl HumanEmitter { } continue; } - // print out the span location and spacer before we print the annotated source // to do this, we need to know if this span will be primary let is_primary = primary_lo.file.name == annotated_file.file.name; @@ -1982,11 +1986,11 @@ impl HumanEmitter { multilines.extend(&to_add); } } - trace!("buffer: {:#?}", buffer.render()); + trace!("buffer: {:#?}", buffer.render(level)); } // final step: take our styled buffer, render it, then output it - emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?; + emit_to_destination(&buffer.render(level), level, &mut self.dst, self.short_message)?; Ok(()) } @@ -2467,7 +2471,7 @@ impl HumanEmitter { buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle); } - emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?; + emit_to_destination(&buffer.render(level), level, &mut self.dst, self.short_message)?; Ok(()) } @@ -2517,7 +2521,7 @@ impl HumanEmitter { } } if let Err(e) = emit_to_destination( - &buffer.render(), + &buffer.render(level), level, &mut self.dst, self.short_message, @@ -3085,7 +3089,7 @@ impl FileWithAnnotatedLines { multiline_depth: 0, }); } - + info!("{msp:?}"); let mut output = vec![]; let mut multiline_annotations = vec![]; @@ -3319,7 +3323,7 @@ const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ ('\u{2069}', "�"), ]; -fn normalize_whitespace(s: &str) -> String { +pub(crate) fn normalize_whitespace(s: &str) -> String { const { let mut i = 1; while i < OUTPUT_REPLACEMENTS.len() { @@ -3364,7 +3368,28 @@ fn overlaps(a1: &Annotation, a2: &Annotation, padding: usize) -> bool { ) } -fn emit_to_destination( +pub trait WriteColor: io::Write { + fn supports_color(&self) -> bool; +} + +impl WriteColor for anstream::AutoStream { + fn supports_color(&self) -> bool { + match self.current_choice() { + anstream::ColorChoice::Always + | anstream::ColorChoice::AlwaysAnsi + | anstream::ColorChoice::Auto => true, + anstream::ColorChoice::Never => false, + } + } +} + +impl WriteColor for std::io::Sink { + fn supports_color(&self) -> bool { + false + } +} + +pub(crate) fn emit_to_destination( rendered_buffer: &[Vec], lvl: &Level, dst: &mut Destination, @@ -3387,10 +3412,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 { - let style = part.style.color_spec(*lvl); - dst.set_color(&style)?; - write!(dst, "{}", part.text)?; - dst.reset()?; + let style = part.style; + write!(dst, "{style}{}{style:#}", part.text)?; } if !short_message && (!lvl.is_failure_note() || pos != rendered_buffer.len() - 1) { writeln!(dst)?; @@ -3403,8 +3426,8 @@ fn emit_to_destination( pub type Destination = Box; struct Buffy { - buffer_writer: BufferWriter, - buffer: Buffer, + buffer_writer: anstream::Stderr, + buffer: Vec, } impl Write for Buffy { @@ -3413,7 +3436,7 @@ impl Write for Buffy { } fn flush(&mut self) -> io::Result<()> { - self.buffer_writer.print(&self.buffer)?; + self.buffer_writer.write_all(&self.buffer)?; self.buffer.clear(); Ok(()) } @@ -3430,15 +3453,12 @@ impl Drop for Buffy { 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() + match self.buffer_writer.current_choice() { + anstream::ColorChoice::Always + | anstream::ColorChoice::AlwaysAnsi + | anstream::ColorChoice::Auto => true, + anstream::ColorChoice::Never => false, + } } } @@ -3450,11 +3470,11 @@ pub fn stderr_destination(color: ColorConfig) -> Destination { // // On non-Windows we rely on the atomicity of `write` to ensure errors // don't get all jumbled up. + let buffer_writer = anstream::Stderr::new(std::io::stderr(), choice); if cfg!(windows) { - Box::new(StandardStream::stderr(choice)) + Box::new(buffer_writer) } else { - let buffer_writer = BufferWriter::stderr(choice); - let buffer = buffer_writer.buffer(); + let buffer = Vec::new(); Box::new(Buffy { buffer_writer, buffer }) } } @@ -3462,49 +3482,38 @@ pub fn stderr_destination(color: ColorConfig) -> Destination { /// On Windows, BRIGHT_BLUE is hard to read on black. Use cyan instead. /// /// See #36178. -const BRIGHT_BLUE: Color = if cfg!(windows) { Color::Cyan } else { Color::Blue }; +const BRIGHT_BLUE: anstyle::Style = if cfg!(windows) { + anstyle::AnsiColor::BrightCyan.on_default() +} else { + anstyle::AnsiColor::BrightBlue.on_default() +}; impl Style { - fn color_spec(&self, lvl: Level) -> ColorSpec { - let mut spec = ColorSpec::new(); + pub(crate) fn anstyle(&self, lvl: Level) -> anstyle::Style { match self { - Style::Addition => { - spec.set_fg(Some(Color::Green)).set_intense(true); - } - Style::Removal => { - spec.set_fg(Some(Color::Red)).set_intense(true); - } - Style::LineAndColumn => {} - Style::LineNumber => { - spec.set_bold(true); - spec.set_intense(true); - spec.set_fg(Some(BRIGHT_BLUE)); - } - Style::Quotation => {} - Style::MainHeaderMsg => { - spec.set_bold(true); - if cfg!(windows) { - spec.set_intense(true).set_fg(Some(Color::White)); - } + Style::Addition => anstyle::AnsiColor::BrightGreen.on_default(), + Style::Removal => anstyle::AnsiColor::BrightRed.on_default(), + Style::LineAndColumn => anstyle::Style::new(), + Style::LineNumber => BRIGHT_BLUE.effects(anstyle::Effects::BOLD), + Style::Quotation => anstyle::Style::new(), + Style::MainHeaderMsg => if cfg!(windows) { + anstyle::AnsiColor::BrightWhite.on_default() + } else { + anstyle::Style::new() } + .effects(anstyle::Effects::BOLD), Style::UnderlinePrimary | Style::LabelPrimary => { - spec = lvl.color(); - spec.set_bold(true); + lvl.color().effects(anstyle::Effects::BOLD) } Style::UnderlineSecondary | Style::LabelSecondary => { - spec.set_bold(true).set_intense(true); - spec.set_fg(Some(BRIGHT_BLUE)); - } - Style::HeaderMsg | Style::NoStyle => {} - Style::Level(lvl) => { - spec = lvl.color(); - spec.set_bold(true); + BRIGHT_BLUE.effects(anstyle::Effects::BOLD) } + Style::HeaderMsg | Style::NoStyle => anstyle::Style::new(), + Style::Level(lvl) => lvl.color().effects(anstyle::Effects::BOLD), Style::Highlight => { - spec.set_bold(true).set_fg(Some(Color::Magenta)); + anstyle::AnsiColor::Magenta.on_default().effects(anstyle::Effects::BOLD) } } - spec } } diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 719d4ca625ae7..e52e998013120 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -15,6 +15,7 @@ use std::path::Path; use std::sync::{Arc, Mutex}; use std::vec; +use anstream::AutoStream; use derive_setters::Setters; use rustc_data_structures::sync::IntoDynSyncSend; use rustc_error_messages::FluentArgs; @@ -23,12 +24,11 @@ use rustc_span::Span; use rustc_span::hygiene::ExpnData; use rustc_span::source_map::{FilePathMapping, SourceMap}; use serde::Serialize; -use termcolor::{ColorSpec, WriteColor}; use crate::diagnostic::IsLint; use crate::emitter::{ ColorConfig, Destination, Emitter, HumanEmitter, HumanReadableErrorType, OutputTheme, - TimingEvent, should_show_source_code, + TimingEvent, WriteColor, should_show_source_code, }; use crate::registry::Registry; use crate::timings::{TimingRecord, TimingSection}; @@ -333,8 +333,8 @@ impl Diagnostic { // generate regular command line output and store it in the json // A threadsafe buffer for writing. - #[derive(Default, Clone)] - struct BufWriter(Arc>>); + #[derive(Clone)] + struct BufWriter(Arc>>>); impl Write for BufWriter { fn write(&mut self, buf: &[u8]) -> io::Result { @@ -344,17 +344,15 @@ 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(()) + match self.0.lock().unwrap().current_choice() { + anstream::ColorChoice::Always + | anstream::ColorChoice::AlwaysAnsi + | anstream::ColorChoice::Auto => true, + anstream::ColorChoice::Never => false, + } } } @@ -382,13 +380,12 @@ impl Diagnostic { children .insert(0, Diagnostic::from_sub_diagnostic(&diag.emitted_at_sub_diag(), &args, je)); } - let buf = BufWriter::default(); - let mut dst: Destination = Box::new(buf.clone()); + let buf = BufWriter(Arc::new(Mutex::new(AutoStream::new( + Vec::new(), + je.color_config.to_color_choice(), + )))); let short = je.json_rendered.short(); - match je.color_config { - ColorConfig::Always | ColorConfig::Auto => dst = Box::new(termcolor::Ansi::new(dst)), - ColorConfig::Never => {} - } + let dst: Destination = Box::new(buf.clone()); HumanEmitter::new(dst, je.translator.clone()) .short_message(short) .sm(je.sm.clone()) @@ -405,7 +402,7 @@ impl Diagnostic { }) .emit_diagnostic(diag, registry); let buf = Arc::try_unwrap(buf.0).unwrap().into_inner().unwrap(); - let buf = String::from_utf8(buf).unwrap(); + let buf = String::from_utf8(buf.into_inner()).unwrap(); Diagnostic { message: translated_message.to_string(), diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 381d780077d19..cb5da52c8029e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -39,6 +39,8 @@ use std::path::{Path, PathBuf}; use std::{fmt, panic}; use Level::*; +pub use anstream::{AutoStream, ColorChoice}; +pub use anstyle::*; pub use codes::*; pub use diagnostic::{ BugAbort, Diag, DiagArg, DiagArgMap, DiagArgName, DiagArgValue, DiagInner, DiagStyledString, @@ -1951,25 +1953,21 @@ impl fmt::Display for Level { } impl Level { - fn color(self) -> ColorSpec { - let mut spec = ColorSpec::new(); + fn color(self) -> anstyle::Style { match self { - Bug | Fatal | Error | DelayedBug => { - spec.set_fg(Some(Color::Red)).set_intense(true); - } + Bug | Fatal | Error | DelayedBug => anstyle::AnsiColor::BrightRed.on_default(), ForceWarning | Warning => { - spec.set_fg(Some(Color::Yellow)).set_intense(cfg!(windows)); - } - Note | OnceNote => { - spec.set_fg(Some(Color::Green)).set_intense(true); - } - Help | OnceHelp => { - spec.set_fg(Some(Color::Cyan)).set_intense(true); + if cfg!(windows) { + anstyle::AnsiColor::BrightYellow.on_default() + } else { + anstyle::AnsiColor::Yellow.on_default() + } } - FailureNote => {} + Note | OnceNote => anstyle::AnsiColor::BrightGreen.on_default(), + Help | OnceHelp => anstyle::AnsiColor::BrightCyan.on_default(), + FailureNote => anstyle::Style::new(), Allow | Expect => unreachable!(), } - spec } pub fn to_str(self) -> &'static str { diff --git a/compiler/rustc_errors/src/snippet.rs b/compiler/rustc_errors/src/snippet.rs index f09c2ed5534a5..21c3132d4f98e 100644 --- a/compiler/rustc_errors/src/snippet.rs +++ b/compiler/rustc_errors/src/snippet.rs @@ -192,7 +192,7 @@ impl Annotation { #[derive(Debug)] pub(crate) struct StyledString { pub text: String, - pub style: Style, + pub style: anstyle::Style, } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs index 790efd0286e9d..a85a11cee24f7 100644 --- a/compiler/rustc_errors/src/styled_buffer.rs +++ b/compiler/rustc_errors/src/styled_buffer.rs @@ -1,5 +1,6 @@ // Code for creating styled buffers +use crate::Level; use crate::snippet::{Style, StyledString}; #[derive(Debug)] @@ -27,7 +28,7 @@ impl StyledBuffer { } /// Returns content of `StyledBuffer` split by lines and line styles - pub(crate) fn render(&self) -> Vec> { + pub(crate) fn render(&self, lvl: &Level) -> Vec> { // Tabs are assumed to have been replaced by spaces in calling code. debug_assert!(self.lines.iter().all(|r| !r.iter().any(|sc| sc.chr == '\t'))); @@ -35,15 +36,16 @@ impl StyledBuffer { let mut styled_vec: Vec = vec![]; for styled_line in &self.lines { - let mut current_style = Style::NoStyle; + let mut current_style = anstyle::Style::new(); let mut current_text = String::new(); for sc in styled_line { - if sc.style != current_style { + let style = sc.style.anstyle(*lvl); + if style != current_style { if !current_text.is_empty() { styled_vec.push(StyledString { text: current_text, style: current_style }); } - current_style = sc.style; + current_style = style; current_text = String::new(); } current_text.push(sc.chr); diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index c4a0ae2ce9dd9..e1f3f9f76b245 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -25,5 +25,4 @@ unicode-width = "0.2.0" # tidy-alphabetical-end [dev-dependencies] -termcolor = "1.2" diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index 43a1d779a75d7..81c52ecaa4363 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -13,7 +13,7 @@ use rustc_ast::token::{self, Delimiter, Token}; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_ast::{self as ast, PatKind, visit}; use rustc_ast_pretty::pprust::item_to_string; -use rustc_errors::emitter::{HumanEmitter, OutputTheme}; +use rustc_errors::emitter::{HumanEmitter, OutputTheme, WriteColor}; use rustc_errors::translation::Translator; use rustc_errors::{DiagCtxt, MultiSpan, PResult}; use rustc_session::parse::ParseSess; @@ -21,7 +21,6 @@ use rustc_span::source_map::{FilePathMapping, SourceMap}; use rustc_span::{ BytePos, FileName, Pos, Span, Symbol, create_default_session_globals_then, kw, sym, }; -use termcolor::WriteColor; use crate::parser::{ForceCollect, Parser}; use crate::{new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal}; @@ -163,14 +162,6 @@ 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 { diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index cdada5a223062..0c7883a59c816 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -12,7 +12,7 @@ path = "src/bin/main.rs" [dependencies] # tidy-alphabetical-start -anstyle-svg = "0.1.3" +anstyle-svg = "0.1.8" build_helper = { path = "../../build_helper" } camino = "1" colored = "2" diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index bf813d2131e87..91729db307871 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -251,7 +251,11 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "aho-corasick", "allocator-api2", // FIXME: only appears in Cargo.lock due to https://github.com/rust-lang/cargo/issues/10801 "annotate-snippets", + "anstream", "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", "ar_archive_writer", "arrayref", "arrayvec", @@ -263,6 +267,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "cc", "cfg-if", "cfg_aliases", + "colorchoice", "constant_time_eq", "cpufeatures", "crc32fast", @@ -312,6 +317,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "indexmap", "intl-memoizer", "intl_pluralrules", + "is_terminal_polyfill", "itertools", "itoa", "jiff", @@ -336,6 +342,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "object", "odht", "once_cell", + "once_cell_polyfill", "overload", "parking_lot", "parking_lot_core", @@ -422,6 +429,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "unicode-security", "unicode-width", "unicode-xid", + "utf8parse", "valuable", "version_check", "wasi", diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg b/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg index 1cedbf75e4bf6..17f3a25be9f32 100644 --- a/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg +++ b/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg @@ -1,9 +1,9 @@ - +