1
Fork 0

Rollup merge of #121783 - nnethercote:emitter-cleanups, r=oli-obk

Emitter cleanups

Some cleanups I made when reading emitter code. In particular, `HumanEmitter` and `JsonEmitter` have gone from three constructors to one.

r? `@oli-obk`
This commit is contained in:
Guillaume Gomez 2024-02-29 17:08:38 +01:00 committed by GitHub
commit 0e9f02d6fa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 138 additions and 219 deletions

View file

@ -373,7 +373,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
impl<B: WriteBackendMethods> CodegenContext<B> { impl<B: WriteBackendMethods> CodegenContext<B> {
pub fn create_dcx(&self) -> DiagCtxt { pub fn create_dcx(&self) -> DiagCtxt {
DiagCtxt::with_emitter(Box::new(self.diag_emitter.clone())) DiagCtxt::new(Box::new(self.diag_emitter.clone()))
} }
pub fn config(&self, kind: ModuleKind) -> &ModuleConfig { pub fn config(&self, kind: ModuleKind) -> &ModuleConfig {

View file

@ -21,6 +21,7 @@ use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
use rustc_data_structures::profiling::{ use rustc_data_structures::profiling::{
get_resident_set_size, print_time_passes_entry, TimePassesFormat, get_resident_set_size, print_time_passes_entry, TimePassesFormat,
}; };
use rustc_errors::emitter::stderr_destination;
use rustc_errors::registry::Registry; use rustc_errors::registry::Registry;
use rustc_errors::{ use rustc_errors::{
markdown, ColorConfig, DiagCtxt, ErrCode, ErrorGuaranteed, FatalError, PResult, markdown, ColorConfig, DiagCtxt, ErrCode, ErrorGuaranteed, FatalError, PResult,
@ -1384,11 +1385,11 @@ fn report_ice(
) { ) {
let fallback_bundle = let fallback_bundle =
rustc_errors::fallback_fluent_bundle(crate::DEFAULT_LOCALE_RESOURCES.to_vec(), false); rustc_errors::fallback_fluent_bundle(crate::DEFAULT_LOCALE_RESOURCES.to_vec(), false);
let emitter = Box::new(rustc_errors::emitter::HumanEmitter::stderr( let emitter = Box::new(rustc_errors::emitter::HumanEmitter::new(
rustc_errors::ColorConfig::Auto, stderr_destination(rustc_errors::ColorConfig::Auto),
fallback_bundle, fallback_bundle,
)); ));
let dcx = rustc_errors::DiagCtxt::with_emitter(emitter); let dcx = rustc_errors::DiagCtxt::new(emitter);
// a .span_bug or .bug call has already printed what // a .span_bug or .bug call has already printed what
// it wants to print. // it wants to print.

View file

@ -21,12 +21,11 @@ use crate::{
FluentBundle, LazyFallbackBundle, Level, MultiSpan, Subdiag, SubstitutionHighlight, FluentBundle, LazyFallbackBundle, Level, MultiSpan, Subdiag, SubstitutionHighlight,
SuggestionStyle, TerminalUrl, SuggestionStyle, TerminalUrl,
}; };
use rustc_lint_defs::pluralize;
use derive_setters::Setters; use derive_setters::Setters;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::sync::{DynSend, IntoDynSyncSend, Lrc}; use rustc_data_structures::sync::{DynSend, IntoDynSyncSend, Lrc};
use rustc_error_messages::{FluentArgs, SpanLabel}; use rustc_error_messages::{FluentArgs, SpanLabel};
use rustc_lint_defs::pluralize;
use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::hygiene::{ExpnKind, MacroKind};
use std::borrow::Cow; use std::borrow::Cow;
use std::cmp::{max, min, Reverse}; use std::cmp::{max, min, Reverse};
@ -35,7 +34,7 @@ use std::io::prelude::*;
use std::io::{self, IsTerminal}; use std::io::{self, IsTerminal};
use std::iter; use std::iter;
use std::path::Path; use std::path::Path;
use termcolor::{Ansi, Buffer, BufferWriter, ColorChoice, ColorSpec, StandardStream}; use termcolor::{Buffer, BufferWriter, ColorChoice, ColorSpec, StandardStream};
use termcolor::{Color, WriteColor}; use termcolor::{Color, WriteColor};
/// Default column width, used in tests and when terminal dimensions cannot be determined. /// Default column width, used in tests and when terminal dimensions cannot be determined.
@ -58,18 +57,6 @@ impl HumanReadableErrorType {
HumanReadableErrorType::AnnotateSnippet(cc) => (false, cc), HumanReadableErrorType::AnnotateSnippet(cc) => (false, cc),
} }
} }
pub fn new_emitter(
self,
mut dst: Box<dyn WriteColor + Send>,
fallback_bundle: LazyFallbackBundle,
) -> HumanEmitter {
let (short, color_config) = self.unzip();
let color = color_config.suggests_using_colors();
if !dst.supports_color() && color {
dst = Box::new(Ansi::new(dst));
}
HumanEmitter::new(dst, fallback_bundle).short_message(short)
}
} }
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
@ -130,8 +117,8 @@ impl Margin {
fn was_cut_right(&self, line_len: usize) -> bool { fn was_cut_right(&self, line_len: usize) -> bool {
let right = let right =
if self.computed_right == self.span_right || self.computed_right == self.label_right { if self.computed_right == self.span_right || self.computed_right == self.label_right {
// Account for the "..." padding given above. Otherwise we end up with code lines that // Account for the "..." padding given above. Otherwise we end up with code lines
// do fit but end in "..." as if they were trimmed. // that do fit but end in "..." as if they were trimmed.
self.computed_right - 6 self.computed_right - 6
} else { } else {
self.computed_right self.computed_right
@ -628,12 +615,6 @@ impl ColorConfig {
ColorConfig::Auto => ColorChoice::Never, ColorConfig::Auto => ColorChoice::Never,
} }
} }
fn suggests_using_colors(self) -> bool {
match self {
ColorConfig::Always | ColorConfig::Auto => true,
ColorConfig::Never => false,
}
}
} }
/// Handles the writing of `HumanReadableErrorType::Default` and `HumanReadableErrorType::Short` /// Handles the writing of `HumanReadableErrorType::Default` and `HumanReadableErrorType::Short`
@ -657,19 +638,14 @@ pub struct HumanEmitter {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct FileWithAnnotatedLines { pub(crate) struct FileWithAnnotatedLines {
pub file: Lrc<SourceFile>, pub(crate) file: Lrc<SourceFile>,
pub lines: Vec<Line>, pub(crate) lines: Vec<Line>,
multiline_depth: usize, multiline_depth: usize,
} }
impl HumanEmitter { impl HumanEmitter {
pub fn stderr(color_config: ColorConfig, fallback_bundle: LazyFallbackBundle) -> HumanEmitter { pub fn new(dst: Destination, fallback_bundle: LazyFallbackBundle) -> HumanEmitter {
let dst = from_stderr(color_config);
Self::create(dst, fallback_bundle)
}
fn create(dst: Destination, fallback_bundle: LazyFallbackBundle) -> HumanEmitter {
HumanEmitter { HumanEmitter {
dst: IntoDynSyncSend(dst), dst: IntoDynSyncSend(dst),
sm: None, sm: None,
@ -686,13 +662,6 @@ impl HumanEmitter {
} }
} }
pub fn new(
dst: Box<dyn WriteColor + Send>,
fallback_bundle: LazyFallbackBundle,
) -> HumanEmitter {
Self::create(dst, fallback_bundle)
}
fn maybe_anonymized(&self, line_num: usize) -> Cow<'static, str> { fn maybe_anonymized(&self, line_num: usize) -> Cow<'static, str> {
if self.ui_testing { if self.ui_testing {
Cow::Borrowed(ANONYMIZED_LINE_NUM) Cow::Borrowed(ANONYMIZED_LINE_NUM)
@ -724,8 +693,9 @@ impl HumanEmitter {
.skip(left) .skip(left)
.take_while(|ch| { .take_while(|ch| {
// Make sure that the trimming on the right will fall within the terminal width. // Make sure that the trimming on the right will fall within the terminal width.
// FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is. // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char`
// For now, just accept that sometimes the code line will be longer than desired. // is. For now, just accept that sometimes the code line will be longer than
// desired.
let next = unicode_width::UnicodeWidthChar::width(*ch).unwrap_or(1); let next = unicode_width::UnicodeWidthChar::width(*ch).unwrap_or(1);
if taken + next > right - left { if taken + next > right - left {
return false; return false;
@ -2228,8 +2198,8 @@ impl HumanEmitter {
buffer.puts(*row_num - 1, max_line_num_len + 3, &line, Style::NoStyle); buffer.puts(*row_num - 1, max_line_num_len + 3, &line, Style::NoStyle);
*row_num += 1; *row_num += 1;
} }
// If the last line is exactly equal to the line we need to add, we can skip both of them. // If the last line is exactly equal to the line we need to add, we can skip both of
// This allows us to avoid output like the following: // them. This allows us to avoid output like the following:
// 2 - & // 2 - &
// 2 + if true { true } else { false } // 2 + if true { true } else { false }
// 3 - if true { true } else { false } // 3 - if true { true } else { false }
@ -2586,6 +2556,7 @@ fn num_overlap(
let extra = if inclusive { 1 } else { 0 }; let extra = if inclusive { 1 } else { 0 };
(b_start..b_end + extra).contains(&a_start) || (a_start..a_end + extra).contains(&b_start) (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 { fn overlaps(a1: &Annotation, a2: &Annotation, padding: usize) -> bool {
num_overlap( num_overlap(
a1.start_col.display, a1.start_col.display,
@ -2632,7 +2603,7 @@ fn emit_to_destination(
Ok(()) Ok(())
} }
pub type Destination = Box<(dyn WriteColor + Send)>; pub type Destination = Box<dyn WriteColor + Send>;
struct Buffy { struct Buffy {
buffer_writer: BufferWriter, buffer_writer: BufferWriter,
@ -2674,7 +2645,7 @@ impl WriteColor for Buffy {
} }
} }
fn from_stderr(color: ColorConfig) -> Destination { pub fn stderr_destination(color: ColorConfig) -> Destination {
let choice = color.to_color_choice(); let choice = color.to_color_choice();
// On Windows we'll be performing global synchronization on the entire // On Windows we'll be performing global synchronization on the entire
// system for emitting rustc errors, so there's no need to buffer // system for emitting rustc errors, so there's no need to buffer

View file

@ -23,9 +23,11 @@ impl<'args> TranslateError<'args> {
pub fn message(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self { pub fn message(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self {
Self::One { id, args, kind: TranslateErrorKind::MessageMissing } Self::One { id, args, kind: TranslateErrorKind::MessageMissing }
} }
pub fn primary(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self { pub fn primary(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self {
Self::One { id, args, kind: TranslateErrorKind::PrimaryBundleMissing } Self::One { id, args, kind: TranslateErrorKind::PrimaryBundleMissing }
} }
pub fn attribute( pub fn attribute(
id: &'args Cow<'args, str>, id: &'args Cow<'args, str>,
args: &'args FluentArgs<'args>, args: &'args FluentArgs<'args>,
@ -33,6 +35,7 @@ impl<'args> TranslateError<'args> {
) -> Self { ) -> Self {
Self::One { id, args, kind: TranslateErrorKind::AttributeMissing { attr } } Self::One { id, args, kind: TranslateErrorKind::AttributeMissing { attr } }
} }
pub fn value(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self { pub fn value(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self {
Self::One { id, args, kind: TranslateErrorKind::ValueMissing } Self::One { id, args, kind: TranslateErrorKind::ValueMissing }
} }

View file

@ -9,42 +9,49 @@
// FIXME: spec the JSON output properly. // FIXME: spec the JSON output properly.
use rustc_span::source_map::{FilePathMapping, SourceMap}; use crate::emitter::{
use termcolor::{ColorSpec, WriteColor}; should_show_source_code, ColorConfig, Destination, Emitter, HumanEmitter,
HumanReadableErrorType,
use crate::emitter::{should_show_source_code, Emitter, HumanReadableErrorType}; };
use crate::registry::Registry; use crate::registry::Registry;
use crate::translation::{to_fluent_args, Translate}; use crate::translation::{to_fluent_args, Translate};
use crate::{ use crate::{
diagnostic::IsLint, CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, diagnostic::IsLint, CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel,
Subdiag, TerminalUrl, Subdiag, TerminalUrl,
}; };
use rustc_lint_defs::Applicability; use derive_setters::Setters;
use rustc_data_structures::sync::{IntoDynSyncSend, Lrc}; use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
use rustc_error_messages::FluentArgs; use rustc_error_messages::FluentArgs;
use rustc_lint_defs::Applicability;
use rustc_span::hygiene::ExpnData; use rustc_span::hygiene::ExpnData;
use rustc_span::source_map::SourceMap;
use rustc_span::Span; use rustc_span::Span;
use serde::Serialize;
use std::error::Report; use std::error::Report;
use std::io::{self, Write}; use std::io::{self, Write};
use std::path::Path; use std::path::Path;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::vec; use std::vec;
use termcolor::{ColorSpec, WriteColor};
use serde::Serialize;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
#[derive(Setters)]
pub struct JsonEmitter { pub struct JsonEmitter {
#[setters(skip)]
dst: IntoDynSyncSend<Box<dyn Write + Send>>, dst: IntoDynSyncSend<Box<dyn Write + Send>>,
registry: Option<Registry>, registry: Option<Registry>,
#[setters(skip)]
sm: Lrc<SourceMap>, sm: Lrc<SourceMap>,
fluent_bundle: Option<Lrc<FluentBundle>>, fluent_bundle: Option<Lrc<FluentBundle>>,
#[setters(skip)]
fallback_bundle: LazyFallbackBundle, fallback_bundle: LazyFallbackBundle,
#[setters(skip)]
pretty: bool, pretty: bool,
ui_testing: bool, ui_testing: bool,
ignored_directories_in_source_blocks: Vec<String>, ignored_directories_in_source_blocks: Vec<String>,
#[setters(skip)]
json_rendered: HumanReadableErrorType, json_rendered: HumanReadableErrorType,
diagnostic_width: Option<usize>, diagnostic_width: Option<usize>,
macro_backtrace: bool, macro_backtrace: bool,
@ -53,98 +60,30 @@ pub struct JsonEmitter {
} }
impl JsonEmitter { impl JsonEmitter {
pub fn stderr(
registry: Option<Registry>,
source_map: Lrc<SourceMap>,
fluent_bundle: Option<Lrc<FluentBundle>>,
fallback_bundle: LazyFallbackBundle,
pretty: bool,
json_rendered: HumanReadableErrorType,
diagnostic_width: Option<usize>,
macro_backtrace: bool,
track_diagnostics: bool,
terminal_url: TerminalUrl,
) -> JsonEmitter {
JsonEmitter {
dst: IntoDynSyncSend(Box::new(io::BufWriter::new(io::stderr()))),
registry,
sm: source_map,
fluent_bundle,
fallback_bundle,
pretty,
ui_testing: false,
ignored_directories_in_source_blocks: Vec::new(),
json_rendered,
diagnostic_width,
macro_backtrace,
track_diagnostics,
terminal_url,
}
}
pub fn basic(
pretty: bool,
json_rendered: HumanReadableErrorType,
fluent_bundle: Option<Lrc<FluentBundle>>,
fallback_bundle: LazyFallbackBundle,
diagnostic_width: Option<usize>,
macro_backtrace: bool,
track_diagnostics: bool,
terminal_url: TerminalUrl,
) -> JsonEmitter {
let file_path_mapping = FilePathMapping::empty();
JsonEmitter::stderr(
None,
Lrc::new(SourceMap::new(file_path_mapping)),
fluent_bundle,
fallback_bundle,
pretty,
json_rendered,
diagnostic_width,
macro_backtrace,
track_diagnostics,
terminal_url,
)
}
pub fn new( pub fn new(
dst: Box<dyn Write + Send>, dst: Box<dyn Write + Send>,
registry: Option<Registry>, sm: Lrc<SourceMap>,
source_map: Lrc<SourceMap>,
fluent_bundle: Option<Lrc<FluentBundle>>,
fallback_bundle: LazyFallbackBundle, fallback_bundle: LazyFallbackBundle,
pretty: bool, pretty: bool,
json_rendered: HumanReadableErrorType, json_rendered: HumanReadableErrorType,
diagnostic_width: Option<usize>,
macro_backtrace: bool,
track_diagnostics: bool,
terminal_url: TerminalUrl,
) -> JsonEmitter { ) -> JsonEmitter {
JsonEmitter { JsonEmitter {
dst: IntoDynSyncSend(dst), dst: IntoDynSyncSend(dst),
registry, registry: None,
sm: source_map, sm,
fluent_bundle, fluent_bundle: None,
fallback_bundle, fallback_bundle,
pretty, pretty,
ui_testing: false, ui_testing: false,
ignored_directories_in_source_blocks: Vec::new(), ignored_directories_in_source_blocks: Vec::new(),
json_rendered, json_rendered,
diagnostic_width, diagnostic_width: None,
macro_backtrace, macro_backtrace: false,
track_diagnostics, track_diagnostics: false,
terminal_url, terminal_url: TerminalUrl::No,
} }
} }
pub fn ui_testing(self, ui_testing: bool) -> Self {
Self { ui_testing, ..self }
}
pub fn ignored_directories_in_source_blocks(self, value: Vec<String>) -> Self {
Self { ignored_directories_in_source_blocks: value, ..self }
}
fn emit(&mut self, val: EmitTyped<'_>) -> io::Result<()> { fn emit(&mut self, val: EmitTyped<'_>) -> io::Result<()> {
if self.pretty { if self.pretty {
serde_json::to_writer_pretty(&mut *self.dst, &val)? serde_json::to_writer_pretty(&mut *self.dst, &val)?
@ -162,7 +101,7 @@ enum EmitTyped<'a> {
Diagnostic(Diagnostic), Diagnostic(Diagnostic),
Artifact(ArtifactNotification<'a>), Artifact(ArtifactNotification<'a>),
FutureIncompat(FutureIncompatReport<'a>), FutureIncompat(FutureIncompatReport<'a>),
UnusedExtern(UnusedExterns<'a, 'a, 'a>), UnusedExtern(UnusedExterns<'a>),
} }
impl Translate for JsonEmitter { impl Translate for JsonEmitter {
@ -332,14 +271,15 @@ struct FutureIncompatReport<'a> {
// We could unify this struct the one in rustdoc but they have different // We could unify this struct the one in rustdoc but they have different
// ownership semantics, so doing so would create wasteful allocations. // ownership semantics, so doing so would create wasteful allocations.
#[derive(Serialize)] #[derive(Serialize)]
struct UnusedExterns<'a, 'b, 'c> { struct UnusedExterns<'a> {
/// The severity level of the unused dependencies lint /// The severity level of the unused dependencies lint
lint_level: &'a str, lint_level: &'a str,
/// List of unused externs by their names. /// List of unused externs by their names.
unused_extern_names: &'b [&'c str], unused_extern_names: &'a [&'a str],
} }
impl Diagnostic { impl Diagnostic {
/// Converts from `rustc_errors::DiagInner` to `Diagnostic`.
fn from_errors_diagnostic(diag: crate::DiagInner, je: &JsonEmitter) -> Diagnostic { fn from_errors_diagnostic(diag: crate::DiagInner, je: &JsonEmitter) -> Diagnostic {
let args = to_fluent_args(diag.args.iter()); let args = to_fluent_args(diag.args.iter());
let sugg = diag.suggestions.iter().flatten().map(|sugg| { let sugg = diag.suggestions.iter().flatten().map(|sugg| {
@ -405,9 +345,14 @@ impl Diagnostic {
.collect(); .collect();
let buf = BufWriter::default(); let buf = BufWriter::default();
let output = buf.clone(); let mut dst: Destination = Box::new(buf.clone());
je.json_rendered let (short, color_config) = je.json_rendered.unzip();
.new_emitter(Box::new(buf), je.fallback_bundle.clone()) match color_config {
ColorConfig::Always | ColorConfig::Auto => dst = Box::new(termcolor::Ansi::new(dst)),
ColorConfig::Never => {}
}
HumanEmitter::new(dst, je.fallback_bundle.clone())
.short_message(short)
.sm(Some(je.sm.clone())) .sm(Some(je.sm.clone()))
.fluent_bundle(je.fluent_bundle.clone()) .fluent_bundle(je.fluent_bundle.clone())
.diagnostic_width(je.diagnostic_width) .diagnostic_width(je.diagnostic_width)
@ -417,8 +362,8 @@ impl Diagnostic {
.ui_testing(je.ui_testing) .ui_testing(je.ui_testing)
.ignored_directories_in_source_blocks(je.ignored_directories_in_source_blocks.clone()) .ignored_directories_in_source_blocks(je.ignored_directories_in_source_blocks.clone())
.emit_diagnostic(diag); .emit_diagnostic(diag);
let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap(); let buf = Arc::try_unwrap(buf.0).unwrap().into_inner().unwrap();
let output = String::from_utf8(output).unwrap(); let buf = String::from_utf8(buf).unwrap();
Diagnostic { Diagnostic {
message: translated_message.to_string(), message: translated_message.to_string(),
@ -426,7 +371,7 @@ impl Diagnostic {
level, level,
spans, spans,
children, children,
rendered: Some(output), rendered: Some(buf),
} }
} }

View file

@ -1,7 +1,7 @@
use super::*; use super::*;
use crate::emitter::ColorConfig;
use crate::DiagCtxt; use crate::DiagCtxt;
use rustc_span::source_map::FilePathMapping;
use rustc_span::BytePos; use rustc_span::BytePos;
use std::str; use std::str;
@ -48,20 +48,14 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
let output = Arc::new(Mutex::new(Vec::new())); let output = Arc::new(Mutex::new(Vec::new()));
let je = JsonEmitter::new( let je = JsonEmitter::new(
Box::new(Shared { data: output.clone() }), Box::new(Shared { data: output.clone() }),
None,
sm, sm,
None,
fallback_bundle, fallback_bundle,
true, true, // pretty
HumanReadableErrorType::Short(ColorConfig::Never), HumanReadableErrorType::Short(ColorConfig::Never),
None,
false,
false,
TerminalUrl::No,
); );
let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1)); let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1));
let dcx = DiagCtxt::with_emitter(Box::new(je)); let dcx = DiagCtxt::new(Box::new(je));
dcx.span_err(span, "foo"); dcx.span_err(span, "foo");
let bytes = output.lock().unwrap(); let bytes = output.lock().unwrap();

View file

@ -59,11 +59,11 @@ pub use snippet::Style;
// See https://github.com/rust-lang/rust/pull/115393. // See https://github.com/rust-lang/rust/pull/115393.
pub use termcolor::{Color, ColorSpec, WriteColor}; pub use termcolor::{Color, ColorSpec, WriteColor};
use emitter::{is_case_difference, DynEmitter, Emitter, HumanEmitter}; use emitter::{is_case_difference, DynEmitter, Emitter};
use registry::Registry; use registry::Registry;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::stable_hasher::{Hash128, StableHasher}; use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
use rustc_data_structures::sync::{Lock, Lrc}; use rustc_data_structures::sync::Lock;
use rustc_data_structures::AtomicRef; use rustc_data_structures::AtomicRef;
use rustc_lint_defs::LintExpectationId; use rustc_lint_defs::LintExpectationId;
use rustc_span::source_map::SourceMap; use rustc_span::source_map::SourceMap;
@ -217,10 +217,10 @@ impl CodeSuggestion {
use rustc_span::{CharPos, Pos}; use rustc_span::{CharPos, Pos};
/// Extracts a substring from the provided `line_opt` based on the specified low and high indices, /// Extracts a substring from the provided `line_opt` based on the specified low and high
/// appends it to the given buffer `buf`, and returns the count of newline characters in the substring /// indices, appends it to the given buffer `buf`, and returns the count of newline
/// for accurate highlighting. /// characters in the substring for accurate highlighting. If `line_opt` is `None`, a
/// If `line_opt` is `None`, a newline character is appended to the buffer, and 0 is returned. /// newline character is appended to the buffer, and 0 is returned.
/// ///
/// ## Returns /// ## Returns
/// ///
@ -482,8 +482,8 @@ struct DiagCtxtInner {
/// have been converted. /// have been converted.
check_unstable_expect_diagnostics: bool, check_unstable_expect_diagnostics: bool,
/// Expected [`DiagInner`][struct@diagnostic::DiagInner]s store a [`LintExpectationId`] as part of /// Expected [`DiagInner`][struct@diagnostic::DiagInner]s store a [`LintExpectationId`] as part
/// the lint level. [`LintExpectationId`]s created early during the compilation /// of the lint level. [`LintExpectationId`]s created early during the compilation
/// (before `HirId`s have been defined) are not stable and can therefore not be /// (before `HirId`s have been defined) are not stable and can therefore not be
/// stored on disk. This buffer stores these diagnostics until the ID has been /// stored on disk. This buffer stores these diagnostics until the ID has been
/// replaced by a stable [`LintExpectationId`]. The [`DiagInner`][struct@diagnostic::DiagInner]s /// replaced by a stable [`LintExpectationId`]. The [`DiagInner`][struct@diagnostic::DiagInner]s
@ -590,13 +590,6 @@ impl Drop for DiagCtxtInner {
} }
impl DiagCtxt { impl DiagCtxt {
pub fn with_tty_emitter(
sm: Option<Lrc<SourceMap>>,
fallback_bundle: LazyFallbackBundle,
) -> Self {
let emitter = Box::new(HumanEmitter::stderr(ColorConfig::Auto, fallback_bundle).sm(sm));
Self::with_emitter(emitter)
}
pub fn disable_warnings(mut self) -> Self { pub fn disable_warnings(mut self) -> Self {
self.inner.get_mut().flags.can_emit_warnings = false; self.inner.get_mut().flags.can_emit_warnings = false;
self self
@ -612,7 +605,7 @@ impl DiagCtxt {
self self
} }
pub fn with_emitter(emitter: Box<DynEmitter>) -> Self { pub fn new(emitter: Box<DynEmitter>) -> Self {
Self { Self {
inner: Lock::new(DiagCtxtInner { inner: Lock::new(DiagCtxtInner {
flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() }, flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },

View file

@ -33,7 +33,7 @@ fn create_test_handler() -> (DiagCtxt, Lrc<SourceMap>, Arc<Mutex<Vec<u8>>>) {
let emitter = HumanEmitter::new(Box::new(Shared { data: output.clone() }), fallback_bundle) let emitter = HumanEmitter::new(Box::new(Shared { data: output.clone() }), fallback_bundle)
.sm(Some(source_map.clone())) .sm(Some(source_map.clone()))
.diagnostic_width(Some(140)); .diagnostic_width(Some(140));
let dcx = DiagCtxt::with_emitter(Box::new(emitter)); let dcx = DiagCtxt::new(Box::new(emitter));
(dcx, source_map, output) (dcx, source_map, output)
} }

View file

@ -13,9 +13,10 @@ use crate::Session;
use rustc_ast::node_id::NodeId; use rustc_ast::node_id::NodeId;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc}; use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc};
use rustc_errors::{emitter::SilentEmitter, DiagCtxt}; use rustc_errors::emitter::{stderr_destination, HumanEmitter, SilentEmitter};
use rustc_errors::{ use rustc_errors::{
fallback_fluent_bundle, Diag, DiagnosticMessage, EmissionGuarantee, MultiSpan, StashKey, fallback_fluent_bundle, ColorConfig, Diag, DiagCtxt, DiagnosticMessage, EmissionGuarantee,
MultiSpan, StashKey,
}; };
use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures}; use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
use rustc_span::edition::Edition; use rustc_span::edition::Edition;
@ -235,7 +236,11 @@ impl ParseSess {
pub fn new(locale_resources: Vec<&'static str>, file_path_mapping: FilePathMapping) -> Self { pub fn new(locale_resources: Vec<&'static str>, file_path_mapping: FilePathMapping) -> Self {
let fallback_bundle = fallback_fluent_bundle(locale_resources, false); let fallback_bundle = fallback_fluent_bundle(locale_resources, false);
let sm = Lrc::new(SourceMap::new(file_path_mapping)); let sm = Lrc::new(SourceMap::new(file_path_mapping));
let dcx = DiagCtxt::with_tty_emitter(Some(sm.clone()), fallback_bundle); let emitter = Box::new(
HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle)
.sm(Some(sm.clone())),
);
let dcx = DiagCtxt::new(emitter);
ParseSess::with_dcx(dcx, sm) ParseSess::with_dcx(dcx, sm)
} }
@ -264,9 +269,11 @@ impl ParseSess {
pub fn with_silent_emitter(fatal_note: String) -> Self { pub fn with_silent_emitter(fatal_note: String) -> Self {
let fallback_bundle = fallback_fluent_bundle(Vec::new(), false); let fallback_bundle = fallback_fluent_bundle(Vec::new(), false);
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
let fatal_dcx = DiagCtxt::with_tty_emitter(None, fallback_bundle).disable_warnings(); let emitter =
let dcx = DiagCtxt::with_emitter(Box::new(SilentEmitter { fatal_dcx, fatal_note })) Box::new(HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle));
.disable_warnings(); let fatal_dcx = DiagCtxt::new(emitter);
let dcx =
DiagCtxt::new(Box::new(SilentEmitter { fatal_dcx, fatal_note })).disable_warnings();
ParseSess::with_dcx(dcx, sm) ParseSess::with_dcx(dcx, sm)
} }

View file

@ -18,7 +18,7 @@ use rustc_data_structures::sync::{
AtomicU64, DynSend, DynSync, Lock, Lrc, MappedReadGuard, ReadGuard, RwLock, AtomicU64, DynSend, DynSync, Lock, Lrc, MappedReadGuard, ReadGuard, RwLock,
}; };
use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter;
use rustc_errors::emitter::{DynEmitter, HumanEmitter, HumanReadableErrorType}; use rustc_errors::emitter::{stderr_destination, DynEmitter, HumanEmitter, HumanReadableErrorType};
use rustc_errors::json::JsonEmitter; use rustc_errors::json::JsonEmitter;
use rustc_errors::registry::Registry; use rustc_errors::registry::Registry;
use rustc_errors::{ use rustc_errors::{
@ -28,7 +28,7 @@ use rustc_errors::{
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
pub use rustc_span::def_id::StableCrateId; pub use rustc_span::def_id::StableCrateId;
use rustc_span::edition::Edition; use rustc_span::edition::Edition;
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap}; use rustc_span::source_map::{FileLoader, FilePathMapping, RealFileLoader, SourceMap};
use rustc_span::{SourceFileHashAlgorithm, Span, Symbol}; use rustc_span::{SourceFileHashAlgorithm, Span, Symbol};
use rustc_target::asm::InlineAsmArch; use rustc_target::asm::InlineAsmArch;
use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel}; use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
@ -39,6 +39,7 @@ use rustc_target::spec::{
use std::any::Any; use std::any::Any;
use std::env; use std::env;
use std::fmt; use std::fmt;
use std::io;
use std::ops::{Div, Mul}; use std::ops::{Div, Mul};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::str::FromStr; use std::str::FromStr;
@ -982,7 +983,7 @@ fn default_emitter(
); );
Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing)) Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing))
} else { } else {
let emitter = HumanEmitter::stderr(color_config, fallback_bundle) let emitter = HumanEmitter::new(stderr_destination(color_config), fallback_bundle)
.fluent_bundle(bundle) .fluent_bundle(bundle)
.sm(Some(source_map)) .sm(Some(source_map))
.short_message(short) .short_message(short)
@ -998,22 +999,23 @@ fn default_emitter(
} }
} }
config::ErrorOutputType::Json { pretty, json_rendered } => Box::new( config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(
JsonEmitter::stderr( JsonEmitter::new(
Some(registry), Box::new(io::BufWriter::new(io::stderr())),
source_map, source_map,
bundle,
fallback_bundle, fallback_bundle,
pretty, pretty,
json_rendered, json_rendered,
sopts.diagnostic_width,
macro_backtrace,
track_diagnostics,
terminal_url,
) )
.registry(Some(registry))
.fluent_bundle(bundle)
.ui_testing(sopts.unstable_opts.ui_testing) .ui_testing(sopts.unstable_opts.ui_testing)
.ignored_directories_in_source_blocks( .ignored_directories_in_source_blocks(
sopts.unstable_opts.ignore_directory_in_diagnostics_source_blocks.clone(), sopts.unstable_opts.ignore_directory_in_diagnostics_source_blocks.clone(),
), )
.diagnostic_width(sopts.diagnostic_width)
.macro_backtrace(macro_backtrace)
.track_diagnostics(track_diagnostics)
.terminal_url(terminal_url),
), ),
} }
} }
@ -1080,8 +1082,8 @@ pub fn build_session(
); );
let emitter = default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle); let emitter = default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle);
let mut dcx = DiagCtxt::with_emitter(emitter) let mut dcx =
.with_flags(sopts.unstable_opts.dcx_flags(can_emit_warnings)); DiagCtxt::new(emitter).with_flags(sopts.unstable_opts.dcx_flags(can_emit_warnings));
if let Some(ice_file) = ice_file { if let Some(ice_file) = ice_file {
dcx = dcx.with_ice_file(ice_file); dcx = dcx.with_ice_file(ice_file);
} }
@ -1402,7 +1404,7 @@ pub struct EarlyDiagCtxt {
impl EarlyDiagCtxt { impl EarlyDiagCtxt {
pub fn new(output: ErrorOutputType) -> Self { pub fn new(output: ErrorOutputType) -> Self {
let emitter = mk_emitter(output); let emitter = mk_emitter(output);
Self { dcx: DiagCtxt::with_emitter(emitter) } Self { dcx: DiagCtxt::new(emitter) }
} }
/// Swap out the underlying dcx once we acquire the user's preference on error emission /// Swap out the underlying dcx once we acquire the user's preference on error emission
@ -1412,7 +1414,7 @@ impl EarlyDiagCtxt {
self.dcx.abort_if_errors(); self.dcx.abort_if_errors();
let emitter = mk_emitter(output); let emitter = mk_emitter(output);
self.dcx = DiagCtxt::with_emitter(emitter); self.dcx = DiagCtxt::new(emitter);
} }
#[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::untranslatable_diagnostic)]
@ -1473,17 +1475,17 @@ fn mk_emitter(output: ErrorOutputType) -> Box<DynEmitter> {
let emitter: Box<DynEmitter> = match output { let emitter: Box<DynEmitter> = match output {
config::ErrorOutputType::HumanReadable(kind) => { config::ErrorOutputType::HumanReadable(kind) => {
let (short, color_config) = kind.unzip(); let (short, color_config) = kind.unzip();
Box::new(HumanEmitter::stderr(color_config, fallback_bundle).short_message(short)) Box::new(
HumanEmitter::new(stderr_destination(color_config), fallback_bundle)
.short_message(short),
)
} }
config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(JsonEmitter::basic( config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(JsonEmitter::new(
Box::new(io::BufWriter::new(io::stderr())),
Lrc::new(SourceMap::new(FilePathMapping::empty())),
fallback_bundle,
pretty, pretty,
json_rendered, json_rendered,
None,
fallback_bundle,
None,
false,
false,
TerminalUrl::No,
)), )),
}; };
emitter emitter

View file

@ -1,7 +1,7 @@
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_data_structures::unord::UnordSet; use rustc_data_structures::unord::UnordSet;
use rustc_errors::emitter::{DynEmitter, HumanEmitter}; use rustc_errors::emitter::{stderr_destination, DynEmitter, HumanEmitter};
use rustc_errors::json::JsonEmitter; use rustc_errors::json::JsonEmitter;
use rustc_errors::{codes::*, ErrorGuaranteed, TerminalUrl}; use rustc_errors::{codes::*, ErrorGuaranteed, TerminalUrl};
use rustc_feature::UnstableFeatures; use rustc_feature::UnstableFeatures;
@ -20,6 +20,7 @@ use rustc_span::symbol::sym;
use rustc_span::{source_map, Span}; use rustc_span::{source_map, Span};
use std::cell::RefCell; use std::cell::RefCell;
use std::io;
use std::mem; use std::mem;
use std::rc::Rc; use std::rc::Rc;
use std::sync::LazyLock; use std::sync::LazyLock;
@ -141,7 +142,7 @@ pub(crate) fn new_dcx(
ErrorOutputType::HumanReadable(kind) => { ErrorOutputType::HumanReadable(kind) => {
let (short, color_config) = kind.unzip(); let (short, color_config) = kind.unzip();
Box::new( Box::new(
HumanEmitter::stderr(color_config, fallback_bundle) HumanEmitter::new(stderr_destination(color_config), fallback_bundle)
.sm(source_map.map(|sm| sm as _)) .sm(source_map.map(|sm| sm as _))
.short_message(short) .short_message(short)
.teach(unstable_opts.teach) .teach(unstable_opts.teach)
@ -155,24 +156,22 @@ pub(crate) fn new_dcx(
Lrc::new(source_map::SourceMap::new(source_map::FilePathMapping::empty())) Lrc::new(source_map::SourceMap::new(source_map::FilePathMapping::empty()))
}); });
Box::new( Box::new(
JsonEmitter::stderr( JsonEmitter::new(
None, Box::new(io::BufWriter::new(io::stderr())),
source_map, source_map,
None,
fallback_bundle, fallback_bundle,
pretty, pretty,
json_rendered, json_rendered,
diagnostic_width,
false,
unstable_opts.track_diagnostics,
TerminalUrl::No,
) )
.ui_testing(unstable_opts.ui_testing), .ui_testing(unstable_opts.ui_testing)
.diagnostic_width(diagnostic_width)
.track_diagnostics(unstable_opts.track_diagnostics)
.terminal_url(TerminalUrl::No),
) )
} }
}; };
rustc_errors::DiagCtxt::with_emitter(emitter).with_flags(unstable_opts.dcx_flags(true)) rustc_errors::DiagCtxt::new(emitter).with_flags(unstable_opts.dcx_flags(true))
} }
/// Parse, resolve, and typecheck the given crate. /// Parse, resolve, and typecheck the given crate.

View file

@ -1,6 +1,7 @@
use rustc_ast as ast; use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_errors::emitter::stderr_destination;
use rustc_errors::{ColorConfig, ErrorGuaranteed, FatalError}; use rustc_errors::{ColorConfig, ErrorGuaranteed, FatalError};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::{self as hir, intravisit, CRATE_HIR_ID}; use rustc_hir::{self as hir, intravisit, CRATE_HIR_ID};
@ -576,14 +577,14 @@ pub(crate) fn make_test(
rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
false, false,
); );
supports_color = HumanEmitter::stderr(ColorConfig::Auto, fallback_bundle.clone()) supports_color =
.diagnostic_width(Some(80)) HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle.clone())
.supports_color(); .supports_color();
let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle); let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);
// FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
let dcx = DiagCtxt::with_emitter(Box::new(emitter)).disable_warnings(); let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
let sess = ParseSess::with_dcx(dcx, sm); let sess = ParseSess::with_dcx(dcx, sm);
let mut found_main = false; let mut found_main = false;
@ -768,7 +769,7 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle); let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);
let dcx = DiagCtxt::with_emitter(Box::new(emitter)).disable_warnings(); let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
let sess = ParseSess::with_dcx(dcx, sm); let sess = ParseSess::with_dcx(dcx, sm);
let mut parser = let mut parser =
match maybe_new_parser_from_source_str(&sess, filename, source.to_owned()) { match maybe_new_parser_from_source_str(&sess, filename, source.to_owned()) {

View file

@ -42,7 +42,7 @@ fn check_rust_syntax(
let emitter = BufferEmitter { buffer: Lrc::clone(&buffer), fallback_bundle }; let emitter = BufferEmitter { buffer: Lrc::clone(&buffer), fallback_bundle };
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
let dcx = DiagCtxt::with_emitter(Box::new(emitter)).disable_warnings(); let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
let source = dox[code_block.code].to_owned(); let source = dox[code_block.code].to_owned();
let sess = ParseSess::with_dcx(dcx, sm); let sess = ParseSess::with_dcx(dcx, sm);

View file

@ -45,7 +45,7 @@ pub fn check(
let fallback_bundle = let fallback_bundle =
rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false); rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false);
let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle); let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);
let dcx = DiagCtxt::with_emitter(Box::new(emitter)).disable_warnings(); let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
#[expect(clippy::arc_with_non_send_sync)] // `Lrc` is expected by with_dcx #[expect(clippy::arc_with_non_send_sync)] // `Lrc` is expected by with_dcx
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
let sess = ParseSess::with_dcx(dcx, sm); let sess = ParseSess::with_dcx(dcx, sm);

View file

@ -3,7 +3,7 @@ use std::path::Path;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use rustc_data_structures::sync::{IntoDynSyncSend, Lrc}; use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter}; use rustc_errors::emitter::{stderr_destination, DynEmitter, Emitter, HumanEmitter};
use rustc_errors::translation::Translate; use rustc_errors::translation::Translate;
use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel}; use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel};
use rustc_session::parse::ParseSess as RawParseSess; use rustc_session::parse::ParseSess as RawParseSess;
@ -150,9 +150,12 @@ fn default_dcx(
rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
false, false,
); );
Box::new(HumanEmitter::stderr(emit_color, fallback_bundle).sm(Some(source_map.clone()))) Box::new(
HumanEmitter::new(stderr_destination(emit_color), fallback_bundle)
.sm(Some(source_map.clone())),
)
}; };
DiagCtxt::with_emitter(Box::new(SilentOnIgnoredFilesEmitter { DiagCtxt::new(Box::new(SilentOnIgnoredFilesEmitter {
has_non_ignorable_parser_errors: false, has_non_ignorable_parser_errors: false,
source_map, source_map,
emitter, emitter,
@ -229,7 +232,7 @@ impl ParseSess {
} }
pub(crate) fn set_silent_emitter(&mut self) { pub(crate) fn set_silent_emitter(&mut self) {
self.parse_sess.dcx = DiagCtxt::with_emitter(silent_emitter()); self.parse_sess.dcx = DiagCtxt::new(silent_emitter());
} }
pub(crate) fn span_to_filename(&self, span: Span) -> FileName { pub(crate) fn span_to_filename(&self, span: Span) -> FileName {