summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_errors/src/emitter.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_errors/src/emitter.rs')
-rw-r--r--compiler/rustc_errors/src/emitter.rs124
1 files changed, 76 insertions, 48 deletions
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 4df2198fb..628e19999 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -28,6 +28,7 @@ use rustc_error_messages::{FluentArgs, SpanLabel};
use rustc_span::hygiene::{ExpnKind, MacroKind};
use std::borrow::Cow;
use std::cmp::{max, min, Reverse};
+use std::error::Report;
use std::io::prelude::*;
use std::io::{self, IsTerminal};
use std::iter;
@@ -250,7 +251,7 @@ pub trait Emitter: Translate {
let mut primary_span = diag.span.clone();
let suggestions = diag.suggestions.as_deref().unwrap_or(&[]);
if let Some((sugg, rest)) = suggestions.split_first() {
- let msg = self.translate_message(&sugg.msg, fluent_args);
+ let msg = self.translate_message(&sugg.msg, fluent_args).map_err(Report::new).unwrap();
if rest.is_empty() &&
// ^ if there is only one suggestion
// don't display multi-suggestions as labels
@@ -845,7 +846,10 @@ impl EmitterWriter {
// 3 | |
// 4 | | }
// | |_^ test
- if let [ann] = &line.annotations[..] {
+ let mut buffer_ops = vec![];
+ let mut annotations = vec![];
+ let mut short_start = true;
+ for ann in &line.annotations {
if let AnnotationType::MultilineStart(depth) = ann.annotation_type {
if source_string.chars().take(ann.start_col).all(|c| c.is_whitespace()) {
let style = if ann.is_primary {
@@ -853,11 +857,24 @@ impl EmitterWriter {
} else {
Style::UnderlineSecondary
};
- buffer.putc(line_offset, width_offset + depth - 1, '/', style);
- return vec![(depth, style)];
+ annotations.push((depth, style));
+ buffer_ops.push((line_offset, width_offset + depth - 1, '/', style));
+ } else {
+ short_start = false;
+ break;
}
+ } else if let AnnotationType::MultilineLine(_) = ann.annotation_type {
+ } else {
+ short_start = false;
+ break;
}
}
+ if short_start {
+ for (y, x, c, s) in buffer_ops {
+ buffer.putc(y, x, c, s);
+ }
+ return annotations;
+ }
// We want to display like this:
//
@@ -1308,8 +1325,8 @@ impl EmitterWriter {
// see how it *looks* with
// very *weird* formats
// see?
- for &(ref text, ref style) in msg.iter() {
- let text = self.translate_message(text, args);
+ for (text, style) in msg.iter() {
+ let text = self.translate_message(text, args).map_err(Report::new).unwrap();
let lines = text.split('\n').collect::<Vec<_>>();
if lines.len() > 1 {
for (i, line) in lines.iter().enumerate() {
@@ -1370,8 +1387,8 @@ impl EmitterWriter {
buffer.append(0, ": ", header_style);
label_width += 2;
}
- for &(ref text, _) in msg.iter() {
- let text = self.translate_message(text, args);
+ for (text, _) in msg.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() {
buffer.append(
@@ -1408,49 +1425,58 @@ impl EmitterWriter {
if !sm.ensure_source_file_source_present(annotated_file.file.clone()) {
if !self.short_message {
// We'll just print an unannotated message.
- for (annotation_id, line) in annotated_file.lines.into_iter().enumerate() {
+ for (annotation_id, line) in annotated_file.lines.iter().enumerate() {
let mut annotations = line.annotations.clone();
annotations.sort_by_key(|a| Reverse(a.start_col));
let mut line_idx = buffer.num_lines();
- buffer.append(
- line_idx,
- &format!(
- "{}:{}:{}",
- sm.filename_for_diagnostics(&annotated_file.file.name),
- sm.doctest_offset_line(&annotated_file.file.name, line.line_index),
- annotations[0].start_col + 1,
- ),
- Style::LineAndColumn,
- );
- if annotation_id == 0 {
- buffer.prepend(line_idx, "--> ", Style::LineNumber);
+
+ let labels: Vec<_> = annotations
+ .iter()
+ .filter_map(|a| Some((a.label.as_ref()?, a.is_primary)))
+ .filter(|(l, _)| !l.is_empty())
+ .collect();
+
+ if annotation_id == 0 || !labels.is_empty() {
+ buffer.append(
+ line_idx,
+ &format!(
+ "{}:{}:{}",
+ sm.filename_for_diagnostics(&annotated_file.file.name),
+ sm.doctest_offset_line(
+ &annotated_file.file.name,
+ line.line_index
+ ),
+ annotations[0].start_col + 1,
+ ),
+ Style::LineAndColumn,
+ );
+ if annotation_id == 0 {
+ buffer.prepend(line_idx, "--> ", Style::LineNumber);
+ } else {
+ buffer.prepend(line_idx, "::: ", Style::LineNumber);
+ }
for _ in 0..max_line_num_len {
buffer.prepend(line_idx, " ", Style::NoStyle);
}
line_idx += 1;
- };
- for (i, annotation) in annotations.into_iter().enumerate() {
- if let Some(label) = &annotation.label {
- let style = if annotation.is_primary {
- Style::LabelPrimary
- } else {
- Style::LabelSecondary
- };
- if annotation_id == 0 {
- buffer.prepend(line_idx, " |", Style::LineNumber);
- for _ in 0..max_line_num_len {
- buffer.prepend(line_idx, " ", Style::NoStyle);
- }
- line_idx += 1;
- buffer.append(line_idx + i, " = note: ", style);
- for _ in 0..max_line_num_len {
- buffer.prepend(line_idx, " ", Style::NoStyle);
- }
- } else {
- buffer.append(line_idx + i, ": ", style);
- }
- buffer.append(line_idx + i, label, style);
+ }
+ for (label, is_primary) in labels.into_iter() {
+ let style = if is_primary {
+ Style::LabelPrimary
+ } else {
+ Style::LabelSecondary
+ };
+ buffer.prepend(line_idx, " |", Style::LineNumber);
+ for _ in 0..max_line_num_len {
+ buffer.prepend(line_idx, " ", Style::NoStyle);
}
+ line_idx += 1;
+ buffer.append(line_idx, " = note: ", style);
+ for _ in 0..max_line_num_len {
+ buffer.prepend(line_idx, " ", Style::NoStyle);
+ }
+ buffer.append(line_idx, label, style);
+ line_idx += 1;
}
}
}
@@ -1765,7 +1791,7 @@ impl EmitterWriter {
if let Some(span) = span.primary_span() {
// Compare the primary span of the diagnostic with the span of the suggestion
- // being emitted. If they belong to the same file, we don't *need* to show the
+ // being emitted. If they belong to the same file, we don't *need* to show the
// file name, saving in verbosity, but if it *isn't* we do need it, otherwise we're
// telling users to make a change but not clarifying *where*.
let loc = sm.lookup_char_pos(parts[0].span.lo());
@@ -2276,7 +2302,9 @@ impl FileWithAnnotatedLines {
hi.col_display += 1;
}
- let label = label.as_ref().map(|m| emitter.translate_message(m, args).to_string());
+ let label = label.as_ref().map(|m| {
+ emitter.translate_message(m, args).map_err(Report::new).unwrap().to_string()
+ });
if lo.line != hi.line {
let ml = MultilineAnnotation {
@@ -2304,7 +2332,7 @@ impl FileWithAnnotatedLines {
}
// Find overlapping multiline annotations, put them at different depths
- multiline_annotations.sort_by_key(|&(_, ref ml)| (ml.line_start, usize::MAX - ml.line_end));
+ multiline_annotations.sort_by_key(|(_, ml)| (ml.line_start, usize::MAX - ml.line_end));
for (_, ann) in multiline_annotations.clone() {
for (_, a) in multiline_annotations.iter_mut() {
// Move all other multiline annotations overlapping with this one
@@ -2501,11 +2529,11 @@ fn emit_to_destination(
//
// On Unix systems, we write into a buffered terminal rather than directly to a terminal. When
// the .flush() is called we take the buffer created from the buffered writes and write it at
- // one shot. Because the Unix systems use ANSI for the colors, which is a text-based styling
+ // one shot. Because the Unix systems use ANSI for the colors, which is a text-based styling
// scheme, this buffered approach works and maintains the styling.
//
// On Windows, styling happens through calls to a terminal API. This prevents us from using the
- // same buffering approach. Instead, we use a global Windows mutex, which we acquire long
+ // same buffering approach. Instead, we use a global Windows mutex, which we acquire long
// enough to output the full error message, then we release.
let _buffer_lock = lock::acquire_global_lock("rustc_errors");
for (pos, line) in rendered_buffer.iter().enumerate() {