about summary refs log tree commit diff
path: root/compiler/rustc_errors/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_errors/src')
-rw-r--r--compiler/rustc_errors/src/emitter.rs167
1 files changed, 99 insertions, 68 deletions
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index e9e7065ec03..269d34ea432 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -656,11 +656,6 @@ impl Emitter for SilentEmitter {
     }
 }
 
-/// Maximum number of lines we will print for a multiline suggestion; arbitrary.
-///
-/// This should be replaced with a more involved mechanism to output multiline suggestions that
-/// more closely mimics the regular diagnostic output, where irrelevant code lines are elided.
-pub const MAX_SUGGESTION_HIGHLIGHT_LINES: usize = 6;
 /// Maximum number of suggestions to be shown
 ///
 /// Arbitrary, but taken from trait import suggestion limit
@@ -1839,79 +1834,115 @@ impl EmitterWriter {
                 }
                 row_num += line_end - line_start;
             }
-            for (line_pos, (line, highlight_parts)) in
-                lines.by_ref().zip(highlights).take(MAX_SUGGESTION_HIGHLIGHT_LINES).enumerate()
-            {
-                // Print the span column to avoid confusion
-                buffer.puts(
-                    row_num,
-                    0,
-                    &self.maybe_anonymized(line_start + line_pos),
-                    Style::LineNumber,
-                );
-                if let DisplaySuggestion::Diff = show_code_change {
-                    // Add the line number for both addition and removal to drive the point home.
-                    //
-                    // N - fn foo<A: T>(bar: A) {
-                    // N + fn foo(bar: impl T) {
+            let mut unhighlighted_lines = Vec::new();
+            for (line_pos, (line, highlight_parts)) in lines.by_ref().zip(highlights).enumerate() {
+                debug!(%line_pos, %line, ?highlight_parts);
+
+                let print_line = |line_pos: usize,
+                                  line: &str,
+                                  highlight_parts: &Vec<SubstitutionHighlight>,
+                                  buffer: &mut StyledBuffer,
+                                  row_num: &mut usize| {
+                    // Print the span column to avoid confusion
                     buffer.puts(
-                        row_num - 1,
+                        *row_num,
                         0,
                         &self.maybe_anonymized(line_start + line_pos),
                         Style::LineNumber,
                     );
-                    buffer.puts(row_num - 1, max_line_num_len + 1, "- ", Style::Removal);
-                    buffer.puts(
-                        row_num - 1,
-                        max_line_num_len + 3,
-                        &normalize_whitespace(
-                            &*file_lines
-                                .file
-                                .get_line(file_lines.lines[line_pos].line_index)
-                                .unwrap(),
-                        ),
-                        Style::NoStyle,
-                    );
-                    buffer.puts(row_num, max_line_num_len + 1, "+ ", Style::Addition);
-                } else if is_multiline {
-                    match &highlight_parts[..] {
-                        [SubstitutionHighlight { start: 0, end }] if *end == line.len() => {
-                            buffer.puts(row_num, max_line_num_len + 1, "+ ", Style::Addition);
-                        }
-                        [] => {
-                            draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
-                        }
-                        _ => {
-                            buffer.puts(row_num, max_line_num_len + 1, "~ ", Style::Addition);
+                    if let DisplaySuggestion::Diff = show_code_change {
+                        // Add the line number for both addition and removal to drive the point home.
+                        //
+                        // N - fn foo<A: T>(bar: A) {
+                        // N + fn foo(bar: impl T) {
+                        buffer.puts(
+                            *row_num - 1,
+                            0,
+                            &self.maybe_anonymized(line_start + line_pos),
+                            Style::LineNumber,
+                        );
+                        buffer.puts(*row_num - 1, max_line_num_len + 1, "- ", Style::Removal);
+                        buffer.puts(
+                            *row_num - 1,
+                            max_line_num_len + 3,
+                            &normalize_whitespace(
+                                &*file_lines
+                                    .file
+                                    .get_line(file_lines.lines[line_pos].line_index)
+                                    .unwrap(),
+                            ),
+                            Style::NoStyle,
+                        );
+                        buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition);
+                    } else if is_multiline {
+                        match &highlight_parts[..] {
+                            [SubstitutionHighlight { start: 0, end }] if *end == line.len() => {
+                                buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition);
+                            }
+                            [] => {
+                                draw_col_separator(buffer, *row_num, max_line_num_len + 1);
+                            }
+                            _ => {
+                                buffer.puts(*row_num, max_line_num_len + 1, "~ ", Style::Addition);
+                            }
                         }
+                    } else {
+                        draw_col_separator(buffer, *row_num, max_line_num_len + 1);
                     }
-                } else {
-                    draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
-                }
 
-                // print the suggestion
-                buffer.append(row_num, &normalize_whitespace(line), Style::NoStyle);
+                    // print the suggestion
+                    buffer.append(*row_num, &normalize_whitespace(line), Style::NoStyle);
 
-                // Colorize addition/replacements with green.
-                for &SubstitutionHighlight { start, end } in highlight_parts {
-                    // Account for tabs when highlighting (#87972).
-                    let tabs: usize = line
-                        .chars()
-                        .take(start)
-                        .map(|ch| match ch {
-                            '\t' => 3,
-                            _ => 0,
-                        })
-                        .sum();
-                    buffer.set_style_range(
-                        row_num,
-                        max_line_num_len + 3 + start + tabs,
-                        max_line_num_len + 3 + end + tabs,
-                        Style::Addition,
-                        true,
-                    );
+                    // Colorize addition/replacements with green.
+                    for &SubstitutionHighlight { start, end } in highlight_parts {
+                        // Account for tabs when highlighting (#87972).
+                        let tabs: usize = line
+                            .chars()
+                            .take(start)
+                            .map(|ch| match ch {
+                                '\t' => 3,
+                                _ => 0,
+                            })
+                            .sum();
+                        buffer.set_style_range(
+                            *row_num,
+                            max_line_num_len + 3 + start + tabs,
+                            max_line_num_len + 3 + end + tabs,
+                            Style::Addition,
+                            true,
+                        );
+                    }
+                    *row_num += 1;
+                };
+
+                if highlight_parts.is_empty() {
+                    unhighlighted_lines.push((line_pos, line));
+                    continue;
                 }
-                row_num += 1;
+
+                match unhighlighted_lines.len() {
+                    0 => (),
+                    // Since we show first line, "..." line and last line,
+                    // There is no reason to hide if there are 3 or less lines
+                    // (because then we just replace a line with ... which is
+                    // not helpful)
+                    n if n <= 3 => unhighlighted_lines.drain(..).for_each(|(p, l)| {
+                        print_line(p, l, &Vec::new(), &mut buffer, &mut row_num)
+                    }),
+                    _ => {
+                        unhighlighted_lines
+                            .drain(..1)
+                            .next()
+                            .map(|(p, l)| print_line(p, l, &Vec::new(), &mut buffer, &mut row_num));
+                        buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber);
+                        row_num += 1;
+                        unhighlighted_lines
+                            .pop()
+                            .map(|(p, l)| print_line(p, l, &Vec::new(), &mut buffer, &mut row_num));
+                    }
+                }
+
+                print_line(line_pos, line, highlight_parts, &mut buffer, &mut row_num)
             }
 
             // This offset and the ones below need to be signed to account for replacement code