Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macros: introduce fluent_messages macro #97327

Merged

Conversation

davidtwco
Copy link
Member

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..

fluent_messages! {
    typeck => "./typeck.ftl",
}

..where typeck.ftl has the following contents..

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...

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:

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:

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

@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label May 23, 2022
@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 23, 2022
@oli-obk
Copy link
Contributor

oli-obk commented May 24, 2022

@bors r+

@bors
Copy link
Contributor

bors commented May 24, 2022

📌 Commit d7d5a0b has been approved by oli-obk

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 24, 2022
Comment on lines +25 to +30
error: expected a message field for "missing-message"
--> ./missing-message.ftl:1:1
|
1 | missing-message =
| ^^^^^^^^^^^^^^^^^^
|
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spans into non-Rust code are so cool

Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request May 24, 2022
…mpile-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`
@Dylan-DPC

This comment was marked as resolved.

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels May 24, 2022
@davidtwco davidtwco force-pushed the diagnostic-translation-compile-time-validation branch from d7d5a0b to f3d0cda Compare May 24, 2022 14:29
With `ignore (rust)` rather than `ignore (pseudo-Rust)` my editor
highlights the code in the block, which is nicer.

Signed-off-by: David Wood <david.wood@huawei.com>
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..

```ignore (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, and will generate the following code:

```ignore (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:

```ignore (rust)
let mut err = sess.struct_span_err(
    span,
    fluent::typeck::field_multiply_specified_in_initializer
);
err.span_default_label(span);
err.span_label(
    previous_use_span,
    fluent::typeck::field_multiply_specified_in_initializer_label_previous_use
);
err.emit();
```

Signed-off-by: David Wood <david.wood@huawei.com>
Use new typed Fluent identifiers for the "missing type parameters"
diagnostic in the typeck crate which was manually creating
`DiagnosticMessage`s previously.

Signed-off-by: David Wood <david.wood@huawei.com>
@davidtwco davidtwco force-pushed the diagnostic-translation-compile-time-validation branch from f3d0cda to ce9901f Compare May 24, 2022 15:48
@oli-obk
Copy link
Contributor

oli-obk commented May 26, 2022

@bors r+

@bors
Copy link
Contributor

bors commented May 26, 2022

📌 Commit ce9901f has been approved by oli-obk

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 26, 2022
@bors
Copy link
Contributor

bors commented May 26, 2022

⌛ Testing commit ce9901f with merge 71836c3f551ade22dbe2eda2361c4a93574ae786...

@rust-log-analyzer
Copy link
Collaborator

The job x86_64-apple-2 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
      Memory: 14 GB
      System Firmware Version: VMW71.00V.13989454.B64.1906190538
      Apple ROM Info: [MS_VM_CERT/SHA1/27d66596a61c48dd3dc7216fd715126e33f59ae7]Welcome to the Virtual Machine
      SMC Version (system): 2.8f0
      Serial Number (system): VMRd/GyU2YJf
      Provisioning UDID: 4203018E-580F-C1B5-9525-B745CECA79EB

hw.ncpu: 3
hw.byteorder: 1234
---
Some tests failed in compiletest suite=rustdoc mode=rustdoc host=x86_64-apple-darwin target=x86_64-apple-darwin

failures:

---- [rustdoc] src/test/rustdoc/primitive/no_std.rs stdout ----
thread '[rustdoc] src/test/rustdoc/primitive/no_std.rs' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 22, kind: InvalidInput, message: "Invalid argument" }', src/tools/compiletest/src/runtest.rs:2252:34


failures:
    [rustdoc] src/test/rustdoc/primitive/no_std.rs

@bors
Copy link
Contributor

bors commented May 26, 2022

💔 Test failed - checks-actions

@bors bors removed the S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. label May 26, 2022
@bors bors added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 26, 2022
@davidtwco
Copy link
Member Author

This seems pretty spurious.

@bors retry

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 27, 2022
bors added a commit to rust-lang-ci/rust that referenced this pull request May 28, 2022
Rollup of 5 pull requests

Successful merges:

 - rust-lang#94640 (Partially stabilize `(const_)slice_ptr_len` feature by stabilizing `NonNull::len`)
 - rust-lang#97034 (Implement `Hash` for `core::alloc::Layout`)
 - rust-lang#97327 (macros: introduce `fluent_messages` macro )
 - rust-lang#97448 (docs: Don't imply that OsStr on Unix is always UTF-8)
 - rust-lang#97466 ([bootstrap] Move `sanitize_sh` from `dist` to `install`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 7e7dd1c into rust-lang:master May 28, 2022
@rustbot rustbot added this to the 1.63.0 milestone May 28, 2022
@davidtwco davidtwco deleted the diagnostic-translation-compile-time-validation branch May 28, 2022 12:00
@compiler-errors compiler-errors added the A-translation Area: Translation infrastructure, and migrating existing diagnostics to SessionDiagnostic label Aug 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-translation Area: Translation infrastructure, and migrating existing diagnostics to SessionDiagnostic S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants