diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index a2807c852632e..a2c026706ada9 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -13,6 +13,7 @@ pub use unic_langid::{LanguageIdentifier, langid}; mod diagnostic_impls; pub use diagnostic_impls::DiagArgFromDisplay; +use rustc_data_structures::fx::FxIndexMap; pub fn register_functions(bundle: &mut fluent_bundle::bundle::FluentBundle) { bundle @@ -310,6 +311,10 @@ pub enum DiagArgValue { StrListSepByAnd(Vec>), } +/// A mapping from diagnostic argument names to their values. +/// This contains all the arguments necessary to format a diagnostic message. +pub type DiagArgMap = FxIndexMap; + /// Converts a value of a type into a `DiagArg` (typically a field of an `Diag` struct). /// Implemented as a custom trait rather than `From` so that it is implemented on the type being /// converted rather than on `DiagArgValue`, which enables types from other `rustc_*` crates to diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index bc1a56b5c092b..145937b22bea5 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -16,7 +16,7 @@ use annotate_snippets::{AnnotationKind, Group, Origin, Padding, Patch, Renderer, use anstream::ColorChoice; use derive_setters::Setters; use rustc_data_structures::sync::IntoDynSyncSend; -use rustc_error_messages::{FluentArgs, SpanLabel}; +use rustc_error_messages::{DiagArgMap, SpanLabel}; use rustc_lint_defs::pluralize; use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, FileName, Pos, SourceFile, Span}; @@ -26,7 +26,7 @@ use crate::emitter::{ ConfusionType, Destination, MAX_SUGGESTIONS, OutputTheme, detect_confusion_type, is_different, normalize_whitespace, should_show_source_code, }; -use crate::translation::{format_diag_message, format_diag_messages, to_fluent_args}; +use crate::translation::{format_diag_message, format_diag_messages}; use crate::{ CodeSuggestion, DiagInner, DiagMessage, Emitter, ErrCode, Level, MultiSpan, Style, Subdiag, SuggestionStyle, TerminalUrl, @@ -70,14 +70,12 @@ impl Debug for AnnotateSnippetEmitter { impl Emitter for AnnotateSnippetEmitter { /// The entry point for the diagnostics generation 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() { diag.children.insert(0, diag.emitted_at_sub_diag()); } let mut suggestions = diag.suggestions.unwrap_tag(); - self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args); + self.primary_span_formatted(&mut diag.span, &mut suggestions, &diag.args); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( &mut diag.span, @@ -89,7 +87,7 @@ impl Emitter for AnnotateSnippetEmitter { self.emit_messages_default( &diag.level, &diag.messages, - &fluent_args, + &diag.args, &diag.code, &diag.span, &diag.children, @@ -145,7 +143,7 @@ impl AnnotateSnippetEmitter { &mut self, level: &Level, msgs: &[(DiagMessage, Style)], - args: &FluentArgs<'_>, + args: &DiagArgMap, code: &Option, msp: &MultiSpan, children: &[Subdiag], @@ -539,7 +537,7 @@ impl AnnotateSnippetEmitter { &self, msgs: &[(DiagMessage, Style)], level: Level, - args: &FluentArgs<'_>, + args: &DiagArgMap, ) -> String { msgs.iter() .filter_map(|(m, style)| { @@ -673,7 +671,7 @@ struct Annotation { } fn collect_annotations( - args: &FluentArgs<'_>, + args: &DiagArgMap, msp: &MultiSpan, sm: &Arc, ) -> Vec<(Arc, Vec)> { diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 41005d12a1918..27a70534c5bc8 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -7,8 +7,7 @@ use std::panic; use std::path::PathBuf; use std::thread::panicking; -use rustc_data_structures::fx::FxIndexMap; -use rustc_error_messages::{DiagArgName, DiagArgValue, IntoDiagArg}; +use rustc_error_messages::{DiagArgMap, DiagArgName, DiagArgValue, IntoDiagArg}; use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_macros::{Decodable, Encodable}; use rustc_span::source_map::Spanned; @@ -20,8 +19,6 @@ use crate::{ MultiSpan, StashKey, Style, Substitution, SubstitutionPart, SuggestionStyle, Suggestions, }; -pub type DiagArgMap = FxIndexMap; - /// Trait for types that `Diag::emit` can return as a "guarantee" (or "proof") /// token that the emission happened. pub trait EmissionGuarantee: Sized { diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index e50d8ab67e6cb..8bb7dc35d82d4 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -17,7 +17,7 @@ use anstream::{AutoStream, ColorChoice}; use anstyle::{AnsiColor, Effects}; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::sync::DynSend; -use rustc_error_messages::FluentArgs; +use rustc_error_messages::DiagArgMap; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::SourceMap; use rustc_span::{FileName, SourceFile, Span}; @@ -102,7 +102,7 @@ pub trait Emitter { &self, primary_span: &mut MultiSpan, suggestions: &mut Vec, - fluent_args: &FluentArgs<'_>, + fluent_args: &DiagArgMap, ) { if let Some((sugg, rest)) = suggestions.split_first() { let msg = format_diag_message(&sugg.msg, fluent_args); diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index ab7a685e0461f..3b266d058b14f 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -17,7 +17,7 @@ use std::vec; use anstream::{AutoStream, ColorChoice}; use derive_setters::Setters; use rustc_data_structures::sync::IntoDynSyncSend; -use rustc_error_messages::FluentArgs; +use rustc_error_messages::DiagArgMap; use rustc_lint_defs::Applicability; use rustc_span::hygiene::ExpnData; use rustc_span::source_map::{FilePathMapping, SourceMap}; @@ -31,7 +31,7 @@ use crate::emitter::{ should_show_source_code, }; use crate::timings::{TimingRecord, TimingSection}; -use crate::translation::{format_diag_message, format_diag_messages, to_fluent_args}; +use crate::translation::{format_diag_message, format_diag_messages}; use crate::{CodeSuggestion, MultiSpan, SpanLabel, Subdiag, Suggestions, TerminalUrl}; #[cfg(test)] @@ -298,14 +298,13 @@ struct UnusedExterns<'a> { impl Diagnostic { /// Converts from `rustc_errors::DiagInner` to `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 = format_diag_message(&sugg.msg, &args); + let translated_message = format_diag_message(&sugg.msg, &diag.args); Diagnostic { message: translated_message.to_string(), code: None, level: "help", - spans: DiagnosticSpan::from_suggestion(sugg, &args, je), + spans: DiagnosticSpan::from_suggestion(sugg, &diag.args, je), children: vec![], rendered: None, } @@ -331,7 +330,7 @@ impl Diagnostic { } } - let translated_message = format_diag_messages(&diag.messages, &args); + let translated_message = format_diag_messages(&diag.messages, &diag.args); let code = if let Some(code) = diag.code { Some(DiagnosticCode { @@ -344,16 +343,18 @@ impl Diagnostic { None }; let level = diag.level.to_str(); - let spans = DiagnosticSpan::from_multispan(&diag.span, &args, je); + let spans = DiagnosticSpan::from_multispan(&diag.span, &diag.args, je); let mut children: Vec = diag .children .iter() - .map(|c| Diagnostic::from_sub_diagnostic(c, &args, je)) + .map(|c| Diagnostic::from_sub_diagnostic(c, &diag.args, je)) .chain(sugg) .collect(); if je.track_diagnostics && diag.span.has_primary_spans() && !diag.span.is_dummy() { - children - .insert(0, Diagnostic::from_sub_diagnostic(&diag.emitted_at_sub_diag(), &args, je)); + children.insert( + 0, + Diagnostic::from_sub_diagnostic(&diag.emitted_at_sub_diag(), &diag.args, je), + ); } let buf = BufWriter(Arc::new(Mutex::new(Vec::new()))); let dst: Destination = AutoStream::new( @@ -388,11 +389,7 @@ impl Diagnostic { } } - fn from_sub_diagnostic( - subdiag: &Subdiag, - args: &FluentArgs<'_>, - je: &JsonEmitter, - ) -> Diagnostic { + fn from_sub_diagnostic(subdiag: &Subdiag, args: &DiagArgMap, je: &JsonEmitter) -> Diagnostic { let translated_message = format_diag_messages(&subdiag.messages, args); Diagnostic { message: translated_message.to_string(), @@ -409,7 +406,7 @@ impl DiagnosticSpan { fn from_span_label( span: SpanLabel, suggestion: Option<(&String, Applicability)>, - args: &FluentArgs<'_>, + args: &DiagArgMap, je: &JsonEmitter, ) -> DiagnosticSpan { Self::from_span_etc( @@ -509,11 +506,7 @@ impl DiagnosticSpan { } } - fn from_multispan( - msp: &MultiSpan, - args: &FluentArgs<'_>, - je: &JsonEmitter, - ) -> Vec { + fn from_multispan(msp: &MultiSpan, args: &DiagArgMap, je: &JsonEmitter) -> Vec { msp.span_labels() .into_iter() .map(|span_str| Self::from_span_label(span_str, None, args, je)) @@ -522,7 +515,7 @@ impl DiagnosticSpan { fn from_suggestion( suggestion: &CodeSuggestion, - args: &FluentArgs<'_>, + args: &DiagArgMap, je: &JsonEmitter, ) -> Vec { suggestion diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 0386ce9eed95b..eab919f08ab50 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -39,8 +39,8 @@ pub use anstyle::{ pub use codes::*; pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer}; pub use diagnostic::{ - BugAbort, Diag, DiagArgMap, DiagInner, DiagStyledString, Diagnostic, EmissionGuarantee, - FatalAbort, LintDiagnostic, LintDiagnosticBox, StringPart, Subdiag, Subdiagnostic, + BugAbort, Diag, DiagInner, DiagStyledString, Diagnostic, EmissionGuarantee, FatalAbort, + LintDiagnostic, LintDiagnosticBox, StringPart, Subdiag, Subdiagnostic, }; pub use diagnostic_impls::{ DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter, @@ -53,7 +53,7 @@ use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::{DynSend, Lock}; use rustc_data_structures::{AtomicRef, assert_matches}; pub use rustc_error_messages::{ - DiagArg, DiagArgFromDisplay, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg, + DiagArg, DiagArgFromDisplay, DiagArgMap, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg, LanguageIdentifier, MultiSpan, SpanLabel, fluent_bundle, into_diag_arg_using_display, }; use rustc_hashes::Hash128; @@ -1434,7 +1434,7 @@ impl DiagCtxtInner { message: DiagMessage, args: impl Iterator>, ) -> String { - let args = crate::translation::to_fluent_args(args); + let args = args.map(|(name, val)| (name.clone(), val.clone())).collect(); format_diag_message(&message, &args).to_string() } diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index 0ae1451482068..0de40cd84dcf9 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -1,7 +1,7 @@ use std::borrow::Cow; pub use rustc_error_messages::FluentArgs; -use rustc_error_messages::{langid, register_functions}; +use rustc_error_messages::{DiagArgMap, langid, register_functions}; use tracing::{debug, trace}; use crate::fluent_bundle::FluentResource; @@ -12,7 +12,7 @@ use crate::{DiagArg, DiagMessage, Style, fluent_bundle}; /// /// Typically performed once for each diagnostic at the start of `emit_diagnostic` and then /// passed around as a reference thereafter. -pub fn to_fluent_args<'iter>(iter: impl Iterator>) -> FluentArgs<'static> { +fn to_fluent_args<'iter>(iter: impl Iterator>) -> FluentArgs<'static> { let mut args = if let Some(size) = iter.size_hint().1 { FluentArgs::with_capacity(size) } else { @@ -29,14 +29,15 @@ pub fn to_fluent_args<'iter>(iter: impl Iterator>) -> Flue /// Convert `DiagMessage`s to a string pub fn format_diag_messages( messages: &[(DiagMessage, Style)], - args: &FluentArgs<'_>, + args: &DiagArgMap, ) -> Cow<'static, str> { Cow::Owned(messages.iter().map(|(m, _)| format_diag_message(m, args)).collect::()) } /// Convert a `DiagMessage` to a string -pub fn format_diag_message<'a>(message: &'a DiagMessage, args: &'a FluentArgs<'_>) -> Cow<'a, str> { +pub fn format_diag_message<'a>(message: &'a DiagMessage, args: &DiagArgMap) -> Cow<'a, str> { trace!(?message, ?args); + match message { DiagMessage::Str(msg) => Cow::Borrowed(msg), // This translates an inline fluent diagnostic message @@ -52,9 +53,10 @@ pub fn format_diag_message<'a>(message: &'a DiagMessage, args: &'a FluentArgs<'_ register_functions(&mut bundle); let message = bundle.get_message(GENERATED_MSG_ID).unwrap(); let value = message.value().unwrap(); + let args = to_fluent_args(args.iter()); let mut errs = vec![]; - let translated = bundle.format_pattern(value, Some(args), &mut errs).to_string(); + let translated = bundle.format_pattern(value, Some(&args), &mut errs).to_string(); debug!(?translated, ?errs); if errs.is_empty() { Cow::Owned(translated) diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index a755efe515477..be1168b2eceec 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use rustc_data_structures::sync::Lock; use rustc_errors::emitter::Emitter; -use rustc_errors::translation::{format_diag_message, to_fluent_args}; +use rustc_errors::translation::format_diag_message; use rustc_errors::{Applicability, DiagCtxt, DiagInner}; use rustc_parse::{source_str_to_stream, unwrap_or_emit_fatal}; use rustc_resolve::rustdoc::source_span_for_markdown_range; @@ -150,8 +150,7 @@ impl Emitter for BufferEmitter { fn emit_diagnostic(&mut self, diag: DiagInner) { let mut buffer = self.buffer.borrow_mut(); - let fluent_args = to_fluent_args(diag.args.iter()); - let translated_main_message = format_diag_message(&diag.messages[0].0, &fluent_args); + let translated_main_message = format_diag_message(&diag.messages[0].0, &diag.args); buffer.messages.push(format!("error from rustc: {translated_main_message}")); if diag.is_error() {