Overhaul Diagnostic args.

First, introduce a typedef `DiagnosticArgMap`.

Second, make the `args` field public, and remove the `args` getter and
`replace_args` setter. These were necessary previously because the getter
had a `#[allow(rustc::potential_query_instability)]` attribute, but that
was removed in #120931 when the args were changed from `FxHashMap` to
`FxIndexMap`. (All the other `Diagnostic` fields are public.)
This commit is contained in:
Nicholas Nethercote 2024-02-16 06:07:49 +11:00
parent f8131a48a4
commit b38ed1afa6
10 changed files with 24 additions and 31 deletions

View file

@ -103,8 +103,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_
fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
let diag: DiagnosticBuilder<'_, G> = self.0.into_diagnostic(dcx, level);
let (message, _) = diag.messages.first().expect("`LlvmError` with no message");
let message = dcx.eagerly_translate_to_string(message.clone(), diag.args());
let message = dcx.eagerly_translate_to_string(message.clone(), diag.args.iter());
DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config)
.with_arg("error", message)
}

View file

@ -16,8 +16,8 @@
use rustc_errors::emitter::Emitter;
use rustc_errors::translation::Translate;
use rustc_errors::{
DiagCtxt, DiagnosticArgName, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, ErrCode,
FatalError, FluentBundle, Level, Style,
DiagCtxt, DiagnosticArgMap, DiagnosticBuilder, DiagnosticMessage, ErrCode, FatalError,
FluentBundle, Level, Style,
};
use rustc_fs_util::link_or_copy;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
@ -1001,7 +1001,7 @@ pub(crate) enum Message<B: WriteBackendMethods> {
struct Diagnostic {
msgs: Vec<(DiagnosticMessage, Style)>,
args: FxIndexMap<DiagnosticArgName, DiagnosticArgValue>,
args: DiagnosticArgMap,
code: Option<ErrCode>,
lvl: Level,
}
@ -1813,8 +1813,8 @@ fn fallback_fluent_bundle(&self) -> &FluentBundle {
impl Emitter for SharedEmitter {
fn emit_diagnostic(&mut self, diag: rustc_errors::Diagnostic) {
let args: FxIndexMap<DiagnosticArgName, DiagnosticArgValue> =
diag.args().map(|(name, arg)| (name.clone(), arg.clone())).collect();
let args: DiagnosticArgMap =
diag.args.iter().map(|(name, arg)| (name.clone(), arg.clone())).collect();
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
msgs: diag.messages.clone(),
args: args.clone(),
@ -1857,7 +1857,7 @@ pub fn check(&self, sess: &Session, blocking: bool) {
let dcx = sess.dcx();
let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msgs);
d.code = diag.code; // may be `None`, that's ok
d.replace_args(diag.args);
d.args = diag.args;
dcx.emit_diagnostic(d);
}
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {

View file

@ -437,7 +437,7 @@ fn debug(self) -> String
let mut diag = dcx.struct_allow(DiagnosticMessage::Str(String::new().into()));
let message = self.diagnostic_message();
self.add_args(&mut diag);
let s = dcx.eagerly_translate_to_string(message, diag.args());
let s = dcx.eagerly_translate_to_string(message, diag.args.iter());
diag.cancel();
s
})
@ -864,7 +864,7 @@ fn add_args<G: EmissionGuarantee>(self, diag: &mut DiagnosticBuilder<'_, G>) {
let dummy_level = Level::Bug;
let dummy_diag: DiagnosticBuilder<'_, ()> =
e.into_diagnostic().into_diagnostic(diag.dcx, dummy_level);
for (name, val) in dummy_diag.args() {
for (name, val) in dummy_diag.args.iter() {
diag.arg(name.clone(), val.clone());
}
dummy_diag.cancel();

View file

@ -446,7 +446,7 @@ pub fn format_interp_error<'tcx>(dcx: &DiagCtxt, e: InterpErrorInfo<'tcx>) -> St
let mut diag = dcx.struct_allow("");
let msg = e.diagnostic_message();
e.add_args(&mut diag);
let s = dcx.eagerly_translate_to_string(msg, diag.args());
let s = dcx.eagerly_translate_to_string(msg, diag.args.iter());
diag.cancel();
s
}

View file

@ -45,7 +45,7 @@ fn fallback_fluent_bundle(&self) -> &FluentBundle {
impl Emitter for AnnotateSnippetEmitter {
/// The entry point for the diagnostics generation
fn emit_diagnostic(&mut self, mut diag: Diagnostic) {
let fluent_args = to_fluent_args(diag.args());
let fluent_args = to_fluent_args(diag.args.iter());
let mut suggestions = diag.suggestions.unwrap_or(vec![]);
self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args);

View file

@ -43,6 +43,8 @@ pub enum DiagnosticArgValue {
StrListSepByAnd(Vec<Cow<'static, str>>),
}
pub type DiagnosticArgMap = FxIndexMap<DiagnosticArgName, DiagnosticArgValue>;
/// Trait for types that `DiagnosticBuilder::emit` can return as a "guarantee"
/// (or "proof") token that the emission happened.
pub trait EmissionGuarantee: Sized {
@ -275,7 +277,7 @@ pub struct Diagnostic {
pub span: MultiSpan,
pub children: Vec<SubDiagnostic>,
pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
args: FxIndexMap<DiagnosticArgName, DiagnosticArgValue>,
pub args: DiagnosticArgMap,
/// This is not used for highlighting or rendering any error message. Rather, it can be used
/// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of
@ -403,14 +405,6 @@ pub(crate) fn arg(&mut self, name: impl Into<DiagnosticArgName>, arg: impl IntoD
self.args.insert(name.into(), arg.into_diagnostic_arg());
}
pub fn args(&self) -> impl Iterator<Item = DiagnosticArg<'_>> {
self.args.iter()
}
pub fn replace_args(&mut self, args: FxIndexMap<DiagnosticArgName, DiagnosticArgValue>) {
self.args = args;
}
/// Fields used for Hash, and PartialEq trait.
fn keys(
&self,
@ -431,7 +425,7 @@ fn keys(
&self.span,
&self.children,
&self.suggestions,
self.args().collect(),
self.args.iter().collect(),
// omit self.sort_span
&self.is_lint,
// omit self.emitted_at
@ -1165,7 +1159,7 @@ pub fn subdiagnostic(
subdiagnostic: impl AddToDiagnostic,
) -> &mut Self {
subdiagnostic.add_to_diagnostic_with(self, |diag, msg| {
let args = diag.args();
let args = diag.args.iter();
let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
dcx.eagerly_translate(msg, args)
});

View file

@ -519,7 +519,7 @@ fn source_map(&self) -> Option<&Lrc<SourceMap>> {
}
fn emit_diagnostic(&mut self, mut diag: Diagnostic) {
let fluent_args = to_fluent_args(diag.args());
let fluent_args = to_fluent_args(diag.args.iter());
let mut suggestions = diag.suggestions.unwrap_or(vec![]);
self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args);

View file

@ -341,7 +341,7 @@ struct UnusedExterns<'a, 'b, 'c> {
impl Diagnostic {
fn from_errors_diagnostic(diag: crate::Diagnostic, je: &JsonEmitter) -> Diagnostic {
let args = to_fluent_args(diag.args());
let args = to_fluent_args(diag.args.iter());
let sugg = diag.suggestions.iter().flatten().map(|sugg| {
let translated_message =
je.translate_message(&sugg.msg, &args).map_err(Report::new).unwrap();

View file

@ -37,9 +37,10 @@
pub use codes::*;
pub use diagnostic::{
AddToDiagnostic, BugAbort, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgName,
DiagnosticArgValue, DiagnosticBuilder, DiagnosticStyledString, EmissionGuarantee, FatalAbort,
IntoDiagnostic, IntoDiagnosticArg, StringPart, SubDiagnostic, SubdiagnosticMessageOp,
AddToDiagnostic, BugAbort, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgMap,
DiagnosticArgName, DiagnosticArgValue, DiagnosticBuilder, DiagnosticStyledString,
EmissionGuarantee, FatalAbort, IntoDiagnostic, IntoDiagnosticArg, StringPart, SubDiagnostic,
SubdiagnosticMessageOp,
};
pub use diagnostic_impls::{
DiagnosticArgFromDisplay, DiagnosticSymbolList, ExpectedLifetimeParameter,
@ -1482,9 +1483,8 @@ fn eagerly_translate_for_subdiag(
diag: &Diagnostic,
msg: impl Into<SubdiagnosticMessage>,
) -> SubdiagnosticMessage {
let args = diag.args();
let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
self.eagerly_translate(msg, args)
self.eagerly_translate(msg, diag.args.iter())
}
fn flush_delayed(&mut self) {

View file

@ -159,7 +159,7 @@ impl Emitter for BufferEmitter {
fn emit_diagnostic(&mut self, diag: Diagnostic) {
let mut buffer = self.buffer.borrow_mut();
let fluent_args = to_fluent_args(diag.args());
let fluent_args = to_fluent_args(diag.args.iter());
let translated_main_message = self
.translate_message(&diag.messages[0].0, &fluent_args)
.unwrap_or_else(|e| panic!("{e}"));