summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_error_messages/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_error_messages/src/lib.rs88
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)
}