Skip to content

Commit 34a6c9f

Browse files
committed
Auto merge of #95968 - davidtwco:translation-lazy-fallback, r=oli-obk
errors: lazily load fallback fluent bundle Addresses (hopefully) #95667 (comment). Loading the fallback bundle in compilation sessions that won't go on to emit any errors unnecessarily degrades compile time performance, so lazily create the Fluent bundle when it is first required. r? `@ghost` (just for perf initially)
2 parents dc4bfcb + 9bfe0e3 commit 34a6c9f

File tree

19 files changed

+94
-81
lines changed

19 files changed

+94
-81
lines changed

Diff for: compiler/rustc_codegen_ssa/src/back/write.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1731,7 +1731,7 @@ impl Emitter for SharedEmitter {
17311731
None
17321732
}
17331733

1734-
fn fallback_fluent_bundle(&self) -> &Lrc<rustc_errors::FluentBundle> {
1734+
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
17351735
panic!("shared emitter attempted to translate a diagnostic");
17361736
}
17371737
}

Diff for: compiler/rustc_driver/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1173,7 +1173,7 @@ static DEFAULT_HOOK: SyncLazy<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send +
11731173
/// hook.
11741174
pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
11751175
let fallback_bundle =
1176-
rustc_errors::fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle");
1176+
rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
11771177
let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
11781178
rustc_errors::ColorConfig::Auto,
11791179
None,
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
parser-struct-literal-body-without-path =
2+
struct literal body without path
3+
.suggestion = you might have forgotten to add the struct literal inside the block

Diff for: compiler/rustc_error_messages/locales/en-US/diagnostics.ftl renamed to compiler/rustc_error_messages/locales/en-US/typeck.ftl

-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
parser-struct-literal-body-without-path =
2-
struct literal body without path
3-
.suggestion = you might have forgotten to add the struct literal inside the block
4-
51
typeck-field-multiply-specified-in-initializer =
62
field `{$ident}` specified more than once
73
.label = used more than once

Diff for: compiler/rustc_error_messages/src/lib.rs

+29-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#![feature(let_chains)]
2+
#![feature(once_cell)]
23
#![feature(path_try_exists)]
4+
#![feature(type_alias_impl_trait)]
35

46
use fluent_bundle::FluentResource;
57
use fluent_syntax::parser::ParserError;
@@ -14,6 +16,11 @@ use std::io;
1416
use std::path::{Path, PathBuf};
1517
use tracing::{instrument, trace};
1618

19+
#[cfg(not(parallel_compiler))]
20+
use std::lazy::Lazy;
21+
#[cfg(parallel_compiler)]
22+
use std::lazy::SyncLazy as Lazy;
23+
1724
#[cfg(parallel_compiler)]
1825
use intl_memoizer::concurrent::IntlLangMemoizer;
1926
#[cfg(not(parallel_compiler))]
@@ -22,7 +29,8 @@ use intl_memoizer::IntlLangMemoizer;
2229
pub use fluent_bundle::{FluentArgs, FluentError, FluentValue};
2330
pub use unic_langid::{langid, LanguageIdentifier};
2431

25-
static FALLBACK_FLUENT_RESOURCE: &'static str = include_str!("../locales/en-US/diagnostics.ftl");
32+
pub static DEFAULT_LOCALE_RESOURCES: &'static [&'static str] =
33+
&[include_str!("../locales/en-US/typeck.ftl"), include_str!("../locales/en-US/parser.ftl")];
2634

2735
pub type FluentBundle = fluent_bundle::bundle::FluentBundle<FluentResource, IntlLangMemoizer>;
2836

@@ -192,20 +200,30 @@ pub fn fluent_bundle(
192200
Ok(Some(bundle))
193201
}
194202

203+
/// Type alias for the result of `fallback_fluent_bundle` - a reference-counted pointer to a lazily
204+
/// evaluated fluent bundle.
205+
pub type LazyFallbackBundle = Lrc<Lazy<FluentBundle, impl FnOnce() -> FluentBundle>>;
206+
195207
/// Return the default `FluentBundle` with standard "en-US" diagnostic messages.
196208
#[instrument(level = "trace")]
197209
pub fn fallback_fluent_bundle(
210+
resources: &'static [&'static str],
198211
with_directionality_markers: bool,
199-
) -> Result<Lrc<FluentBundle>, TranslationBundleError> {
200-
let fallback_resource = FluentResource::try_new(FALLBACK_FLUENT_RESOURCE.to_string())
201-
.map_err(TranslationBundleError::from)?;
202-
trace!(?fallback_resource);
203-
let mut fallback_bundle = new_bundle(vec![langid!("en-US")]);
204-
// See comment in `fluent_bundle`.
205-
fallback_bundle.set_use_isolating(with_directionality_markers);
206-
fallback_bundle.add_resource(fallback_resource).map_err(TranslationBundleError::from)?;
207-
let fallback_bundle = Lrc::new(fallback_bundle);
208-
Ok(fallback_bundle)
212+
) -> LazyFallbackBundle {
213+
Lrc::new(Lazy::new(move || {
214+
let mut fallback_bundle = new_bundle(vec![langid!("en-US")]);
215+
// See comment in `fluent_bundle`.
216+
fallback_bundle.set_use_isolating(with_directionality_markers);
217+
218+
for resource in resources {
219+
let resource = FluentResource::try_new(resource.to_string())
220+
.expect("failed to parse fallback fluent resource");
221+
trace!(?resource);
222+
fallback_bundle.add_resource_overriding(resource);
223+
}
224+
225+
fallback_bundle
226+
}))
209227
}
210228

211229
/// Identifier for the Fluent message/attribute corresponding to a diagnostic message.

