Rollup merge of #97327 - davidtwco:diagnostic-translation-compile-time-validation, r=oli-obk
macros: introduce `fluent_messages` macro Adds a new `fluent_messages` macro which performs compile-time validation of the compiler's Fluent resources (i.e. that the resources parse and don't multiply define the same messages) and generates constants that make using those messages in diagnostics more ergonomic. For example, given the following invocation of the macro.. ```rust fluent_messages! { typeck => "./typeck.ftl", } ``` ..where `typeck.ftl` has the following contents.. ```fluent typeck-field-multiply-specified-in-initializer = field `{$ident}` specified more than once .label = used more than once .label-previous-use = first use of `{$ident}` ``` ...then the macro parse the Fluent resource, emitting a diagnostic if it fails to do so... ```text error: could not parse Fluent resource --> $DIR/test.rs:35:28 | LL | missing_message => "./missing-message.ftl", | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: see additional errors emitted error: expected a message field for "missing-message" --> ./missing-message.ftl:1:1 | 1 | missing-message = | ^^^^^^^^^^^^^^^^^^ | ``` ...or generating the following code if it succeeds: ```rust pub static DEFAULT_LOCALE_RESOURCES: &'static [&'static str] = &[ include_str!("./typeck.ftl"), ]; mod fluent_generated { mod typeck { pub const field_multiply_specified_in_initializer: DiagnosticMessage = DiagnosticMessage::fluent("typeck-field-multiply-specified-in-initializer"); pub const field_multiply_specified_in_initializer_label_previous_use: DiagnosticMessage = DiagnosticMessage::fluent_attr( "typeck-field-multiply-specified-in-initializer", "previous-use-label" ); } } ``` When emitting a diagnostic, the generated constants can be used as follows: ```rust let mut err = sess.struct_span_err( span, fluent::typeck::field_multiply_specified_in_initializer ); err.span_label( span, fluent::typeck::field_multiply_specified_in_initializer_label ); err.span_label( previous_use_span, fluent::typeck::field_multiply_specified_in_initializer_label_previous_use ); err.emit(); ``` I'd like to reduce the verbosity of referring to labels/notes/helps with this scheme (though it wasn't much better before), but I'll leave that for a follow-up. r? `@oli-obk` cc `@pvdrz` `@compiler-errors`
This commit is contained in:
commit
7e7dd1c069
14 changed files with 455 additions and 18 deletions
|
@ -1,7 +1,5 @@
|
|||
//! Errors emitted by typeck.
|
||||
use rustc_errors::{
|
||||
error_code, Applicability, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed,
|
||||
};
|
||||
use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_session::{parse::ParseSess, SessionDiagnostic};
|
||||
|
@ -264,10 +262,9 @@ pub struct MissingTypeParams {
|
|||
// Manual implementation of `SessionDiagnostic` to be able to call `span_to_snippet`.
|
||||
impl<'a> SessionDiagnostic<'a> for MissingTypeParams {
|
||||
fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
static SLUG: &'static str = "typeck-missing-type-params";
|
||||
let mut err = sess.span_diagnostic.struct_span_err_with_code(
|
||||
self.span,
|
||||
DiagnosticMessage::fluent(SLUG),
|
||||
rustc_errors::fluent::typeck::missing_type_params,
|
||||
error_code!(E0393),
|
||||
);
|
||||
err.set_arg("parameterCount", self.missing_type_params.len());
|
||||
|
@ -280,7 +277,7 @@ impl<'a> SessionDiagnostic<'a> for MissingTypeParams {
|
|||
.join(", "),
|
||||
);
|
||||
|
||||
err.span_label(self.def_span, DiagnosticMessage::fluent_attr(SLUG, "label"));
|
||||
err.span_label(self.def_span, rustc_errors::fluent::typeck::missing_type_params_label);
|
||||
|
||||
let mut suggested = false;
|
||||
if let (Ok(snippet), true) = (
|
||||
|
@ -298,7 +295,7 @@ impl<'a> SessionDiagnostic<'a> for MissingTypeParams {
|
|||
// least we can clue them to the correct syntax `Iterator<Type>`.
|
||||
err.span_suggestion(
|
||||
self.span,
|
||||
DiagnosticMessage::fluent_attr(SLUG, "suggestion"),
|
||||
rustc_errors::fluent::typeck::missing_type_params_suggestion,
|
||||
format!("{}<{}>", snippet, self.missing_type_params.join(", ")),
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
|
@ -306,10 +303,13 @@ impl<'a> SessionDiagnostic<'a> for MissingTypeParams {
|
|||
}
|
||||
}
|
||||
if !suggested {
|
||||
err.span_label(self.span, DiagnosticMessage::fluent_attr(SLUG, "no-suggestion-label"));
|
||||
err.span_label(
|
||||
self.span,
|
||||
rustc_errors::fluent::typeck::missing_type_params_no_suggestion_label,
|
||||
);
|
||||
}
|
||||
|
||||
err.note(DiagnosticMessage::fluent_attr(SLUG, "note"));
|
||||
err.note(rustc_errors::fluent::typeck::missing_type_params_note);
|
||||
err
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue