//! The current rustc diagnostics emitter.
//!
//! An `Emitter` takes care of generating the output from a `Diag` struct.
//!
//! There are various `Emitter` implementations that generate different output formats such as
//! JSON and human readable output.
//!
//! The output types are defined in `rustc_session::config::ErrorOutputType`.

use std::borrow::Cow;
use std::cmp::{Reverse, max, min};
use std::error::Report;
use std::io::prelude::*;
use std::io::{self, IsTerminal};
use std::iter;
use std::path::Path;
use std::sync::Arc;

use derive_setters::Setters;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::sync::{DynSend, IntoDynSyncSend};
use rustc_error_messages::{FluentArgs, SpanLabel};
use rustc_lexer;
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 crate::diagnostic::DiagLocation;
use crate::registry::Registry;
use crate::snippet::{
    Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString,
};
use crate::styled_buffer::StyledBuffer;
use crate::timings::TimingRecord;
use crate::translation::{Translator, to_fluent_args};
use crate::{
    CodeSuggestion, DiagInner, DiagMessage, ErrCode, Level, MultiSpan, Subdiag,
    SubstitutionHighlight, SuggestionStyle, TerminalUrl,
};

/// Default column width, used in tests and when terminal dimensions cannot be determined.
const DEFAULT_COLUMN_WIDTH: usize = 140;

/// Describes the way the content of the `rendered` field of the json output is generated
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum HumanReadableErrorType {
    Default,
    Unicode,
    AnnotateSnippet,
    Short,
}

impl HumanReadableErrorType {
    pub fn short(&self) -> bool {
        *self == HumanReadableErrorType::Short
    }
}

#[derive(Clone, Copy, Debug)]
struct Margin {
    /// The available whitespace in the left that can be consumed when centering.
    pub whitespace_left: usize,
    /// The column of the beginning of leftmost span.
    pub span_left: usize,
    /// The column of the end of rightmost span.
    pub span_right: usize,
    /// The beginning of the line to be displayed.
    pub computed_left: usize,
    /// The end of the line to be displayed.
    pub computed_right: usize,
    /// The current width of the terminal. Uses value of `DEFAULT_COLUMN_WIDTH` constant by default
    /// and in tests.
    pub column_width: usize,
    /// The end column of a span label, including the span. Doesn't account for labels not in the
    /// same line as the span.
    pub label_right: usize,
}

impl Margin {
    fn new(
        whitespace_left: usize,
        span_left: usize,
        span_right: usize,
        label_right: usize,
        column_width: usize,
        max_line_len: usize,
    ) -> Self {
        // The 6 is padding to give a bit of room for `...` when displaying:
        // ```
        // error: message
        //   --> file.rs:16:58
        //    |
        // 16 | ... fn foo(self) -> Self::Bar {
        //    |                     ^^^^^^^^^
        // ```

        let mut m = Margin {
            whitespace_left: whitespace_left.saturating_sub(6),
            span_left: span_left.saturating_sub(6),
            span_right: span_right + 6,
            computed_left: 0,
            computed_right: 0,
            column_width,
            label_right: label_right + 6,
        };
        m.compute(max_line_len);
        m
    }

    fn was_cut_left(&self) -> bool {
        self.computed_left > 0
    }

    fn compute(&mut self, max_line_len: usize) {
        // When there's a lot of whitespace (>20), we want to trim it as it is useless.
        // FIXME: this doesn't account for '\t', but to do so correctly we need to perform that
        // calculation later, right before printing in order to be accurate with both unicode
        // handling and trimming of long lines.
        self.computed_left = if self.whitespace_left > 20 {
            self.whitespace_left - 16 // We want some padding.
        } else {
            0
        };
        // We want to show as much as possible, max_line_len is the rightmost boundary for the
        // relevant code.
        self.computed_right = max(max_line_len, self.computed_left);

        if self.computed_right - self.computed_left > self.column_width {
            // Trimming only whitespace isn't enough, let's get craftier.
            if self.label_right - self.whitespace_left <= self.column_width {
                // Attempt to fit the code window only trimming whitespace.
                self.computed_left = self.whitespace_left;
                self.computed_right = self.computed_left + self.column_width;
            } else if self.label_right - self.span_left <= self.column_width {
                // Attempt to fit the code window considering only the spans and labels.
                let padding_left = (self.column_width - (self.label_right - self.span_left)) / 2;
                self.computed_left = self.span_left.saturating_sub(padding_left);
                self.computed_right = self.computed_left + self.column_width;
            } else if self.span_right - self.span_left <= self.column_width {
                // Attempt to fit the code window considering the spans and labels plus padding.
                let padding_left = (self.column_width - (self.span_right - self.span_left)) / 5 * 2;
                self.computed_left = self.span_left.saturating_sub(padding_left);
                self.computed_right = self.computed_left + self.column_width;
            } else {
                // Mostly give up but still don't show the full line.
                self.computed_left = self.span_left;
                self.computed_right = self.span_right;
            }
        }
    }

    fn left(&self, line_len: usize) -> usize {
        min(self.computed_left, line_len)
    }

    fn right(&self, line_len: usize) -> usize {
        if line_len.saturating_sub(self.computed_left) <= self.column_width {
            line_len
        } else {
            min(line_len, self.computed_right)
        }
    }
}

pub enum TimingEvent {
    Start,
    End,
}

const ANONYMIZED_LINE_NUM: &str = "LL";

pub type DynEmitter = dyn Emitter + DynSend;

/// Emitter trait for emitting errors and other structured information.
pub trait Emitter {
    /// Emit a structured diagnostic.
    fn emit_diagnostic(&mut self, diag: DiagInner, registry: &Registry);

    /// Emit a notification that an artifact has been output.
    /// Currently only supported for the JSON format.
    fn emit_artifact_notification(&mut self, _path: &Path, _artifact_type: &str) {}

    /// Emit a timestamp with start/end of a timing section.
    /// Currently only supported for the JSON format.
    fn emit_timing_section(&mut self, _record: TimingRecord, _event: TimingEvent) {}

    /// Emit a report about future breakage.
    /// Currently only supported for the JSON format.
    fn emit_future_breakage_report(&mut self, _diags: Vec<DiagInner>, _registry: &Registry) {}

    /// Emit list of unused externs.
    /// Currently only supported for the JSON format.
    fn emit_unused_externs(
        &mut self,
        _lint_level: rustc_lint_defs::Level,
        _unused_externs: &[&str],
    ) {
    }

    /// Checks if should show explanations about "rustc --explain"
    fn should_show_explain(&self) -> bool {
        true
    }

    /// Checks if we can use colors in the current output stream.
    fn supports_color(&self) -> bool {
        false
    }

    fn source_map(&self) -> Option<&SourceMap>;

    fn translator(&self) -> &Translator;

    /// Formats the substitutions of the primary_span
    ///
    /// There are a lot of conditions to this method, but in short:
    ///
    /// * If the current `DiagInner` has only one visible `CodeSuggestion`,
    ///   we format the `help` suggestion depending on the content of the
    ///   substitutions. In that case, we modify the span and clear the
    ///   suggestions.
    ///
    /// * If the current `DiagInner` has multiple suggestions,
    ///   we leave `primary_span` and the suggestions untouched.
    fn primary_span_formatted(
        &self,
        primary_span: &mut MultiSpan,
        suggestions: &mut Vec<CodeSuggestion>,
        fluent_args: &FluentArgs<'_>,
    ) {
        if let Some((sugg, rest)) = suggestions.split_first() {
            let msg = self
                .translator()
                .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
               && let [substitution] = sugg.substitutions.as_slice()
               // don't display multipart suggestions as labels
               && let [part] = substitution.parts.as_slice()
               // don't display long messages as labels
               && msg.split_whitespace().count() < 10
               // don't display multiline suggestions as labels
               && !part.snippet.contains('\n')
               && ![
                    // when this style is set we want the suggestion to be a message, not inline
                    SuggestionStyle::HideCodeAlways,
                    // trivial suggestion for tooling's sake, never shown
                    SuggestionStyle::CompletelyHidden,
                    // subtle suggestion, never shown inline
                    SuggestionStyle::ShowAlways,
               ].contains(&sugg.style)
            {
                let snippet = part.snippet.trim();
                let msg = if snippet.is_empty() || sugg.style.hide_inline() {
                    // This substitution is only removal OR we explicitly don't want to show the
                    // code inline (`hide_inline`). Therefore, we don't show the substitution.
                    format!("help: {msg}")
                } else {
                    // Show the default suggestion text with the substitution
                    format!(
                        "help: {}{}: `{}`",
                        msg,
                        if self
                            .source_map()
                            .is_some_and(|sm| is_case_difference(sm, snippet, part.span,))
                        {
                            " (notice the capitalization)"
                        } else {
                            ""
                        },
                        snippet,
                    )
                };
                primary_span.push_span_label(part.span, msg);

                // We return only the modified primary_span
                suggestions.clear();
            } else {
                // if there are multiple suggestions, print them all in full
                // to be consistent. We could try to figure out if we can
                // make one (or the first one) inline, but that would give
                // undue importance to a semi-random suggestion
            }
        } else {
            // do nothing
        }
    }

    fn fix_multispans_in_extern_macros_and_render_macro_backtrace(
        &self,
        span: &mut MultiSpan,
        children: &mut Vec<Subdiag>,
        level: &Level,
        backtrace: bool,
    ) {
        // Check for spans in macros, before `fix_multispans_in_extern_macros`
        // has a chance to replace them.
        let has_macro_spans: Vec<_> = iter::once(&*span)
            .chain(children.iter().map(|child| &child.span))
            .flat_map(|span| span.primary_spans())
            .flat_map(|sp| sp.macro_backtrace())
            .filter_map(|expn_data| {
                match expn_data.kind {
                    ExpnKind::Root => None,

                    // Skip past non-macro entries, just in case there
                    // are some which do actually involve macros.
                    ExpnKind::Desugaring(..) | ExpnKind::AstPass(..) => None,

                    ExpnKind::Macro(macro_kind, name) => {
                        Some((macro_kind, name, expn_data.hide_backtrace))
                    }
                }
            })
            .collect();

        if !backtrace {
            self.fix_multispans_in_extern_macros(span, children);
        }

        self.render_multispans_macro_backtrace(span, children, backtrace);

        if !backtrace {
            // Skip builtin macros, as their expansion isn't relevant to the end user. This includes
            // actual intrinsics, like `asm!`.
            if let Some((macro_kind, name, _)) = has_macro_spans.first()
                && let Some((_, _, false)) = has_macro_spans.last()
            {
                // Mark the actual macro this originates from
                let and_then = if let Some((macro_kind, last_name, _)) = has_macro_spans.last()
                    && last_name != name
                {
                    let descr = macro_kind.descr();
                    format!(" which comes from the expansion of the {descr} `{last_name}`")
                } else {
                    "".to_string()
                };

                let descr = macro_kind.descr();
                let msg = format!(
                    "this {level} originates in the {descr} `{name}`{and_then} \
                    (in Nightly builds, run with -Z macro-backtrace for more info)",
                );

                children.push(Subdiag {
                    level: Level::Note,
                    messages: vec![(DiagMessage::from(msg), Style::NoStyle)],
                    span: MultiSpan::new(),
                });
            }
        }
    }

    fn render_multispans_macro_backtrace(
        &self,
        span: &mut MultiSpan,
        children: &mut Vec<Subdiag>,
        backtrace: bool,
    ) {
        for span in iter::once(span).chain(children.iter_mut().map(|child| &mut child.span)) {
            self.render_multispan_macro_backtrace(span, backtrace);
        }
    }

    fn render_multispan_macro_backtrace(&self, span: &mut MultiSpan, always_backtrace: bool) {
        let mut new_labels = FxIndexSet::default();

        for &sp in span.primary_spans() {
            if sp.is_dummy() {
                continue;
            }

            // FIXME(eddyb) use `retain` on `macro_backtrace` to remove all the
            // entries we don't want to print, to make sure the indices being
            // printed are contiguous (or omitted if there's only one entry).
            let macro_backtrace: Vec<_> = sp.macro_backtrace().collect();
            for (i, trace) in macro_backtrace.iter().rev().enumerate() {
                if trace.def_site.is_dummy() {
                    continue;
                }

                if always_backtrace {
                    new_labels.insert((
                        trace.def_site,
                        format!(
                            "in this expansion of `{}`{}",
                            trace.kind.descr(),
                            if macro_backtrace.len() > 1 {
                                // if macro_backtrace.len() == 1 it'll be
                                // pointed at by "in this macro invocation"
                                format!(" (#{})", i + 1)
                            } else {
                                String::new()
                            },
                        ),
                    ));
                }

                // Don't add a label on the call site if the diagnostic itself
                // already points to (a part of) that call site, as the label
                // is meant for showing the relevant invocation when the actual
                // diagnostic is pointing to some part of macro definition.
                //
                // This also handles the case where an external span got replaced
                // with the call site span by `fix_multispans_in_extern_macros`.
                //
                // NB: `-Zmacro-backtrace` overrides this, for uniformity, as the
                // "in this expansion of" label above is always added in that mode,
                // and it needs an "in this macro invocation" label to match that.
                let redundant_span = trace.call_site.contains(sp);

                if !redundant_span || always_backtrace {
                    let msg: Cow<'static, _> = match trace.kind {
                        ExpnKind::Macro(MacroKind::Attr, _) => {
                            "this procedural macro expansion".into()
                        }
                        ExpnKind::Macro(MacroKind::Derive, _) => {
                            "this derive macro expansion".into()
                        }
                        ExpnKind::Macro(MacroKind::Bang, _) => "this macro invocation".into(),
                        ExpnKind::Root => "the crate root".into(),
                        ExpnKind::AstPass(kind) => kind.descr().into(),
                        ExpnKind::Desugaring(kind) => {
                            format!("this {} desugaring", kind.descr()).into()
                        }
                    };
                    new_labels.insert((
                        trace.call_site,
                        format!(
                            "in {}{}",
                            msg,
                            if macro_backtrace.len() > 1 && always_backtrace {
                                // only specify order when the macro
                                // backtrace is multiple levels deep
                                format!(" (#{})", i + 1)
                            } else {
                                String::new()
                            },
                        ),
                    ));
                }
                if !always_backtrace {
                    break;
                }
            }
        }

        for (label_span, label_text) in new_labels {
            span.push_span_label(label_span, label_text);
        }
    }

    // This does a small "fix" for multispans by looking to see if it can find any that
    // point directly at external macros. Since these are often difficult to read,
    // this will change the span to point at the use site.
    fn fix_multispans_in_extern_macros(&self, span: &mut MultiSpan, children: &mut Vec<Subdiag>) {
        debug!("fix_multispans_in_extern_macros: before: span={:?} children={:?}", span, children);
        self.fix_multispan_in_extern_macros(span);
        for child in children.iter_mut() {
            self.fix_multispan_in_extern_macros(&mut child.span);
        }
        debug!("fix_multispans_in_extern_macros: after: span={:?} children={:?}", span, children);
    }

    // This "fixes" MultiSpans that contain `Span`s pointing to locations inside of external macros.
    // Since these locations are often difficult to read,
    // we move these spans from the external macros to their corresponding use site.
    fn fix_multispan_in_extern_macros(&self, span: &mut MultiSpan) {
        let Some(source_map) = self.source_map() else { return };
        // First, find all the spans in external macros and point instead at their use site.
        let replacements: Vec<(Span, Span)> = span
            .primary_spans()
            .iter()
            .copied()
            .chain(span.span_labels().iter().map(|sp_label| sp_label.span))
            .filter_map(|sp| {
                if !sp.is_dummy() && source_map.is_imported(sp) {
                    let maybe_callsite = sp.source_callsite();
                    if sp != maybe_callsite {
                        return Some((sp, maybe_callsite));
                    }
                }
                None
            })
            .collect();

        // After we have them, make sure we replace these 'bad' def sites with their use sites.
        for (from, to) in replacements {
            span.replace(from, to);
        }
    }
}

impl Emitter for HumanEmitter {
    fn source_map(&self) -> Option<&SourceMap> {
        self.sm.as_deref()
    }

    fn emit_diagnostic(&mut self, mut diag: DiagInner, _registry: &Registry) {
        let fluent_args = to_fluent_args(diag.args.iter());

        let mut suggestions = diag.suggestions.unwrap_tag();
        self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args);

        self.fix_multispans_in_extern_macros_and_render_macro_backtrace(
            &mut diag.span,
            &mut diag.children,
            &diag.level,
            self.macro_backtrace,
        );

        self.emit_messages_default(
            &diag.level,
            &diag.messages,
            &fluent_args,
            &diag.code,
            &diag.span,
            &diag.children,
            &suggestions,
            self.track_diagnostics.then_some(&diag.emitted_at),
        );
    }

    fn should_show_explain(&self) -> bool {
        !self.short_message
    }

    fn supports_color(&self) -> bool {
        self.dst.supports_color()
    }

    fn translator(&self) -> &Translator {
        &self.translator
    }
}

/// An emitter that does nothing when emitting a non-fatal diagnostic.
/// Fatal diagnostics are forwarded to `fatal_emitter` to avoid silent
/// failures of rustc, as witnessed e.g. in issue #89358.
pub struct FatalOnlyEmitter {
    pub fatal_emitter: Box<dyn Emitter + DynSend>,
    pub fatal_note: Option<String>,
}

impl Emitter for FatalOnlyEmitter {
    fn source_map(&self) -> Option<&SourceMap> {
        None
    }

    fn emit_diagnostic(&mut self, mut diag: DiagInner, registry: &Registry) {
        if diag.level == Level::Fatal {
            if let Some(fatal_note) = &self.fatal_note {
                diag.sub(Level::Note, fatal_note.clone(), MultiSpan::new());
            }
            self.fatal_emitter.emit_diagnostic(diag, registry);
        }
    }

    fn translator(&self) -> &Translator {
        self.fatal_emitter.translator()
    }
}

pub struct SilentEmitter {
    pub translator: Translator,
}

impl Emitter for SilentEmitter {
    fn source_map(&self) -> Option<&SourceMap> {
        None
    }

    fn emit_diagnostic(&mut self, _diag: DiagInner, _registry: &Registry) {}

    fn translator(&self) -> &Translator {
        &self.translator
    }
}

/// Maximum number of suggestions to be shown
///
/// Arbitrary, but taken from trait import suggestion limit
pub const MAX_SUGGESTIONS: usize = 4;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ColorConfig {
    Auto,
    Always,
    Never,
}

impl ColorConfig {
    pub fn to_color_choice(self) -> ColorChoice {
        match self {
            ColorConfig::Always => {
                if io::stderr().is_terminal() {
                    ColorChoice::Always
                } else {
                    ColorChoice::AlwaysAnsi
                }
            }
            ColorConfig::Never => ColorChoice::Never,
            ColorConfig::Auto if io::stderr().is_terminal() => ColorChoice::Auto,
            ColorConfig::Auto => ColorChoice::Never,
        }
    }
}

#[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 {
    #[setters(skip)]
    dst: IntoDynSyncSend<Destination>,
    sm: Option<Arc<SourceMap>>,
    #[setters(skip)]
    translator: Translator,
    short_message: bool,
    ui_testing: bool,
    ignored_directories_in_source_blocks: Vec<String>,
    diagnostic_width: Option<usize>,

    macro_backtrace: bool,
    track_diagnostics: bool,
    terminal_url: TerminalUrl,
    theme: OutputTheme,
}

#[derive(Debug)]
pub(crate) struct FileWithAnnotatedLines {
    pub(crate) file: Arc<SourceFile>,
    pub(crate) lines: Vec<Line>,
    multiline_depth: usize,
}

impl HumanEmitter {
    pub fn new(dst: Destination, translator: Translator) -> HumanEmitter {
        HumanEmitter {
            dst: IntoDynSyncSend(dst),
            sm: None,
            translator,
            short_message: false,
            ui_testing: false,
            ignored_directories_in_source_blocks: Vec::new(),
            diagnostic_width: None,
            macro_backtrace: false,
            track_diagnostics: false,
            terminal_url: TerminalUrl::No,
            theme: OutputTheme::Ascii,
        }
    }

    fn maybe_anonymized(&self, line_num: usize) -> Cow<'static, str> {
        if self.ui_testing {
            Cow::Borrowed(ANONYMIZED_LINE_NUM)
        } else {
            Cow::Owned(line_num.to_string())
        }
    }

    fn draw_line(
        &self,
        buffer: &mut StyledBuffer,
        source_string: &str,
        line_index: usize,
        line_offset: usize,
        width_offset: usize,
        code_offset: usize,
        margin: Margin,
    ) -> usize {
        let line_len = source_string.len();
        // 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 code: String = source_string
            .chars()
            .enumerate()
            .skip_while(|(i, _)| *i < left)
            .take_while(|(i, _)| *i < right)
            .map(|(_, c)| c)
            .collect();
        let code = normalize_whitespace(&code);
        let was_cut_right =
            source_string.chars().enumerate().skip_while(|(i, _)| *i < right).next().is_some();
        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, placeholder, Style::LineNumber);
        }
        if was_cut_right {
            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 + str_width(&code) - padding,
                placeholder,
                Style::LineNumber,
            );
        }
        buffer.puts(line_offset, 0, &self.maybe_anonymized(line_index), Style::LineNumber);

        self.draw_col_separator_no_space(buffer, line_offset, width_offset - 2);
        left
    }

    #[instrument(level = "trace", skip(self), ret)]
    fn render_source_line(
        &self,
        buffer: &mut StyledBuffer,
        file: Arc<SourceFile>,
        line: &Line,
        width_offset: usize,
        code_offset: usize,
        margin: Margin,
        close_window: bool,
    ) -> Vec<(usize, Style)> {
        // Draw:
        //
        //   LL | ... code ...
        //      |     ^^-^ span label
        //      |       |
        //      |       secondary span label
        //
        //   ^^ ^ ^^^ ^^^^ ^^^ we don't care about code too far to the right of a span, we trim it
        //   |  | |   |
        //   |  | |   actual code found in your source code and the spans we use to mark it
        //   |  | when there's too much wasted space to the left, trim it
        //   |  vertical divider between the column number and the code
        //   column number

        if line.line_index == 0 {
            return Vec::new();
        }

        let Some(source_string) = file.get_line(line.line_index - 1) else {
            return Vec::new();
        };
        trace!(?source_string);

        let line_offset = buffer.num_lines();

        // Left trim.
        // FIXME: This looks fishy. See #132860.
        let left = self.draw_line(
            buffer,
            &source_string,
            line.line_index,
            line_offset,
            width_offset,
            code_offset,
            margin,
        );

        // Special case when there's only one annotation involved, it is the start of a multiline
        // span and there's no text at the beginning of the code line. Instead of doing the whole
        // graph:
        //
        // 2 |   fn foo() {
        //   |  _^
        // 3 | |
        // 4 | | }
        //   | |_^ test
        //
        // we simplify the output to:
        //
        // 2 | / fn foo() {
        // 3 | |
        // 4 | | }
        //   | |_^ test
        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.file).all(|c| c.is_whitespace()) {
                    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;
                }
            } 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:
        //
        //      vec.push(vec.pop().unwrap());
        //      ---      ^^^               - previous borrow ends here
        //      |        |
        //      |        error occurs here
        //      previous borrow of `vec` occurs here
        //
        // But there are some weird edge cases to be aware of:
        //
        //      vec.push(vec.pop().unwrap());
        //      --------                    - previous borrow ends here
        //      ||
        //      |this makes no sense
        //      previous borrow of `vec` occurs here
        //
        // For this reason, we group the lines into "highlight lines"
        // and "annotations lines", where the highlight lines have the `^`.

        // Sort the annotations by (start, end col)
        // The labels are reversed, sort and then reversed again.
        // Consider a list of annotations (A1, A2, C1, C2, B1, B2) where
        // the letter signifies the span. Here we are only sorting by the
        // span and hence, the order of the elements with the same span will
        // not change. On reversing the ordering (|a, b| but b.cmp(a)), you get
        // (C1, C2, B1, B2, A1, A2). All the elements with the same span are
        // still ordered first to last, but all the elements with different
        // spans are ordered by their spans in last to first order. Last to
        // first order is important, because the jiggly lines and | are on
        // the left, so the rightmost span needs to be rendered first,
        // otherwise the lines would end up needing to go over a message.

        let mut annotations = line.annotations.clone();
        annotations.sort_by_key(|a| Reverse(a.start_col));

        // First, figure out where each label will be positioned.
        //
        // In the case where you have the following annotations:
        //
        //      vec.push(vec.pop().unwrap());
        //      --------                    - previous borrow ends here [C]
        //      ||
        //      |this makes no sense [B]
        //      previous borrow of `vec` occurs here [A]
        //
        // `annotations_position` will hold [(2, A), (1, B), (0, C)].
        //
        // We try, when possible, to stick the rightmost annotation at the end
        // of the highlight line:
        //
        //      vec.push(vec.pop().unwrap());
        //      ---      ---               - previous borrow ends here
        //
        // But sometimes that's not possible because one of the other
        // annotations overlaps it. For example, from the test
        // `span_overlap_label`, we have the following annotations
        // (written on distinct lines for clarity):
        //
        //      fn foo(x: u32) {
        //      --------------
        //             -
        //
        // In this case, we can't stick the rightmost-most label on
        // the highlight line, or we would get:
        //
        //      fn foo(x: u32) {
        //      -------- x_span
        //      |
        //      fn_span
        //
        // which is totally weird. Instead we want:
        //
        //      fn foo(x: u32) {
        //      --------------
        //      |      |
        //      |      x_span
        //      fn_span
        //
        // which is...less weird, at least. In fact, in general, if
        // the rightmost span overlaps with any other span, we should
        // use the "hang below" version, so we can at least make it
        // clear where the span *starts*. There's an exception for this
        // logic, when the labels do not have a message:
        //
        //      fn foo(x: u32) {
        //      --------------
        //             |
        //             x_span
        //
        // instead of:
        //
        //      fn foo(x: u32) {
        //      --------------
        //      |      |
        //      |      x_span
        //      <EMPTY LINE>
        //
        let mut overlap = vec![false; annotations.len()];
        let mut annotations_position = vec![];
        let mut line_len: usize = 0;
        let mut p = 0;
        for (i, annotation) in annotations.iter().enumerate() {
            for (j, next) in annotations.iter().enumerate() {
                if overlaps(next, annotation, 0) && j > i {
                    overlap[i] = true;
                    overlap[j] = true;
                }
                if overlaps(next, annotation, 0)  // This label overlaps with another one and both
                    && annotation.has_label()     // take space (they have text and are not
                    && j > i                      // multiline lines).
                    && p == 0
                // We're currently on the first line, move the label one line down
                {
                    // If we're overlapping with an un-labelled annotation with the same span
                    // we can just merge them in the output
                    if next.start_col == annotation.start_col
                        && next.end_col == annotation.end_col
                        && !next.has_label()
                    {
                        continue;
                    }

                    // This annotation needs a new line in the output.
                    p += 1;
                    break;
                }
            }
            annotations_position.push((p, annotation));
            for (j, next) in annotations.iter().enumerate() {
                if j > i {
                    let l = next.label.as_ref().map_or(0, |label| label.len() + 2);
                    if (overlaps(next, annotation, l) // Do not allow two labels to be in the same
                                                     // line if they overlap including padding, to
                                                     // avoid situations like:
                                                     //
                                                     //      fn foo(x: u32) {
                                                     //      -------^------
                                                     //      |      |
                                                     //      fn_spanx_span
                                                     //
                        && annotation.has_label()    // Both labels must have some text, otherwise
                        && next.has_label())         // they are not overlapping.
                                                     // Do not add a new line if this annotation
                                                     // or the next are vertical line placeholders.
                        || (annotation.takes_space() // If either this or the next annotation is
                            && next.has_label())     // multiline start/end, move it to a new line
                        || (annotation.has_label()   // so as not to overlap the horizontal lines.
                            && next.takes_space())
                        || (annotation.takes_space() && next.takes_space())
                        || (overlaps(next, annotation, l)
                            && next.end_col <= annotation.end_col
                            && next.has_label()
                            && p == 0)
                    // Avoid #42595.
                    {
                        // This annotation needs a new line in the output.
                        p += 1;
                        break;
                    }
                }
            }
            line_len = max(line_len, p);
        }

        if line_len != 0 {
            line_len += 1;
        }

        // If there are no annotations or the only annotations on this line are
        // MultilineLine, then there's only code being shown, stop processing.
        if line.annotations.iter().all(|a| a.is_line()) {
            return vec![];
        }

        if annotations_position
            .iter()
            .all(|(_, ann)| matches!(ann.annotation_type, AnnotationType::MultilineStart(_)))
            && let Some(max_pos) = annotations_position.iter().map(|(pos, _)| *pos).max()
        {
            // Special case the following, so that we minimize overlapping multiline spans.
            //
            // 3 │       X0 Y0 Z0
            //   │ ┏━━━━━┛  │  │     < We are writing these lines
            //   │ ┃┌───────┘  │     < by reverting the "depth" of
            //   │ ┃│┌─────────┘     < their multiline spans.
            // 4 │ ┃││   X1 Y1 Z1
            // 5 │ ┃││   X2 Y2 Z2
            //   │ ┃│└────╿──│──┘ `Z` label
            //   │ ┃└─────│──┤
            //   │ ┗━━━━━━┥  `Y` is a good letter too
            //   ╰╴       `X` is a good letter
            for (pos, _) in &mut annotations_position {
                *pos = max_pos - *pos;
            }
            // We know then that we don't need an additional line for the span label, saving us
            // one line of vertical space.
            line_len = line_len.saturating_sub(1);
        }

        // Write the column separator.
        //
        // After this we will have:
        //
        // 2 |   fn foo() {
        //   |
        //   |
        //   |
        // 3 |
        // 4 |   }
        //   |
        for pos in 0..=line_len {
            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
        // (only the first and last lines need this).
        //
        // After this we will have:
        //
        // 2 |   fn foo() {
        //   |  __________
        //   |
        //   |
        // 3 |
        // 4 |   }
        //   |  _
        for &(pos, annotation) in &annotations_position {
            let underline = self.underline(annotation.is_primary);
            let pos = pos + 1;
            match annotation.annotation_type {
                AnnotationType::MultilineStart(depth) | AnnotationType::MultilineEnd(depth) => {
                    let pre: usize = source_string
                        .chars()
                        .take(annotation.start_col.file)
                        .skip(left)
                        .map(|c| char_width(c))
                        .sum();
                    self.draw_range(
                        buffer,
                        underline.multiline_horizontal,
                        line_offset + pos,
                        width_offset + depth,
                        code_offset + pre,
                        underline.style,
                    );
                }
                _ => {}
            }
        }

        // Write the vertical lines for labels that are on a different line as the underline.
        //
        // After this we will have:
        //
        // 2 |   fn foo() {
        //   |  __________
        //   | |    |
        //   | |
        // 3 | |
        // 4 | | }
        //   | |_
        for &(pos, annotation) in &annotations_position {
            let underline = self.underline(annotation.is_primary);
            let pos = pos + 1;

            let code_offset = code_offset
                + source_string
                    .chars()
                    .take(annotation.start_col.file)
                    .skip(left)
                    .map(|c| char_width(c))
                    .sum::<usize>();
            if pos > 1 && (annotation.has_label() || annotation.takes_space()) {
                for p in line_offset + 1..=line_offset + pos {
                    buffer.putc(
                        p,
                        code_offset,
                        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,
                        underline.bottom_right,
                        underline.style,
                    );
                }
                if let AnnotationType::MultilineEnd(_) = annotation.annotation_type
                    && annotation.has_label()
                {
                    buffer.putc(
                        line_offset + pos,
                        code_offset,
                        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,
                            underline.multiline_vertical,
                            underline.style,
                        );
                    }
                }
                AnnotationType::MultilineEnd(depth) => {
                    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,
                    );
                }
                _ => (),
            }
        }

        // Write the labels on the annotations that actually have a label.
        //
        // After this we will have:
        //
        // 2 |   fn foo() {
        //   |  __________
        //   |      |
        //   |      something about `foo`
        // 3 |
        // 4 |   }
        //   |  _  test
        for &(pos, annotation) in &annotations_position {
            let style =
                if annotation.is_primary { Style::LabelPrimary } else { Style::LabelSecondary };
            let (pos, col) = if pos == 0 {
                let pre: usize = source_string
                    .chars()
                    .take(annotation.end_col.file)
                    .skip(left)
                    .map(|c| char_width(c))
                    .sum();
                if annotation.end_col.file == 0 {
                    (pos + 1, (pre + 2))
                } else {
                    let pad = if annotation.end_col.file - annotation.start_col.file == 0 {
                        2
                    } else {
                        1
                    };
                    (pos + 1, (pre + pad))
                }
            } else {
                let pre: usize = source_string
                    .chars()
                    .take(annotation.start_col.file)
                    .skip(left)
                    .map(|c| char_width(c))
                    .sum();
                (pos + 2, pre)
            };
            if let Some(ref label) = annotation.label {
                buffer.puts(line_offset + pos, code_offset + col, label, style);
            }
        }

        // Sort from biggest span to smallest span so that smaller spans are
        // represented in the output:
        //
        // x | fn foo()
        //   | ^^^---^^
        //   | |  |
        //   | |  something about `foo`
        //   | something about `fn foo()`
        annotations_position.sort_by_key(|(_, ann)| {
            // Decreasing order. When annotations share the same length, prefer `Primary`.
            (Reverse(ann.len()), ann.is_primary)
        });

        // Write the underlines.
        //
        // After this we will have:
        //
        // 2 |   fn foo() {
        //   |  ____-_____^
        //   |      |
        //   |      something about `foo`
        // 3 |
        // 4 |   }
        //   |  _^  test
        for &(pos, annotation) in &annotations_position {
            let uline = self.underline(annotation.is_primary);
            let width = annotation.end_col.file - annotation.start_col.file;
            let previous: String =
                source_string.chars().take(annotation.start_col.file).skip(left).collect();
            let underlined: String =
                source_string.chars().skip(annotation.start_col.file).take(width).collect();
            debug!(?previous, ?underlined);
            let code_offset = code_offset
                + source_string
                    .chars()
                    .take(annotation.start_col.file)
                    .skip(left)
                    .map(|c| char_width(c))
                    .sum::<usize>();
            let ann_width: usize = source_string
                .chars()
                .skip(annotation.start_col.file)
                .take(width)
                .map(|c| char_width(c))
                .sum();
            let ann_width = if ann_width == 0
                && matches!(annotation.annotation_type, AnnotationType::Singleline)
            {
                1
            } else {
                ann_width
            };
            for p in 0..ann_width {
                // The default span label underline.
                buffer.putc(line_offset + 1, code_offset + p, 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,
                    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,
                    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, uline.label_start, uline.style);
            }
        }

        // We look for individual *long* spans, and we trim the *middle*, so that we render
        // LL | ...= [0, 0, 0, ..., 0, 0];
        //    |      ^^^^^^^^^^...^^^^^^^ expected `&[u8]`, found `[{integer}; 1680]`
        for (i, (_pos, annotation)) in annotations_position.iter().enumerate() {
            // Skip cases where multiple spans overlap each other.
            if overlap[i] {
                continue;
            };
            let AnnotationType::Singleline = annotation.annotation_type else { continue };
            let width = annotation.end_col.display - annotation.start_col.display;
            if width > margin.column_width * 2 && width > 10 {
                // If the terminal is *too* small, we keep at least a tiny bit of the span for
                // display.
                let pad = max(margin.column_width / 3, 5);
                // Code line
                buffer.replace(
                    line_offset,
                    annotation.start_col.file + pad,
                    annotation.end_col.file - pad,
                    self.margin(),
                );
                // Underline line
                buffer.replace(
                    line_offset + 1,
                    annotation.start_col.file + pad,
                    annotation.end_col.file - pad,
                    self.margin(),
                );
            }
        }
        annotations_position
            .iter()
            .filter_map(|&(_, annotation)| match annotation.annotation_type {
                AnnotationType::MultilineStart(p) | AnnotationType::MultilineEnd(p) => {
                    let style = if annotation.is_primary {
                        Style::LabelPrimary
                    } else {
                        Style::LabelSecondary
                    };
                    Some((p, style))
                }
                _ => None,
            })
            .collect::<Vec<_>>()
    }

    fn get_multispan_max_line_num(&mut self, msp: &MultiSpan) -> usize {
        let Some(ref sm) = self.sm else {
            return 0;
        };

        let will_be_emitted = |span: Span| {
            !span.is_dummy() && {
                let file = sm.lookup_source_file(span.hi());
                should_show_source_code(&self.ignored_directories_in_source_blocks, sm, &file)
            }
        };

        let mut max = 0;
        for primary_span in msp.primary_spans() {
            if will_be_emitted(*primary_span) {
                let hi = sm.lookup_char_pos(primary_span.hi());
                max = (hi.line).max(max);
            }
        }
        if !self.short_message {
            for span_label in msp.span_labels() {
                if will_be_emitted(span_label.span) {
                    let hi = sm.lookup_char_pos(span_label.span.hi());
                    max = (hi.line).max(max);
                }
            }
        }

        max
    }

    fn get_max_line_num(&mut self, span: &MultiSpan, children: &[Subdiag]) -> usize {
        let primary = self.get_multispan_max_line_num(span);
        children
            .iter()
            .map(|sub| self.get_multispan_max_line_num(&sub.span))
            .max()
            .unwrap_or(0)
            .max(primary)
    }

    /// Adds a left margin to every line but the first, given a padding length and the label being
    /// displayed, keeping the provided highlighting.
    fn msgs_to_buffer(
        &self,
        buffer: &mut StyledBuffer,
        msgs: &[(DiagMessage, Style)],
        args: &FluentArgs<'_>,
        padding: usize,
        label: &str,
        override_style: Option<Style>,
    ) -> usize {
        // The extra 5 ` ` is padding that's always needed to align to the `note: `:
        //
        //   error: message
        //     --> file.rs:13:20
        //      |
        //   13 |     <CODE>
        //      |      ^^^^
        //      |
        //      = note: multiline
        //              message
        //   ++^^^----xx
        //    |  |   | |
        //    |  |   | magic `2`
        //    |  |   length of label
        //    |  magic `3`
        //    `max_line_num_len`
        let padding = " ".repeat(padding + label.len() + 5);

        /// Returns `override` if it is present and `style` is `NoStyle` or `style` otherwise
        fn style_or_override(style: Style, override_: Option<Style>) -> Style {
            match (style, override_) {
                (Style::NoStyle, Some(override_)) => override_,
                _ => style,
            }
        }

        let mut line_number = 0;

        // Provided the following diagnostic message:
        //
        //     let msgs = vec![
        //       ("
        //       ("highlighted multiline\nstring to\nsee how it ", Style::NoStyle),
        //       ("looks", Style::Highlight),
        //       ("with\nvery ", Style::NoStyle),
        //       ("weird", Style::Highlight),
        //       (" formats\n", Style::NoStyle),
        //       ("see?", Style::Highlight),
        //     ];
        //
        // the expected output on a note is (* surround the highlighted text)
        //
        //        = note: highlighted multiline
        //                string to
        //                see how it *looks* with
        //                very *weird* formats
        //                see?
        for (text, style) in msgs.iter() {
            let text = self.translator.translate_message(text, args).map_err(Report::new).unwrap();
            let text = &normalize_whitespace(&text);
            let lines = text.split('\n').collect::<Vec<_>>();
            if lines.len() > 1 {
                for (i, line) in lines.iter().enumerate() {
                    if i != 0 {
                        line_number += 1;
                        buffer.append(line_number, &padding, Style::NoStyle);
                    }
                    buffer.append(line_number, line, style_or_override(*style, override_style));
                }
            } else {
                buffer.append(line_number, text, style_or_override(*style, override_style));
            }
        }
        line_number
    }

    #[instrument(level = "trace", skip(self, args), ret)]
    fn emit_messages_default_inner(
        &mut self,
        msp: &MultiSpan,
        msgs: &[(DiagMessage, Style)],
        args: &FluentArgs<'_>,
        code: &Option<ErrCode>,
        level: &Level,
        max_line_num_len: usize,
        is_secondary: bool,
        emitted_at: Option<&DiagLocation>,
        is_cont: bool,
    ) -> io::Result<()> {
        let mut buffer = StyledBuffer::new();

        if !msp.has_primary_spans() && !msp.has_span_labels() && is_secondary && !self.short_message
        {
            // This is a secondary message with no span info
            for _ in 0..max_line_num_len {
                buffer.prepend(0, " ", Style::NoStyle);
            }
            self.draw_note_separator(&mut buffer, 0, max_line_num_len + 1, is_cont);
            if *level != Level::FailureNote {
                buffer.append(0, level.to_str(), Style::MainHeaderMsg);
                buffer.append(0, ": ", Style::NoStyle);
            }
            let printed_lines =
                self.msgs_to_buffer(&mut buffer, msgs, args, max_line_num_len, "note", None);
            if is_cont && matches!(self.theme, OutputTheme::Unicode) {
                // There's another note after this one, associated to the subwindow above.
                // We write additional vertical lines to join them:
                //   ╭▸ test.rs:3:3
                //   │
                // 3 │   code
                //   │   ━━━━
                //   │
                //   ├ note: foo
                //   │       bar
                //   ╰ note: foo
                //           bar
                for i in 1..=printed_lines {
                    self.draw_col_separator_no_space(&mut buffer, i, max_line_num_len + 1);
                }
            }
        } else {
            let mut label_width = 0;
            // The failure note level itself does not provide any useful diagnostic information
            if *level != Level::FailureNote {
                buffer.append(0, level.to_str(), Style::Level(*level));
                label_width += level.to_str().len();
            }
            if let Some(code) = code {
                buffer.append(0, "[", Style::Level(*level));
                let code = if let TerminalUrl::Yes = self.terminal_url {
                    let path = "https://doc.rust-lang.org/error_codes";
                    format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07")
                } else {
                    code.to_string()
                };
                buffer.append(0, &code, Style::Level(*level));
                buffer.append(0, "]", Style::Level(*level));
                label_width += 2 + code.len();
            }
            let header_style = if is_secondary {
                Style::HeaderMsg
            } else if self.short_message {
                // For short messages avoid bolding the message, as it doesn't look great (#63835).
                Style::NoStyle
            } else {
                Style::MainHeaderMsg
            };
            if *level != Level::FailureNote {
                buffer.append(0, ": ", header_style);
                label_width += 2;
            }
            let mut line = 0;
            for (text, style) in msgs.iter() {
                let text =
                    self.translator.translate_message(text, args).map_err(Report::new).unwrap();
                // Account for newlines to align output to its label.
                for text in normalize_whitespace(&text).lines() {
                    buffer.append(
                        line,
                        &format!(
                            "{}{}",
                            if line == 0 { String::new() } else { " ".repeat(label_width) },
                            text
                        ),
                        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.translator.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);
                }
            }
        }
        let mut annotated_files = FileWithAnnotatedLines::collect_annotations(self, args, msp);
        trace!("{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);
        };
        let primary_lo = sm.lookup_char_pos(primary_span.lo());
        if let Ok(pos) =
            annotated_files.binary_search_by(|x| x.file.name.cmp(&primary_lo.file.name))
        {
            annotated_files.swap(0, pos);
        }

        // Print out the annotate source lines that correspond with the error
        for annotated_file in annotated_files {
            // we can't annotate anything if the source is unavailable.
            if !should_show_source_code(
                &self.ignored_directories_in_source_blocks,
                sm,
                &annotated_file.file,
            ) {
                if !self.short_message {
                    // We'll just print an unannotated message.
                    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();

                        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.file + 1,
                                ),
                                Style::LineAndColumn,
                            );
                            if annotation_id == 0 {
                                buffer.prepend(line_idx, self.file_start(), Style::LineNumber);
                            } else {
                                buffer.prepend(
                                    line_idx,
                                    self.secondary_file_start(),
                                    Style::LineNumber,
                                );
                            }
                            for _ in 0..max_line_num_len {
                                buffer.prepend(line_idx, " ", Style::NoStyle);
                            }
                            line_idx += 1;
                        }
                        for (label, is_primary) in labels.into_iter() {
                            let style = if is_primary {
                                Style::LabelPrimary
                            } else {
                                Style::LabelSecondary
                            };
                            let pipe = self.col_separator();
                            buffer.prepend(line_idx, &format!(" {pipe}"), Style::LineNumber);
                            for _ in 0..max_line_num_len {
                                buffer.prepend(line_idx, " ", Style::NoStyle);
                            }
                            line_idx += 1;
                            let chr = self.note_separator();
                            buffer.append(line_idx, &format!(" {chr} note: "), style);
                            for _ in 0..max_line_num_len {
                                buffer.prepend(line_idx, " ", Style::NoStyle);
                            }
                            buffer.append(line_idx, label, style);
                            line_idx += 1;
                        }
                    }
                }
                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;
            if is_primary {
                let loc = primary_lo.clone();
                if !self.short_message {
                    // remember where we are in the output buffer for easy reference
                    let buffer_msg_line_offset = buffer.num_lines();

                    buffer.prepend(buffer_msg_line_offset, self.file_start(), Style::LineNumber);
                    buffer.append(
                        buffer_msg_line_offset,
                        &format!(
                            "{}:{}:{}",
                            sm.filename_for_diagnostics(&loc.file.name),
                            sm.doctest_offset_line(&loc.file.name, loc.line),
                            loc.col.0 + 1,
                        ),
                        Style::LineAndColumn,
                    );
                    for _ in 0..max_line_num_len {
                        buffer.prepend(buffer_msg_line_offset, " ", Style::NoStyle);
                    }
                } else {
                    buffer.prepend(
                        0,
                        &format!(
                            "{}:{}:{}: ",
                            sm.filename_for_diagnostics(&loc.file.name),
                            sm.doctest_offset_line(&loc.file.name, loc.line),
                            loc.col.0 + 1,
                        ),
                        Style::LineAndColumn,
                    );
                }
            } else if !self.short_message {
                // remember where we are in the output buffer for easy reference
                let buffer_msg_line_offset = buffer.num_lines();

                // Add spacing line, as shown:
                //   --> $DIR/file:54:15
                //    |
                // LL |         code
                //    |         ^^^^
                //    | (<- It prints *this* line)
                //   ::: $DIR/other_file.rs:15:5
                //    |
                // LL |     code
                //    |     ----
                self.draw_col_separator_no_space(
                    &mut buffer,
                    buffer_msg_line_offset,
                    max_line_num_len + 1,
                );

                // Then, the secondary file indicator
                buffer.prepend(
                    buffer_msg_line_offset + 1,
                    self.secondary_file_start(),
                    Style::LineNumber,
                );
                let loc = if let Some(first_line) = annotated_file.lines.first() {
                    let col = if let Some(first_annotation) = first_line.annotations.first() {
                        format!(":{}", first_annotation.start_col.file + 1)
                    } else {
                        String::new()
                    };
                    format!(
                        "{}:{}{}",
                        sm.filename_for_diagnostics(&annotated_file.file.name),
                        sm.doctest_offset_line(&annotated_file.file.name, first_line.line_index),
                        col
                    )
                } else {
                    format!("{}", sm.filename_for_diagnostics(&annotated_file.file.name))
                };
                buffer.append(buffer_msg_line_offset + 1, &loc, Style::LineAndColumn);
                for _ in 0..max_line_num_len {
                    buffer.prepend(buffer_msg_line_offset + 1, " ", Style::NoStyle);
                }
            }

            if !self.short_message {
                // Put in the spacer between the location and annotated source
                let buffer_msg_line_offset = buffer.num_lines();
                self.draw_col_separator_no_space(
                    &mut buffer,
                    buffer_msg_line_offset,
                    max_line_num_len + 1,
                );

                // Contains the vertical lines' positions for active multiline annotations
                let mut multilines = FxIndexMap::default();

                // Get the left-side margin to remove it
                let mut whitespace_margin = usize::MAX;
                for line_idx in 0..annotated_file.lines.len() {
                    let file = Arc::clone(&annotated_file.file);
                    let line = &annotated_file.lines[line_idx];
                    if let Some(source_string) =
                        line.line_index.checked_sub(1).and_then(|l| file.get_line(l))
                    {
                        // Whitespace can only be removed (aka considered leading)
                        // if the lexer considers it whitespace.
                        // non-rustc_lexer::is_whitespace() chars are reported as an
                        // error (ex. no-break-spaces \u{a0}), and thus can't be considered
                        // for removal during error reporting.
                        // FIXME: doesn't account for '\t' properly.
                        let leading_whitespace = source_string
                            .chars()
                            .take_while(|c| rustc_lexer::is_whitespace(*c))
                            .count();
                        if source_string.chars().any(|c| !rustc_lexer::is_whitespace(c)) {
                            whitespace_margin = min(whitespace_margin, leading_whitespace);
                        }
                    }
                }
                if whitespace_margin == usize::MAX {
                    whitespace_margin = 0;
                }

                // Left-most column any visible span points at.
                let mut span_left_margin = usize::MAX;
                for line in &annotated_file.lines {
                    for ann in &line.annotations {
                        span_left_margin = min(span_left_margin, ann.start_col.file);
                        span_left_margin = min(span_left_margin, ann.end_col.file);
                    }
                }
                if span_left_margin == usize::MAX {
                    span_left_margin = 0;
                }

                // Right-most column any visible span points at.
                let mut span_right_margin = 0;
                let mut label_right_margin = 0;
                let mut max_line_len = 0;
                for line in &annotated_file.lines {
                    max_line_len = max(
                        max_line_len,
                        line.line_index
                            .checked_sub(1)
                            .and_then(|l| annotated_file.file.get_line(l))
                            .map_or(0, |s| s.len()),
                    );
                    for ann in &line.annotations {
                        span_right_margin = max(span_right_margin, ann.start_col.file);
                        span_right_margin = max(span_right_margin, ann.end_col.file);
                        // FIXME: account for labels not in the same line
                        let label_right = ann.label.as_ref().map_or(0, |l| l.len() + 1);
                        label_right_margin =
                            max(label_right_margin, ann.end_col.file + label_right);
                    }
                }

                let width_offset = 3 + max_line_num_len;
                let code_offset = if annotated_file.multiline_depth == 0 {
                    width_offset
                } else {
                    width_offset + annotated_file.multiline_depth + 1
                };

                let column_width = self.column_width(code_offset);

                let margin = Margin::new(
                    whitespace_margin,
                    span_left_margin,
                    span_right_margin,
                    label_right_margin,
                    column_width,
                    max_line_len,
                );

                // Next, output the annotate source for this file
                for line_idx in 0..annotated_file.lines.len() {
                    let previous_buffer_line = buffer.num_lines();

                    let depths = self.render_source_line(
                        &mut buffer,
                        Arc::clone(&annotated_file.file),
                        &annotated_file.lines[line_idx],
                        width_offset,
                        code_offset,
                        margin,
                        !is_cont && line_idx + 1 == annotated_file.lines.len(),
                    );

                    let mut to_add = FxHashMap::default();

                    for (depth, style) in depths {
                        // FIXME(#120456) - is `swap_remove` correct?
                        if multilines.swap_remove(&depth).is_none() {
                            to_add.insert(depth, style);
                        }
                    }

                    // Set the multiline annotation vertical lines to the left of
                    // the code in this line.
                    for (depth, style) in &multilines {
                        for line in previous_buffer_line..buffer.num_lines() {
                            self.draw_multiline_line(
                                &mut buffer,
                                line,
                                width_offset,
                                *depth,
                                *style,
                            );
                        }
                    }
                    // check to see if we need to print out or elide lines that come between
                    // this annotated line and the next one.
                    if line_idx < (annotated_file.lines.len() - 1) {
                        let line_idx_delta = annotated_file.lines[line_idx + 1].line_index
                            - annotated_file.lines[line_idx].line_index;
                        if line_idx_delta > 2 {
                            let last_buffer_line_num = buffer.num_lines();
                            self.draw_line_separator(
                                &mut buffer,
                                last_buffer_line_num,
                                width_offset,
                            );

                            // Set the multiline annotation vertical lines on `...` bridging line.
                            for (depth, style) in &multilines {
                                self.draw_multiline_line(
                                    &mut buffer,
                                    last_buffer_line_num,
                                    width_offset,
                                    *depth,
                                    *style,
                                );
                            }
                            if let Some(line) = annotated_file.lines.get(line_idx) {
                                for ann in &line.annotations {
                                    if let AnnotationType::MultilineStart(pos) = ann.annotation_type
                                    {
                                        // In the case where we have elided the entire start of the
                                        // multispan because those lines were empty, we still need
                                        // to draw the `|`s across the `...`.
                                        self.draw_multiline_line(
                                            &mut buffer,
                                            last_buffer_line_num,
                                            width_offset,
                                            pos,
                                            if ann.is_primary {
                                                Style::UnderlinePrimary
                                            } else {
                                                Style::UnderlineSecondary
                                            },
                                        );
                                    }
                                }
                            }
                        } else if line_idx_delta == 2 {
                            let unannotated_line = annotated_file
                                .file
                                .get_line(annotated_file.lines[line_idx].line_index)
                                .unwrap_or_else(|| Cow::from(""));

                            let last_buffer_line_num = buffer.num_lines();

                            self.draw_line(
                                &mut buffer,
                                &normalize_whitespace(&unannotated_line),
                                annotated_file.lines[line_idx + 1].line_index - 1,
                                last_buffer_line_num,
                                width_offset,
                                code_offset,
                                margin,
                            );

                            for (depth, style) in &multilines {
                                self.draw_multiline_line(
                                    &mut buffer,
                                    last_buffer_line_num,
                                    width_offset,
                                    *depth,
                                    *style,
                                );
                            }
                            if let Some(line) = annotated_file.lines.get(line_idx) {
                                for ann in &line.annotations {
                                    if let AnnotationType::MultilineStart(pos) = ann.annotation_type
                                    {
                                        self.draw_multiline_line(
                                            &mut buffer,
                                            last_buffer_line_num,
                                            width_offset,
                                            pos,
                                            if ann.is_primary {
                                                Style::UnderlinePrimary
                                            } else {
                                                Style::UnderlineSecondary
                                            },
                                        );
                                    }
                                }
                            }
                        }
                    }

                    multilines.extend(&to_add);
                }
            }
            trace!("buffer: {:#?}", buffer.render());
        }

        if let Some(tracked) = emitted_at {
            let track = format!("-Ztrack-diagnostics: created at {tracked}");
            let len = buffer.num_lines();
            buffer.append(len, &track, Style::NoStyle);
        }

        // final step: take our styled buffer, render it, then output it
        emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;

        Ok(())
    }

    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) {
            DEFAULT_COLUMN_WIDTH
        } else {
            termize::dimensions()
                .map(|(w, _)| w.saturating_sub(code_offset))
                .unwrap_or(DEFAULT_COLUMN_WIDTH)
        }
    }

    fn emit_suggestion_default(
        &mut self,
        span: &MultiSpan,
        suggestion: &CodeSuggestion,
        args: &FluentArgs<'_>,
        level: &Level,
        max_line_num_len: usize,
    ) -> io::Result<()> {
        let Some(ref sm) = self.sm else {
            return Ok(());
        };

        // Render the replacements for each suggestion
        let suggestions = suggestion.splice_lines(sm);
        debug!(?suggestions);

        if suggestions.is_empty() {
            // Here we check if there are suggestions that have actual code changes. We sometimes
            // suggest the same code that is already there, instead of changing how we produce the
            // suggestions and filtering there, we just don't emit the suggestion.
            // Suggestions coming from macros can also have malformed spans. This is a heavy handed
            // approach to avoid ICEs by ignoring the suggestion outright.
            return Ok(());
        }

        let mut buffer = StyledBuffer::new();

        // Render the suggestion message
        buffer.append(0, level.to_str(), Style::Level(*level));
        buffer.append(0, ": ", Style::HeaderMsg);

        let mut msg = vec![(suggestion.msg.to_owned(), Style::NoStyle)];
        if suggestions
            .iter()
            .take(MAX_SUGGESTIONS)
            .any(|(_, _, _, only_capitalization)| *only_capitalization)
        {
            msg.push((" (notice the capitalization difference)".into(), Style::NoStyle));
        }
        self.msgs_to_buffer(
            &mut buffer,
            &msg,
            args,
            max_line_num_len,
            "suggestion",
            Some(Style::HeaderMsg),
        );

        let other_suggestions = suggestions.len().saturating_sub(MAX_SUGGESTIONS);

        let mut row_num = 2;
        for (i, (complete, parts, highlights, _)) in
            suggestions.into_iter().enumerate().take(MAX_SUGGESTIONS)
        {
            debug!(?complete, ?parts, ?highlights);

            let has_deletion =
                parts.iter().any(|p| p.is_deletion(sm) || p.is_destructive_replacement(sm));
            let is_multiline = complete.lines().count() > 1;

            if i == 0 {
                self.draw_col_separator_start(&mut buffer, row_num - 1, max_line_num_len + 1);
            } else {
                buffer.puts(
                    row_num - 1,
                    max_line_num_len + 1,
                    self.multi_suggestion_separator(),
                    Style::LineNumber,
                );
            }
            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
                // 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());
                if loc.file.name != sm.span_to_filename(span) && loc.file.name.is_real() {
                    // --> file.rs:line:col
                    //  |
                    let arrow = self.file_start();
                    buffer.puts(row_num - 1, 0, arrow, Style::LineNumber);
                    let filename = sm.filename_for_diagnostics(&loc.file.name);
                    let offset = sm.doctest_offset_line(&loc.file.name, loc.line);
                    let message = format!("{}:{}:{}", filename, offset, loc.col.0 + 1);
                    if row_num == 2 {
                        let col = usize::max(max_line_num_len + 1, arrow.len());
                        buffer.puts(1, col, &message, Style::LineAndColumn);
                    } else {
                        buffer.append(row_num - 1, &message, Style::LineAndColumn);
                    }
                    for _ in 0..max_line_num_len {
                        buffer.prepend(row_num - 1, " ", Style::NoStyle);
                    }
                    self.draw_col_separator_no_space(&mut buffer, row_num, max_line_num_len + 1);
                    row_num += 1;
                }
            }
            let show_code_change = if has_deletion && !is_multiline {
                DisplaySuggestion::Diff
            } else if let [part] = &parts[..]
                && part.snippet.ends_with('\n')
                && part.snippet.trim() == complete.trim()
            {
                // We are adding a line(s) of code before code that was already there.
                DisplaySuggestion::Add
            } else if (parts.len() != 1 || parts[0].snippet.trim() != complete.trim())
                && !is_multiline
            {
                DisplaySuggestion::Underline
            } else {
                DisplaySuggestion::None
            };

            if let DisplaySuggestion::Diff = show_code_change {
                row_num += 1;
            }

            let file_lines = sm
                .span_to_lines(parts[0].span)
                .expect("span_to_lines failed when emitting suggestion");

            assert!(!file_lines.lines.is_empty() || parts[0].span.is_dummy());

            let line_start = sm.lookup_char_pos(parts[0].span.lo()).line;
            let mut lines = complete.lines();
            if lines.clone().next().is_none() {
                // Account for a suggestion to completely remove a line(s) with whitespace (#94192).
                let line_end = sm.lookup_char_pos(parts[0].span.hi()).line;
                for line in line_start..=line_end {
                    buffer.puts(
                        row_num - 1 + line - line_start,
                        0,
                        &self.maybe_anonymized(line),
                        Style::LineNumber,
                    );
                    buffer.puts(
                        row_num - 1 + line - line_start,
                        max_line_num_len + 1,
                        "- ",
                        Style::Removal,
                    );
                    buffer.puts(
                        row_num - 1 + line - line_start,
                        max_line_num_len + 3,
                        &normalize_whitespace(&file_lines.file.get_line(line - 1).unwrap()),
                        Style::Removal,
                    );
                }
                row_num += line_end - line_start;
            }
            let mut unhighlighted_lines = Vec::new();
            let mut last_pos = 0;
            let mut is_item_attribute = false;
            for (line_pos, (line, highlight_parts)) in lines.by_ref().zip(highlights).enumerate() {
                last_pos = line_pos;
                debug!(%line_pos, %line, ?highlight_parts);

                // Remember lines that are not highlighted to hide them if needed
                if highlight_parts.is_empty() {
                    unhighlighted_lines.push((line_pos, line));
                    continue;
                }
                if highlight_parts.len() == 1
                    && line.trim().starts_with("#[")
                    && line.trim().ends_with(']')
                {
                    is_item_attribute = true;
                }

                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)| {
                        self.draw_code_line(
                            &mut buffer,
                            &mut row_num,
                            &[],
                            p + line_start,
                            l,
                            show_code_change,
                            max_line_num_len,
                            &file_lines,
                            is_multiline,
                        )
                    }),
                    // Print first unhighlighted line, "..." and last unhighlighted line, like so:
                    //
                    // LL | this line was highlighted
                    // LL | this line is just for context
                    // ...
                    // LL | this line is just for context
                    // LL | this line was highlighted
                    _ => {
                        let last_line = unhighlighted_lines.pop();
                        let first_line = unhighlighted_lines.drain(..).next();

                        if let Some((p, l)) = first_line {
                            self.draw_code_line(
                                &mut buffer,
                                &mut row_num,
                                &[],
                                p + line_start,
                                l,
                                show_code_change,
                                max_line_num_len,
                                &file_lines,
                                is_multiline,
                            )
                        }

                        let placeholder = self.margin();
                        let padding = str_width(placeholder);
                        buffer.puts(
                            row_num,
                            max_line_num_len.saturating_sub(padding),
                            placeholder,
                            Style::LineNumber,
                        );
                        row_num += 1;

                        if let Some((p, l)) = last_line {
                            self.draw_code_line(
                                &mut buffer,
                                &mut row_num,
                                &[],
                                p + line_start,
                                l,
                                show_code_change,
                                max_line_num_len,
                                &file_lines,
                                is_multiline,
                            )
                        }
                    }
                }

                self.draw_code_line(
                    &mut buffer,
                    &mut row_num,
                    &highlight_parts,
                    line_pos + line_start,
                    line,
                    show_code_change,
                    max_line_num_len,
                    &file_lines,
                    is_multiline,
                )
            }
            if let DisplaySuggestion::Add = show_code_change
                && is_item_attribute
            {
                // The suggestion adds an entire line of code, ending on a newline, so we'll also
                // print the *following* line, to provide context of what we're advising people to
                // do. Otherwise you would only see contextless code that can be confused for
                // already existing code, despite the colors and UI elements.
                // We special case `#[derive(_)]\n` and other attribute suggestions, because those
                // are the ones where context is most useful.
                let file_lines = sm
                    .span_to_lines(parts[0].span.shrink_to_hi())
                    .expect("span_to_lines failed when emitting suggestion");
                let line_num = sm.lookup_char_pos(parts[0].span.lo()).line;
                if let Some(line) = file_lines.file.get_line(line_num - 1) {
                    let line = normalize_whitespace(&line);
                    self.draw_code_line(
                        &mut buffer,
                        &mut row_num,
                        &[],
                        line_num + last_pos + 1,
                        &line,
                        DisplaySuggestion::None,
                        max_line_num_len,
                        &file_lines,
                        is_multiline,
                    )
                }
            }

            // This offset and the ones below need to be signed to account for replacement code
            // that is shorter than the original code.
            let mut offsets: Vec<(usize, isize)> = Vec::new();
            // Only show an underline in the suggestions if the suggestion is not the
            // entirety of the code being shown and the displayed code is not multiline.
            if let DisplaySuggestion::Diff | DisplaySuggestion::Underline | DisplaySuggestion::Add =
                show_code_change
            {
                for part in parts {
                    let snippet = if let Ok(snippet) = sm.span_to_snippet(part.span) {
                        snippet
                    } else {
                        String::new()
                    };
                    let span_start_pos = sm.lookup_char_pos(part.span.lo()).col_display;
                    let span_end_pos = sm.lookup_char_pos(part.span.hi()).col_display;

                    // If this addition is _only_ whitespace, then don't trim it,
                    // or else we're just not rendering anything.
                    let is_whitespace_addition = part.snippet.trim().is_empty();

                    // Do not underline the leading...
                    let start = if is_whitespace_addition {
                        0
                    } else {
                        part.snippet.len().saturating_sub(part.snippet.trim_start().len())
                    };
                    // ...or trailing spaces. Account for substitutions containing unicode
                    // characters.
                    let sub_len: usize = str_width(if is_whitespace_addition {
                        &part.snippet
                    } else {
                        part.snippet.trim()
                    });

                    let offset: isize = offsets
                        .iter()
                        .filter_map(
                            |(start, v)| if span_start_pos < *start { None } else { Some(v) },
                        )
                        .sum();
                    let underline_start = (span_start_pos + start) as isize + offset;
                    let underline_end = (span_start_pos + start + sub_len) as isize + offset;
                    assert!(underline_start >= 0 && underline_end >= 0);
                    let padding: usize = max_line_num_len + 3;
                    for p in underline_start..underline_end {
                        if let DisplaySuggestion::Underline = show_code_change
                            && is_different(sm, &part.snippet, part.span)
                        {
                            // If this is a replacement, underline with `~`, if this is an addition
                            // underline with `+`.
                            buffer.putc(
                                row_num,
                                (padding as isize + p) as usize,
                                if part.is_addition(sm) { '+' } else { self.diff() },
                                Style::Addition,
                            );
                        }
                    }
                    if let DisplaySuggestion::Diff = show_code_change {
                        // Colorize removal with red in diff format.

                        // Below, there's some tricky buffer indexing going on. `row_num` at this
                        // point corresponds to:
                        //
                        //    |
                        // LL | CODE
                        //    | ++++  <- `row_num`
                        //
                        // in the buffer. When we have a diff format output, we end up with
                        //
                        //    |
                        // LL - OLDER   <- row_num - 2
                        // LL + NEWER
                        //    |         <- row_num
                        //
                        // The `row_num - 2` is to select the buffer line that has the "old version
                        // of the diff" at that point. When the removal is a single line, `i` is
                        // `0`, `newlines` is `1` so `(newlines - i - 1)` ends up being `0`, so row
                        // points at `LL - OLDER`. When the removal corresponds to multiple lines,
                        // we end up with `newlines > 1` and `i` being `0..newlines - 1`.
                        //
                        //    |
                        // LL - OLDER   <- row_num - 2 - (newlines - last_i - 1)
                        // LL - CODE
                        // LL - BEING
                        // LL - REMOVED <- row_num - 2 - (newlines - first_i - 1)
                        // LL + NEWER
                        //    |         <- row_num

                        let newlines = snippet.lines().count();
                        if newlines > 0 && row_num > newlines {
                            // Account for removals where the part being removed spans multiple
                            // lines.
                            // FIXME: We check the number of rows because in some cases, like in
                            // `tests/ui/lint/invalid-nan-comparison-suggestion.rs`, the rendered
                            // suggestion will only show the first line of code being replaced. The
                            // proper way of doing this would be to change the suggestion rendering
                            // logic to show the whole prior snippet, but the current output is not
                            // too bad to begin with, so we side-step that issue here.
                            for (i, line) in snippet.lines().enumerate() {
                                let line = normalize_whitespace(line);
                                let row = row_num - 2 - (newlines - i - 1);
                                // On the first line, we highlight between the start of the part
                                // span, and the end of that line.
                                // On the last line, we highlight between the start of the line, and
                                // the column of the part span end.
                                // On all others, we highlight the whole line.
                                let start = if i == 0 {
                                    (padding as isize + span_start_pos as isize) as usize
                                } else {
                                    padding
                                };
                                let end = if i == 0 {
                                    (padding as isize
                                        + span_start_pos as isize
                                        + line.len() as isize)
                                        as usize
                                } else if i == newlines - 1 {
                                    (padding as isize + span_end_pos as isize) as usize
                                } else {
                                    (padding as isize + line.len() as isize) as usize
                                };
                                buffer.set_style_range(row, start, end, Style::Removal, true);
                            }
                        } else {
                            // The removed code fits all in one line.
                            buffer.set_style_range(
                                row_num - 2,
                                (padding as isize + span_start_pos as isize) as usize,
                                (padding as isize + span_end_pos as isize) as usize,
                                Style::Removal,
                                true,
                            );
                        }
                    }

                    // length of the code after substitution
                    let full_sub_len = str_width(&part.snippet) as isize;

                    // length of the code to be substituted
                    let snippet_len = span_end_pos as isize - span_start_pos as isize;
                    // For multiple substitutions, use the position *after* the previous
                    // substitutions have happened, only when further substitutions are
                    // located strictly after.
                    offsets.push((span_end_pos, full_sub_len - snippet_len));
                }
                row_num += 1;
            }

            // if we elided some lines, add an ellipsis
            if lines.next().is_some() {
                let placeholder = self.margin();
                let padding = str_width(placeholder);
                buffer.puts(
                    row_num,
                    max_line_num_len.saturating_sub(padding),
                    placeholder,
                    Style::LineNumber,
                );
            } else {
                let row = match show_code_change {
                    DisplaySuggestion::Diff
                    | DisplaySuggestion::Add
                    | DisplaySuggestion::Underline => row_num - 1,
                    DisplaySuggestion::None => row_num,
                };
                self.draw_col_separator_end(&mut buffer, row, max_line_num_len + 1);
                row_num = row + 1;
            }
        }
        if other_suggestions > 0 {
            let msg = format!(
                "and {} other candidate{}",
                other_suggestions,
                pluralize!(other_suggestions)
            );
            buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle);
        }

        emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
        Ok(())
    }

    #[instrument(level = "trace", skip(self, args, code, children, suggestions))]
    fn emit_messages_default(
        &mut self,
        level: &Level,
        messages: &[(DiagMessage, Style)],
        args: &FluentArgs<'_>,
        code: &Option<ErrCode>,
        span: &MultiSpan,
        children: &[Subdiag],
        suggestions: &[CodeSuggestion],
        emitted_at: Option<&DiagLocation>,
    ) {
        let max_line_num_len = if self.ui_testing {
            ANONYMIZED_LINE_NUM.len()
        } else {
            let n = self.get_max_line_num(span, children);
            num_decimal_digits(n)
        };

        match self.emit_messages_default_inner(
            span,
            messages,
            args,
            code,
            level,
            max_line_num_len,
            false,
            emitted_at,
            !children.is_empty()
                || suggestions.iter().any(|s| s.style != SuggestionStyle::CompletelyHidden),
        ) {
            Ok(()) => {
                if !children.is_empty()
                    || suggestions.iter().any(|s| s.style != SuggestionStyle::CompletelyHidden)
                {
                    let mut buffer = StyledBuffer::new();
                    if !self.short_message {
                        if let Some(child) = children.iter().next()
                            && child.span.primary_spans().is_empty()
                        {
                            // We'll continue the vertical bar to point into the next note.
                            self.draw_col_separator_no_space(&mut buffer, 0, max_line_num_len + 1);
                        } else {
                            // We'll close the vertical bar to visually end the code window.
                            self.draw_col_separator_end(&mut buffer, 0, max_line_num_len + 1);
                        }
                    }
                    if let Err(e) = emit_to_destination(
                        &buffer.render(),
                        level,
                        &mut self.dst,
                        self.short_message,
                    ) {
                        panic!("failed to emit error: {e}")
                    }
                }
                if !self.short_message {
                    for (i, child) in children.iter().enumerate() {
                        assert!(child.level.can_be_subdiag());
                        let span = &child.span;
                        // FIXME: audit that this behaves correctly with suggestions.
                        let should_close = match children.get(i + 1) {
                            Some(c) => !c.span.primary_spans().is_empty(),
                            None => i + 1 == children.len(),
                        };
                        if let Err(err) = self.emit_messages_default_inner(
                            span,
                            &child.messages,
                            args,
                            &None,
                            &child.level,
                            max_line_num_len,
                            true,
                            None,
                            !should_close,
                        ) {
                            panic!("failed to emit error: {err}");
                        }
                    }
                    for (i, sugg) in suggestions.iter().enumerate() {
                        match sugg.style {
                            SuggestionStyle::CompletelyHidden => {
                                // do not display this suggestion, it is meant only for tools
                            }
                            SuggestionStyle::HideCodeAlways => {
                                if let Err(e) = self.emit_messages_default_inner(
                                    &MultiSpan::new(),
                                    &[(sugg.msg.to_owned(), Style::HeaderMsg)],
                                    args,
                                    &None,
                                    &Level::Help,
                                    max_line_num_len,
                                    true,
                                    None,
                                    // FIXME: this needs to account for the suggestion type,
                                    //        some don't take any space.
                                    i + 1 != suggestions.len(),
                                ) {
                                    panic!("failed to emit error: {e}");
                                }
                            }
                            SuggestionStyle::HideCodeInline
                            | SuggestionStyle::ShowCode
                            | SuggestionStyle::ShowAlways => {
                                if let Err(e) = self.emit_suggestion_default(
                                    span,
                                    sugg,
                                    args,
                                    &Level::Help,
                                    max_line_num_len,
                                ) {
                                    panic!("failed to emit error: {e}");
                                }
                            }
                        }
                    }
                }
            }
            Err(e) => panic!("failed to emit error: {e}"),
        }

        match writeln!(self.dst) {
            Err(e) => panic!("failed to emit error: {e}"),
            _ => {
                if let Err(e) = self.dst.flush() {
                    panic!("failed to emit error: {e}")
                }
            }
        }
    }

    fn draw_code_line(
        &self,
        buffer: &mut StyledBuffer,
        row_num: &mut usize,
        highlight_parts: &[SubstitutionHighlight],
        line_num: usize,
        line_to_add: &str,
        show_code_change: DisplaySuggestion,
        max_line_num_len: usize,
        file_lines: &FileLines,
        is_multiline: bool,
    ) {
        if let DisplaySuggestion::Diff = show_code_change {
            // We need to print more than one line if the span we need to remove is multiline.
            // For more info: https://github.com/rust-lang/rust/issues/92741
            let lines_to_remove = file_lines.lines.iter().take(file_lines.lines.len() - 1);
            for (index, line_to_remove) in lines_to_remove.enumerate() {
                buffer.puts(
                    *row_num - 1,
                    0,
                    &self.maybe_anonymized(line_num + index),
                    Style::LineNumber,
                );
                buffer.puts(*row_num - 1, max_line_num_len + 1, "- ", Style::Removal);
                let line = normalize_whitespace(
                    &file_lines.file.get_line(line_to_remove.line_index).unwrap(),
                );
                buffer.puts(*row_num - 1, max_line_num_len + 3, &line, Style::NoStyle);
                *row_num += 1;
            }
            // If the last line is exactly equal to the line we need to add, we can skip both of
            // them. This allows us to avoid output like the following:
            // 2 - &
            // 2 + if true { true } else { false }
            // 3 - if true { true } else { false }
            // If those lines aren't equal, we print their diff
            let last_line_index = file_lines.lines[file_lines.lines.len() - 1].line_index;
            let last_line = &file_lines.file.get_line(last_line_index).unwrap();
            if last_line != line_to_add {
                buffer.puts(
                    *row_num - 1,
                    0,
                    &self.maybe_anonymized(line_num + file_lines.lines.len() - 1),
                    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(last_line),
                    Style::NoStyle,
                );
                if !line_to_add.trim().is_empty() {
                    // Check if after the removal, the line is left with only whitespace. If so, we
                    // will not show an "addition" line, as removing the whole line is what the user
                    // would really want.
                    // For example, for the following:
                    //   |
                    // 2 -     .await
                    // 2 +     (note the left over whitespace)
                    //   |
                    // We really want
                    //   |
                    // 2 -     .await
                    //   |
                    // *row_num -= 1;
                    buffer.puts(*row_num, 0, &self.maybe_anonymized(line_num), Style::LineNumber);
                    buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition);
                    buffer.append(*row_num, &normalize_whitespace(line_to_add), Style::NoStyle);
                } else {
                    *row_num -= 1;
                }
            } else {
                *row_num -= 2;
            }
        } else if is_multiline {
            buffer.puts(*row_num, 0, &self.maybe_anonymized(line_num), Style::LineNumber);
            match &highlight_parts {
                [SubstitutionHighlight { start: 0, end }] if *end == line_to_add.len() => {
                    buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition);
                }
                [] => {
                    // FIXME: needed? Doesn't get exercised in any test.
                    self.draw_col_separator_no_space(buffer, *row_num, max_line_num_len + 1);
                }
                _ => {
                    let diff = self.diff();
                    buffer.puts(
                        *row_num,
                        max_line_num_len + 1,
                        &format!("{diff} "),
                        Style::Addition,
                    );
                }
            }
            //   LL | line_to_add
            //   ++^^^
            //    |  |
            //    |  magic `3`
            //    `max_line_num_len`
            buffer.puts(
                *row_num,
                max_line_num_len + 3,
                &normalize_whitespace(line_to_add),
                Style::NoStyle,
            );
        } else if let DisplaySuggestion::Add = show_code_change {
            buffer.puts(*row_num, 0, &self.maybe_anonymized(line_num), Style::LineNumber);
            buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition);
            buffer.append(*row_num, &normalize_whitespace(line_to_add), Style::NoStyle);
        } else {
            buffer.puts(*row_num, 0, &self.maybe_anonymized(line_num), Style::LineNumber);
            self.draw_col_separator(buffer, *row_num, max_line_num_len + 1);
            buffer.append(*row_num, &normalize_whitespace(line_to_add), Style::NoStyle);
        }

        // Colorize addition/replacements with green.
        for &SubstitutionHighlight { start, end } in highlight_parts {
            // This is a no-op for empty ranges
            if start != end {
                // Account for tabs when highlighting (#87972).
                let tabs: usize = line_to_add
                    .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;
    }

    fn underline(&self, is_primary: bool) -> UnderlineParts {
        //               X0 Y0
        // label_start > ┯━━━━ < underline
        //               │ < vertical_text_line
        //               text

        //    multiline_start_down ⤷ X0 Y0
        //            top_left > ┌───╿──┘ < top_right_flat
        //           top_left > ┏│━━━┙ < top_right
        // multiline_vertical > ┃│
        //                      ┃│   X1 Y1
        //                      ┃│   X2 Y2
        //                      ┃└────╿──┘ < multiline_end_same_line
        //        bottom_left > ┗━━━━━┥ < bottom_right_with_text
        //   multiline_horizontal ^   `X` is a good letter

        // multiline_whole_line > ┏ X0 Y0
        //                        ┃   X1 Y1
        //                        ┗━━━━┛ < multiline_end_same_line

        // multiline_whole_line > ┏ X0 Y0
        //                        ┃ X1 Y1
        //                        ┃  ╿ < multiline_end_up
        //                        ┗━━┛ < bottom_right

        match (self.theme, is_primary) {
            (OutputTheme::Ascii, true) => UnderlineParts {
                style: Style::UnderlinePrimary,
                underline: '^',
                label_start: '^',
                vertical_text_line: '|',
                multiline_vertical: '|',
                multiline_horizontal: '_',
                multiline_whole_line: '/',
                multiline_start_down: '^',
                bottom_right: '|',
                top_left: ' ',
                top_right_flat: '^',
                bottom_left: '|',
                multiline_end_up: '^',
                multiline_end_same_line: '^',
                multiline_bottom_right_with_text: '|',
            },
            (OutputTheme::Ascii, false) => UnderlineParts {
                style: Style::UnderlineSecondary,
                underline: '-',
                label_start: '-',
                vertical_text_line: '|',
                multiline_vertical: '|',
                multiline_horizontal: '_',
                multiline_whole_line: '/',
                multiline_start_down: '-',
                bottom_right: '|',
                top_left: ' ',
                top_right_flat: '-',
                bottom_left: '|',
                multiline_end_up: '-',
                multiline_end_same_line: '-',
                multiline_bottom_right_with_text: '|',
            },
            (OutputTheme::Unicode, true) => UnderlineParts {
                style: Style::UnderlinePrimary,
                underline: '━',
                label_start: '┯',
                vertical_text_line: '│',
                multiline_vertical: '┃',
                multiline_horizontal: '━',
                multiline_whole_line: '┏',
                multiline_start_down: '╿',
                bottom_right: '┙',
                top_left: '┏',
                top_right_flat: '┛',
                bottom_left: '┗',
                multiline_end_up: '╿',
                multiline_end_same_line: '┛',
                multiline_bottom_right_with_text: '┥',
            },
            (OutputTheme::Unicode, false) => UnderlineParts {
                style: Style::UnderlineSecondary,
                underline: '─',
                label_start: '┬',
                vertical_text_line: '│',
                multiline_vertical: '│',
                multiline_horizontal: '─',
                multiline_whole_line: '┌',
                multiline_start_down: '│',
                bottom_right: '┘',
                top_left: '┌',
                top_right_flat: '┘',
                bottom_left: '└',
                multiline_end_up: '│',
                multiline_end_same_line: '┘',
                multiline_bottom_right_with_text: '┤',
            },
        }
    }

    fn col_separator(&self) -> char {
        match self.theme {
            OutputTheme::Ascii => '|',
            OutputTheme::Unicode => '│',
        }
    }

    fn note_separator(&self) -> char {
        match self.theme {
            OutputTheme::Ascii => '=',
            OutputTheme::Unicode => '╰',
        }
    }

    fn multi_suggestion_separator(&self) -> &'static str {
        match self.theme {
            OutputTheme::Ascii => "|",
            OutputTheme::Unicode => "├╴",
        }
    }

    fn draw_col_separator(&self, buffer: &mut StyledBuffer, line: usize, col: usize) {
        let chr = self.col_separator();
        buffer.puts(line, col, &format!("{chr} "), Style::LineNumber);
    }

    fn draw_col_separator_no_space(&self, buffer: &mut StyledBuffer, line: usize, col: usize) {
        let chr = self.col_separator();
        self.draw_col_separator_no_space_with_style(buffer, chr, line, col, Style::LineNumber);
    }

    fn draw_col_separator_start(&self, buffer: &mut StyledBuffer, line: usize, col: usize) {
        match self.theme {
            OutputTheme::Ascii => {
                self.draw_col_separator_no_space_with_style(
                    buffer,
                    '|',
                    line,
                    col,
                    Style::LineNumber,
                );
            }
            OutputTheme::Unicode => {
                self.draw_col_separator_no_space_with_style(
                    buffer,
                    '╭',
                    line,
                    col,
                    Style::LineNumber,
                );
                self.draw_col_separator_no_space_with_style(
                    buffer,
                    '╴',
                    line,
                    col + 1,
                    Style::LineNumber,
                );
            }
        }
    }

    fn draw_col_separator_end(&self, buffer: &mut StyledBuffer, line: usize, col: usize) {
        match self.theme {
            OutputTheme::Ascii => {
                self.draw_col_separator_no_space_with_style(
                    buffer,
                    '|',
                    line,
                    col,
                    Style::LineNumber,
                );
            }
            OutputTheme::Unicode => {
                self.draw_col_separator_no_space_with_style(
                    buffer,
                    '╰',
                    line,
                    col,
                    Style::LineNumber,
                );
                self.draw_col_separator_no_space_with_style(
                    buffer,
                    '╴',
                    line,
                    col + 1,
                    Style::LineNumber,
                );
            }
        }
    }

    fn draw_col_separator_no_space_with_style(
        &self,
        buffer: &mut StyledBuffer,
        chr: char,
        line: usize,
        col: usize,
        style: Style,
    ) {
        buffer.putc(line, col, chr, style);
    }

    fn draw_range(
        &self,
        buffer: &mut StyledBuffer,
        symbol: char,
        line: usize,
        col_from: usize,
        col_to: usize,
        style: Style,
    ) {
        for col in col_from..col_to {
            buffer.putc(line, col, symbol, style);
        }
    }

    fn draw_note_separator(
        &self,
        buffer: &mut StyledBuffer,
        line: usize,
        col: usize,
        is_cont: bool,
    ) {
        let chr = match self.theme {
            OutputTheme::Ascii => "= ",
            OutputTheme::Unicode if is_cont => "├ ",
            OutputTheme::Unicode => "╰ ",
        };
        buffer.puts(line, col, chr, Style::LineNumber);
    }

    fn draw_multiline_line(
        &self,
        buffer: &mut StyledBuffer,
        line: usize,
        offset: usize,
        depth: usize,
        style: Style,
    ) {
        let chr = match (style, self.theme) {
            (Style::UnderlinePrimary | Style::LabelPrimary, OutputTheme::Ascii) => '|',
            (_, OutputTheme::Ascii) => '|',
            (Style::UnderlinePrimary | Style::LabelPrimary, OutputTheme::Unicode) => '┃',
            (_, OutputTheme::Unicode) => '│',
        };
        buffer.putc(line, offset + depth - 1, chr, style);
    }

    fn file_start(&self) -> &'static str {
        match self.theme {
            OutputTheme::Ascii => "--> ",
            OutputTheme::Unicode => " ╭▸ ",
        }
    }

    fn secondary_file_start(&self) -> &'static str {
        match self.theme {
            OutputTheme::Ascii => "::: ",
            OutputTheme::Unicode => " ⸬ ",
        }
    }

    fn diff(&self) -> char {
        match self.theme {
            OutputTheme::Ascii => '~',
            OutputTheme::Unicode => '±',
        }
    }

    fn draw_line_separator(&self, buffer: &mut StyledBuffer, line: usize, col: usize) {
        let (column, dots) = match self.theme {
            OutputTheme::Ascii => (0, "..."),
            OutputTheme::Unicode => (col - 2, "‡"),
        };
        buffer.puts(line, column, dots, Style::LineNumber);
    }

    fn margin(&self) -> &'static str {
        match self.theme {
            OutputTheme::Ascii => "...",
            OutputTheme::Unicode => "…",
        }
    }
}

#[derive(Debug, Clone, Copy)]
struct UnderlineParts {
    style: Style,
    underline: char,
    label_start: char,
    vertical_text_line: char,
    multiline_vertical: char,
    multiline_horizontal: char,
    multiline_whole_line: char,
    multiline_start_down: char,
    bottom_right: char,
    top_left: char,
    top_right_flat: char,
    bottom_left: char,
    multiline_end_up: char,
    multiline_end_same_line: char,
    multiline_bottom_right_with_text: char,
}

#[derive(Clone, Copy, Debug)]
enum DisplaySuggestion {
    Underline,
    Diff,
    None,
    Add,
}

impl FileWithAnnotatedLines {
    /// Preprocess all the annotations so that they are grouped by file and by line number
    /// This helps us quickly iterate over the whole message (including secondary file spans)
    pub(crate) fn collect_annotations(
        emitter: &dyn Emitter,
        args: &FluentArgs<'_>,
        msp: &MultiSpan,
    ) -> Vec<FileWithAnnotatedLines> {
        fn add_annotation_to_file(
            file_vec: &mut Vec<FileWithAnnotatedLines>,
            file: Arc<SourceFile>,
            line_index: usize,
            ann: Annotation,
        ) {
            for slot in file_vec.iter_mut() {
                // Look through each of our files for the one we're adding to
                if slot.file.name == file.name {
                    // See if we already have a line for it
                    for line_slot in &mut slot.lines {
                        if line_slot.line_index == line_index {
                            line_slot.annotations.push(ann);
                            return;
                        }
                    }
                    // We don't have a line yet, create one
                    slot.lines.push(Line { line_index, annotations: vec![ann] });
                    slot.lines.sort();
                    return;
                }
            }
            // This is the first time we're seeing the file
            file_vec.push(FileWithAnnotatedLines {
                file,
                lines: vec![Line { line_index, annotations: vec![ann] }],
                multiline_depth: 0,
            });
        }

        let mut output = vec![];
        let mut multiline_annotations = vec![];

        if let Some(sm) = emitter.source_map() {
            for SpanLabel { span, is_primary, label } in msp.span_labels() {
                // If we don't have a useful span, pick the primary span if that exists.
                // Worst case we'll just print an error at the top of the main file.
                let span = match (span.is_dummy(), msp.primary_span()) {
                    (_, None) | (false, _) => span,
                    (true, Some(span)) => span,
                };

                let lo = sm.lookup_char_pos(span.lo());
                let mut hi = sm.lookup_char_pos(span.hi());

                // Watch out for "empty spans". If we get a span like 6..6, we
                // want to just display a `^` at 6, so convert that to
                // 6..7. This is degenerate input, but it's best to degrade
                // gracefully -- and the parser likes to supply a span like
                // that for EOF, in particular.

                if lo.col_display == hi.col_display && lo.line == hi.line {
                    hi.col_display += 1;
                }

                let label = label.as_ref().map(|m| {
                    normalize_whitespace(
                        &emitter
                            .translator()
                            .translate_message(m, args)
                            .map_err(Report::new)
                            .unwrap(),
                    )
                });

                if lo.line != hi.line {
                    let ml = MultilineAnnotation {
                        depth: 1,
                        line_start: lo.line,
                        line_end: hi.line,
                        start_col: AnnotationColumn::from_loc(&lo),
                        end_col: AnnotationColumn::from_loc(&hi),
                        is_primary,
                        label,
                        overlaps_exactly: false,
                    };
                    multiline_annotations.push((lo.file, ml));
                } else {
                    let ann = Annotation {
                        start_col: AnnotationColumn::from_loc(&lo),
                        end_col: AnnotationColumn::from_loc(&hi),
                        is_primary,
                        label,
                        annotation_type: AnnotationType::Singleline,
                    };
                    add_annotation_to_file(&mut output, lo.file, lo.line, ann);
                };
            }
        }

        // Find overlapping multiline annotations, put them at different depths
        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
                // one level to the right.
                if !(ann.same_span(a))
                    && num_overlap(ann.line_start, ann.line_end, a.line_start, a.line_end, true)
                {
                    a.increase_depth();
                } else if ann.same_span(a) && &ann != a {
                    a.overlaps_exactly = true;
                } else {
                    break;
                }
            }
        }

        let mut max_depth = 0; // max overlapping multiline spans
        for (_, ann) in &multiline_annotations {
            max_depth = max(max_depth, ann.depth);
        }
        // Change order of multispan depth to minimize the number of overlaps in the ASCII art.
        for (_, a) in multiline_annotations.iter_mut() {
            a.depth = max_depth - a.depth + 1;
        }
        for (file, ann) in multiline_annotations {
            let mut end_ann = ann.as_end();
            if !ann.overlaps_exactly {
                // avoid output like
                //
                //  |        foo(
                //  |   _____^
                //  |  |_____|
                //  | ||         bar,
                //  | ||     );
                //  | ||      ^
                //  | ||______|
                //  |  |______foo
                //  |         baz
                //
                // and instead get
                //
                //  |       foo(
                //  |  _____^
                //  | |         bar,
                //  | |     );
                //  | |      ^
                //  | |      |
                //  | |______foo
                //  |        baz
                add_annotation_to_file(
                    &mut output,
                    Arc::clone(&file),
                    ann.line_start,
                    ann.as_start(),
                );
                // 4 is the minimum vertical length of a multiline span when presented: two lines
                // of code and two lines of underline. This is not true for the special case where
                // the beginning doesn't have an underline, but the current logic seems to be
                // working correctly.
                let middle = min(ann.line_start + 4, ann.line_end);
                // We'll show up to 4 lines past the beginning of the multispan start.
                // We will *not* include the tail of lines that are only whitespace, a comment or
                // a bare delimiter.
                let filter = |s: &str| {
                    let s = s.trim();
                    // Consider comments as empty, but don't consider docstrings to be empty.
                    !(s.starts_with("//") && !(s.starts_with("///") || s.starts_with("//!")))
                        // Consider lines with nothing but whitespace, a single delimiter as empty.
                        && !["", "{", "}", "(", ")", "[", "]"].contains(&s)
                };
                let until = (ann.line_start..middle)
                    .rev()
                    .filter_map(|line| file.get_line(line - 1).map(|s| (line + 1, s)))
                    .find(|(_, s)| filter(s))
                    .map(|(line, _)| line)
                    .unwrap_or(ann.line_start);
                for line in ann.line_start + 1..until {
                    // Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`).
                    add_annotation_to_file(&mut output, Arc::clone(&file), line, ann.as_line());
                }
                let line_end = ann.line_end - 1;
                let end_is_empty = file.get_line(line_end - 1).is_some_and(|s| !filter(&s));
                if middle < line_end && !end_is_empty {
                    add_annotation_to_file(&mut output, Arc::clone(&file), line_end, ann.as_line());
                }
            } else {
                end_ann.annotation_type = AnnotationType::Singleline;
            }
            add_annotation_to_file(&mut output, file, ann.line_end, end_ann);
        }
        for file_vec in output.iter_mut() {
            file_vec.multiline_depth = max_depth;
        }
        output
    }
}

// instead of taking the String length or dividing by 10 while > 0, we multiply a limit by 10 until
// we're higher. If the loop isn't exited by the `return`, the last multiplication will wrap, which
// is OK, because while we cannot fit a higher power of 10 in a usize, the loop will end anyway.
// This is also why we need the max number of decimal digits within a `usize`.
fn num_decimal_digits(num: usize) -> usize {
    #[cfg(target_pointer_width = "64")]
    const MAX_DIGITS: usize = 20;

    #[cfg(target_pointer_width = "32")]
    const MAX_DIGITS: usize = 10;

    #[cfg(target_pointer_width = "16")]
    const MAX_DIGITS: usize = 5;

    let mut lim = 10;
    for num_digits in 1..MAX_DIGITS {
        if num < lim {
            return num_digits;
        }
        lim = lim.wrapping_mul(10);
    }
    MAX_DIGITS
}

// 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`.
const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[
    // 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.
    ('\0', "␀"),
    ('\u{0001}', "␁"),
    ('\u{0002}', "␂"),
    ('\u{0003}', "␃"),
    ('\u{0004}', "␄"),
    ('\u{0005}', "␅"),
    ('\u{0006}', "␆"),
    ('\u{0007}', "␇"),
    ('\u{0008}', "␈"),
    ('\t', "    "), // We do our own tab replacement
    ('\u{000b}', "␋"),
    ('\u{000c}', "␌"),
    ('\u{000d}', "␍"),
    ('\u{000e}', "␎"),
    ('\u{000f}', "␏"),
    ('\u{0010}', "␐"),
    ('\u{0011}', "␑"),
    ('\u{0012}', "␒"),
    ('\u{0013}', "␓"),
    ('\u{0014}', "␔"),
    ('\u{0015}', "␕"),
    ('\u{0016}', "␖"),
    ('\u{0017}', "␗"),
    ('\u{0018}', "␘"),
    ('\u{0019}', "␙"),
    ('\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}', "�"),
];

fn normalize_whitespace(s: &str) -> String {
    const {
        let mut i = 1;
        while i < OUTPUT_REPLACEMENTS.len() {
            assert!(
                OUTPUT_REPLACEMENTS[i - 1].0 < OUTPUT_REPLACEMENTS[i].0,
                "The OUTPUT_REPLACEMENTS array must be sorted (for binary search to work) \
                and must contain no duplicate entries"
            );
            i += 1;
        }
    }
    // Scan the input string for a character in the ordered table above.
    // If it's present, replace it with its alternative string (it can be more than 1 char!).
    // Otherwise, retain the input char.
    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 num_overlap(
    a_start: usize,
    a_end: usize,
    b_start: usize,
    b_end: usize,
    inclusive: bool,
) -> bool {
    let extra = if inclusive { 1 } else { 0 };
    (b_start..b_end + extra).contains(&a_start) || (a_start..a_end + extra).contains(&b_start)
}

fn overlaps(a1: &Annotation, a2: &Annotation, padding: usize) -> bool {
    num_overlap(
        a1.start_col.display,
        a1.end_col.display + padding,
        a2.start_col.display,
        a2.end_col.display,
        false,
    )
}

fn emit_to_destination(
    rendered_buffer: &[Vec<StyledString>],
    lvl: &Level,
    dst: &mut Destination,
    short_message: bool,
) -> io::Result<()> {
    use crate::lock;

    // In order to prevent error message interleaving, where multiple error lines get intermixed
    // when multiple compiler processes error simultaneously, we emit errors with additional
    // steps.
    //
    // 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
    // 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
    // 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() {
        for part in line {
            let style = part.style.color_spec(*lvl);
            dst.set_color(&style)?;
            write!(dst, "{}", part.text)?;
            dst.reset()?;
        }
        if !short_message && (!lvl.is_failure_note() || pos != rendered_buffer.len() - 1) {
            writeln!(dst)?;
        }
    }
    dst.flush()?;
    Ok(())
}