Diff for: compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
use crate::emitter::FileWithAnnotatedLines;
99
use crate::snippet::Line;
1010
use crate::{
11-
CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle, Level,
12-
MultiSpan, Style, SubDiagnostic,
11+
CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle,
12+
LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic,
1313
};
1414
use annotate_snippets::display_list::{DisplayList, FormatOptions};
1515
use annotate_snippets::snippet::*;
@@ -22,7 +22,7 @@ use rustc_span::SourceFile;
2222
pub struct AnnotateSnippetEmitterWriter {
2323
source_map: Option<Lrc<SourceMap>>,
2424
fluent_bundle: Option<Lrc<FluentBundle>>,
25-
fallback_bundle: Lrc<FluentBundle>,
25+
fallback_bundle: LazyFallbackBundle,
2626

2727
/// If true, hides the longer explanation text
2828
short_message: bool,
@@ -67,8 +67,8 @@ impl Emitter for AnnotateSnippetEmitterWriter {
6767
self.fluent_bundle.as_ref()
6868
}
6969

70-
fn fallback_fluent_bundle(&self) -> &Lrc<FluentBundle> {
71-
&self.fallback_bundle
70+
fn fallback_fluent_bundle(&self) -> &FluentBundle {
71+
&**self.fallback_bundle
7272
}
7373

7474
fn should_show_explain(&self) -> bool {
@@ -101,7 +101,7 @@ impl AnnotateSnippetEmitterWriter {
101101
pub fn new(
102102
source_map: Option<Lrc<SourceMap>>,
103103
fluent_bundle: Option<Lrc<FluentBundle>>,
104-
fallback_bundle: Lrc<FluentBundle>,
104+
fallback_bundle: LazyFallbackBundle,
105105
short_message: bool,
106106
macro_backtrace: bool,
107107
) -> Self {

Diff for: compiler/rustc_errors/src/emitter.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Styl
1616
use crate::styled_buffer::StyledBuffer;
1717
use crate::{
1818
CodeSuggestion, Diagnostic, DiagnosticArg, DiagnosticId, DiagnosticMessage, FluentBundle,
19-
Handler, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight, SuggestionStyle,
19+
Handler, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight,
20+
SuggestionStyle,
2021
};
2122

2223
use rustc_lint_defs::pluralize;
@@ -60,7 +61,7 @@ impl HumanReadableErrorType {
6061
dst: Box<dyn Write + Send>,
6162
source_map: Option<Lrc<SourceMap>>,
6263
bundle: Option<Lrc<FluentBundle>>,
63-
fallback_bundle: Lrc<FluentBundle>,
64+
fallback_bundle: LazyFallbackBundle,
6465
teach: bool,
6566
terminal_width: Option<usize>,
6667
macro_backtrace: bool,
@@ -233,7 +234,7 @@ pub trait Emitter {
233234
/// Return `FluentBundle` with localized diagnostics for the default locale of the compiler.
234235
/// Used when the user has not requested a specific language or when a localized diagnostic is
235236
/// unavailable for the requested locale.
236-
fn fallback_fluent_bundle(&self) -> &Lrc<FluentBundle>;
237+
fn fallback_fluent_bundle(&self) -> &FluentBundle;
237238

238239
/// Convert diagnostic arguments (a rustc internal type that exists to implement
239240
/// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation.
@@ -579,8 +580,8 @@ impl Emitter for EmitterWriter {
579580
self.fluent_bundle.as_ref()
580581
}
581582

582-
fn fallback_fluent_bundle(&self) -> &Lrc<FluentBundle> {
583-
&self.fallback_bundle
583+
fn fallback_fluent_bundle(&self) -> &FluentBundle {
584+
&**self.fallback_bundle
584585
}
585586

586587
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
@@ -635,7 +636,7 @@ impl Emitter for SilentEmitter {
635636
None
636637
}
637638

638-
fn fallback_fluent_bundle(&self) -> &Lrc<FluentBundle> {
639+
fn fallback_fluent_bundle(&self) -> &FluentBundle {
639640
panic!("silent emitter attempted to translate message")
640641
}
641642

@@ -695,7 +696,7 @@ pub struct EmitterWriter {
695696
dst: Destination,
696697
sm: Option<Lrc<SourceMap>>,
697698
fluent_bundle: Option<Lrc<FluentBundle>>,
698-
fallback_bundle: Lrc<FluentBundle>,
699+
fallback_bundle: LazyFallbackBundle,
699700
short_message: bool,
700701
teach: bool,
701702
ui_testing: bool,
@@ -716,7 +717,7 @@ impl EmitterWriter {
716717
color_config: ColorConfig,
717718
source_map: Option<Lrc<SourceMap>>,
718719
fluent_bundle: Option<Lrc<FluentBundle>>,
719-
fallback_bundle: Lrc<FluentBundle>,
720+
fallback_bundle: LazyFallbackBundle,
720721
short_message: bool,
721722
teach: bool,
722723
terminal_width: Option<usize>,
@@ -740,7 +741,7 @@ impl EmitterWriter {
740741
dst: Box<dyn Write + Send>,
741742
source_map: Option<Lrc<SourceMap>>,
742743
fluent_bundle: Option<Lrc<FluentBundle>>,
743-
fallback_bundle: Lrc<FluentBundle>,
744+
fallback_bundle: LazyFallbackBundle,
744745
short_message: bool,
745746
teach: bool,
746747
colored: bool,

Diff for: compiler/rustc_errors/src/json.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ use crate::emitter::{Emitter, HumanReadableErrorType};
1515
use crate::registry::Registry;
1616
use crate::DiagnosticId;
1717
use crate::ToolMetadata;
18-
use crate::{CodeSuggestion, FluentBundle, MultiSpan, SpanLabel, SubDiagnostic};
18+
use crate::{
19+
CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic,
20+
};
1921
use rustc_lint_defs::Applicability;
2022

2123
use rustc_data_structures::sync::Lrc;
@@ -38,7 +40,7 @@ pub struct JsonEmitter {
3840
registry: Option<Registry>,
3941
sm: Lrc<SourceMap>,
4042
fluent_bundle: Option<Lrc<FluentBundle>>,
41-
fallback_bundle: Lrc<FluentBundle>,
43+
fallback_bundle: LazyFallbackBundle,
4244
pretty: bool,
4345
ui_testing: bool,
4446
json_rendered: HumanReadableErrorType,
@@ -51,7 +53,7 @@ impl JsonEmitter {
5153
registry: Option<Registry>,
5254
source_map: Lrc<SourceMap>,
5355
fluent_bundle: Option<Lrc<FluentBundle>>,
54-
fallback_bundle: Lrc<FluentBundle>,
56+
fallback_bundle: LazyFallbackBundle,
5557
pretty: bool,
5658
json_rendered: HumanReadableErrorType,
5759
terminal_width: Option<usize>,
@@ -75,7 +77,7 @@ impl JsonEmitter {
7577
pretty: bool,
7678
json_rendered: HumanReadableErrorType,
7779
fluent_bundle: Option<Lrc<FluentBundle>>,
78-
fallback_bundle: Lrc<FluentBundle>,
80+
fallback_bundle: LazyFallbackBundle,
7981
terminal_width: Option<usize>,
8082
macro_backtrace: bool,
8183
) -> JsonEmitter {
@@ -97,7 +99,7 @@ impl JsonEmitter {
9799
registry: Option<Registry>,
98100
source_map: Lrc<SourceMap>,
99101
fluent_bundle: Option<Lrc<FluentBundle>>,
100-
fallback_bundle: Lrc<FluentBundle>,
102+
fallback_bundle: LazyFallbackBundle,
101103
pretty: bool,
102104
json_rendered: HumanReadableErrorType,
103105
terminal_width: Option<usize>,
@@ -192,8 +194,8 @@ impl Emitter for JsonEmitter {
192194
self.fluent_bundle.as_ref()
193195
}
194196

195-
fn fallback_fluent_bundle(&self) -> &Lrc<FluentBundle> {
196-
&self.fallback_bundle
197+
fn fallback_fluent_bundle(&self) -> &FluentBundle {
198+
&**self.fallback_bundle
197199
}
198200

199201
fn should_show_explain(&self) -> bool {

Diff for: compiler/rustc_errors/src/json/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
4040
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
4141
sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned());
4242
let fallback_bundle =
43-
crate::fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle");
43+
crate::fallback_fluent_bundle(rustc_error_messages::DEFAULT_LOCALE_RESOURCES, false);
4444

4545
let output = Arc::new(Mutex::new(Vec::new()));
4646
let je = JsonEmitter::new(

Diff for: compiler/rustc_errors/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use rustc_data_structures::sync::{self, Lock, Lrc};
3333
use rustc_data_structures::AtomicRef;
3434
pub use rustc_error_messages::{
3535
fallback_fluent_bundle, fluent_bundle, DiagnosticMessage, FluentBundle, LanguageIdentifier,
36-
MultiSpan, SpanLabel,
36+
LazyFallbackBundle, MultiSpan, SpanLabel, DEFAULT_LOCALE_RESOURCES,
3737
};
3838
pub use rustc_lint_defs::{pluralize, Applicability};
3939
use rustc_serialize::json::Json;
@@ -547,7 +547,7 @@ impl Handler {
547547
treat_err_as_bug: Option<NonZeroUsize>,
548548
sm: Option<Lrc<SourceMap>>,
549549
fluent_bundle: Option<Lrc<FluentBundle>>,
550-
fallback_bundle: Lrc<FluentBundle>,
550+
fallback_bundle: LazyFallbackBundle,
551551
) -> Self {
552552
Self::with_tty_emitter_and_flags(
553553
color_config,
@@ -562,7 +562,7 @@ impl Handler {
562562
color_config: ColorConfig,
563563
sm: Option<Lrc<SourceMap>>,
564564
fluent_bundle: Option<Lrc<FluentBundle>>,
565-
fallback_bundle: Lrc<FluentBundle>,
565+
fallback_bundle: LazyFallbackBundle,
566566
flags: HandlerFlags,
567567
) -> Self {
568568
let emitter = Box::new(EmitterWriter::stderr(

Diff for: compiler/rustc_expand/src/tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
127127
create_default_session_if_not_set_then(|_| {
128128
let output = Arc::new(Mutex::new(Vec::new()));
129129

130-
let fallback_bundle = rustc_errors::fallback_fluent_bundle(false)
131-
.expect("failed to load fallback fluent bundle");
130+
let fallback_bundle =
131+
rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
132132
let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
133133
source_map.new_source_file(Path::new("test.rs").to_owned().into(), file_text.to_owned());
134134

Diff for: compiler/rustc_session/src/parse.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,7 @@ pub struct ParseSess {
173173
impl ParseSess {
174174
/// Used for testing.
175175
pub fn new(file_path_mapping: FilePathMapping) -> Self {
176-
let fallback_bundle =
177-
fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle");
176+
let fallback_bundle = fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
178177
let sm = Lrc::new(SourceMap::new(file_path_mapping));
179178
let handler = Handler::with_tty_emitter(
180179
ColorConfig::Auto,
@@ -211,8 +210,7 @@ impl ParseSess {
211210
}
212211

213212
pub fn with_silent_emitter(fatal_note: Option<String>) -> Self {
214-
let fallback_bundle =
215-
fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle");
213+
let fallback_bundle = fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
216214
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
217215
let fatal_handler =
218216
Handler::with_tty_emitter(ColorConfig::Auto, false, None, None, None, fallback_bundle);

Diff for: compiler/rustc_session/src/session.rs

+7-15
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc_errors::json::JsonEmitter;
2121
use rustc_errors::registry::Registry;
2222
use rustc_errors::{
2323
fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, EmissionGuarantee,
24-
ErrorGuaranteed, FluentBundle, MultiSpan,
24+
ErrorGuaranteed, FluentBundle, LazyFallbackBundle, MultiSpan,
2525
};
2626
use rustc_macros::HashStable_Generic;
2727
pub use rustc_span::def_id::StableCrateId;
@@ -1080,7 +1080,7 @@ fn default_emitter(
10801080
registry: rustc_errors::registry::Registry,
10811081
source_map: Lrc<SourceMap>,
10821082
bundle: Option<Lrc<FluentBundle>>,
1083-
fallback_bundle: Lrc<FluentBundle>,
1083+
fallback_bundle: LazyFallbackBundle,
10841084
emitter_dest: Option<Box<dyn Write + Send>>,
10851085
) -> Box<dyn Emitter + sync::Send> {
10861086
let macro_backtrace = sopts.debugging_opts.macro_backtrace;
@@ -1215,17 +1215,10 @@ pub fn build_session(
12151215
hash_kind,
12161216
));
12171217

1218-
let fallback_bundle =
1219-
match fallback_fluent_bundle(sopts.debugging_opts.translate_directionality_markers) {
1220-
Ok(bundle) => bundle,
1221-
Err(e) => {
1222-
early_error(
1223-
sopts.error_format,
1224-
&format!("failed to load fallback fluent bundle: {e}"),
1225-
);
1226-
}
1227-
};
1228-
1218+
let fallback_bundle = fallback_fluent_bundle(
1219+
rustc_errors::DEFAULT_LOCALE_RESOURCES,
1220+
sopts.debugging_opts.translate_directionality_markers,
1221+
);
12291222
let emitter =
12301223
default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle, write_dest);
12311224

@@ -1460,8 +1453,7 @@ pub enum IncrCompSession {
14601453
}
14611454

14621455
fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler {
1463-
let fallback_bundle =
1464-
fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle");
1456+
let fallback_bundle = fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
14651457
let emitter: Box<dyn Emitter + sync::Send> = match output {
14661458
config::ErrorOutputType::HumanReadable(kind) => {
14671459
let (short, color_config) = kind.unzip();

Diff for: src/librustdoc/core.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ crate fn new_handler(
146146
debugging_opts: &DebuggingOptions,
147147
) -> rustc_errors::Handler {
148148
let fallback_bundle =
149-
rustc_errors::fallback_fluent_bundle(false).expect("failed to load fallback fluent bundle");
149+
rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
150150
let emitter: Box<dyn Emitter + sync::Send> = match error_format {
151151
ErrorOutputType::HumanReadable(kind) => {
152152
let (short, color_config) = kind.unzip();

0 commit comments

Comments
 (0)