Auto merge of #119922 - nnethercote:fix-Diag-code-is_lint, r=oli-obk

Rework how diagnostic lints are stored.

`Diagnostic::code` has the type `DiagnosticId`, which has `Error` and
`Lint` variants. Plus `Diagnostic::is_lint` is a bool, which should be
redundant w.r.t. `Diagnostic::code`.

Seems simple. Except it's possible for a lint to have an error code, in
which case its `code` field is recorded as `Error`, and `is_lint` is
required to indicate that it's a lint. This is what happens with
`derive(LintDiagnostic)` lints. Which means those lints don't have a
lint name or a `has_future_breakage` field because those are stored in
the `DiagnosticId::Lint`.

It's all a bit messy and confused and seems unintentional.

This commit:
- removes `DiagnosticId`;
- changes `Diagnostic::code` to `Option<String>`, which means both
  errors and lints can straightforwardly have an error code;
- changes `Diagnostic::is_lint` to `Option<IsLint>`, where `IsLint` is a
  new type containing a lint name and a `has_future_breakage` bool, so
  all lints can have those, error code or not.

r? `@oli-obk`
This commit is contained in:
bors 2024-01-17 07:33:52 +00:00
commit 16f4b02dd8
24 changed files with 111 additions and 135 deletions

View File

@ -14,7 +14,7 @@ use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard}; use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard};
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_errors::emitter::Emitter; use rustc_errors::emitter::Emitter;
use rustc_errors::{translation::Translate, DiagCtxt, DiagnosticId, FatalError, Level}; use rustc_errors::{translation::Translate, DiagCtxt, FatalError, Level};
use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, Style}; use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, Style};
use rustc_fs_util::link_or_copy; use rustc_fs_util::link_or_copy;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
@ -1000,7 +1000,7 @@ type DiagnosticArgName<'source> = Cow<'source, str>;
struct Diagnostic { struct Diagnostic {
msgs: Vec<(DiagnosticMessage, Style)>, msgs: Vec<(DiagnosticMessage, Style)>,
args: FxHashMap<DiagnosticArgName<'static>, rustc_errors::DiagnosticArgValue<'static>>, args: FxHashMap<DiagnosticArgName<'static>, rustc_errors::DiagnosticArgValue<'static>>,
code: Option<DiagnosticId>, code: Option<String>,
lvl: Level, lvl: Level,
} }

View File