pub type Destination = Box<dyn WriteColor + Send>;

struct Buffy {
    buffer_writer: BufferWriter,
    buffer: Buffer,
}

impl Write for Buffy {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.buffer.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.buffer_writer.print(&self.buffer)?;
        self.buffer.clear();
        Ok(())
    }
}

impl Drop for Buffy {
    fn drop(&mut self) {
        if !self.buffer.is_empty() {
            self.flush().unwrap();
            panic!("buffers need to be flushed in order to print their contents");
        }
    }
}

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()
    }
}

pub fn stderr_destination(color: ColorConfig) -> Destination {
    let choice = color.to_color_choice();
    // On Windows we'll be performing global synchronization on the entire
    // system for emitting rustc errors, so there's no need to buffer
    // anything.
    //
    // On non-Windows we rely on the atomicity of `write` to ensure errors
    // don't get all jumbled up.
    if cfg!(windows) {
        Box::new(StandardStream::stderr(choice))
    } else {
        let buffer_writer = BufferWriter::stderr(choice);
        let buffer = buffer_writer.buffer();
        Box::new(Buffy { buffer_writer, buffer })
    }
}

/// 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 };

impl Style {
    fn color_spec(&self, lvl: Level) -> ColorSpec {
        let mut spec = ColorSpec::new();
        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::UnderlinePrimary | Style::LabelPrimary => {
                spec = lvl.color();
                spec.set_bold(true);
            }
            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);
            }
            Style::Highlight => {
                spec.set_bold(true).set_fg(Some(Color::Magenta));
            }
        }
        spec
    }
}

