diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 6552cf224ea..a386129e814 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -22,7 +22,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};
+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};
@@ -44,6 +44,7 @@
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum HumanReadableErrorType {
Default,
+ Unicode,
AnnotateSnippet,
Short,
}
@@ -112,8 +113,12 @@ fn was_cut_left(&self) -> bool {
fn was_cut_right(&self, line_len: usize) -> bool {
let right =
if self.computed_right == self.span_right || self.computed_right == self.label_right {
+ // FIXME: This comment refers to the only callsite of this method.
+ // Rephrase it or refactor it, so it can stand on its own.
// Account for the "..." padding given above. Otherwise we end up with code lines
// that do fit but end in "..." as if they were trimmed.
+ // FIXME: Don't hard-code this offset. Is this meant to represent
+ // `2 * str_width(self.margin())`?
self.computed_right - 6
} else {
self.computed_right
@@ -595,6 +600,12 @@ pub fn to_color_choice(self) -> ColorChoice {
}
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum OutputTheme {
+ Ascii,
+ Unicode,
+}
+
/// Handles the writing of `HumanReadableErrorType::Default` and `HumanReadableErrorType::Short`
#[derive(Setters)]
pub struct HumanEmitter {
@@ -613,6 +624,7 @@ pub struct HumanEmitter {
macro_backtrace: bool,
track_diagnostics: bool,
terminal_url: TerminalUrl,
+ theme: OutputTheme,
}
#[derive(Debug)]
@@ -637,6 +649,7 @@ pub fn new(dst: Destination, fallback_bundle: LazyFallbackBundle) -> HumanEmitte
macro_backtrace: false,
track_diagnostics: false,
terminal_url: TerminalUrl::No,
+ theme: OutputTheme::Ascii,
}
}
@@ -664,6 +677,7 @@ fn draw_line(
// Create the source line we will highlight.
let left = margin.left(line_len);
let right = margin.right(line_len);
+ // FIXME: The following code looks fishy. See #132860.
// On long lines, we strip the source line, accounting for unicode.
let mut taken = 0;
let code: String = source_string
@@ -680,17 +694,19 @@ fn draw_line(
})
.collect();
buffer.puts(line_offset, code_offset, &code, Style::Quotation);
+ let placeholder = self.margin();
if margin.was_cut_left() {
// We have stripped some code/whitespace from the beginning, make it clear.
- buffer.puts(line_offset, code_offset, "...", Style::LineNumber);
+ buffer.puts(line_offset, code_offset, placeholder, Style::LineNumber);
}
if margin.was_cut_right(line_len) {
+ let padding = str_width(placeholder);
// We have stripped some code after the rightmost span end, make it clear we did so.
- buffer.puts(line_offset, code_offset + taken - 3, "...", Style::LineNumber);
+ buffer.puts(line_offset, code_offset + taken - padding, placeholder, Style::LineNumber);
}
buffer.puts(line_offset, 0, &self.maybe_anonymized(line_index), Style::LineNumber);
- draw_col_separator_no_space(buffer, line_offset, width_offset - 2);
+ self.draw_col_separator_no_space(buffer, line_offset, width_offset - 2);
}
#[instrument(level = "trace", skip(self), ret)]
@@ -702,6 +718,7 @@ fn render_source_line(
width_offset: usize,
code_offset: usize,
margin: Margin,
+ close_window: bool,
) -> Vec<(usize, Style)> {
// Draw:
//
@@ -732,6 +749,7 @@ fn render_source_line(
// Left trim
let left = margin.left(source_string.len());
+ // FIXME: This looks fishy. See #132860.
// Account for unicode characters of width !=0 that were removed.
let left = source_string.chars().take(left).map(|ch| char_width(ch)).sum();
@@ -767,13 +785,10 @@ fn render_source_line(
for ann in &line.annotations {
if let AnnotationType::MultilineStart(depth) = ann.annotation_type {
if source_string.chars().take(ann.start_col.display).all(|c| c.is_whitespace()) {
- let style = if ann.is_primary {
- Style::UnderlinePrimary
- } else {
- Style::UnderlineSecondary
- };
- annotations.push((depth, style));
- buffer_ops.push((line_offset, width_offset + depth - 1, '/', style));
+ let uline = self.underline(ann.is_primary);
+ let chr = uline.multiline_whole_line;
+ annotations.push((depth, uline.style));
+ buffer_ops.push((line_offset, width_offset + depth - 1, chr, uline.style));
} else {
short_start = false;
break;
@@ -970,7 +985,7 @@ fn render_source_line(
// 3 │ X0 Y0 Z0
// │ ┏━━━━━┛ │ │ < We are writing these lines
// │ ┃┌───────┘ │ < by reverting the "depth" of
- // │ ┃│┌─────────┘ < their multilne spans.
+ // │ ┃│┌─────────┘ < their multiline spans.
// 4 │ ┃││ X1 Y1 Z1
// 5 │ ┃││ X2 Y2 Z2
// │ ┃│└────╿──│──┘ `Z` label
@@ -997,7 +1012,10 @@ fn render_source_line(
// 4 | }
// |
for pos in 0..=line_len {
- draw_col_separator_no_space(buffer, line_offset + pos + 1, width_offset - 2);
+ self.draw_col_separator_no_space(buffer, line_offset + pos + 1, width_offset - 2);
+ }
+ if close_window {
+ self.draw_col_separator_end(buffer, line_offset + line_len + 1, width_offset - 2);
}
// Write the horizontal lines for multiline annotations
@@ -1013,21 +1031,17 @@ fn render_source_line(
// 4 | }
// | _
for &(pos, annotation) in &annotations_position {
- let style = if annotation.is_primary {
- Style::UnderlinePrimary
- } else {
- Style::UnderlineSecondary
- };
+ let underline = self.underline(annotation.is_primary);
let pos = pos + 1;
match annotation.annotation_type {
AnnotationType::MultilineStart(depth) | AnnotationType::MultilineEnd(depth) => {
- draw_range(
+ self.draw_range(
buffer,
- '_',
+ underline.multiline_horizontal,
line_offset + pos,
width_offset + depth,
(code_offset + annotation.start_col.display).saturating_sub(left),
- style,
+ underline.style,
);
}
_ if self.teach => {
@@ -1035,7 +1049,7 @@ fn render_source_line(
line_offset,
(code_offset + annotation.start_col.display).saturating_sub(left),
(code_offset + annotation.end_col.display).saturating_sub(left),
- style,
+ underline.style,
annotation.is_primary,
);
}
@@ -1055,11 +1069,7 @@ fn render_source_line(
// 4 | | }
// | |_
for &(pos, annotation) in &annotations_position {
- let style = if annotation.is_primary {
- Style::UnderlinePrimary
- } else {
- Style::UnderlineSecondary
- };
+ let underline = self.underline(annotation.is_primary);
let pos = pos + 1;
if pos > 1 && (annotation.has_label() || annotation.takes_space()) {
@@ -1067,21 +1077,64 @@ fn render_source_line(
buffer.putc(
p,
(code_offset + annotation.start_col.display).saturating_sub(left),
- '|',
- style,
+ match annotation.annotation_type {
+ AnnotationType::MultilineLine(_) => underline.multiline_vertical,
+ _ => underline.vertical_text_line,
+ },
+ underline.style,
+ );
+ }
+ if let AnnotationType::MultilineStart(_) = annotation.annotation_type {
+ buffer.putc(
+ line_offset + pos,
+ (code_offset + annotation.start_col.display).saturating_sub(left),
+ underline.bottom_right,
+ underline.style,
+ );
+ }
+ if let AnnotationType::MultilineEnd(_) = annotation.annotation_type
+ && annotation.has_label()
+ {
+ buffer.putc(
+ line_offset + pos,
+ (code_offset + annotation.start_col.display).saturating_sub(left),
+ underline.multiline_bottom_right_with_text,
+ underline.style,
);
}
}
match annotation.annotation_type {
AnnotationType::MultilineStart(depth) => {
+ buffer.putc(
+ line_offset + pos,
+ width_offset + depth - 1,
+ underline.top_left,
+ underline.style,
+ );
for p in line_offset + pos + 1..line_offset + line_len + 2 {
- buffer.putc(p, width_offset + depth - 1, '|', style);
+ buffer.putc(
+ p,
+ width_offset + depth - 1,
+ underline.multiline_vertical,
+ underline.style,
+ );
}
}
AnnotationType::MultilineEnd(depth) => {
- for p in line_offset..=line_offset + pos {
- buffer.putc(p, width_offset + depth - 1, '|', style);
+ for p in line_offset..line_offset + pos {
+ buffer.putc(
+ p,
+ width_offset + depth - 1,
+ underline.multiline_vertical,
+ underline.style,
+ );
}
+ buffer.putc(
+ line_offset + pos,
+ width_offset + depth - 1,
+ underline.bottom_left,
+ underline.style,
+ );
}
_ => (),
}
@@ -1102,7 +1155,11 @@ fn render_source_line(
let style =
if annotation.is_primary { Style::LabelPrimary } else { Style::LabelSecondary };
let (pos, col) = if pos == 0 {
- (pos + 1, (annotation.end_col.display + 1).saturating_sub(left))
+ if annotation.end_col.display == 0 {
+ (pos + 1, (annotation.end_col.display + 2).saturating_sub(left))
+ } else {
+ (pos + 1, (annotation.end_col.display + 1).saturating_sub(left))
+ }
} else {
(pos + 2, annotation.start_col.display.saturating_sub(left))
};
@@ -1135,18 +1192,60 @@ fn render_source_line(
// 3 |
// 4 | }
// | _^ test
- for &(_, annotation) in &annotations_position {
- let (underline, style) = if annotation.is_primary {
- ('^', Style::UnderlinePrimary)
- } else {
- ('-', Style::UnderlineSecondary)
- };
+ for &(pos, annotation) in &annotations_position {
+ let uline = self.underline(annotation.is_primary);
for p in annotation.start_col.display..annotation.end_col.display {
+ // The default span label underline.
buffer.putc(
line_offset + 1,
(code_offset + p).saturating_sub(left),
- underline,
- style,
+ uline.underline,
+ uline.style,
+ );
+ }
+
+ if pos == 0
+ && matches!(
+ annotation.annotation_type,
+ AnnotationType::MultilineStart(_) | AnnotationType::MultilineEnd(_)
+ )
+ {
+ // The beginning of a multiline span with its leftward moving line on the same line.
+ buffer.putc(
+ line_offset + 1,
+ (code_offset + annotation.start_col.display).saturating_sub(left),
+ match annotation.annotation_type {
+ AnnotationType::MultilineStart(_) => uline.top_right_flat,
+ AnnotationType::MultilineEnd(_) => uline.multiline_end_same_line,
+ _ => panic!("unexpected annotation type: {annotation:?}"),
+ },
+ uline.style,
+ );
+ } else if pos != 0
+ && matches!(
+ annotation.annotation_type,
+ AnnotationType::MultilineStart(_) | AnnotationType::MultilineEnd(_)
+ )
+ {
+ // The beginning of a multiline span with its leftward moving line on another line,
+ // so we start going down first.
+ buffer.putc(
+ line_offset + 1,
+ (code_offset + annotation.start_col.display).saturating_sub(left),
+ match annotation.annotation_type {
+ AnnotationType::MultilineStart(_) => uline.multiline_start_down,
+ AnnotationType::MultilineEnd(_) => uline.multiline_end_up,
+ _ => panic!("unexpected annotation type: {annotation:?}"),
+ },
+ uline.style,
+ );
+ } else if pos != 0 && annotation.has_label() {
+ // The beginning of a span label with an actual label, we'll point down.
+ buffer.putc(
+ line_offset + 1,
+ (code_offset + annotation.start_col.display).saturating_sub(left),
+ uline.label_start,
+ uline.style,
);
}
}
@@ -1217,7 +1316,7 @@ fn msgs_to_buffer(
padding: usize,
label: &str,
override_style: Option
+
+
+
+
+ error[E0308]: `match` arms have incompatible types
+
+ ╭▸ $DIR/huge_multispan_highlight.rs:99:18
+
+ │
+
+ LL │ let _ = match true {
+
+ │ ────────── `match` arms have incompatible types
+
+ LL │ true => (
+
+ │ ┌─────────────────┘
+
+ LL │ │ // last line shown in multispan header
+
+ ‡ │
+
+ LL │ │
+
+ LL │ │ ),
+
+ │ └─────────┘ this is found to be of type `()`
+
+ LL │ false => "
+
+ │ ┏━━━━━━━━━━━━━━━━━━┛
+
+ ‡ ┃
+
+ LL │ ┃
+
+ LL │ ┃ ",
+
+ ╰╴┗━━━━━━━━━┛ expected `()`, found `&str`
+
+
+
+ error[E0308]: `match` arms have incompatible types
+
+ ╭▸ $DIR/huge_multispan_highlight.rs:216:18
+
+ │
+
+ LL │ let _ = match true {
+
+ │ ────────── `match` arms have incompatible types
+
+ LL │ true => (
+
+ │ ┌─────────────────┘
+
+ LL │ │
+
+ LL │ │ 1 // last line shown in multispan header
+
+ ‡ │
+
+ LL │ │
+
+ LL │ │ ),
+
+ │ └─────────┘ this is found to be of type `{integer}`
+
+ LL │ false => "
+
+ │ ┏━━━━━━━━━━━━━━━━━━┛
+
+ LL │ ┃
+
+ LL │ ┃
+
+ LL │ ┃ 1 last line shown in multispan
+
+ ‡ ┃
+
+ LL │ ┃
+
+ LL │ ┃ ",
+
+ ╰╴┗━━━━━━━━━┛ expected integer, found `&str`
+
+
+
+ error: aborting due to 2 previous errors
+
+
+
+ For more information about this error, try `rustc --explain E0308`.
+
+
+
+
+
+
diff --git a/tests/ui/diagnostic-width/E0271.stderr b/tests/ui/diagnostic-width/E0271.ascii.stderr
similarity index 94%
rename from tests/ui/diagnostic-width/E0271.stderr
rename to tests/ui/diagnostic-width/E0271.ascii.stderr
index 31ec3fe366f..e276299e9e8 100644
--- a/tests/ui/diagnostic-width/E0271.stderr
+++ b/tests/ui/diagnostic-width/E0271.ascii.stderr
@@ -1,5 +1,5 @@
error[E0271]: type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`
- --> $DIR/E0271.rs:18:5
+ --> $DIR/E0271.rs:20:5
|
LL | / Box::new(
LL | | Ok::<_, ()>(
@@ -11,7 +11,7 @@ LL | | )
| |_____^ type mismatch resolving `, ...>>, ...> as Future>::Error == Foo`
|
note: expected this to be `Foo`
- --> $DIR/E0271.rs:8:18
+ --> $DIR/E0271.rs:10:18
|
LL | type Error = E;
| ^
diff --git a/tests/ui/diagnostic-width/E0271.rs b/tests/ui/diagnostic-width/E0271.rs
index d8cb24898ac..ce41ad2952b 100644
--- a/tests/ui/diagnostic-width/E0271.rs
+++ b/tests/ui/diagnostic-width/E0271.rs
@@ -1,4 +1,6 @@
-//@ compile-flags: --diagnostic-width=40
+//@ revisions: ascii unicode
+//@[ascii] compile-flags: --diagnostic-width=40
+//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode --diagnostic-width=40
//@ normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
trait Future {
type Error;
@@ -15,7 +17,7 @@ impl Future for Option {
struct Foo;
fn foo() -> Box> {
- Box::new( //~ ERROR E0271
+ Box::new( //[ascii]~ ERROR E0271
Ok::<_, ()>(
Err::<(), _>(
Ok::<_, ()>(
diff --git a/tests/ui/diagnostic-width/E0271.unicode.stderr b/tests/ui/diagnostic-width/E0271.unicode.stderr
new file mode 100644
index 00000000000..4a96ca36cd7
--- /dev/null
+++ b/tests/ui/diagnostic-width/E0271.unicode.stderr
@@ -0,0 +1,22 @@
+error[E0271]: type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`
+ ╭▸ $DIR/E0271.rs:20:5
+ │
+LL │ ┏ Box::new(
+LL │ ┃ Ok::<_, ()>(
+LL │ ┃ Err::<(), _>(
+LL │ ┃ Ok::<_, ()>(
+ ‡ ┃
+LL │ ┃ )
+LL │ ┃ )
+ │ ┗━━━━━┛ type mismatch resolving `, ...>>, ...> as Future>::Error == Foo`
+ ╰╴
+note: expected this to be `Foo`
+ ╭▸ $DIR/E0271.rs:10:18
+ │
+LL │ type Error = E;
+ │ ━
+ ╰ note: required for the cast from `Box>, ()>>, ()>>, ()>>` to `Box<(dyn Future + 'static)>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/diagnostic-width/flag-human.stderr b/tests/ui/diagnostic-width/flag-human.ascii.stderr
similarity index 89%
rename from tests/ui/diagnostic-width/flag-human.stderr
rename to tests/ui/diagnostic-width/flag-human.ascii.stderr
index eaa96841080..4593304e087 100644
--- a/tests/ui/diagnostic-width/flag-human.stderr
+++ b/tests/ui/diagnostic-width/flag-human.ascii.stderr
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
- --> $DIR/flag-human.rs:7:17
+ --> $DIR/flag-human.rs:9:17
|
LL | ..._: () = 42;
| -- ^^ expected `()`, found integer
diff --git a/tests/ui/diagnostic-width/flag-human.rs b/tests/ui/diagnostic-width/flag-human.rs
index a46122ed783..1af41659141 100644
--- a/tests/ui/diagnostic-width/flag-human.rs
+++ b/tests/ui/diagnostic-width/flag-human.rs
@@ -1,9 +1,11 @@
-//@ compile-flags: --diagnostic-width=20
+//@ revisions: ascii unicode
+//@[ascii] compile-flags: --diagnostic-width=20
+//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode --diagnostic-width=20
// This test checks that `-Z output-width` effects the human error output by restricting it to an
// arbitrarily low value so that the effect is visible.
fn main() {
let _: () = 42;
- //~^ ERROR mismatched types
+ //[ascii]~^ ERROR mismatched types
}
diff --git a/tests/ui/diagnostic-width/flag-human.unicode.stderr b/tests/ui/diagnostic-width/flag-human.unicode.stderr
new file mode 100644
index 00000000000..50176564786
--- /dev/null
+++ b/tests/ui/diagnostic-width/flag-human.unicode.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+ ╭▸ $DIR/flag-human.rs:9:17
+ │
+LL │ …t _: () = 42;
+ │ ┬─ ━━ expected `()`, found integer
+ │ │
+ ╰╴ expected due to this
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/diagnostic-width/long-E0308.stderr b/tests/ui/diagnostic-width/long-E0308.ascii.stderr
similarity index 88%
rename from tests/ui/diagnostic-width/long-E0308.stderr
rename to tests/ui/diagnostic-width/long-E0308.ascii.stderr
index eb37da037e9..d45d6bf329b 100644
--- a/tests/ui/diagnostic-width/long-E0308.stderr
+++ b/tests/ui/diagnostic-width/long-E0308.ascii.stderr
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
- --> $DIR/long-E0308.rs:44:9
+ --> $DIR/long-E0308.rs:46:9
|
LL | let x: Atype<
| _____________-
@@ -20,11 +20,11 @@ LL | | ))))))))))))))))))))))))))))));
|
= note: expected struct `Atype, ...>`
found enum `Result, ...>`
- = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+ = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.ascii/long-E0308.long-type-hash.txt'
= note: consider using `--verbose` to print the full type name to the console
error[E0308]: mismatched types
- --> $DIR/long-E0308.rs:57:26
+ --> $DIR/long-E0308.rs:59:26
|
LL | ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
| __________________________^
@@ -36,11 +36,11 @@ LL | | ))))))))))))))))))))))));
|
= note: expected enum `Option>`
found enum `Result, ...>`
- = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+ = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.ascii/long-E0308.long-type-hash.txt'
= note: consider using `--verbose` to print the full type name to the console
error[E0308]: mismatched types
- --> $DIR/long-E0308.rs:88:9
+ --> $DIR/long-E0308.rs:90:9
|
LL | let x: Atype<
| ____________-
@@ -56,11 +56,11 @@ LL | | > = ();
|
= note: expected struct `Atype, ...>`
found unit type `()`
- = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+ = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.ascii/long-E0308.long-type-hash.txt'
= note: consider using `--verbose` to print the full type name to the console
error[E0308]: mismatched types
- --> $DIR/long-E0308.rs:91:17
+ --> $DIR/long-E0308.rs:93:17
|
LL | let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
| ____________--___^
@@ -74,7 +74,7 @@ LL | | ))))))))))))))))))))))));
|
= note: expected unit type `()`
found enum `Result, ...>`
- = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+ = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.ascii/long-E0308.long-type-hash.txt'
= note: consider using `--verbose` to print the full type name to the console
error: aborting due to 4 previous errors
diff --git a/tests/ui/diagnostic-width/long-E0308.rs b/tests/ui/diagnostic-width/long-E0308.rs
index 150164ba21b..73f81f5872a 100644
--- a/tests/ui/diagnostic-width/long-E0308.rs
+++ b/tests/ui/diagnostic-width/long-E0308.rs
@@ -1,4 +1,6 @@
-//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
+//@ revisions: ascii unicode
+//@[ascii] compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
+//@[unicode] compile-flags: -Zunstable-options=yes --json=diagnostic-unicode --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
//@ normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
mod a {
diff --git a/tests/ui/diagnostic-width/long-E0308.unicode.stderr b/tests/ui/diagnostic-width/long-E0308.unicode.stderr
new file mode 100644
index 00000000000..3e8d881d7a6
--- /dev/null
+++ b/tests/ui/diagnostic-width/long-E0308.unicode.stderr
@@ -0,0 +1,82 @@
+error[E0308]: mismatched types
+ ╭▸ $DIR/long-E0308.rs:46:9
+ │
+LL │ let x: Atype<
+ │ ┌─────────────┘
+LL │ │ Btype<
+LL │ │ Ctype<
+LL │ │ Atype<
+ ‡ │
+LL │ │ i32
+LL │ │ > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O…
+ │ │┏━━━━━│━━━┛
+ │ └┃─────┤
+ │ ┃ expected due to this
+LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O…
+LL │ ┃ Ok("")
+LL │ ┃ ))))))))))))))))))))))))))))))
+LL │ ┃ ))))))))))))))))))))))))))))));
+ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Atype, ...>`, found `Result, ...>`
+ │
+ ├ note: expected struct `Atype, ...>`
+ │ found enum `Result, ...>`
+ ├ note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.unicode/long-E0308.long-type-hash.txt'
+ ╰ note: consider using `--verbose` to print the full type name to the console
+
+error[E0308]: mismatched types
+ ╭▸ $DIR/long-E0308.rs:59:26
+ │
+LL │ ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(…
+ │ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━┛
+LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok…
+LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+LL │ ┃ ))))))))))))))))))))))))))))))
+LL │ ┃ ))))))))))))))))))))))));
+ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Option>`, found `Result, ...>`
+ │
+ ├ note: expected enum `Option>`
+ │ found enum `Result, ...>`
+ ├ note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.unicode/long-E0308.long-type-hash.txt'
+ ╰ note: consider using `--verbose` to print the full type name to the console
+
+error[E0308]: mismatched types
+ ╭▸ $DIR/long-E0308.rs:90:9
+ │
+LL │ let x: Atype<
+ │ ┌────────────┘
+LL │ │ Btype<
+LL │ │ Ctype<
+LL │ │ Atype<
+ ‡ │
+LL │ │ i32
+LL │ │ > = ();
+ │ │ │ ━━ expected `Atype, ...>`, found `()`
+ │ └─────┤
+ │ expected due to this
+ │
+ ├ note: expected struct `Atype, ...>`
+ │ found unit type `()`
+ ├ note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.unicode/long-E0308.long-type-hash.txt'
+ ╰ note: consider using `--verbose` to print the full type name to the console
+
+error[E0308]: mismatched types
+ ╭▸ $DIR/long-E0308.rs:93:17
+ │
+LL │ let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(…
+ │ ┏━━━━━━━━━━━━┬─━━━┛
+ │ ┃ │
+ │ ┃ expected due to this
+LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok…
+LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+LL │ ┃ ))))))))))))))))))))))))))))))
+LL │ ┃ ))))))))))))))))))))))));
+ │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `()`, found `Result, ...>`
+ │
+ ├ note: expected unit type `()`
+ │ found enum `Result, ...>`
+ ├ note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.unicode/long-E0308.long-type-hash.txt'
+ ╰ note: consider using `--verbose` to print the full type name to the console
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.ascii.stderr
similarity index 97%
rename from tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr
rename to tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.ascii.stderr
index 8f200e15c64..4d8afb6f3ad 100644
--- a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr
+++ b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.ascii.stderr
@@ -1,5 +1,5 @@
error[E0369]: cannot add `&str` to `&str`
- --> $DIR/non-1-width-unicode-multiline-label.rs:5:260
+ --> $DIR/non-1-width-unicode-multiline-label.rs:7:260
|
LL | ...ཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྾྿࿀࿁࿂࿃࿄࿅࿆࿇...࿋࿌࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!";
| -------------- ^ -------------- &str
diff --git a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs
index 1989ea88635..61c4b31e03a 100644
--- a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs
+++ b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs
@@ -1,7 +1,9 @@
+//@ revisions: ascii unicode
+//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode
// ignore-tidy-linelength
fn main() {
let unicode_is_fun = "‱ஹ௸௵꧄.ဪ꧅⸻𒈙𒐫﷽𒌄𒈟𒍼𒁎𒀱𒌧𒅃 𒈓𒍙𒊎𒄡𒅌𒁏𒀰𒐪𒐩𒈙𒐫𪚥";
let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!";
- //~^ ERROR cannot add `&str` to `&str`
+ //[ascii]~^ ERROR cannot add `&str` to `&str`
}
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
new file mode 100644
index 00000000000..ed8ce770bb7
--- /dev/null
+++ b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.unicode.stderr
@@ -0,0 +1,18 @@
+error[E0369]: cannot add `&str` to `&str`
+ ╭▸ $DIR/non-1-width-unicode-multiline-label.rs:7:260
+ │
+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
+ ╭╴
+LL │ let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun.to_owned() + " really fun!";
+ ╰╴ +++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-2.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming-2.ascii.stderr
similarity index 91%
rename from tests/ui/diagnostic-width/non-whitespace-trimming-2.stderr
rename to tests/ui/diagnostic-width/non-whitespace-trimming-2.ascii.stderr
index a7d5c0bfb94..70bd149545c 100644
--- a/tests/ui/diagnostic-width/non-whitespace-trimming-2.stderr
+++ b/tests/ui/diagnostic-width/non-whitespace-trimming-2.ascii.stderr
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
- --> $DIR/non-whitespace-trimming-2.rs:4:311
+ --> $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
diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs b/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs
index abd9e189a75..283506bd6c9 100644
--- a/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs
+++ b/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs
@@ -1,6 +1,8 @@
+//@ revisions: ascii unicode
+//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode
// ignore-tidy-linelength
fn main() {
let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _: usize = 4; let _: usize = 5; let _: usize = 6; let _: usize = 7; let _: usize = 8; let _: usize = 9; let _: usize = 10; let _: usize = 11; let _: usize = 12; let _: usize = 13; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _: usize = 4; let _: usize = 5; let _: usize = 6; let _: usize = 7; let _: usize = 8; let _: usize = 9; let _: usize = 10; let _: usize = 11; let _: usize = 12; let _: usize = 13; let _: usize = 14; let _: usize = 15;
-//~^ ERROR mismatched types
+//[ascii]~^ ERROR mismatched types
}
diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-2.unicode.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming-2.unicode.stderr
new file mode 100644
index 00000000000..600d196de16
--- /dev/null
+++ b/tests/ui/diagnostic-width/non-whitespace-trimming-2.unicode.stderr
@@ -0,0 +1,11 @@
+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
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/error-emitter/highlighting.svg b/tests/ui/error-emitter/highlighting.svg
index be92c00c19b..a4019c78f48 100644
--- a/tests/ui/error-emitter/highlighting.svg
+++ b/tests/ui/error-emitter/highlighting.svg
@@ -49,7 +49,7 @@
LL | fn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin<Box<(
- | ____^^^^^_-
+ | ____^^^^^_-
LL | | dyn Future<Output = Result<Box<(dyn Any + 'static)>, String>> + Send + 'static
diff --git a/tests/ui/error-emitter/highlighting.windows.svg b/tests/ui/error-emitter/highlighting.windows.svg
index 152245da9dd..c2378113b86 100644
--- a/tests/ui/error-emitter/highlighting.windows.svg
+++ b/tests/ui/error-emitter/highlighting.windows.svg
@@ -50,7 +50,7 @@
LL | fn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin<Box<(
- | ____^^^^^_-
+ | ____^^^^^_-
LL | | dyn Future<Output = Result<Box<(dyn Any + 'static)>, String>> + Send + 'static
diff --git a/tests/ui/error-emitter/unicode-output.rs b/tests/ui/error-emitter/unicode-output.rs
new file mode 100644
index 00000000000..ba6db37b66c
--- /dev/null
+++ b/tests/ui/error-emitter/unicode-output.rs
@@ -0,0 +1,21 @@
+//@ compile-flags: -Zunstable-options=yes --error-format=human-unicode --color=always
+//@ edition:2018
+//@ only-linux
+
+use core::pin::Pin;
+use core::future::Future;
+use core::any::Any;
+
+fn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin, String>> + Send + 'static
+)>>) {}
+
+fn wrapped_fn<'a>(_: Box<(dyn Any + Send)>) -> Pin, String>> + Send + 'static
+)>> {
+ Box::pin(async { Err("nope".into()) })
+}
+
+fn main() {
+ query(wrapped_fn);
+}
diff --git a/tests/ui/error-emitter/unicode-output.svg b/tests/ui/error-emitter/unicode-output.svg
new file mode 100644
index 00000000000..f98fd8b7403
--- /dev/null
+++ b/tests/ui/error-emitter/unicode-output.svg
@@ -0,0 +1,72 @@
+
diff --git a/tests/ui/parser/bad-char-literals.stderr b/tests/ui/parser/bad-char-literals.stderr
index 1fb324a1b7e..5a81ede0336 100644
--- a/tests/ui/parser/bad-char-literals.stderr
+++ b/tests/ui/parser/bad-char-literals.stderr
@@ -15,7 +15,7 @@ error: character constant must be escaped: `\n`
LL | '
| ______^
LL | | ';
- | |_
+ | |_^
|
help: escape the character
|