@ -9,8 +9,8 @@ use crate::emitter::FileWithAnnotatedLines;
use crate::snippet::Line; use crate::snippet::Line;
use crate::translation::{to_fluent_args, Translate}; use crate::translation::{to_fluent_args, Translate};
use crate::{ use crate::{
CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle, CodeSuggestion, Diagnostic, DiagnosticMessage, Emitter, FluentBundle, LazyFallbackBundle,
LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic, Level, MultiSpan, Style, SubDiagnostic,
}; };
use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation}; use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
@ -127,7 +127,7 @@ impl AnnotateSnippetEmitter {
level: &Level, level: &Level,
messages: &[(DiagnosticMessage, Style)], messages: &[(DiagnosticMessage, Style)],
args: &FluentArgs<'_>, args: &FluentArgs<'_>,
code: &Option<DiagnosticId>, code: &Option<String>,
msp: &MultiSpan, msp: &MultiSpan,
_children: &[SubDiagnostic], _children: &[SubDiagnostic],
_suggestions: &[CodeSuggestion], _suggestions: &[CodeSuggestion],
@ -181,11 +181,7 @@ impl AnnotateSnippetEmitter {
let snippet = Snippet { let snippet = Snippet {
title: Some(Annotation { title: Some(Annotation {
label: Some(&message), label: Some(&message),
id: code.as_ref().map(|c| match c { id: code.as_deref(),
DiagnosticId::Error(val) | DiagnosticId::Lint { name: val, .. } => {
val.as_str()
}
}),
annotation_type: annotation_type_for_level(*level), annotation_type: annotation_type_for_level(*level),
}), }),
footer: vec![], footer: vec![],

View File

@ -104,7 +104,7 @@ pub struct Diagnostic {
pub(crate) level: Level, pub(crate) level: Level,
pub messages: Vec<(DiagnosticMessage, Style)>, pub messages: Vec<(DiagnosticMessage, Style)>,
pub code: Option<DiagnosticId>, pub code: Option<String>,
pub span: MultiSpan, pub span: MultiSpan,
pub children: Vec<SubDiagnostic>, pub children: Vec<SubDiagnostic>,
pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>, pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
@ -115,9 +115,9 @@ pub struct Diagnostic {
/// `span` if there is one. Otherwise, it is `DUMMY_SP`. /// `span` if there is one. Otherwise, it is `DUMMY_SP`.
pub sort_span: Span, pub sort_span: Span,
/// If diagnostic is from Lint, custom hash function ignores notes /// If diagnostic is from Lint, custom hash function ignores children.
/// otherwise hash is based on the all the fields /// Otherwise hash is based on the all the fields.
pub is_lint: bool, pub is_lint: Option<IsLint>,
/// With `-Ztrack_diagnostics` enabled, /// With `-Ztrack_diagnostics` enabled,
/// we print where in rustc this error was emitted. /// we print where in rustc this error was emitted.
@ -146,13 +146,11 @@ impl fmt::Display for DiagnosticLocation {
} }
#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
pub enum DiagnosticId { pub struct IsLint {
Error(String), /// The lint name.
Lint { pub(crate) name: String,
name: String,
/// Indicates whether this lint should show up in cargo's future breakage report. /// Indicates whether this lint should show up in cargo's future breakage report.
has_future_breakage: bool, has_future_breakage: bool,
},
} }
/// A "sub"-diagnostic attached to a parent diagnostic. /// A "sub"-diagnostic attached to a parent diagnostic.
@ -231,7 +229,7 @@ impl Diagnostic {
suggestions: Ok(vec![]), suggestions: Ok(vec![]),
args: Default::default(), args: Default::default(),
sort_span: DUMMY_SP, sort_span: DUMMY_SP,
is_lint: false, is_lint: None,
emitted_at: DiagnosticLocation::caller(), emitted_at: DiagnosticLocation::caller(),
} }
} }
@ -288,16 +286,13 @@ impl Diagnostic {
/// Indicates whether this diagnostic should show up in cargo's future breakage report. /// Indicates whether this diagnostic should show up in cargo's future breakage report.
pub(crate) fn has_future_breakage(&self) -> bool { pub(crate) fn has_future_breakage(&self) -> bool {
match self.code { matches!(self.is_lint, Some(IsLint { has_future_breakage: true, .. }))
Some(DiagnosticId::Lint { has_future_breakage, .. }) => has_future_breakage,
_ => false,
}
} }
pub(crate) fn is_force_warn(&self) -> bool { pub(crate) fn is_force_warn(&self) -> bool {
match self.level { match self.level {
Level::ForceWarning(_) => { Level::ForceWarning(_) => {
assert!(self.is_lint); assert!(self.is_lint.is_some());
true true
} }
_ => false, _ => false,
@ -893,12 +888,12 @@ impl Diagnostic {
self self
} }
pub fn is_lint(&mut self) -> &mut Self { pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self {
self.is_lint = true; self.is_lint = Some(IsLint { name, has_future_breakage });
self self
} }
pub fn code(&mut self, s: DiagnosticId) -> &mut Self { pub fn code(&mut self, s: String) -> &mut Self {
self.code = Some(s); self.code = Some(s);
self self
} }
@ -908,8 +903,8 @@ impl Diagnostic {
self self
} }
pub fn get_code(&self) -> Option<DiagnosticId> { pub fn get_code(&self) -> Option<&str> {
self.code.clone() self.code.as_deref()
} }
pub fn primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self { pub fn primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self {
@ -995,7 +990,8 @@ impl Diagnostic {
&Level, &Level,
&[(DiagnosticMessage, Style)], &[(DiagnosticMessage, Style)],
Vec<(&Cow<'static, str>, &DiagnosticArgValue<'static>)>, Vec<(&Cow<'static, str>, &DiagnosticArgValue<'static>)>,
&Option<DiagnosticId>, &Option<String>,
&Option<IsLint>,
&MultiSpan, &MultiSpan,
&Result<Vec<CodeSuggestion>, SuggestionsDisabled>, &Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
Option<&[SubDiagnostic]>, Option<&[SubDiagnostic]>,
@ -1005,9 +1001,10 @@ impl Diagnostic {
&self.messages, &self.messages,
self.args().collect(), self.args().collect(),
&self.code, &self.code,
&self.is_lint,
&self.span, &self.span,
&self.suggestions, &self.suggestions,
(if self.is_lint { None } else { Some(&self.children) }), (if self.is_lint.is_some() { None } else { Some(&self.children) }),
) )
} }
} }

View File

@ -1,8 +1,8 @@
use crate::diagnostic::IntoDiagnosticArg; use crate::diagnostic::IntoDiagnosticArg;
use crate::{DiagCtxt, Level, MultiSpan, StashKey}; use crate::{DiagCtxt, Level, MultiSpan, StashKey};
use crate::{ use crate::{
Diagnostic, DiagnosticId, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed, Diagnostic, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed, ExplicitBug,
ExplicitBug, SubdiagnosticMessage, SubdiagnosticMessage,
}; };
use rustc_lint_defs::Applicability; use rustc_lint_defs::Applicability;
use rustc_span::source_map::Spanned; use rustc_span::source_map::Spanned;
@ -395,8 +395,11 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
forward!((span, with_span)( forward!((span, with_span)(
sp: impl Into<MultiSpan>, sp: impl Into<MultiSpan>,
)); ));
forward!((is_lint, with_is_lint)(
name: String, has_future_breakage: bool,
));
forward!((code, with_code)( forward!((code, with_code)(
s: DiagnosticId, s: String,
)); ));
forward!((arg, with_arg)( forward!((arg, with_arg)(
name: impl Into<Cow<'static, str>>, arg: impl IntoDiagnosticArg, name: impl Into<Cow<'static, str>>, arg: impl IntoDiagnosticArg,
@ -437,15 +440,11 @@ impl<G: EmissionGuarantee> Drop for DiagnosticBuilder<'_, G> {
#[macro_export] #[macro_export]
macro_rules! struct_span_code_err { macro_rules! struct_span_code_err {
($dcx:expr, $span:expr, $code:ident, $($message:tt)*) => ({ ($dcx:expr, $span:expr, $code:ident, $($message:tt)*) => ({
$dcx.struct_span_err( $dcx.struct_span_err($span, format!($($message)*)).with_code($crate::error_code!($code))
$span,
format!($($message)*),
)
.with_code($crate::error_code!($code))
}) })
} }
#[macro_export] #[macro_export]
macro_rules! error_code { macro_rules! error_code {
($code:ident) => {{ $crate::DiagnosticId::Error(stringify!($code).to_owned()) }}; ($code:ident) => {{ stringify!($code).to_owned() }};
} }

View File

@ -16,9 +16,9 @@ use crate::snippet::{
use crate::styled_buffer::StyledBuffer; use crate::styled_buffer::StyledBuffer;
use crate::translation::{to_fluent_args, Translate}; use crate::translation::{to_fluent_args, Translate};
use crate::{ use crate::{
diagnostic::DiagnosticLocation, CodeSuggestion, DiagCtxt, Diagnostic, DiagnosticId, diagnostic::DiagnosticLocation, CodeSuggestion, DiagCtxt, Diagnostic, DiagnosticMessage,
DiagnosticMessage, FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight,
SubstitutionHighlight, SuggestionStyle, TerminalUrl, SuggestionStyle, TerminalUrl,
}; };
use rustc_lint_defs::pluralize; use rustc_lint_defs::pluralize;
@ -1309,7 +1309,7 @@ impl HumanEmitter {
msp: &MultiSpan, msp: &MultiSpan,
msgs: &[(DiagnosticMessage, Style)], msgs: &[(DiagnosticMessage, Style)],
args: &FluentArgs<'_>, args: &FluentArgs<'_>,
code: &Option<DiagnosticId>, code: &Option<String>,
level: &Level, level: &Level,
max_line_num_len: usize, max_line_num_len: usize,
is_secondary: bool, is_secondary: bool,
@ -1336,14 +1336,13 @@ impl HumanEmitter {
buffer.append(0, level.to_str(), Style::Level(*level)); buffer.append(0, level.to_str(), Style::Level(*level));
label_width += level.to_str().len(); label_width += level.to_str().len();
} }
// only render error codes, not lint codes if let Some(code) = code {
if let Some(DiagnosticId::Error(ref code)) = *code {
buffer.append(0, "[", Style::Level(*level)); buffer.append(0, "[", Style::Level(*level));
let code = if let TerminalUrl::Yes = self.terminal_url { let code = if let TerminalUrl::Yes = self.terminal_url {
let path = "https://doc.rust-lang.org/error_codes"; let path = "https://doc.rust-lang.org/error_codes";
format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07") Cow::Owned(format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07"))
} else { } else {
code.clone() Cow::Borrowed(code)
}; };
buffer.append(0, &code, Style::Level(*level)); buffer.append(0, &code, Style::Level(*level));
buffer.append(0, "]", Style::Level(*level)); buffer.append(0, "]", Style::Level(*level));
@ -2077,7 +2076,7 @@ impl HumanEmitter {
level: &Level, level: &Level,
messages: &[(DiagnosticMessage, Style)], messages: &[(DiagnosticMessage, Style)],
args: &FluentArgs<'_>, args: &FluentArgs<'_>,
code: &Option<DiagnosticId>, code: &Option<String>,
span: &MultiSpan, span: &MultiSpan,
children: &[SubDiagnostic], children: &[SubDiagnostic],
suggestions: &[CodeSuggestion], suggestions: &[CodeSuggestion],

View File

@ -15,10 +15,9 @@ use termcolor::{ColorSpec, WriteColor};
use crate::emitter::{should_show_source_code, Emitter, 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::DiagnosticId;
use crate::{ use crate::{
CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic, diagnostic::IsLint, CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel,
TerminalUrl, SubDiagnostic, TerminalUrl,
}; };
use rustc_lint_defs::Applicability; use rustc_lint_defs::Applicability;
@ -301,7 +300,8 @@ struct DiagnosticSpanMacroExpansion {
#[derive(Serialize)] #[derive(Serialize)]
struct DiagnosticCode { struct DiagnosticCode {
/// The code itself. /// The error code (e.g. "E1234"), if the diagnostic has one. Or the lint
/// name, if it's a lint without an error code.
code: String, code: String,
/// An explanation for the code. /// An explanation for the code.
explanation: Option<&'static str>, explanation: Option<&'static str>,
@ -399,9 +399,21 @@ impl Diagnostic {
let output = String::from_utf8(output).unwrap(); let output = String::from_utf8(output).unwrap();
let translated_message = je.translate_messages(&diag.messages, &args); let translated_message = je.translate_messages(&diag.messages, &args);
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(),
})
} else if let Some(IsLint { name, .. }) = &diag.is_lint {
Some(DiagnosticCode { code: name.to_string(), explanation: None })
} else {
None
};
Diagnostic { Diagnostic {
message: translated_message.to_string(), message: translated_message.to_string(),
code: DiagnosticCode::map_opt_string(diag.code.clone(), je), code,
level: diag.level.to_str(), level: diag.level.to_str(),
spans: DiagnosticSpan::from_multispan(&diag.span, &args, je), spans: DiagnosticSpan::from_multispan(&diag.span, &args, je),
children: diag children: diag
@ -592,18 +604,3 @@ impl DiagnosticSpanLine {
.unwrap_or_else(|_| vec![]) .unwrap_or_else(|_| vec![])
} }
} }
impl DiagnosticCode {
fn map_opt_string(s: Option<DiagnosticId>, je: &JsonEmitter) -> Option<DiagnosticCode> {
s.map(|s| {
let s = match s {
DiagnosticId::Error(s) => s,
DiagnosticId::Lint { name, .. } => name,
};
let je_result =
je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap();
DiagnosticCode { code: s, explanation: je_result.ok() }
})
}
}

View File

@ -30,7 +30,7 @@ extern crate tracing;
extern crate self as rustc_errors; extern crate self as rustc_errors;
pub use diagnostic::{ pub use diagnostic::{
AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue,
DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
}; };
pub use diagnostic_builder::{ pub use diagnostic_builder::{
@ -442,13 +442,13 @@ struct DiagCtxtInner {
/// This is used for the `good_path_delayed_bugs` check. /// This is used for the `good_path_delayed_bugs` check.
suppressed_expected_diag: bool, suppressed_expected_diag: bool,
/// This set contains the `DiagnosticId` of all emitted diagnostics to avoid /// This set contains the code of all emitted diagnostics to avoid
/// emitting the same diagnostic with extended help (`--teach`) twice, which /// emitting the same diagnostic with extended help (`--teach`) twice, which
/// would be unnecessary repetition. /// would be unnecessary repetition.
taught_diagnostics: FxHashSet<DiagnosticId>, taught_diagnostics: FxHashSet<String>,
/// Used to suggest rustc --explain `<error code>` /// Used to suggest rustc --explain `<error code>`
emitted_diagnostic_codes: FxIndexSet<DiagnosticId>, emitted_diagnostic_codes: FxIndexSet<String>,
/// This set contains a hash of every diagnostic that has been emitted by /// 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 /// this `DiagCtxt`. These hashes is used to avoid emitting the same error
@ -676,7 +676,7 @@ impl DiagCtxt {
let key = (span.with_parent(None), key); let key = (span.with_parent(None), key);
if diag.is_error() { if diag.is_error() {
if diag.is_lint { if diag.is_lint.is_some() {
inner.lint_err_count += 1; inner.lint_err_count += 1;
} else { } else {
inner.err_count += 1; inner.err_count += 1;
@ -695,7 +695,7 @@ impl DiagCtxt {
let key = (span.with_parent(None), key); let key = (span.with_parent(None), key);
let diag = inner.stashed_diagnostics.remove(&key)?; let diag = inner.stashed_diagnostics.remove(&key)?;
if diag.is_error() { if diag.is_error() {
if diag.is_lint { if diag.is_lint.is_some() {
inner.lint_err_count -= 1; inner.lint_err_count -= 1;
} else { } else {
inner.err_count -= 1; inner.err_count -= 1;
@ -715,9 +715,7 @@ impl DiagCtxt {
/// Construct a builder at the `Warning` level at the given `span` and with the `msg`. /// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
/// ///
/// Attempting to `.emit()` the builder will only emit if either: /// An `emit` call on the builder will only emit if `can_emit_warnings` is `true`.
/// * `can_emit_warnings` is `true`
/// * `is_force_warn` was set in `DiagnosticId::Lint`
#[rustc_lint_diagnostics] #[rustc_lint_diagnostics]
#[track_caller] #[track_caller]
pub fn struct_span_warn( pub fn struct_span_warn(
@ -730,9 +728,7 @@ impl DiagCtxt {
/// Construct a builder at the `Warning` level with the `msg`. /// Construct a builder at the `Warning` level with the `msg`.
/// ///
/// Attempting to `.emit()` the builder will only emit if either: /// An `emit` call on the builder will only emit if `can_emit_warnings` is `true`.
/// * `can_emit_warnings` is `true`
/// * `is_force_warn` was set in `DiagnosticId::Lint`
#[rustc_lint_diagnostics] #[rustc_lint_diagnostics]
#[track_caller] #[track_caller]
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
@ -1011,11 +1007,12 @@ impl DiagCtxt {
let mut error_codes = inner let mut error_codes = inner
.emitted_diagnostic_codes .emitted_diagnostic_codes
.iter() .iter()
.filter_map(|x| match &x { .filter_map(|code| {
DiagnosticId::Error(s) if registry.try_find_description(s).is_ok() => { if registry.try_find_description(code).is_ok().clone() {
Some(s.clone()) Some(code.clone())
} else {
None
} }
_ => None,
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if !error_codes.is_empty() { if !error_codes.is_empty() {
@ -1058,8 +1055,8 @@ impl DiagCtxt {
/// ///
/// Used to suppress emitting the same error multiple times with extended explanation when /// Used to suppress emitting the same error multiple times with extended explanation when
/// calling `-Zteach`. /// calling `-Zteach`.
pub fn must_teach(&self, code: &DiagnosticId) -> bool { pub fn must_teach(&self, code: &str) -> bool {
self.inner.borrow_mut().taught_diagnostics.insert(code.clone()) self.inner.borrow_mut().taught_diagnostics.insert(code.to_string())
} }
pub fn force_print_diagnostic(&self, db: Diagnostic) { pub fn force_print_diagnostic(&self, db: Diagnostic) {
@ -1231,7 +1228,7 @@ impl DiagCtxtInner {
for diag in diags { for diag in diags {
// Decrement the count tracking the stash; emitting will increment it. // Decrement the count tracking the stash; emitting will increment it.
if diag.is_error() { if diag.is_error() {
if diag.is_lint { if diag.is_lint.is_some() {
self.lint_err_count -= 1; self.lint_err_count -= 1;
} else { } else {
self.err_count -= 1; self.err_count -= 1;
@ -1363,7 +1360,7 @@ impl DiagCtxtInner {
self.has_printed = true; self.has_printed = true;
} }
if diagnostic.is_error() { if diagnostic.is_error() {
if diagnostic.is_lint { if diagnostic.is_lint.is_some() {
self.lint_err_count += 1; self.lint_err_count += 1;
} else { } else {
self.err_count += 1; self.err_count += 1;

View File

@ -2,7 +2,7 @@ use super::potentially_plural_count;
use crate::errors::LifetimesOrBoundsMismatchOnTrait; use crate::errors::LifetimesOrBoundsMismatchOnTrait;
use hir::def_id::{DefId, DefIdMap, LocalDefId}; use hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_errors::{pluralize, struct_span_code_err, Applicability, DiagnosticId, ErrorGuaranteed}; use rustc_errors::{pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit; use rustc_hir::intravisit;
@ -1382,7 +1382,7 @@ fn compare_number_of_generics<'tcx>(
kind = kind, kind = kind,
), ),
); );
err.code(DiagnosticId::Error("E0049".into())); err.code("E0049".into());
let msg = let msg =
format!("expected {trait_count} {kind} parameter{}", pluralize!(trait_count),); format!("expected {trait_count} {kind} parameter{}", pluralize!(trait_count),);

View File

@ -6,13 +6,13 @@ pub use self::{
missing_cast_for_variadic_arg::*, sized_unsized_cast::*, wrong_number_of_generic_args::*, missing_cast_for_variadic_arg::*, sized_unsized_cast::*, wrong_number_of_generic_args::*,
}; };
use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use rustc_errors::DiagnosticBuilder;
use rustc_session::Session; use rustc_session::Session;
pub trait StructuredDiagnostic<'tcx> { pub trait StructuredDiagnostic<'tcx> {
fn session(&self) -> &Session; fn session(&self) -> &Session;
fn code(&self) -> DiagnosticId; fn code(&self) -> String;
fn diagnostic(&self) -> DiagnosticBuilder<'tcx> { fn diagnostic(&self) -> DiagnosticBuilder<'tcx> {
let err = self.diagnostic_common(); let err = self.diagnostic_common();

View File

@ -1,5 +1,5 @@
use crate::{errors, structured_errors::StructuredDiagnostic}; use crate::{errors, structured_errors::StructuredDiagnostic};
use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use rustc_errors::DiagnosticBuilder;
use rustc_middle::ty::{Ty, TypeVisitableExt}; use rustc_middle::ty::{Ty, TypeVisitableExt};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::Span; use rustc_span::Span;
@ -16,7 +16,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> {
self.sess self.sess
} }
fn code(&self) -> DiagnosticId { fn code(&self) -> String {
rustc_errors::error_code!(E0617) rustc_errors::error_code!(E0617)
} }

View File

@ -1,5 +1,5 @@
use crate::{errors, structured_errors::StructuredDiagnostic}; use crate::{errors, structured_errors::StructuredDiagnostic};
use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use rustc_errors::DiagnosticBuilder;
use rustc_middle::ty::{Ty, TypeVisitableExt}; use rustc_middle::ty::{Ty, TypeVisitableExt};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::Span; use rustc_span::Span;
@ -16,7 +16,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> {
self.sess self.sess
} }
fn code(&self) -> DiagnosticId { fn code(&self) -> String {
rustc_errors::error_code!(E0607) rustc_errors::error_code!(E0607)
} }

View File

@ -1,7 +1,5 @@
use crate::structured_errors::StructuredDiagnostic; use crate::structured_errors::StructuredDiagnostic;
use rustc_errors::{ use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan};
pluralize, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, MultiSpan,
};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt}; use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt};
use rustc_session::Session; use rustc_session::Session;
@ -1107,7 +1105,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> {
self.tcx.sess self.tcx.sess
} }
fn code(&self) -> DiagnosticId { fn code(&self) -> String {
rustc_errors::error_code!(E0107) rustc_errors::error_code!(E0107)
} }

View File

@ -26,7 +26,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{ use rustc_errors::{
pluralize, struct_span_code_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, pluralize, struct_span_code_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder,
DiagnosticId, ErrorGuaranteed, StashKey, ErrorGuaranteed, StashKey,
}; };
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def::{CtorKind, DefKind, Res};
@ -941,7 +941,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
let mut err = self.dcx().struct_span_err(op_span, "invalid left-hand side of assignment"); let mut err = self.dcx().struct_span_err(op_span, "invalid left-hand side of assignment");
err.code(DiagnosticId::Error(err_code.into())); err.code(err_code.into());
err.span_label(lhs.span, "cannot assign to this expression"); err.span_label(lhs.span, "cannot assign to this expression");
self.comes_from_while_condition(lhs.hir_id, |expr| { self.comes_from_while_condition(lhs.hir_id, |expr| {

View File

@ -12,9 +12,7 @@ use crate::{
use itertools::Itertools; use itertools::Itertools;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{ use rustc_errors::{pluralize, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan, StashKey};
pluralize, Applicability, Diagnostic, DiagnosticId, ErrorGuaranteed, MultiSpan, StashKey,
};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
@ -679,7 +677,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pluralize!("was", provided_args.len()) pluralize!("was", provided_args.len())
), ),
); );
err.code(DiagnosticId::Error(err_code.to_owned())); err.code(err_code.to_owned());
err.multipart_suggestion_verbose( err.multipart_suggestion_verbose(
"wrap these arguments in parentheses to construct a tuple", "wrap these arguments in parentheses to construct a tuple",
vec![ vec![
@ -829,7 +827,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pluralize!("was", provided_args.len()) pluralize!("was", provided_args.len())
), ),
) )
.with_code(DiagnosticId::Error(err_code.to_owned())) .with_code(err_code.to_owned())
}; };
// As we encounter issues, keep track of what we want to provide for the suggestion // As we encounter issues, keep track of what we want to provide for the suggestion

View File

@ -52,7 +52,7 @@ use crate::expectation::Expectation;
use crate::fn_ctxt::RawTy; use crate::fn_ctxt::RawTy;
use crate::gather_locals::GatherLocalsVisitor; use crate::gather_locals::GatherLocalsVisitor;
use rustc_data_structures::unord::UnordSet; use rustc_data_structures::unord::UnordSet;
use rustc_errors::{struct_span_code_err, DiagnosticId, ErrorGuaranteed}; use rustc_errors::{struct_span_code_err, ErrorGuaranteed};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::Visitor;
@ -369,7 +369,7 @@ fn report_unexpected_variant_res(
let err = tcx let err = tcx
.dcx() .dcx()
.struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`")) .struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`"))
.with_code(DiagnosticId::Error(err_code.into())); .with_code(err_code.into());
match res { match res {
Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == "E0164" => { Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == "E0164" => {
let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html"; let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html";

View File

@ -41,8 +41,8 @@ pub enum TypeAnnotationNeeded {
E0284, E0284,
} }
impl Into<rustc_errors::DiagnosticId> for TypeAnnotationNeeded { impl Into<String> for TypeAnnotationNeeded {
fn into(self) -> rustc_errors::DiagnosticId { fn into(self) -> String {
match self { match self {
Self::E0282 => rustc_errors::error_code!(E0282), Self::E0282 => rustc_errors::error_code!(E0282),
Self::E0283 => rustc_errors::error_code!(E0283), Self::E0283 => rustc_errors::error_code!(E0283),

View File

@ -211,7 +211,7 @@ impl DiagnosticDeriveVariantBuilder {
let code = nested.parse::<syn::LitStr>()?; let code = nested.parse::<syn::LitStr>()?;
tokens.extend(quote! { tokens.extend(quote! {
diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); diag.code(#code.to_string());
}); });
} else { } else {
span_err(path.span().unwrap(), "unknown argument") span_err(path.span().unwrap(), "unknown argument")

View File

@ -2,7 +2,7 @@ use std::cmp;
use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::sorted_map::SortedMap;
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, MultiSpan}; use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan};
use rustc_hir::{HirId, ItemLocalId}; use rustc_hir::{HirId, ItemLocalId};
use rustc_session::lint::{ use rustc_session::lint::{
builtin::{self, FORBIDDEN_LINT_GROUPS}, builtin::{self, FORBIDDEN_LINT_GROUPS},
@ -322,8 +322,6 @@ pub fn struct_lint_level(
err.span(span); err.span(span);
} }
err.is_lint();
// If this code originates in a foreign macro, aka something that this crate // If this code originates in a foreign macro, aka something that this crate
// did not itself author, then it's likely that there's nothing this crate // did not itself author, then it's likely that there's nothing this crate
// can do about it. We probably want to skip the lint entirely. // can do about it. We probably want to skip the lint entirely.
@ -351,8 +349,7 @@ pub fn struct_lint_level(
// suppressed the lint due to macros. // suppressed the lint due to macros.
err.primary_message(msg); err.primary_message(msg);
let name = lint.name_lower(); err.is_lint(lint.name_lower(), has_future_breakage);
err.code(DiagnosticId::Lint { name, has_future_breakage });
// Lint diagnostics that are covered by the expect level will not be emitted outside // Lint diagnostics that are covered by the expect level will not be emitted outside
// the compiler. It is therefore not necessary to add any information for the user. // the compiler. It is therefore not necessary to add any information for the user.

View File

@ -66,7 +66,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for RequiresUnsafe {
#[track_caller] #[track_caller]
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
let mut diag = DiagnosticBuilder::new(dcx, level, fluent::mir_transform_requires_unsafe); let mut diag = DiagnosticBuilder::new(dcx, level, fluent::mir_transform_requires_unsafe);
diag.code(rustc_errors::DiagnosticId::Error("E0133".to_string())); diag.code("E0133".to_string());
diag.span(self.span); diag.span(self.span);
diag.span_label(self.span, self.details.label()); diag.span_label(self.span, self.details.label());
let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter()); let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter());

View File

@ -180,8 +180,8 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) {
Default::default() Default::default()
}); });
let main_def_opt = tcx.resolutions(()).main_def; let main_def_opt = tcx.resolutions(()).main_def;
let diagnostic_id = error_code!(E0601); let code = error_code!(E0601);
let add_teach_note = tcx.sess.teach(&diagnostic_id); let add_teach_note = tcx.sess.teach(&code);
// The file may be empty, which leads to the diagnostic machinery not emitting this // The file may be empty, which leads to the diagnostic machinery not emitting this
// note. This is a relatively simple way to detect that case and emit a span-less // note. This is a relatively simple way to detect that case and emit a span-less
// note instead. // note instead.

View File

@ -16,7 +16,7 @@ use rustc_ast::ptr::P;
use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
use rustc_ast::*; use rustc_ast::*;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_errors::{Applicability, DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg}; use rustc_errors::{Applicability, DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
@ -533,7 +533,7 @@ impl<'a> PathSource<'a> {
} }
} }
fn error_code(self, has_unexpected_resolution: bool) -> DiagnosticId { fn error_code(self, has_unexpected_resolution: bool) -> String {
use rustc_errors::error_code; use rustc_errors::error_code;
match (self, has_unexpected_resolution) { match (self, has_unexpected_resolution) {
(PathSource::Trait(_), true) => error_code!(E0404), (PathSource::Trait(_), true) => error_code!(E0404),
@ -3821,7 +3821,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
swap(&mut err.span, &mut parent_err.span); swap(&mut err.span, &mut parent_err.span);
err.children = take(&mut parent_err.children); err.children = take(&mut parent_err.children);
err.sort_span = parent_err.sort_span; err.sort_span = parent_err.sort_span;
err.is_lint = parent_err.is_lint; err.is_lint = parent_err.is_lint.clone();
// merge the parent's suggestions with the typo suggestions // merge the parent's suggestions with the typo suggestions
fn append_result<T, E>(res1: &mut Result<Vec<T>, E>, res2: Result<Vec<T>, E>) { fn append_result<T, E>(res1: &mut Result<Vec<T>, E>, res2: Result<Vec<T>, E>) {

View File

@ -257,7 +257,7 @@ enum ResolutionError<'a> {
kind: &'static str, kind: &'static str,
trait_path: String, trait_path: String,
trait_item_span: Span, trait_item_span: Span,
code: rustc_errors::DiagnosticId, code: String,
}, },
/// Error E0201: multiple impl items for the same trait item. /// Error E0201: multiple impl items for the same trait item.
TraitImplDuplicate { name: Symbol, trait_item_span: Span, old_span: Span }, TraitImplDuplicate { name: Symbol, trait_item_span: Span, old_span: Span },

View File

@ -15,8 +15,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
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::SilentEmitter, DiagCtxt};
use rustc_errors::{ use rustc_errors::{
fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan, StashKey,
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;
@ -148,7 +147,7 @@ pub fn feature_warn_issue(
// Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level // Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level
let lint = UNSTABLE_SYNTAX_PRE_EXPANSION; let lint = UNSTABLE_SYNTAX_PRE_EXPANSION;
let future_incompatible = lint.future_incompatible.as_ref().unwrap(); let future_incompatible = lint.future_incompatible.as_ref().unwrap();
err.code(DiagnosticId::Lint { name: lint.name_lower(), has_future_breakage: false }); err.is_lint(lint.name_lower(), /* has_future_breakage */ false);
err.warn(lint.desc); err.warn(lint.desc);
err.note(format!("for more information, see {}", future_incompatible.reference)); err.note(format!("for more information, see {}", future_incompatible.reference));

View File

@ -20,9 +20,8 @@ use rustc_errors::emitter::{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::{
error_code, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticId, error_code, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticMessage,
DiagnosticMessage, ErrorGuaranteed, FatalAbort, FluentBundle, IntoDiagnostic, ErrorGuaranteed, FatalAbort, FluentBundle, IntoDiagnostic, LazyFallbackBundle, TerminalUrl,
LazyFallbackBundle, TerminalUrl,
}; };
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
pub use rustc_span::def_id::StableCrateId; pub use rustc_span::def_id::StableCrateId;
@ -906,7 +905,7 @@ impl Session {
CodegenUnits::Default(16) CodegenUnits::Default(16)
} }
pub fn teach(&self, code: &DiagnosticId) -> bool { pub fn teach(&self, code: &str) -> bool {
self.opts.unstable_opts.teach && self.dcx().must_teach(code) self.opts.unstable_opts.teach && self.dcx().must_teach(code)
} }