diff options
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_error_messages/src/lib.rs | 88 |
1 files changed, 70 insertions, 18 deletions
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 02bb04d98..9465051dd 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -2,6 +2,11 @@ #![feature(once_cell)] #![feature(rustc_attrs)] #![feature(type_alias_impl_trait)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] + +#[macro_use] +extern crate tracing; use fluent_bundle::FluentResource; use fluent_syntax::parser::ParserError; @@ -14,7 +19,6 @@ use std::fmt; use std::fs; use std::io; use std::path::{Path, PathBuf}; -use tracing::{instrument, trace}; #[cfg(not(parallel_compiler))] use std::cell::LazyCell as Lazy; @@ -31,15 +35,38 @@ pub use unic_langid::{langid, LanguageIdentifier}; // Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module. fluent_messages! { + // tidy-alphabetical-start + ast_lowering => "../locales/en-US/ast_lowering.ftl", + ast_passes => "../locales/en-US/ast_passes.ftl", + attr => "../locales/en-US/attr.ftl", borrowck => "../locales/en-US/borrowck.ftl", builtin_macros => "../locales/en-US/builtin_macros.ftl", + codegen_gcc => "../locales/en-US/codegen_gcc.ftl", + codegen_ssa => "../locales/en-US/codegen_ssa.ftl", + compiletest => "../locales/en-US/compiletest.ftl", const_eval => "../locales/en-US/const_eval.ftl", + driver => "../locales/en-US/driver.ftl", + errors => "../locales/en-US/errors.ftl", expand => "../locales/en-US/expand.ftl", + hir_analysis => "../locales/en-US/hir_analysis.ftl", + infer => "../locales/en-US/infer.ftl", + interface => "../locales/en-US/interface.ftl", lint => "../locales/en-US/lint.ftl", + metadata => "../locales/en-US/metadata.ftl", + middle => "../locales/en-US/middle.ftl", + mir_dataflow => "../locales/en-US/mir_dataflow.ftl", + monomorphize => "../locales/en-US/monomorphize.ftl", parser => "../locales/en-US/parser.ftl", passes => "../locales/en-US/passes.ftl", + plugin_impl => "../locales/en-US/plugin_impl.ftl", privacy => "../locales/en-US/privacy.ftl", - typeck => "../locales/en-US/typeck.ftl", + query_system => "../locales/en-US/query_system.ftl", + save_analysis => "../locales/en-US/save_analysis.ftl", + session => "../locales/en-US/session.ftl", + symbol_mangling => "../locales/en-US/symbol_mangling.ftl", + trait_selection => "../locales/en-US/trait_selection.ftl", + ty_utils => "../locales/en-US/ty_utils.ftl", + // tidy-alphabetical-end } pub use fluent_generated::{self as fluent, DEFAULT_LOCALE_RESOURCES}; @@ -247,14 +274,26 @@ type FluentId = Cow<'static, str>; /// Translatable messages for subdiagnostics are typically attributes attached to a larger Fluent /// message so messages of this type must be combined with a `DiagnosticMessage` (using /// `DiagnosticMessage::with_subdiagnostic_message`) before rendering. However, subdiagnostics from -/// the `SessionSubdiagnostic` derive refer to Fluent identifiers directly. +/// the `Subdiagnostic` derive refer to Fluent identifiers directly. #[rustc_diagnostic_item = "SubdiagnosticMessage"] pub enum SubdiagnosticMessage { /// Non-translatable diagnostic message. // FIXME(davidtwco): can a `Cow<'static, str>` be used here? Str(String), + /// Translatable message which has already been translated eagerly. + /// + /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would + /// be instantiated multiple times with different values. As translation normally happens + /// immediately prior to emission, after the diagnostic and subdiagnostic derive logic has run, + /// the setting of diagnostic arguments in the derived code will overwrite previous variable + /// values and only the final value will be set when translation occurs - resulting in + /// incorrect diagnostics. Eager translation results in translation for a subdiagnostic + /// happening immediately after the subdiagnostic derive's logic has been run. This variant + /// stores messages which have been translated eagerly. + // FIXME(#100717): can a `Cow<'static, str>` be used here? + Eager(String), /// Identifier of a Fluent message. Instances of this variant are generated by the - /// `SessionSubdiagnostic` derive. + /// `Subdiagnostic` derive. FluentIdentifier(FluentId), /// Attribute of a Fluent message. Needs to be combined with a Fluent identifier to produce an /// actual translated message. Instances of this variant are generated by the `fluent_messages` @@ -280,8 +319,20 @@ impl<S: Into<String>> From<S> for SubdiagnosticMessage { #[rustc_diagnostic_item = "DiagnosticMessage"] pub enum DiagnosticMessage { /// Non-translatable diagnostic message. - // FIXME(davidtwco): can a `Cow<'static, str>` be used here? + // FIXME(#100717): can a `Cow<'static, str>` be used here? Str(String), + /// Translatable message which has already been translated eagerly. + /// + /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would + /// be instantiated multiple times with different values. As translation normally happens + /// immediately prior to emission, after the diagnostic and subdiagnostic derive logic has run, + /// the setting of diagnostic arguments in the derived code will overwrite previous variable + /// values and only the final value will be set when translation occurs - resulting in + /// incorrect diagnostics. Eager translation results in translation for a subdiagnostic + /// happening immediately after the subdiagnostic derive's logic has been run. This variant + /// stores messages which have been translated eagerly. + // FIXME(#100717): can a `Cow<'static, str>` be used here? + Eager(String), /// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic /// message. /// @@ -300,6 +351,7 @@ impl DiagnosticMessage { pub fn with_subdiagnostic_message(&self, sub: SubdiagnosticMessage) -> Self { let attr = match sub { SubdiagnosticMessage::Str(s) => return DiagnosticMessage::Str(s), + SubdiagnosticMessage::Eager(s) => return DiagnosticMessage::Eager(s), SubdiagnosticMessage::FluentIdentifier(id) => { return DiagnosticMessage::FluentIdentifier(id, None); } @@ -308,24 +360,12 @@ impl DiagnosticMessage { match self { DiagnosticMessage::Str(s) => DiagnosticMessage::Str(s.clone()), + DiagnosticMessage::Eager(s) => DiagnosticMessage::Eager(s.clone()), DiagnosticMessage::FluentIdentifier(id, _) => { DiagnosticMessage::FluentIdentifier(id.clone(), Some(attr)) } } } - - /// Returns the `String` contained within the `DiagnosticMessage::Str` variant, assuming that - /// this diagnostic message is of the legacy, non-translatable variety. Panics if this - /// assumption does not hold. - /// - /// Don't use this - it exists to support some places that do comparison with diagnostic - /// strings. - pub fn expect_str(&self) -> &str { - match self { - DiagnosticMessage::Str(s) => s, - _ => panic!("expected non-translatable diagnostic message"), - } - } } /// `From` impl that enables existing diagnostic calls to functions which now take @@ -336,6 +376,17 @@ impl<S: Into<String>> From<S> for DiagnosticMessage { } } +/// A workaround for "good path" ICEs when formatting types in disables lints. +/// +/// Delays formatting until `.into(): DiagnosticMessage` is used. +pub struct DelayDm<F>(pub F); + +impl<F: FnOnce() -> String> From<DelayDm<F>> for DiagnosticMessage { + fn from(DelayDm(f): DelayDm<F>) -> Self { + DiagnosticMessage::from(f()) + } +} + /// Translating *into* a subdiagnostic message from a diagnostic message is a little strange - but /// the subdiagnostic functions (e.g. `span_label`) take a `SubdiagnosticMessage` and the /// subdiagnostic derive refers to typed identifiers that are `DiagnosticMessage`s, so need to be @@ -345,6 +396,7 @@ impl Into<SubdiagnosticMessage> for DiagnosticMessage { fn into(self) -> SubdiagnosticMessage { match self { DiagnosticMessage::Str(s) => SubdiagnosticMessage::Str(s), + DiagnosticMessage::Eager(s) => SubdiagnosticMessage::Eager(s), DiagnosticMessage::FluentIdentifier(id, None) => { SubdiagnosticMessage::FluentIdentifier(id) } |