Skip to content

Commit 508d7e6

Browse files
committed
errors: use HashMap to store diagnostic args
Eager translation will enable subdiagnostics to be translated multiple times with different arguments - this requires the ability to replace the value of one argument with a new value, which is better suited to a `HashMap` than the previous storage, a `Vec`. Signed-off-by: David Wood <[email protected]>
1 parent febbf71 commit 508d7e6

File tree

7 files changed

+49
-26
lines changed

7 files changed

+49
-26
lines changed

compiler/rustc_codegen_ssa/src/back/write.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ use rustc_data_structures::profiling::TimingGuard;
1515
use rustc_data_structures::profiling::VerboseTimingGuard;
1616
use rustc_data_structures::sync::Lrc;
1717
use rustc_errors::emitter::Emitter;
18-
use rustc_errors::{translation::Translate, DiagnosticId, FatalError, Handler, Level};
18+
use rustc_errors::{
19+
translation::{to_fluent_args, Translate},
20+
DiagnosticId, FatalError, Handler, Level,
21+
};
1922
use rustc_fs_util::link_or_copy;
2023
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
2124
use rustc_incremental::{
@@ -1750,7 +1753,7 @@ impl Translate for SharedEmitter {
17501753

17511754
impl Emitter for SharedEmitter {
17521755
fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) {
1753-
let fluent_args = self.to_fluent_args(diag.args());
1756+
let fluent_args = to_fluent_args(diag.args());
17541757
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
17551758
msg: self.translate_messages(&diag.message, &fluent_args).to_string(),
17561759
code: diag.code.clone(),

compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
88
use crate::emitter::FileWithAnnotatedLines;
99
use crate::snippet::Line;
10-
use crate::translation::Translate;
10+
use crate::translation::{to_fluent_args, Translate};
1111
use crate::{
1212
CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle,
1313
LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic,
@@ -46,7 +46,7 @@ impl Translate for AnnotateSnippetEmitterWriter {
4646
impl Emitter for AnnotateSnippetEmitterWriter {
4747
/// The entry point for the diagnostics generation
4848
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
49-
let fluent_args = self.to_fluent_args(diag.args());
49+
let fluent_args = to_fluent_args(diag.args());
5050

5151
let mut children = diag.children.clone();
5252
let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args);

compiler/rustc_errors/src/diagnostic.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ pub struct SuggestionsDisabled;
2727
/// Simplified version of `FluentArg` that can implement `Encodable` and `Decodable`. Collection of
2828
/// `DiagnosticArg` are converted to `FluentArgs` (consuming the collection) at the start of
2929
/// diagnostic emission.
30-
pub type DiagnosticArg<'source> = (Cow<'source, str>, DiagnosticArgValue<'source>);
30+
pub type DiagnosticArg<'iter, 'source> =
31+
(&'iter DiagnosticArgName<'source>, &'iter DiagnosticArgValue<'source>);
32+
33+
/// Name of a diagnostic argument.
34+
pub type DiagnosticArgName<'source> = Cow<'source, str>;
3135

3236
/// Simplified version of `FluentValue` that can implement `Encodable` and `Decodable`. Converted
3337
/// to a `FluentValue` by the emitter to be used in diagnostic translation.
@@ -229,7 +233,7 @@ pub struct Diagnostic {
229233
pub span: MultiSpan,
230234
pub children: Vec<SubDiagnostic>,
231235
pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
232-
args: Vec<DiagnosticArg<'static>>,
236+
args: FxHashMap<DiagnosticArgName<'static>, DiagnosticArgValue<'static>>,
233237

234238
/// This is not used for highlighting or rendering any error message. Rather, it can be used
235239
/// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of
@@ -321,7 +325,7 @@ impl Diagnostic {
321325
span: MultiSpan::new(),
322326
children: vec![],
323327
suggestions: Ok(vec![]),
324-
args: vec![],
328+
args: Default::default(),
325329
sort_span: DUMMY_SP,
326330
is_lint: false,
327331
}
@@ -956,16 +960,19 @@ impl Diagnostic {
956960
self
957961
}
958962

959-
pub fn args(&self) -> &[DiagnosticArg<'static>] {
960-
&self.args
963+
// Exact iteration order of diagnostic arguments shouldn't make a difference to output because
964+
// they're only used in interpolation.
965+
#[allow(rustc::potential_query_instability)]
966+
pub fn args<'a>(&'a self) -> impl Iterator<Item = DiagnosticArg<'a, 'static>> {
967+
self.args.iter()
961968
}
962969

963970
pub fn set_arg(
964971
&mut self,
965972
name: impl Into<Cow<'static, str>>,
966973
arg: impl IntoDiagnosticArg,
967974
) -> &mut Self {
968-
self.args.push((name.into(), arg.into_diagnostic_arg()));
975+
self.args.insert(name.into(), arg.into_diagnostic_arg());
969976
self
970977
}
971978

compiler/rustc_errors/src/emitter.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_span::{FileLines, SourceFile, Span};
1414

1515
use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString};
1616
use crate::styled_buffer::StyledBuffer;
17-
use crate::translation::Translate;
17+
use crate::translation::{to_fluent_args, Translate};
1818
use crate::{
1919
CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, FluentBundle, Handler,
2020
LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight, SuggestionStyle,
@@ -535,7 +535,7 @@ impl Emitter for EmitterWriter {
535535
}
536536

537537
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
538-
let fluent_args = self.to_fluent_args(diag.args());
538+
let fluent_args = to_fluent_args(diag.args());
539539

540540
let mut children = diag.children.clone();
541541
let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args);

compiler/rustc_errors/src/json.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_span::source_map::{FilePathMapping, SourceMap};
1313

1414
use crate::emitter::{Emitter, HumanReadableErrorType};
1515
use crate::registry::Registry;
16-
use crate::translation::Translate;
16+
use crate::translation::{to_fluent_args, Translate};
1717
use crate::DiagnosticId;
1818
use crate::{
1919
CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic,
@@ -312,7 +312,7 @@ struct UnusedExterns<'a, 'b, 'c> {
312312

313313
impl Diagnostic {
314314
fn from_errors_diagnostic(diag: &crate::Diagnostic, je: &JsonEmitter) -> Diagnostic {
315-
let args = je.to_fluent_args(diag.args());
315+
let args = to_fluent_args(diag.args());
316316
let sugg = diag.suggestions.iter().flatten().map(|sugg| {
317317
let translated_message = je.translate_message(&sugg.msg, &args);
318318
Diagnostic {

compiler/rustc_errors/src/translation.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,27 @@ use rustc_data_structures::sync::Lrc;
44
use rustc_error_messages::FluentArgs;
55
use std::borrow::Cow;
66

7+
/// Convert diagnostic arguments (a rustc internal type that exists to implement
8+
/// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation.
9+
///
10+
/// Typically performed once for each diagnostic at the start of `emit_diagnostic` and then
11+
/// passed around as a reference thereafter.
12+
pub fn to_fluent_args<'iter, 'arg: 'iter>(
13+
iter: impl Iterator<Item = DiagnosticArg<'iter, 'arg>>,
14+
) -> FluentArgs<'arg> {
15+
let mut args = if let Some(size) = iter.size_hint().1 {
16+
FluentArgs::with_capacity(size)
17+
} else {
18+
FluentArgs::new()
19+
};
20+
21+
for (k, v) in iter {
22+
args.set(k.clone(), v.clone());
23+
}
24+
25+
args
26+
}
27+
728
pub trait Translate {
829
/// Return `FluentBundle` with localized diagnostics for the locale requested by the user. If no
930
/// language was requested by the user then this will be `None` and `fallback_fluent_bundle`
@@ -15,15 +36,6 @@ pub trait Translate {
1536
/// unavailable for the requested locale.
1637
fn fallback_fluent_bundle(&self) -> &FluentBundle;
1738

18-
/// Convert diagnostic arguments (a rustc internal type that exists to implement
19-
/// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation.
20-
///
21-
/// Typically performed once for each diagnostic at the start of `emit_diagnostic` and then
22-
/// passed around as a reference thereafter.
23-
fn to_fluent_args<'arg>(&self, args: &[DiagnosticArg<'arg>]) -> FluentArgs<'arg> {
24-
FromIterator::from_iter(args.iter().cloned())
25-
}
26-
2739
/// Convert `DiagnosticMessage`s to a string, performing translation if necessary.
2840
fn translate_messages(
2941
&self,

src/librustdoc/passes/check_code_block_syntax.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
//! Validates syntax inside Rust code blocks (\`\`\`rust).
22
use rustc_data_structures::sync::{Lock, Lrc};
33
use rustc_errors::{
4-
emitter::Emitter, translation::Translate, Applicability, Diagnostic, Handler,
5-
LazyFallbackBundle,
4+
emitter::Emitter,
5+
translation::{to_fluent_args, Translate},
6+
Applicability, Diagnostic, Handler, LazyFallbackBundle,
67
};
78
use rustc_parse::parse_stream_from_source_str;
89
use rustc_session::parse::ParseSess;
@@ -193,7 +194,7 @@ impl Emitter for BufferEmitter {
193194
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
194195
let mut buffer = self.buffer.borrow_mut();
195196

196-
let fluent_args = self.to_fluent_args(diag.args());
197+
let fluent_args = to_fluent_args(diag.args());
197198
let translated_main_message = self.translate_message(&diag.message[0].0, &fluent_args);
198199

199200
buffer.messages.push(format!("error from rustc: {}", translated_main_message));

0 commit comments

Comments
 (0)