errors: only eagerly translate subdiagnostics

Subdiagnostics don't need to be lazily translated, they can always be
eagerly translated. Eager translation is slightly more complex as we need
to have a `DiagCtxt` available to perform the translation, which involves
slightly more threading of that context.

This slight increase in complexity should enable later simplifications -
like passing `DiagCtxt` into `AddToDiagnostic` and moving Fluent messages
into the diagnostic structs rather than having them in separate files
(working on that was what led to this change).

Signed-off-by: David Wood <david@davidtw.co>
This commit is contained in:
David Wood 2024-02-14 14:17:27 +00:00
parent bb89df6903
commit b80fc5d4e8
No known key found for this signature in database
43 changed files with 532 additions and 388 deletions

View file

@ -263,14 +263,10 @@ pub enum SubdiagnosticMessage {
/// 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.
Eager(Cow<'static, str>),
/// be instantiated multiple times with different values. These subdiagnostics' messages
/// are translated when they are added to the parent diagnostic, producing this variant of
/// `DiagnosticMessage`.
Translated(Cow<'static, str>),
/// Identifier of a Fluent message. Instances of this variant are generated by the
/// `Subdiagnostic` derive.
FluentIdentifier(FluentId),
@ -307,19 +303,15 @@ impl From<Cow<'static, str>> for SubdiagnosticMessage {
pub enum DiagnosticMessage {
/// Non-translatable diagnostic message.
Str(Cow<'static, str>),
/// Translatable message which has already been translated eagerly.
/// Translatable message which has been already translated.
///
/// 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.
Eager(Cow<'static, str>),
/// be instantiated multiple times with different values. These subdiagnostics' messages
/// are translated when they are added to the parent diagnostic, producing this variant of
/// `DiagnosticMessage`.
Translated(Cow<'static, str>),
/// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic
/// message.
/// message. Yet to be translated.
///
/// <https://projectfluent.org/fluent/guide/hello.html>
/// <https://projectfluent.org/fluent/guide/attributes.html>
@ -336,7 +328,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::Translated(s) => return DiagnosticMessage::Translated(s),
SubdiagnosticMessage::FluentIdentifier(id) => {
return DiagnosticMessage::FluentIdentifier(id, None);
}
@ -345,7 +337,7 @@ impl DiagnosticMessage {
match self {
DiagnosticMessage::Str(s) => DiagnosticMessage::Str(s.clone()),
DiagnosticMessage::Eager(s) => DiagnosticMessage::Eager(s.clone()),
DiagnosticMessage::Translated(s) => DiagnosticMessage::Translated(s.clone()),
DiagnosticMessage::FluentIdentifier(id, _) => {
DiagnosticMessage::FluentIdentifier(id.clone(), Some(attr))
}
@ -354,7 +346,7 @@ impl DiagnosticMessage {
pub fn as_str(&self) -> Option<&str> {
match self {
DiagnosticMessage::Eager(s) | DiagnosticMessage::Str(s) => Some(s),
DiagnosticMessage::Translated(s) | DiagnosticMessage::Str(s) => Some(s),
DiagnosticMessage::FluentIdentifier(_, _) => None,
}
}
@ -396,7 +388,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::Translated(s) => SubdiagnosticMessage::Translated(s),
DiagnosticMessage::FluentIdentifier(id, None) => {
SubdiagnosticMessage::FluentIdentifier(id)
}