diff options
| author | bors <bors@rust-lang.org> | 2024-08-07 09:26:42 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-08-07 09:26:42 +0000 |
| commit | 384f8586cb7d3770b2572e9a998a33706f0983ac (patch) | |
| tree | ef23cabaebea1904b592c6c16b23d00ebe32d964 /compiler/rustc_errors | |
| parent | c755314d780b0ac0e712efc258533bbd8431d1f0 (diff) | |
| parent | 630ad887720e8c1357e0196021e2246de3b96fdd (diff) | |
| download | rust-384f8586cb7d3770b2572e9a998a33706f0983ac.tar.gz rust-384f8586cb7d3770b2572e9a998a33706f0983ac.zip | |
Auto merge of #3793 - rust-lang:rustup-2024-08-07, r=RalfJung
Automatic Rustup
Diffstat (limited to 'compiler/rustc_errors')
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/emitter.rs | 105 |
2 files changed, 93 insertions, 33 deletions
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index e1dcbf5b280..67ca6d50cca 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -741,6 +741,16 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } + #[rustc_lint_diagnostics] + pub fn highlighted_span_note( + &mut self, + span: impl Into<MultiSpan>, + msg: Vec<StringPart>, + ) -> &mut Self { + self.sub_with_highlights(Level::Note, msg, span.into()); + self + } + /// This is like [`Diag::note()`], but it's only printed once. #[rustc_lint_diagnostics] pub fn note_once(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self { @@ -815,6 +825,17 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } + /// Add a help message attached to this diagnostic with a customizable highlighted message. + #[rustc_lint_diagnostics] + pub fn highlighted_span_help( + &mut self, + span: impl Into<MultiSpan>, + msg: Vec<StringPart>, + ) -> &mut Self { + self.sub_with_highlights(Level::Help, msg, span.into()); + self + } + /// Prints the span with some help above it. /// This is like [`Diag::help()`], but it gets its own span. #[rustc_lint_diagnostics] diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 8963b009c31..88ed3128164 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1346,10 +1346,11 @@ impl HumanEmitter { buffer.append(0, ": ", header_style); label_width += 2; } - for (text, _) in msgs.iter() { + let mut line = 0; + for (text, style) in msgs.iter() { let text = self.translate_message(text, args).map_err(Report::new).unwrap(); // Account for newlines to align output to its label. - for (line, text) in normalize_whitespace(&text).lines().enumerate() { + for text in normalize_whitespace(&text).lines() { buffer.append( line, &format!( @@ -1357,8 +1358,38 @@ impl HumanEmitter { if line == 0 { String::new() } else { " ".repeat(label_width) }, text ), - header_style, + match style { + Style::Highlight => *style, + _ => header_style, + }, ); + line += 1; + } + // We add lines above, but if the last line has no explicit newline (which would + // yield an empty line), then we revert one line up to continue with the next + // styled text chunk on the same line as the last one from the prior one. Otherwise + // every `text` would appear on their own line (because even though they didn't end + // in '\n', they advanced `line` by one). + if line > 0 { + line -= 1; + } + } + if self.short_message { + let labels = msp + .span_labels() + .into_iter() + .filter_map(|label| match label.label { + Some(msg) if label.is_primary => { + let text = self.translate_message(&msg, args).ok()?; + if !text.trim().is_empty() { Some(text.to_string()) } else { None } + } + _ => None, + }) + .collect::<Vec<_>>() + .join(", "); + if !labels.is_empty() { + buffer.append(line, ": ", Style::NoStyle); + buffer.append(line, &labels, Style::NoStyle); } } } @@ -2564,22 +2595,13 @@ fn num_decimal_digits(num: usize) -> usize { // We replace some characters so the CLI output is always consistent and underlines aligned. // Keep the following list in sync with `rustc_span::char_width`. +// ATTENTION: keep lexicografically sorted so that the binary search will work const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ - ('\t', " "), // We do our own tab replacement - ('\u{200D}', ""), // Replace ZWJ with nothing for consistent terminal output of grapheme clusters. - ('\u{202A}', "�"), // The following unicode text flow control characters are inconsistently - ('\u{202B}', "�"), // supported across CLIs and can cause confusion due to the bytes on disk - ('\u{202D}', "�"), // not corresponding to the visible source code, so we replace them always. - ('\u{202E}', "�"), - ('\u{2066}', "�"), - ('\u{2067}', "�"), - ('\u{2068}', "�"), - ('\u{202C}', "�"), - ('\u{2069}', "�"), + // tidy-alphabetical-start // In terminals without Unicode support the following will be garbled, but in *all* terminals // the underlying codepoint will be as well. We could gate this replacement behind a "unicode // support" gate. - ('\u{0000}', "␀"), + ('\0', "␀"), ('\u{0001}', "␁"), ('\u{0002}', "␂"), ('\u{0003}', "␃"), @@ -2588,11 +2610,12 @@ const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ ('\u{0006}', "␆"), ('\u{0007}', "␇"), ('\u{0008}', "␈"), - ('\u{000B}', "␋"), - ('\u{000C}', "␌"), - ('\u{000D}', "␍"), - ('\u{000E}', "␎"), - ('\u{000F}', "␏"), + ('\u{0009}', " "), // We do our own tab replacement + ('\u{000b}', "␋"), + ('\u{000c}', "␌"), + ('\u{000d}', "␍"), + ('\u{000e}', "␎"), + ('\u{000f}', "␏"), ('\u{0010}', "␐"), ('\u{0011}', "␑"), ('\u{0012}', "␒"), @@ -2603,21 +2626,37 @@ const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ ('\u{0017}', "␗"), ('\u{0018}', "␘"), ('\u{0019}', "␙"), - ('\u{001A}', "␚"), - ('\u{001B}', "␛"), - ('\u{001C}', "␜"), - ('\u{001D}', "␝"), - ('\u{001E}', "␞"), - ('\u{001F}', "␟"), - ('\u{007F}', "␡"), + ('\u{001a}', "␚"), + ('\u{001b}', "␛"), + ('\u{001c}', "␜"), + ('\u{001d}', "␝"), + ('\u{001e}', "␞"), + ('\u{001f}', "␟"), + ('\u{007f}', "␡"), + ('\u{200d}', ""), // Replace ZWJ for consistent terminal output of grapheme clusters. + ('\u{202a}', "�"), // The following unicode text flow control characters are inconsistently + ('\u{202b}', "�"), // supported across CLIs and can cause confusion due to the bytes on disk + ('\u{202c}', "�"), // not corresponding to the visible source code, so we replace them always. + ('\u{202d}', "�"), + ('\u{202e}', "�"), + ('\u{2066}', "�"), + ('\u{2067}', "�"), + ('\u{2068}', "�"), + ('\u{2069}', "�"), + // tidy-alphabetical-end ]; -fn normalize_whitespace(str: &str) -> String { - let mut s = str.to_string(); - for (c, replacement) in OUTPUT_REPLACEMENTS { - s = s.replace(*c, replacement); - } - s +fn normalize_whitespace(s: &str) -> String { + // Scan the input string for a character in the ordered table above. If it's present, replace + // it with it's alternative string (it can be more than 1 char!). Otherwise, retain the input + // char. At the end, allocate all chars into a string in one operation. + s.chars().fold(String::with_capacity(s.len()), |mut s, c| { + match OUTPUT_REPLACEMENTS.binary_search_by_key(&c, |(k, _)| *k) { + Ok(i) => s.push_str(OUTPUT_REPLACEMENTS[i].1), + _ => s.push(c), + } + s + }) } fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) { |