/// Whether the original and suggested code are the same.
pub fn is_different(sm: &SourceMap, suggested: &str, sp: Span) -> bool {
    let found = match sm.span_to_snippet(sp) {
        Ok(snippet) => snippet,
        Err(e) => {
            warn!(error = ?e, "Invalid span {:?}", sp);
            return true;
        }
    };
    found != suggested
}

/// Whether the original and suggested code are visually similar enough to warrant extra wording.
pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool {
    // FIXME: this should probably be extended to also account for `FO0` → `FOO` and unicode.
    let found = match sm.span_to_snippet(sp) {
        Ok(snippet) => snippet,
        Err(e) => {
            warn!(error = ?e, "Invalid span {:?}", sp);
            return false;
        }
    };
    let ascii_confusables = &['c', 'f', 'i', 'k', 'o', 's', 'u', 'v', 'w', 'x', 'y', 'z'];
    // All the chars that differ in capitalization are confusable (above):
    let confusable = iter::zip(found.chars(), suggested.chars())
        .filter(|(f, s)| f != s)
        .all(|(f, s)| (ascii_confusables.contains(&f) || ascii_confusables.contains(&s)));
    confusable && found.to_lowercase() == suggested.to_lowercase()
            // FIXME: We sometimes suggest the same thing we already have, which is a
            //        bug, but be defensive against that here.
            && found != suggested
}

pub(crate) fn should_show_source_code(
    ignored_directories: &[String],
    sm: &SourceMap,
    file: &SourceFile,
) -> bool {
    if !sm.ensure_source_file_source_present(file) {
        return false;
    }

    let FileName::Real(name) = &file.name else { return true };
    name.local_path()
        .map(|path| ignored_directories.iter().all(|dir| !path.starts_with(dir)))
        .unwrap_or(true)
}
