Replace Registry type with a lazily initialized static

And move try_find_description to rustc_errors::codes.
This commit is contained in:
bjorn3 2026-02-04 19:52:53 +00:00
parent 1851937577
commit 639cb694df
11 changed files with 73 additions and 90 deletions

View file

@ -1981,11 +1981,7 @@ impl SharedEmitter {
}
impl Emitter for SharedEmitter {
fn emit_diagnostic(
&mut self,
mut diag: rustc_errors::DiagInner,
_registry: &rustc_errors::registry::Registry,
) {
fn emit_diagnostic(&mut self, mut diag: rustc_errors::DiagInner) {
// Check that we aren't missing anything interesting when converting to
// the cut-down local `DiagInner`.
assert!(!diag.span.has_span_labels());

View file

@ -34,7 +34,6 @@ use rustc_data_structures::profiling::{
};
pub use rustc_errors::catch_fatal_errors;
use rustc_errors::emitter::stderr_destination;
use rustc_errors::registry::Registry;
use rustc_errors::translation::Translator;
use rustc_errors::{ColorConfig, DiagCtxt, ErrCode, PResult, markdown};
use rustc_feature::find_gated_cfg;
@ -451,13 +450,11 @@ pub enum Compilation {
}
fn handle_explain(early_dcx: &EarlyDiagCtxt, code: &str, color: ColorConfig) {
let registry = Registry::new();
// Allow "E0123" or "0123" form.
let upper_cased_code = code.to_ascii_uppercase();
if let Ok(code) = upper_cased_code.trim_prefix('E').parse::<u32>()
&& code <= ErrCode::MAX_AS_U32
&& let Ok(description) = registry.try_find_description(ErrCode::from_u32(code))
&& let Ok(description) = rustc_errors::codes::try_find_description(ErrCode::from_u32(code))
{
let mut is_in_code_block = false;
let mut text = String::new();

View file

@ -27,7 +27,6 @@ use crate::emitter::{
ConfusionType, Destination, MAX_SUGGESTIONS, OutputTheme, detect_confusion_type, is_different,
normalize_whitespace, should_show_source_code,
};
use crate::registry::Registry;
use crate::translation::{Translator, to_fluent_args};
use crate::{
CodeSuggestion, DiagInner, DiagMessage, Emitter, ErrCode, Level, MultiSpan, Style, Subdiag,
@ -73,7 +72,7 @@ impl Debug for AnnotateSnippetEmitter {
impl Emitter for AnnotateSnippetEmitter {
/// The entry point for the diagnostics generation
fn emit_diagnostic(&mut self, mut diag: DiagInner, _registry: &Registry) {
fn emit_diagnostic(&mut self, mut diag: DiagInner) {
let fluent_args = to_fluent_args(diag.args.iter());
if self.track_diagnostics && diag.span.has_primary_spans() && !diag.span.is_dummy() {

View file

@ -5,6 +5,9 @@
//! long description text.
use std::fmt;
use std::sync::LazyLock;
use rustc_data_structures::fx::FxHashMap;
rustc_index::newtype_index! {
#[max = 9999] // Because all error codes have four digits.
@ -27,15 +30,28 @@ macro_rules! define_error_code_constants_and_diagnostics_table {
$(
pub const ${concat(E, $num)}: $crate::ErrCode = $crate::ErrCode::from_u32($num);
)*
pub(crate) static DIAGNOSTICS: &[($crate::ErrCode, &str)] = &[
$( (
${concat(E, $num)},
include_str!(
concat!("../../rustc_error_codes/src/error_codes/E", stringify!($num), ".md")
)
), )*
];
static DIAGNOSTICS: LazyLock<FxHashMap<ErrCode, &'static str>> = LazyLock::new(|| {
[
$( (
${concat(E, $num)},
include_str!(
concat!("../../rustc_error_codes/src/error_codes/E", stringify!($num), ".md")
)
), )*
]
.iter()
.copied()
.collect()
});
)
}
rustc_error_codes::error_codes!(define_error_code_constants_and_diagnostics_table);
#[derive(Debug)]
pub struct InvalidErrorCode;
/// Returns `InvalidErrorCode` if the code requested does not exist.
pub fn try_find_description(code: ErrCode) -> Result<&'static str, InvalidErrorCode> {
DIAGNOSTICS.get(&code).copied().ok_or(InvalidErrorCode)
}

View file

@ -24,7 +24,6 @@ use rustc_span::source_map::SourceMap;
use rustc_span::{FileName, SourceFile, Span};
use tracing::{debug, warn};
use crate::registry::Registry;
use crate::timings::TimingRecord;
use crate::translation::Translator;
use crate::{
@ -54,7 +53,7 @@ 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);
fn emit_diagnostic(&mut self, diag: DiagInner);
/// Emit a notification that an artifact has been output.
/// Currently only supported for the JSON format.
@ -66,7 +65,7 @@ pub trait Emitter {
/// 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) {}
fn emit_future_breakage_report(&mut self, _diags: Vec<DiagInner>) {}
/// Emit list of unused externs.
/// Currently only supported for the JSON format.
@ -380,9 +379,9 @@ impl Emitter for EmitterWithNote {
None
}
fn emit_diagnostic(&mut self, mut diag: DiagInner, registry: &Registry) {
fn emit_diagnostic(&mut self, mut diag: DiagInner) {
diag.sub(Level::Note, self.note.clone(), MultiSpan::new());
self.emitter.emit_diagnostic(diag, registry);
self.emitter.emit_diagnostic(diag);
}
fn translator(&self) -> &Translator {
@ -399,7 +398,7 @@ impl Emitter for SilentEmitter {
None
}
fn emit_diagnostic(&mut self, _diag: DiagInner, _registry: &Registry) {}
fn emit_diagnostic(&mut self, _diag: DiagInner) {}
fn translator(&self) -> &Translator {
&self.translator

View file

@ -31,7 +31,6 @@ use crate::emitter::{
ColorConfig, Destination, Emitter, HumanReadableErrorType, OutputTheme, TimingEvent,
should_show_source_code,
};
use crate::registry::Registry;
use crate::timings::{TimingRecord, TimingSection};
use crate::translation::{Translator, to_fluent_args};
use crate::{CodeSuggestion, MultiSpan, SpanLabel, Subdiag, Suggestions, TerminalUrl};
@ -107,8 +106,8 @@ enum EmitTyped<'a> {
}
impl Emitter for JsonEmitter {
fn emit_diagnostic(&mut self, diag: crate::DiagInner, registry: &Registry) {
let data = Diagnostic::from_errors_diagnostic(diag, self, registry);
fn emit_diagnostic(&mut self, diag: crate::DiagInner) {
let data = Diagnostic::from_errors_diagnostic(diag, self);
let result = self.emit(EmitTyped::Diagnostic(data));
if let Err(e) = result {
panic!("failed to print diagnostics: {e:?}");
@ -139,7 +138,7 @@ impl Emitter for JsonEmitter {
}
}
fn emit_future_breakage_report(&mut self, diags: Vec<crate::DiagInner>, registry: &Registry) {
fn emit_future_breakage_report(&mut self, diags: Vec<crate::DiagInner>) {
let data: Vec<FutureBreakageItem<'_>> = diags
.into_iter()
.map(|mut diag| {
@ -153,7 +152,7 @@ impl Emitter for JsonEmitter {
}
FutureBreakageItem {
diagnostic: EmitTyped::Diagnostic(Diagnostic::from_errors_diagnostic(
diag, self, registry,
diag, self,
)),
}
})
@ -307,11 +306,7 @@ struct UnusedExterns<'a> {
impl Diagnostic {
/// Converts from `rustc_errors::DiagInner` to `Diagnostic`.
fn from_errors_diagnostic(
diag: crate::DiagInner,
je: &JsonEmitter,
registry: &Registry,
) -> Diagnostic {
fn from_errors_diagnostic(diag: crate::DiagInner, je: &JsonEmitter) -> Diagnostic {
let args = to_fluent_args(diag.args.iter());
let sugg_to_diag = |sugg: &CodeSuggestion| {
let translated_message =
@ -351,7 +346,7 @@ impl Diagnostic {
let code = if let Some(code) = diag.code {
Some(DiagnosticCode {
code: code.to_string(),
explanation: registry.try_find_description(code).ok(),
explanation: crate::codes::try_find_description(code).ok(),
})
} else if let Some(IsLint { name, .. }) = &diag.is_lint {
Some(DiagnosticCode { code: name.to_string(), explanation: None })
@ -388,7 +383,7 @@ impl Diagnostic {
.ui_testing(je.ui_testing)
.ignored_directories_in_source_blocks(je.ignored_directories_in_source_blocks.clone())
.theme(if je.json_rendered.unicode { OutputTheme::Unicode } else { OutputTheme::Ascii })
.emit_diagnostic(diag, registry);
.emit_diagnostic(diag);
let buf = Arc::try_unwrap(buf.0).unwrap().into_inner().unwrap();
let buf = String::from_utf8(buf).unwrap();

View file

@ -71,7 +71,6 @@ use rustc_span::{DUMMY_SP, Span};
use tracing::debug;
use crate::emitter::TimingEvent;
use crate::registry::Registry;
use crate::timings::TimingRecord;
pub mod annotate_snippet_emitter_writer;
@ -84,7 +83,6 @@ pub mod error;
pub mod json;
mod lock;
pub mod markdown;
pub mod registry;
#[cfg(test)]
mod tests;
pub mod timings;
@ -299,8 +297,6 @@ impl<'a> std::ops::Deref for DiagCtxtHandle<'a> {
struct DiagCtxtInner {
flags: DiagCtxtFlags,
registry: Registry,
/// The error guarantees from all emitted errors. The length gives the error count.
err_guars: Vec<ErrorGuaranteed>,
/// The error guarantee from all emitted lint errors. The length gives the
@ -534,7 +530,6 @@ impl DiagCtxt {
let mut inner = self.inner.borrow_mut();
let DiagCtxtInner {
flags: _,
registry: _,
err_guars,
lint_err_guars,
delayed_bugs,
@ -808,7 +803,7 @@ impl<'a> DiagCtxtHandle<'a> {
.emitted_diagnostic_codes
.iter()
.filter_map(|&code| {
if inner.registry.try_find_description(code).is_ok() {
if crate::codes::try_find_description(code).is_ok() {
Some(code.to_string())
} else {
None
@ -880,7 +875,7 @@ impl<'a> DiagCtxtHandle<'a> {
let inner = &mut *self.inner.borrow_mut();
let diags = std::mem::take(&mut inner.future_breakage_diagnostics);
if !diags.is_empty() {
inner.emitter.emit_future_breakage_report(diags, &inner.registry);
inner.emitter.emit_future_breakage_report(diags);
}
}
@ -1181,7 +1176,6 @@ impl DiagCtxtInner {
fn new(emitter: Box<DynEmitter>) -> Self {
Self {
flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
registry: Registry::new(),
err_guars: Vec::new(),
lint_err_guars: Vec::new(),
delayed_bugs: Vec::new(),
@ -1357,7 +1351,7 @@ impl DiagCtxtInner {
}
self.has_printed = true;
self.emitter.emit_diagnostic(diagnostic, &self.registry);
self.emitter.emit_diagnostic(diagnostic);
}
if is_error {

View file

@ -1,23 +0,0 @@
use rustc_data_structures::fx::FxHashMap;
use crate::ErrCode;
#[derive(Debug)]
pub struct InvalidErrorCode;
#[derive(Clone)]
pub struct Registry {
long_descriptions: FxHashMap<ErrCode, &'static str>,
}
impl Registry {
pub fn new() -> Registry {
Registry { long_descriptions: crate::codes::DIAGNOSTICS.iter().copied().collect() }
}
/// Returns `InvalidErrorCode` if the code requested does not exist in the
/// registry.
pub fn try_find_description(&self, code: ErrCode) -> Result<&'static str, InvalidErrorCode> {
self.long_descriptions.get(&code).copied().ok_or(InvalidErrorCode)
}
}

View file

@ -5,7 +5,6 @@ use std::sync::Arc;
use rustc_data_structures::sync::Lock;
use rustc_errors::emitter::Emitter;
use rustc_errors::registry::Registry;
use rustc_errors::translation::{Translator, to_fluent_args};
use rustc_errors::{Applicability, DiagCtxt, DiagInner};
use rustc_parse::{source_str_to_stream, unwrap_or_emit_fatal};
@ -150,7 +149,7 @@ struct BufferEmitter {
}
impl Emitter for BufferEmitter {
fn emit_diagnostic(&mut self, diag: DiagInner, _registry: &Registry) {
fn emit_diagnostic(&mut self, diag: DiagInner) {
let mut buffer = self.buffer.borrow_mut();
let fluent_args = to_fluent_args(diag.args.iter());

View file

@ -1,10 +1,11 @@
#![feature(rustc_private)]
extern crate rustc_driver;
extern crate rustc_error_codes;
extern crate rustc_errors;
extern crate rustc_log;
extern crate rustc_session;
extern crate rustc_errors;
use std::env;
use std::error::Error;
use std::fs::{self, File};
@ -16,7 +17,22 @@ use mdbook_driver::MDBook;
use mdbook_driver::book::{BookItem, Chapter};
use mdbook_driver::config::Config;
use mdbook_summary::parse_summary;
use rustc_errors::codes::DIAGNOSTICS;
use rustc_errors::codes::ErrCode;
macro_rules! define_error_codes_table {
($($num:literal,)*) => (
static DIAGNOSTICS: &[(ErrCode, &str)] = &[
$( (
ErrCode::from_u32($num),
include_str!(
concat!("../../../compiler/rustc_error_codes/src/error_codes/E", stringify!($num), ".md")
)
), )*
];
)
}
rustc_error_codes::error_codes!(define_error_codes_table);
enum OutputFormat {
HTML,

View file

@ -5,7 +5,6 @@ use std::sync::atomic::{AtomicBool, Ordering};
use rustc_data_structures::sync::IntoDynSyncSend;
use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter;
use rustc_errors::emitter::{DynEmitter, Emitter, SilentEmitter, stderr_destination};
use rustc_errors::registry::Registry;
use rustc_errors::translation::Translator;
use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel};
use rustc_session::parse::ParseSess as RawParseSess;
@ -41,10 +40,10 @@ struct SilentOnIgnoredFilesEmitter {
}
impl SilentOnIgnoredFilesEmitter {
fn handle_non_ignoreable_error(&mut self, diag: DiagInner, registry: &Registry) {
fn handle_non_ignoreable_error(&mut self, diag: DiagInner) {
self.has_non_ignorable_parser_errors = true;
self.can_reset.store(false, Ordering::Release);
self.emitter.emit_diagnostic(diag, registry);
self.emitter.emit_diagnostic(diag);
}
}
@ -53,9 +52,9 @@ impl Emitter for SilentOnIgnoredFilesEmitter {
None
}
fn emit_diagnostic(&mut self, diag: DiagInner, registry: &Registry) {
fn emit_diagnostic(&mut self, diag: DiagInner) {
if diag.level() == DiagnosticLevel::Fatal {
return self.handle_non_ignoreable_error(diag, registry);
return self.handle_non_ignoreable_error(diag);
}
if let Some(primary_span) = &diag.span.primary_span() {
let file_name = self.source_map.span_to_filename(*primary_span);
@ -73,7 +72,7 @@ impl Emitter for SilentOnIgnoredFilesEmitter {
}
}
}
self.handle_non_ignoreable_error(diag, registry);
self.handle_non_ignoreable_error(diag);
}
fn translator(&self) -> &Translator {
@ -340,7 +339,7 @@ mod tests {
None
}
fn emit_diagnostic(&mut self, _diag: DiagInner, _registry: &Registry) {
fn emit_diagnostic(&mut self, _diag: DiagInner) {
self.num_emitted_errors.fetch_add(1, Ordering::Release);
}
@ -401,7 +400,6 @@ mod tests {
let source =
String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#);
source_map.new_source_file(filename(&source_map, "foo.rs"), source);
let registry = Registry::new();
let mut emitter = build_emitter(
Arc::clone(&num_emitted_errors),
Arc::clone(&can_reset_errors),
@ -410,7 +408,7 @@ mod tests {
);
let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1)));
let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, Some(span));
emitter.emit_diagnostic(fatal_diagnostic, &registry);
emitter.emit_diagnostic(fatal_diagnostic);
assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1);
assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
}
@ -424,7 +422,6 @@ mod tests {
let source_map = Arc::new(SourceMap::new(FilePathMapping::empty()));
let source = String::from(r#"pub fn bar() { 1x; }"#);
source_map.new_source_file(filename(&source_map, "foo.rs"), source);
let registry = Registry::new();
let mut emitter = build_emitter(
Arc::clone(&num_emitted_errors),
Arc::clone(&can_reset_errors),
@ -433,7 +430,7 @@ mod tests {
);
let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1)));
let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span));
emitter.emit_diagnostic(non_fatal_diagnostic, &registry);
emitter.emit_diagnostic(non_fatal_diagnostic);
assert_eq!(num_emitted_errors.load(Ordering::Acquire), 0);
assert_eq!(can_reset_errors.load(Ordering::Acquire), true);
}
@ -446,7 +443,6 @@ mod tests {
let source_map = Arc::new(SourceMap::new(FilePathMapping::empty()));
let source = String::from(r#"pub fn bar() { 1x; }"#);
source_map.new_source_file(filename(&source_map, "foo.rs"), source);
let registry = Registry::new();
let mut emitter = build_emitter(
Arc::clone(&num_emitted_errors),
Arc::clone(&can_reset_errors),
@ -455,7 +451,7 @@ mod tests {
);
let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1)));
let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span));
emitter.emit_diagnostic(non_fatal_diagnostic, &registry);
emitter.emit_diagnostic(non_fatal_diagnostic);
assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1);
assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
}
@ -474,7 +470,6 @@ mod tests {
source_map.new_source_file(filename(&source_map, "bar.rs"), bar_source);
source_map.new_source_file(filename(&source_map, "foo.rs"), foo_source);
source_map.new_source_file(filename(&source_map, "fatal.rs"), fatal_source);
let registry = Registry::new();
let mut emitter = build_emitter(
Arc::clone(&num_emitted_errors),
Arc::clone(&can_reset_errors),
@ -486,9 +481,9 @@ mod tests {
let bar_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(bar_span));
let foo_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(foo_span));
let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, None);
emitter.emit_diagnostic(bar_diagnostic, &registry);
emitter.emit_diagnostic(foo_diagnostic, &registry);
emitter.emit_diagnostic(fatal_diagnostic, &registry);
emitter.emit_diagnostic(bar_diagnostic);
emitter.emit_diagnostic(foo_diagnostic);
emitter.emit_diagnostic(fatal_diagnostic);
assert_eq!(num_emitted_errors.load(Ordering::Acquire), 2);
assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
}