Stop using String
for error codes.
Error codes are integers, but `String` is used everywhere to represent them. Gross! This commit introduces `ErrCode`, an integral newtype for error codes, replacing `String`. It also introduces a constant for every error code, e.g. `E0123`, and removes the `error_code!` macro. The constants are imported wherever used with `use rustc_errors::codes::*`. With the old code, we have three different ways to specify an error code at a use point: ``` error_code!(E0123) // macro call struct_span_code_err!(dcx, span, E0123, "msg"); // bare ident arg to macro call \#[diag(name, code = "E0123")] // string struct Diag; ``` With the new code, they all use the `E0123` constant. ``` E0123 // constant struct_span_code_err!(dcx, span, E0123, "msg"); // constant \#[diag(name, code = E0123)] // constant struct Diag; ``` The commit also changes the structure of the error code definitions: - `rustc_error_codes` now just defines a higher-order macro listing the used error codes and nothing else. - Because that's now the only thing in the `rustc_error_codes` crate, I moved it into the `lib.rs` file and removed the `error_codes.rs` file. - `rustc_errors` uses that macro to define everything, e.g. the error code constants and the `DIAGNOSTIC_TABLES`. This is in its new `codes.rs` file.
This commit is contained in:
parent
0321de2778
commit
5d9dfbd08f
110 changed files with 1624 additions and 1572 deletions
|
@ -9,8 +9,8 @@ use crate::emitter::FileWithAnnotatedLines;
|
|||
use crate::snippet::Line;
|
||||
use crate::translation::{to_fluent_args, Translate};
|
||||
use crate::{
|
||||
CodeSuggestion, Diagnostic, DiagnosticMessage, Emitter, FluentBundle, LazyFallbackBundle,
|
||||
Level, MultiSpan, Style, SubDiagnostic,
|
||||
CodeSuggestion, Diagnostic, DiagnosticMessage, Emitter, ErrCode, FluentBundle,
|
||||
LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic,
|
||||
};
|
||||
use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
|
@ -127,7 +127,7 @@ impl AnnotateSnippetEmitter {
|
|||
level: &Level,
|
||||
messages: &[(DiagnosticMessage, Style)],
|
||||
args: &FluentArgs<'_>,
|
||||
code: &Option<String>,
|
||||
code: &Option<ErrCode>,
|
||||
msp: &MultiSpan,
|
||||
_children: &[SubDiagnostic],
|
||||
_suggestions: &[CodeSuggestion],
|
||||
|
@ -178,6 +178,7 @@ impl AnnotateSnippetEmitter {
|
|||
.collect::<Vec<Owned>>()
|
||||
})
|
||||
.collect();
|
||||
let code = code.map(|code| code.to_string());
|
||||
let snippet = Snippet {
|
||||
title: Some(Annotation {
|
||||
label: Some(&message),
|
||||
|
|
39
compiler/rustc_errors/src/codes.rs
Normal file
39
compiler/rustc_errors/src/codes.rs
Normal file
|
@ -0,0 +1,39 @@
|
|||
//! This module defines the following.
|
||||
//! - The `ErrCode` type.
|
||||
//! - A constant for every error code, with a name like `E0123`.
|
||||
//! - A static table `DIAGNOSTICS` pairing every error code constant with its
|
||||
//! long description text.
|
||||
|
||||
use std::fmt;
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
#[max = 9999] // Because all error codes have four digits.
|
||||
#[orderable]
|
||||
#[encodable]
|
||||
#[debug_format = "ErrCode({})"]
|
||||
pub struct ErrCode {}
|
||||
}
|
||||
|
||||
impl fmt::Display for ErrCode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "E{:04}", self.as_u32())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! define_error_code_constants_and_diagnostics_table {
|
||||
($($name:ident: $num:literal,)*) => (
|
||||
$(
|
||||
pub const $name: $crate::ErrCode = $crate::ErrCode::from_u32($num);
|
||||
)*
|
||||
pub static DIAGNOSTICS: &[($crate::ErrCode, &str)] = &[
|
||||
$( (
|
||||
$name,
|
||||
include_str!(
|
||||
concat!("../../rustc_error_codes/src/error_codes/", stringify!($name), ".md")
|
||||
)
|
||||
), )*
|
||||
];
|
||||
)
|
||||
}
|
||||
|
||||
rustc_error_codes::error_codes!(define_error_code_constants_and_diagnostics_table);
|
|
@ -1,7 +1,8 @@
|
|||
use crate::snippet::Style;
|
||||
use crate::{
|
||||
CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level,
|
||||
MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
|
||||
CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee,
|
||||
ErrCode, Level, MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart,
|
||||
SuggestionStyle,
|
||||
};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||
use rustc_error_messages::fluent_value_from_str_list_sep_by_and;
|
||||
|
@ -104,7 +105,7 @@ pub struct Diagnostic {
|
|||
pub(crate) level: Level,
|
||||
|
||||
pub messages: Vec<(DiagnosticMessage, Style)>,
|
||||
pub code: Option<String>,
|
||||
pub code: Option<ErrCode>,
|
||||
pub span: MultiSpan,
|
||||
pub children: Vec<SubDiagnostic>,
|
||||
pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
|
||||
|
@ -893,8 +894,8 @@ impl Diagnostic {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn code(&mut self, s: String) -> &mut Self {
|
||||
self.code = Some(s);
|
||||
pub fn code(&mut self, code: ErrCode) -> &mut Self {
|
||||
self.code = Some(code);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -903,8 +904,8 @@ impl Diagnostic {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn get_code(&self) -> Option<&str> {
|
||||
self.code.as_deref()
|
||||
pub fn get_code(&self) -> Option<ErrCode> {
|
||||
self.code
|
||||
}
|
||||
|
||||
pub fn primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self {
|
||||
|
@ -990,7 +991,7 @@ impl Diagnostic {
|
|||
&Level,
|
||||
&[(DiagnosticMessage, Style)],
|
||||
Vec<(&Cow<'static, str>, &DiagnosticArgValue<'static>)>,
|
||||
&Option<String>,
|
||||
&Option<ErrCode>,
|
||||
&Option<IsLint>,
|
||||
&MultiSpan,
|
||||
&Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::diagnostic::IntoDiagnosticArg;
|
||||
use crate::{DiagCtxt, Level, MultiSpan, StashKey};
|
||||
use crate::{
|
||||
Diagnostic, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed, ExplicitBug,
|
||||
Diagnostic, DiagnosticMessage, DiagnosticStyledString, ErrCode, ErrorGuaranteed, ExplicitBug,
|
||||
SubdiagnosticMessage,
|
||||
};
|
||||
use rustc_lint_defs::Applicability;
|
||||
|
@ -399,7 +399,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
|||
name: String, has_future_breakage: bool,
|
||||
));
|
||||
forward!((code, with_code)(
|
||||
s: String,
|
||||
code: ErrCode,
|
||||
));
|
||||
forward!((arg, with_arg)(
|
||||
name: impl Into<Cow<'static, str>>, arg: impl IntoDiagnosticArg,
|
||||
|
@ -439,12 +439,7 @@ impl<G: EmissionGuarantee> Drop for DiagnosticBuilder<'_, G> {
|
|||
|
||||
#[macro_export]
|
||||
macro_rules! struct_span_code_err {
|
||||
($dcx:expr, $span:expr, $code:ident, $($message:tt)*) => ({
|
||||
$dcx.struct_span_err($span, format!($($message)*)).with_code($crate::error_code!($code))
|
||||
($dcx:expr, $span:expr, $code:expr, $($message:tt)*) => ({
|
||||
$dcx.struct_span_err($span, format!($($message)*)).with_code($code)
|
||||
})
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! error_code {
|
||||
($code:ident) => {{ stringify!($code).to_owned() }};
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::diagnostic::DiagnosticLocation;
|
||||
use crate::{fluent_generated as fluent, AddToDiagnostic};
|
||||
use crate::{
|
||||
DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
|
||||
DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, ErrCode, IntoDiagnostic,
|
||||
IntoDiagnosticArg, Level,
|
||||
};
|
||||
use rustc_ast as ast;
|
||||
|
@ -93,6 +93,7 @@ into_diagnostic_arg_using_display!(
|
|||
&TargetTriple,
|
||||
SplitDebuginfo,
|
||||
ExitStatus,
|
||||
ErrCode,
|
||||
);
|
||||
|
||||
into_diagnostic_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
|
||||
|
|
|
@ -17,8 +17,8 @@ use crate::styled_buffer::StyledBuffer;
|
|||
use crate::translation::{to_fluent_args, Translate};
|
||||
use crate::{
|
||||
diagnostic::DiagnosticLocation, CodeSuggestion, DiagCtxt, Diagnostic, DiagnosticMessage,
|
||||
FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight,
|
||||
SuggestionStyle, TerminalUrl,
|
||||
ErrCode, FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic,
|
||||
SubstitutionHighlight, SuggestionStyle, TerminalUrl,
|
||||
};
|
||||
use rustc_lint_defs::pluralize;
|
||||
|
||||
|
@ -1309,7 +1309,7 @@ impl HumanEmitter {
|
|||
msp: &MultiSpan,
|
||||
msgs: &[(DiagnosticMessage, Style)],
|
||||
args: &FluentArgs<'_>,
|
||||
code: &Option<String>,
|
||||
code: &Option<ErrCode>,
|
||||
level: &Level,
|
||||
max_line_num_len: usize,
|
||||
is_secondary: bool,
|
||||
|
@ -1340,9 +1340,9 @@ impl HumanEmitter {
|
|||
buffer.append(0, "[", Style::Level(*level));
|
||||
let code = if let TerminalUrl::Yes = self.terminal_url {
|
||||
let path = "https://doc.rust-lang.org/error_codes";
|
||||
Cow::Owned(format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07"))
|
||||
format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07")
|
||||
} else {
|
||||
Cow::Borrowed(code)
|
||||
code.to_string()
|
||||
};
|
||||
buffer.append(0, &code, Style::Level(*level));
|
||||
buffer.append(0, "]", Style::Level(*level));
|
||||
|
@ -2076,7 +2076,7 @@ impl HumanEmitter {
|
|||
level: &Level,
|
||||
messages: &[(DiagnosticMessage, Style)],
|
||||
args: &FluentArgs<'_>,
|
||||
code: &Option<String>,
|
||||
code: &Option<ErrCode>,
|
||||
span: &MultiSpan,
|
||||
children: &[SubDiagnostic],
|
||||
suggestions: &[CodeSuggestion],
|
||||
|
|
|
@ -400,10 +400,10 @@ impl Diagnostic {
|
|||
|
||||
let translated_message = je.translate_messages(&diag.messages, &args);
|
||||
|
||||
let code = if let Some(code) = &diag.code {
|
||||
let code = if let Some(code) = diag.code {
|
||||
Some(DiagnosticCode {
|
||||
code: code.to_string(),
|
||||
explanation: je.registry.as_ref().unwrap().try_find_description(&code).ok(),
|
||||
explanation: je.registry.as_ref().unwrap().try_find_description(code).ok(),
|
||||
})
|
||||
} else if let Some(IsLint { name, .. }) = &diag.is_lint {
|
||||
Some(DiagnosticCode { code: name.to_string(), explanation: None })
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#![feature(error_reporter)]
|
||||
#![feature(extract_if)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
@ -30,6 +31,7 @@ extern crate tracing;
|
|||
|
||||
extern crate self as rustc_errors;
|
||||
|
||||
pub use codes::*;
|
||||
pub use diagnostic::{
|
||||
AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue,
|
||||
DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
|
||||
|
@ -78,6 +80,7 @@ use std::path::{Path, PathBuf};
|
|||
use Level::*;
|
||||
|
||||
pub mod annotate_snippet_emitter_writer;
|
||||
pub mod codes;
|
||||
mod diagnostic;
|
||||
mod diagnostic_builder;
|
||||
mod diagnostic_impls;
|
||||
|
@ -446,10 +449,10 @@ struct DiagCtxtInner {
|
|||
/// This set contains the code of all emitted diagnostics to avoid
|
||||
/// emitting the same diagnostic with extended help (`--teach`) twice, which
|
||||
/// would be unnecessary repetition.
|
||||
taught_diagnostics: FxHashSet<String>,
|
||||
taught_diagnostics: FxHashSet<ErrCode>,
|
||||
|
||||
/// Used to suggest rustc --explain `<error code>`
|
||||
emitted_diagnostic_codes: FxIndexSet<String>,
|
||||
emitted_diagnostic_codes: FxIndexSet<ErrCode>,
|
||||
|
||||
/// This set contains a hash of every diagnostic that has been emitted by
|
||||
/// this `DiagCtxt`. These hashes is used to avoid emitting the same error
|
||||
|
@ -1004,9 +1007,9 @@ impl DiagCtxt {
|
|||
let mut error_codes = inner
|
||||
.emitted_diagnostic_codes
|
||||
.iter()
|
||||
.filter_map(|code| {
|
||||
.filter_map(|&code| {
|
||||
if registry.try_find_description(code).is_ok().clone() {
|
||||
Some(code.clone())
|
||||
Some(code.to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -1052,8 +1055,8 @@ impl DiagCtxt {
|
|||
///
|
||||
/// Used to suppress emitting the same error multiple times with extended explanation when
|
||||
/// calling `-Zteach`.
|
||||
pub fn must_teach(&self, code: &str) -> bool {
|
||||
self.inner.borrow_mut().taught_diagnostics.insert(code.to_string())
|
||||
pub fn must_teach(&self, code: ErrCode) -> bool {
|
||||
self.inner.borrow_mut().taught_diagnostics.insert(code)
|
||||
}
|
||||
|
||||
pub fn force_print_diagnostic(&self, db: Diagnostic) {
|
||||
|
@ -1313,8 +1316,8 @@ impl DiagCtxtInner {
|
|||
|
||||
let mut guaranteed = None;
|
||||
(*TRACK_DIAGNOSTIC)(diagnostic, &mut |mut diagnostic| {
|
||||
if let Some(ref code) = diagnostic.code {
|
||||
self.emitted_diagnostic_codes.insert(code.clone());
|
||||
if let Some(code) = diagnostic.code {
|
||||
self.emitted_diagnostic_codes.insert(code);
|
||||
}
|
||||
|
||||
let already_emitted = {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::ErrCode;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -5,17 +6,17 @@ pub struct InvalidErrorCode;
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct Registry {
|
||||
long_descriptions: FxHashMap<&'static str, &'static str>,
|
||||
long_descriptions: FxHashMap<ErrCode, &'static str>,
|
||||
}
|
||||
|
||||
impl Registry {
|
||||
pub fn new(long_descriptions: &[(&'static str, &'static str)]) -> Registry {
|
||||
pub fn new(long_descriptions: &[(ErrCode, &'static str)]) -> Registry {
|
||||
Registry { long_descriptions: long_descriptions.iter().copied().collect() }
|
||||
}
|
||||
|
||||
/// Returns `InvalidErrorCode` if the code requested does not exist in the
|
||||
/// registry.
|
||||
pub fn try_find_description(&self, code: &str) -> Result<&'static str, InvalidErrorCode> {
|
||||
self.long_descriptions.get(code).copied().ok_or(InvalidErrorCode)
|
||||
pub fn try_find_description(&self, code: ErrCode) -> Result<&'static str, InvalidErrorCode> {
|
||||
self.long_descriptions.get(&code).copied().ok_or(InvalidErrorCode)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue